我正在尝试编写一段语法来表达层次结构的字段访问,例如 abc ,其中 c 是 ab <的字段/ em>和 b 是 a 的字段。
要评估 a.b.c.d.e 的值,我们需要评估 a.b.c.d 的值,然后获取 e 的值。 要评估 abcd 的值,我们需要评估 abc 的值,然后获取 d 的值,依此类推......
如果您有这样的树(箭头表示“lhs是rhs的父母”):
Node(e) -> Node(d) -> Node(c) -> Node(b) -> Node(a)
评估很简单。使用递归,我们只需要解析子的值,然后访问正确的字段。
问题是:我的ANTLR语法文件中有3条规则:
tokens {
LBRACE = '{' ;
RBRACE = '}' ;
LBRACK = '[' ;
RBRACK = ']' ;
DOT = '.' ;
....
}
reference
: DOLLAR LBRACE selector RBRACE -> ^(NODE_VAR_REFERENCE selector)
;
selector
: IDENT access -> ^(IDENT access)
;
access
: DOT IDENT access? -> ^(IDENT<node=com.at.cson.ast.FieldAccessTree> access?)
| LBRACK IDENT RBRACK access? -> ^(IDENT<node=com.at.cson.ast.FieldAccessTree> access?)
| LBRACK INTEGER RBRACK access? -> ^(INTEGER<node=com.at.cson.ast.ArrayAccessTree> access?)
;
正如所料,我的树有这样的形式:
ReferenceTree
IdentTree[a]
FieldAccessTree[b]
FieldAccessTree[c]
FieldAccessTree[d]
FieldAccessTree[e]
评估并不像在其他情况下那么容易,因为我需要获取当前节点的值,然后将其提供给孩子等等......
有没有办法使用ANTLR来反转树的顺序,或者我需要手动执行它?
答案 0 :(得分:1)
您只能使用内联树运算符 1 ,^
而不是重写规则来执行此操作。
演示:
grammar T;
options {
output=AST;
}
tokens {
ROOT;
LBRACK = '[' ;
RBRACK = ']' ;
DOT = '.' ;
}
parse
: selector+ EOF -> ^(ROOT selector+)
;
selector
: IDENT (access^)*
;
access
: DOT IDENT -> IDENT
| LBRACK IDENT RBRACK -> IDENT
| LBRACK INTEGER RBRACK -> INTEGER
;
IDENT : 'a'..'z'+;
INTEGER : '0'..'9'+;
SPACE : ' ' {skip();};
解析输入:
a.b.c a[1][2][3]
将生成以下AST:
1 有关内联树运算符和重写规则的详细信息,请参阅:How to output the AST built using ANTLR?