ANTLR 4中的优先模糊度

时间:2014-12-23 17:58:13

标签: antlr4

我有一个巨大的ANTLR语法,我面临一小部分问题。语法有两个规则expr和集合定义如下:

expr:
   id
  |(PLUS|MINUS|MULTIPLY|AND|NEGATION)expr
  | expr (MULTIPLY |DIVIDE| MODULO)
  | expr (PLUS | MINUS) expr
 ;

 set:
    EMPTY
   | MULTIPLY set 
   | set PLUS set
   | UNION '(' set (COMMA set)* ')'
   | INTER '(' set (COMMA set)* ')'
   | expr
  ;

这里的问题是,对于一组形式* s1 + * s2应该减少如下:

set -> set PLUS set 

然后RHS中的每个集合应该减少到:

set -> MULTIPLY set
set -> expr
term -> id

但他们正在减少:

set -> MULTIPLY set
set -> expr
expr -> expr PLUS expr 

由于forn *s1 +*s2的哪一组被解析为*(s1 + *s2)而不是(*s1) + (*s2)

set的规则之一,将其减少为expr。语法中还有许多其他类似的规则可以减少到expr。这里出现了问题,因为set和expr中的一些规则是相似的。但由于某些规则不同,我无法将它们合并在一起。

即使规则MULTIPLY set的优先级高于set PLUS set,设置也会设置为MUTIPLY set规则。

有没有办法解决这个问题?

编辑:

添加一个工作示例:

语法:

grammar T;

expr
 : ID
  | ( PLUS | MINUS | MULTIPLY | AND | NEGATION ) expr
  | expr ( MULTIPLY | DIVIDE | MODULO )
  | expr ( PLUS | MINUS ) expr
 ;

 set:
    EMPTY
    | MULTIPLY set 
    | set PLUS set
    | UNION '(' set (COMMA set)* ')'
    | INTER '(' set (COMMA set)* ')'
    | expr
  ;
 ID : [a-zA-Z] [a-zA-Z0-9]*;
 PLUS : '+';
 MINUS : '-';
 MULTIPLY : '*';
 AND : '&&';
 NEGATION : '!';
 DIVIDE : '/';
 MODULO : '%';
 COMMA : ',';
 EMPTY: '\\empty';
 UNION: '\\union';
 INTER: '\\inter';
 SPACES : [ \t\r\n] -> skip;

执行它的代码:

TLexer lexer = new TLexer(new ANTLRInputStream("*s1 + *s2"));
TParser parser = new TParser(new CommonTokenStream(lexer));
RuleContext tree  = parser.set();
tree.inspect(parser);

输出它:

  set
  / \
 *  set
     |
    expr
    / | \
   /  |  \
 expr +  expr
  |       / \
  s1     *  expr
             |
             s2   

1 个答案:

答案 0 :(得分:0)

我无法重现这一点。

鉴于语法:

grammar T;

expr
 : ID
 | ( PLUS | MINUS | MULTIPLY | AND | NEGATION ) expr
 | expr ( MULTIPLY | DIVIDE | MODULO )
 | expr ( PLUS | MINUS ) expr
 ;

ID : [a-zA-Z] [a-zA-Z0-9]*;
PLUS : '+';
MINUS : '-';
MULTIPLY : '*';
AND : '&&';
NEGATION : '!';
DIVIDE : '/';
MODULO : '%';
SPACES : [ \t\r\n] -> skip;

您的输入*s1 + *s2将被解析为:

     expr
    / | \
   /  |  \
 expr +  expr
 / \     / \
*  expr *  expr
    |       |
    s1      s2

或者,用普通代码:

TLexer lexer = new TLexer(new ANTLRInputStream("*s1 + *s2"));
TParser parser = new TParser(new CommonTokenStream(lexer));
System.out.println(parser.expr().toStringTree(parser));

将打印:

(expr (expr * (expr s1)) + (expr * (expr s2)))