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

无法让 Antlr4 解析器遵循隐式乘法的运算顺序

徐子石
2023-03-14

我是ANTLR的新手,我试图使用ANTLR4和C#为计算器应用程序生成一个相对简单的解析器。这是我的语法文件。

parser grammar CalculatorExpressionParser;

options{
language = CSharp2;
}

expr:  FUNC expr? (COMMA expr)* RIGHTPAREN               #CallFunction
    |  LEFTPAREN expr RIGHTPAREN                         #Parens
    |  expr POW<assoc=right> expr                        #Pow
    |  expr op=(MULTIPLY | DIVIDE)? expr                 #MultDivide
    |  expr op=(ADD | SUBTRACT) expr                     #AddSubtract
    |  SUBTRACT expr                                     #Negative
    |  NUMBER                                            #Number
    ;

我编写了一个自定义词法分析器来生成令牌,以便在解析之前支持变量的隐式乘法和转换为其数字等效值。

但是输入后,我得到以下结果。

2+6/3 => 4 (correct)
6/3+2 => 1.2 (should be 4)
6/(3+2) => 4 (also correct)

1+2*3 => 7 (correct)
2*3+1 => 8 (should be 7 too)
(2*3)+1 => 7 (correct)

请注意,我尝试关闭错误恢复功能并将其设置为报告所有歧义错误,但似乎没有收到任何错误。

无论如何,如果我通过删除除法/乘法运算符之后的?将语法更改为以下内容,那么它似乎工作得很好,除了不再支持隐式乘法。

parser grammar CalculatorExpressionParser;

options{
language = CSharp2;
}

expr:  FUNC expr? (COMMA expr)* RIGHTPAREN               #CallFunction
    |  LEFTPAREN expr RIGHTPAREN                         #Parens
    |  expr POW<assoc=right> expr                        #Pow
    |  expr op=(MULTIPLY | DIVIDE) expr                  #MultDivide
    |  expr op=(ADD | SUBTRACT) expr                     #AddSubtract
    |  SUBTRACT expr                                     #Negative
    |  NUMBER                                            #Number
    ;

我想知道为什么输入?会破坏匹配顺序?有没有简单的方法来解决这个问题?

共有2个答案

公西财
2023-03-14

将 expr 语句拆分为多个语句,以便获得正确的操作顺序。

通常是这样的:注意每个expr只处理一组数学运算,然后向下调用一个较低优先级的规则。通常最底层的规则是原子操作符,如< code>INT或< code>FLOAT

所以在这种情况下,你要处理逻辑和或,然后是比较,然后是指数,然后是乘法/除法,然后是加法/减法。

注意,我还应该指出,这里我创建了一个AST树,而不是内联操作。

expr
: subExpr -> ^(EXPR subExpr)
;

subExpr : logicalAndExp (addSubtractOp^ logicalAndExp)*
;   

logicalAndExp
: logicalOrExp (multiplyDivideOp^  logicalOrExp)*    
;

logicalOrExp
: comparatorExp (CARET^  comparatorExp)*    
;

comparatorExp
: powExp (comparatorOp^  powExp)*   
;

powExp  : multExp (BARBAR^   multExp)*  
;

multExp 
:  expressionAtom (AMPAMP^ expressionAtom)*
;expression 
: subExpr -> ^(EXPR subExpr)
;

subExpr : logicalAndExp (addSubtractOp^ logicalAndExp)*
;   

logicalAndExp
: logicalOrExp (multiplyDivideOp^  logicalOrExp)*    
;

logicalOrExp
: comparatorExp (CARET^  comparatorExp)*    
;

comparatorExp
: powExp (comparatorOp^  powExp)*   
;

powExp  : multExp (BARBAR^   multExp)*  
;

multExp 
:  expressionAtom (AMPAMP^ expressionAtom)*
;
米迪
2023-03-14

“expr expr”不符合操作符的模式,尽管ANTLR 4.2可能会处理这个问题。Sam仍在更新C#目标。

 类似资料:
  • 我对ANTLR相对来说是新的,所以请原谅我。 但是当我试图解析下面的表达式时 我最终出现以下错误: 第1:38行:'''处的令牌识别错误 第1:42行:'''处的令牌识别错误 规则r没有方法或者它有参数 规则'r'的意思是什么?我怎么能理解问题的原因呢?任何帮助都将不胜感激!

  • 问题内容: 我最近不得不使用解析器来做一个项目。我下载ANTLR4并按照书中描述的步骤进行操作The Definitive ANTLR4 Reference。以下是我在命令行中键入的步骤: 一切正常,它生成我需要的java文件。但是,当我进入 它报告 无法将Hello加载为词法分析器或解析器。 我在Google上搜索了一些信息,但仍然无法确定发生了什么。 问题答案: 您通过在语法上运行ANTLR生

  • 我有一个利用CharsAsTokens人造lexer的无扫描解析器语法,它为ANTLR4到4.6版本生成了一个可用的Java解析器类。但是,当更新到ANTLR 4.7.2到4.9.3-Snapshot时,该工具会生成代码,从相同的语法文件产生数十个编译错误,如下所述。 我这里的问题很简单:是否不再支持无扫描解析器语法,或者必须在4.7和更高版本中以不同的方式指定基于字符的终端? 更新: 不幸的是,

  • 我最近不得不使用解析器来做一个项目。我下载了,并按照《最终ANTLR4Reference》一书中描述的步骤进行操作。以下是我在命令行中键入的步骤: 所有事情都很好,它生成我需要的java文件。但是,在我输入之后 它报告说 无法将Hello作为lexer或分析器加载。 我谷歌了一些信息,但仍然不知道发生了什么。

  • 我正在为用ANTLR4编写的Decaf编程语言创建解析器和lexer规则。我试图解析一个测试文件,但不断地得到一个错误,一定是语法有问题,但我无法理解。 我的测试文件如下所示: 错误是:第2行:8不匹配的输入“10”应为INT_LITERAL 下面是完整的decaf.g4语法文件

  • 问题内容: 我觉得这里缺少明显的东西! 输出: 当然应该输出: 这是怎么了 问题答案: 字典未排序。如果需要依赖顺序,则需要一个OrderedDict- Python 2.7的模块中有一个,或者您可以使用多种食谱之一。