ANTLR表达式解释器

时间:2010-12-19 12:42:46

标签: antlr antlr3

我已经创建了以下语法:我想知道如何构建一个在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;};

1 个答案:

答案 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*)
  ;