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

Antlr4解析不一致

华飞驰
2023-03-14

在我刚刚编写的一个测试解析器中,我遇到了一个奇怪的问题,我不太明白。

将其简化为显示问题的最小示例,让我们从以下语法开始:

grammar Testing;

cscript                           // This is the construct I shortened
    : (statement_list)* ;

statement_list
    : statement ';' statement_list?
    | block
    ;

statement
    : assignment_statement
    ;

block : '{' statement_list? '}' ;

expression
    : left=expression op=('*'|'/') right=expression              # arithmeticExpression
    | left=expression op=('+'|'-') right=expression              # arithmeticExpression
    | left=expression op=Comparison_operator right=expression    # comparisonExpression
    | ID                                                         # variableValueExpression
    | constant                                                   # ignore  // will be executed with the rule name
    ;

assignment_statement
    : ID op=Assignment_operator expression
    ;

constant
    : INT
    | REAL;

Assignment_operator : ('=' | '+=' | '-=') ;

Comparison_operator : ('<' | '>' | '==' | '!=') ;

Comment : '//' .*? '\n' -> skip;

fragment NUM : [0-9];

INT : NUM+;
REAL
    : NUM* '.' NUM+
    | '.' NUM+
    | INT
    ; 

ID : [a-zA-Z_] [a-zA-Z_0-9]*;

WS : [ \t\r\n]+ -> skip;
z = x + y;

这是语法的变化:

cscript
    : (statement_list | variable_declaration ';')* ;

variable_declaration
    : type ID ('=' expression)?
    ;

type
    : 'int'
    | 'real'
    ;

statement_list
    : statement ';' statement_list?
    | block
    ;

statement
    : assignment_statement
    ;

// (continue as before)

突然间,相同的测试输入被错误地分解成两个statement_list,每个statement_list都继续到一个带有“missing”;“警告,第一个返回“z=”的不完整的assignment_statement,第二个返回“x+”的不完整的assignment_statement。

我尝试以文本形式显示解析树:

cscript
    statement_list
        statement
            assignment_statement
                'z'
                '=' [marked as error]
        [warning: missing ';']
    statement_list
        statement
            assignment_statement
                'x'
                '+' [marked as error]
        'y' [marked as error]
        ';'
int x = 22;
[@0,0:2='int',<4>,1:0]
[@1,4:4='x',<22>,1:4]
[@2,6:6='=',<1>,1:6]
[@3,8:9='22',<20>,1:8]
[@4,10:10=';',<12>,1:10]
[@5,13:13='z',<22>,2:0]
[@6,15:15='=',<1>,2:2]
[@7,17:17='x',<22>,2:4]
[@8,19:19='+',<18>,2:6]
[@9,21:21='y',<22>,2:8]
[@10,22:22=';',<12>,2:9]
[@11,25:24='<EOF>',<-1>,3:0]
line 1:6 mismatched input '=' expecting '='

由于问题似乎出现在variable_declaration部分,我甚至尝试将其分解为两个解析规则,如下所示:

cscript
    : (statement_list | variable_declaration_and_assignment SEMICOLON | variable_declaration SEMICOLON)* ;

variable_declaration_and_assignment
    : type ID EQUAL expression
    ;

variable_declaration
    : type ID
    ;

结果是:

line 1:6 no viable alternative at input 'intx='

仍然卡住:-(顺便说一下:将“int x=22;”拆分为“int x;”和“x=22;”。叹息

cscript
    : (statement_list | variable_declaration)* ;

...

variable_declaration
    : type ID (EQUAL expression)? SEMICOLON
    ;

...

Assignment_operator : (EQUAL | PLUS_EQ | MINUS_EQ) ;

// among others
PLUS_EQ : '+=';
MINUS_EQ : '-=';
EQUAL: '=';

...
[@0,0:2='int',<4>,1:0]
[@1,4:4='x',<22>,1:4]
[@2,6:6='=',<1>,1:6]
...
line 1:6 mismatched input '=' expecting ';'

这可能是问题所在吗?

共有1个答案

蓬新
2023-03-14

好吧,似乎这里的主要内容是:想想你的定义,以及你如何定义它们。为文字创建显式的lexer规则,而不是在解析器规则中隐式定义它们。如果解析器给出了奇怪的错误,请检查从lexer获得的令牌值,因为它们首先必须是正确的,否则解析器没有机会完成它的工作。

 类似资料:
  • 我所开发的ANTR4语法。在解析字符串期间 时间;25 10 * * *;' faccalc_minus1_cron.out.'yyyyMMdd。嗯;美国/New_York 我有以下错误 表达式中的字符无效!表达式:;'无效字符:;'无关输入“;”应为{“”,整数,“-”,“/”,“,”},缺少“;”“\uu”处的时区格式不正确:faccalc\u minus1 我不理解为什么,因为正则表达式规则

  • 我有一个语法,当解析在一次传递(整个文件)很好。 现在我希望将解析分解成组件。并在子库上运行解析器。我遇到了一个问题,我假设其他解析子库的人会看到下面的规则: 当上面的规则从一个顶级的开始规则解析到EOF时,一切都很好。当解析为子规则(而不是解析为EOF)时,解析器在没有thing子句时会感到不安,因为它希望看到“,”字符或EOF字符。 第8行:0不匹配的输入“%”应为{,“,”} 当我解析到EO

  • 我试图以C#为目标,使用Antlr4解析一个日期。在我的情况下,有效日期应具有以下内容 采用格式 年份只能有4位数字 月和日只能有2位 我知道类似的问题已经出现了,但它们的解决方案似乎对我不起作用 如何创建将解析日期的antlr4语法 ANTLR:识别日期和数字的最简单方法? 我在某个地方读到过,有一种类似优先级的解析,其中基于语法文件如何编写的顶级规则首先被评估。因此,考虑一下,除了日期,我的语

  • 有什么方法可以让ANTLR4自动删除生成的解析树中的冗余节点吗? 更具体地说,我一直在试验GLSL的语法,由于自动处理操作符优先级所需的规则转发,您最终会在解析树中看到长的线性“表达式”序列。 大多数生成的树节点都只是简单地“转发到下一个优先级”,所以不要提供任何有用的语法信息--你只需要每个序列中最后一个表达式节点(即规则转发停止的点),或者它成为一个实际的树节点并拥有多个子节点的点(即在源中遇

  • 我在调试一个ANTLR语法时遇到了问题,我正在为Gameboy程序集工作。它似乎工作正常,但由于某些原因,它不能在某些边缘情况下处理十六进制的0x表示法。 如果我的输入字符串是“JR0x10”,antlr将失败,并出现'No Valide alternative at input‘错误。按照我的理解,这意味着我要么没有解析令牌流的规则,要么没有正确理解'0x'。如果我使用“JR$10”(我支持的替

  • 如果在antlr4 lexer中有一个ONELINE_STRING片段规则标识一行上的一个简单引号字符串,那么如何在lexer中创建一个更通用的字符串规则,该规则将相邻的ONELINE_STRING连接起来(即,只要它们都在不同的行上开始,仅用空格和/或注释分隔)? 即, 将被解析为两个字符串标记,“foo”后跟“bar” 同时: 示例1: Sample3(注意,'output'是该语言中的关键字