当前位置: 首页 > 知识库问答 >
问题:

ANTLR 4中的优先模糊性

水铭晨
2023-03-14

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

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的规则之一,将其简化为exr。语法中还有许多其他类似的规则也简化为exr。这里出现的问题是因为set和exr中的一些规则是相似的。但是因为有些规则不同,我不能将它们合并在一起。

在集合中,即使规则乘法集合的优先级高于集合加集合,集合也会被多重集合规则减少。

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

编辑:

添加一个工作示例:

语法:

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个答案

漆雕皓轩
2023-03-14

我无法复制这个。

给定语法:

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)))
 类似资料:
  • 我在这里开发了一个小语法,我有一个问题: 为什么解析器没有在解析树的顶部看到(->)规则?这是优先级问题吗?

  • 标准的TestCase之一是,lexer应该从中生成令牌流。不幸的是,由于ANTLR优先匹配较长的令牌,它生成令牌流,这将导致解析器引发错误。 是否可以先让ANTLR4 lexer尝试使用较短的令牌进行匹配?向添加lookahead-type规则并不是一个很好的解决方案,因为我需要考虑各种潜在的词法冲突(例如,被命名为,而不是,等等)。 编辑: 但这并不是一个真正的可扩展或可维护的解决方案,而且还

  • Casbin支持参考优先级加载策略。 通过隐式优先级加载策略 这非常简单,顺序决定了策略的优先级,策略出现的越早优先级就越高。 model.conf: [policy_effect] e = priority(p.eft) || deny 通过显式优先级加载策略 另见: casbin#550 策略的第一个要素一定是优先级,并且优先级值较小的将具有较高的优先地位。 如果优先级有非数字字符,它将是被

  • 我需要一个优先级队列,它首先获得具有最高优先级值的项目。我当前正在使用队列库中的PriorityQueue类。但是,这个函数只先返回值最小的项。我尝试了一些很难看的解决方案,比如(sys.maxint-priority)作为优先级,但我只是想知道是否存在更优雅的解决方案。

  • 根据优先表,一元后缀递增和递减运算符比关系运算符有更多的优先级,那么为什么在这样的表达式(x++>=10)中,关系运算符首先计算,然后变量递增呢?

  • 问题内容: 我正在尝试使ThreadPoolExecutor具有优先权。所以我定义一个 因此,关键是现在的队列引用。但是当我声明: 编译器在第一行给出错误: 构造函数ThreadPoolExecutor(int,int,int,TimeUnit,PriorityBlockingQueue,FileAccess.mThreadFactory)是未定义的 ,只有一个快速修复程序: 将’queue’的类