[英]Expressions in a CoCo to ANTLR translator
我在實用程序中解析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*)
它有效,但黑客加強了我的信念,即基本的錯誤。
任何提示非常感謝。
你的規則:
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:
expression
明確表示它只能返回一個OR_EXPR
節點。 您可以嘗試以下方式:
expression
:
term
|
term ('|' term)+
-> ^( OR_EXPR term term* )
;
再往下,您可以使用:
term
: factor*;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.