我在实用程序中解析CoCo / R语法以自动化CoCo - > ANTLR翻译。核心ANTLR语法是:
rule '=' expression '.' ;
expression
: term ('|' term)*
-> ^( OR_EXPR term term* )
;
term
: (factor (factor)*)? ;
factor
: symbol
| '(' expression ')'
-> ^( GROUPED_EXPR expression )
| '[' expression']'
-> ^( OPTIONAL_EXPR expression)
| '{' expression '}'
-> ^( SEQUENCE_EXPR expression)
;
symbol
: IF_ACTION
| ID (ATTRIBUTES)?
| STRINGLITERAL
;
我的问题在于这些结构:
CS = { ExternAliasDirective }
{ UsingDirective }
EOF .
CS导致带有OR_EXPR节点的AST,尽管没有“|”字符 实际出现了。我确定这是由于定义 表达,但我看不到任何其他方式来编写规则。
我做了这个实验来解决歧义。
// explicitly test for the presence of an '|' character
expression
@init { bool ored = false; }
: term {ored = (input.LT(1).Type == OR); } (OR term)*
-> {ored}? ^(OR_EXPR term term*)
-> ^(LIST term term*)
它有效,但黑客加强了我的信念,即基本的错误。
任何提示都非常感激。
答案 0 :(得分:4)
你的规则:
expression
: term ('|' term)*
-> ^( OR_EXPR term term* )
;
始终使重写规则创建一个类型为OR_EXPR
的根的树。您可以像这样创建“子重写规则”:
expression
: (term -> REWRITE_RULE_X) ('|' term -> ^(REWRITE_RULE_Y))*
;
要解决语法中的模糊性,最简单的方法是启用全局回溯,这可以在语法的options { ... }
部分完成。
快速演示:
grammar CocoR;
options {
output=AST;
backtrack=true;
}
tokens {
RULE;
GROUP;
SEQUENCE;
OPTIONAL;
OR;
ATOMS;
}
parse
: rule EOF -> rule
;
rule
: ID '=' expr* '.' -> ^(RULE ID expr*)
;
expr
: (a=atoms -> $a) ('|' b=atoms -> ^(OR $expr $b))*
;
atoms
: atom+ -> ^(ATOMS atom+)
;
atom
: ID
| '(' expr ')' -> ^(GROUP expr)
| '{' expr '}' -> ^(SEQUENCE expr)
| '[' expr ']' -> ^(OPTIONAL expr)
;
ID
: ('a'..'z' | 'A'..'Z') ('a'..'z' | 'A'..'Z' | '0'..'9')*
;
Space
: (' ' | '\t' | '\r' | '\n') {skip();}
;
输入:
CS = { ExternAliasDirective }
{ UsingDirective }
EOF .
产生AST:
和输入:
foo = a | b ({c} | d [e f]) .
产生
要测试此课程的课程:
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import org.antlr.stringtemplate.*;
public class Main {
public static void main(String[] args) throws Exception {
/*
String source =
"CS = { ExternAliasDirective } \n" +
"{ UsingDirective } \n" +
"EOF . ";
*/
String source = "foo = a | b ({c} | d [e f]) .";
ANTLRStringStream in = new ANTLRStringStream(source);
CocoRLexer lexer = new CocoRLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
CocoRParser parser = new CocoRParser(tokens);
CocoRParser.parse_return returnValue = parser.parse();
CommonTree tree = (CommonTree)returnValue.getTree();
DOTTreeGenerator gen = new DOTTreeGenerator();
StringTemplate st = gen.toDOT(tree);
System.out.println(st);
}
}
并且使用此类生成的输出,我使用以下网站创建AST图像:http://graph.gafol.net/
HTH
要考虑OR
表达式中的epsilon(空字符串),您可以尝试一下(快速测试!),如下所示:
expr
: (a=atoms -> $a) ( ( '|' b=atoms -> ^(OR $expr $b)
| '|' -> ^(OR $expr NOTHING)
)
)*
;
解析来源:
foo = a | b | .
进入以下AST:
答案 1 :(得分:0)
expression
的制作明确表示它只能返回OR_EXPR
个节点。您可以尝试以下方式:
expression
:
term
|
term ('|' term)+
-> ^( OR_EXPR term term* )
;
再往下,您可以使用:
term
: factor*;