假設(a)()
也將是有效的,這裏的解決此問題的方法:
grammar T;
options {
output=AST;
}
tokens {
EXPR_LIST;
CALL;
INDEX;
LOOKUP;
}
parse
: expr EOF -> expr
;
expr
: add_expr
;
add_expr
: mul_exp (('+' | '-')^ mul_exp)*
;
mul_exp
: atom (('*' | '/')^ atom)*
;
atom
: fncall
| NUM
;
fncall
: (fncall_start -> fncall_start) ('(' expr_list ')' -> ^(CALL $fncall expr_list)
| '[' expr ']' -> ^(INDEX $fncall expr)
| '.' ID -> ^(LOOKUP $fncall ID)
)*
;
fncall_start
: ID
| '(' expr ')' -> expr
;
expr_list
: (expr (',' expr)*)? -> ^(EXPR_LIST expr*)
;
NUM : '0'..'9'+;
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*;
從語法生成上述將解析輸入解析器:
(foo.bar().array[i*2])(42)(1,2,3)
和構造如下的AST:
沒有樹重寫規則,語法看起來是這樣的:
grammar T;
parse
: expr EOF
;
expr
: add_expr
;
add_expr
: mul_exp (('+' | '-') mul_exp)*
;
mul_exp
: atom (('*' | '/') atom)*
;
atom
: fncall
| NUM
;
fncall
: fncall_start ('(' expr_list ')' | '[' expr ']' | '.' ID)*
;
fncall_start
: ID
| '(' expr ')'
;
expr_list
: (expr (',' expr)*)?
;
NUM : '0'..'9'+;
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*;
你介意解釋謂詞在這種情況下的工作原理嗎?但非常感謝代碼。 –
@luxun,我沒有使用任何謂詞:它只是一個創建AST的(簡單)語法,所以有一些重寫規則。我編輯了我的答案,包括相同的語法,但沒有重寫規則(不用說,這個語法不會像我發佈的圖像中那樣創建AST)。 –
啊我明白了。非常感謝。 –