开发者

ANTLR expression interpreter

I have created the following grammar: I would like some idea how to build an interpreter that returns a tree in java, which I can later use for printing in the screen, Im bit stack on how to start on it.

grammar myDSL;

options {
  language = Java;
}
@header {
  package DSL;
}
@lexer::header {
  package DSL;
}


program
    :  IDENT '={' 开发者_JS百科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;};


A couple of remarks:

There's no need to set the language for Java, which is the default target language. So you can remove this:

options {
  language = Java;
}

Your IDENT contains an error:

IDENT: ('a'..'z' | 'A'..'Z')('a'..'z' | 'A'..'Z' | '0'..'0')*;

the '0'..'0') should most probably be '0'..'9').

The sub rule (INTEGER ','?)* also matches source like 1 2 3 4 (no comma's at all!). Perhaps you meant to do: (INTEGER (',' INTEGER)*)?

Now, as to your question: how to let ANTLR construct a proper AST? This can be done by adding output = AST; in your options block:

options {
  //language = Java;
  output = AST;
}

And then either adding the "tree operators" ^ and ! in your parser rules, or by using tree rewrite rules: rule: a b c -> ^(c b a).

The "tree operator" ^ is used to define the root of the (sub) tree and ! is used to exclude a token from the (sub) tree.

Rewrite rules have ^( /* tokens here */ ) where the first token (right after ^() is the root of the (sub) tree, and all following tokens are child nodes of the root.

An example might be in order. Let's take your first rule:

program
  :  IDENT '={' components* '}'
  ;

and you want to let IDENT be the root, components* the children and you want to exclude ={ and } from the tree. You can do that by doing:

program
  :  IDENT^ '={'! components* '}'!
  ;

or by doing:

program
  :  IDENT '={' components* '}' -> ^(IDENT components*)
  ;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜