我已经创建了以下语法:我想知道如何构建一个在java中返回一个树的解释器,我可以在以后用它在屏幕上进行打印,我会在如何启动它的位置堆栈。
grammar myDSL;
options {
language = Java;
}
@header {
package DSL;
}
@lexer::header {
package DSL;
}
program
: IDENT '={' components* '}'
;
components
: IDENT '=('(shape)(shape|connectors)* ')'
;
shape
: 'Box' '(' (INTEGER ','?)* ')'
| 'Cylinder' '(' (INTEGER ','?)* ')'
| 'Sphere' '(' (INTEGER ','?)* ')'
;
connectors
: type '(' (INTEGER ','?)* ')'
;
type
: 'MG'
| 'EL'
;
IDENT: ('a'..'z' | 'A'..'Z')('a'..'z' | 'A'..'Z' | '0'..'0')*;
INTEGER: '0'..'9'+;
// This if for the empty spaces between tokens and avoids them in the parser
WS: (' ' | '\t' | '\n' | '\r' | '\f')+ {$channel=HIDDEN;};
COMMENT: '//' .* ('\n' | '\r') {$channel=HIDDEN;};
答案 0 :(得分:3)
几句话:
无需为Java设置语言,Java是默认目标语言。所以你可以删除它:
options {
language = Java;
}
您的IDENT
包含错误:
IDENT: ('a'..'z' | 'A'..'Z')('a'..'z' | 'A'..'Z' | '0'..'0')*;
'0'..'0')
最有可能是'0'..'9')
。
子规则(INTEGER ','?)*
也匹配1 2 3 4
这样的来源(根本没有逗号!)。也许你打算这样做:(INTEGER (',' INTEGER)*)?
现在,关于你的问题:如何让ANTLR构建一个合适的AST?这可以通过在选项块中添加output = AST;
来完成:
options {
//language = Java;
output = AST;
}
然后在解析器规则中添加“树操作符”^
和!
,或者使用树重写规则:rule: a b c -> ^(c b a)
。
“树操作符”^
用于定义(子)树的根,!
用于从(子)树中排除令牌。
重写规则有^( /* tokens here */ )
,其中第一个标记(在^(
之后)是(子)树的根,并且所有后续标记都是根的子节点。
一个例子可能是有序的。让我们采取你的第一条规则:
program
: IDENT '={' components* '}'
;
并且您希望让IDENT
成为孩子的components*
,并且您希望从树中排除={
和}
。你可以这样做:
program
: IDENT^ '={'! components* '}'!
;
或通过:
program
: IDENT '={' components* '}' -> ^(IDENT components*)
;