为什么此ANTLR语法未返回正确的类型?

问题描述 投票:0回答:1

我正在为各种基本语言编写示例语法,其中包含类似以下的说明:

i8 my_variable_1_8
i16 my_second_variable_2_something_else
i32 another_variable
i4 forth
i8 last_one_1
void empty
void empty_for_the_2_time

请注意,变量名可以按任何顺序包含任何字母,数字,下划线和点。自动柜员机我对诸如``.... variable_name ....`这样的情况不感兴趣,所以让我们接受它们:)

我当前使用的PoC语法在下面的段落中:

grammar example;

prog:   (expr NEWLINE)+;

expr    : instr
    ;

instr     : type WORD
      ; 

type    : 'i' NUMBER
    | 'void'
        ;

NUMBER  : ('-')* ([0-9])+
    ;

WORD :  (LETTER|'_'|'.'|[0-9])+
     ;

LETTER   : ([a-z]|[A-Z]) ;

NEWLINE  : [\r\n]+ ;

WS: [ \t\n\r]+ -> skip ;

我要解析的示例文件是

i32 i_cannot_parse_this_1_as_i_want
void hello 

输出为

➜  grammar antlr4 -no-listener example.g4 && javac *.java && grun example prog -tokens example.txt
[@0,0:2='i32',<WORD>,1:0]
[@1,4:34='i_cannot_parse_this_1_as_i_want',<WORD>,1:4]
[@2,35:35='\n',<NEWLINE>,1:35]
[@3,36:39='void',<'void'>,2:0]
[@4,41:45='hello',<WORD>,2:5]
[@5,48:47='<EOF>',<EOF>,3:0]
line 1:0 mismatched input 'i32' expecting {'i', 'void'}
➜  grammar

如您所见,i32被认为是WORD,而不是类型。关于优先级,我肯定有一些遗漏,但我无法理解。

最后,我想说的是,我创建了解析器规则type,因为在运行时,一旦我重写了visitInstr方法,我便希望能够执行类似ctx.type().NUMBER()的操作。

是否有更好的方法来实现这一目标?请考虑我想添加其他更复杂的类型。

非常感谢您的时间

antlr antlr4
1个回答
0
投票
确实按照词法分析器规则翻译,使您的词法分析器看起来像这样:

T__0 : 'i'; T__1 : 'void'; NUMBER : ('-')* ([0-9])+; WORD : (LETTER|'_'|'.'|[0-9])+; LETTER : ([a-z]|[A-Z]); NEWLINE : [\r\n]+; WS : [ \t\n\r]+ -> skip; // NOTE: remove the \n\r from this class since it is already matched by NEWLINE

如果现在向词法分析器输入i32,它将创建一个WORD令牌。它将不会创建两个标记T__0i)和NUMBER32),因为词法分析器会尝试使给定输入的最长匹配。这就是它的工作方式。

[此外,通过将type设为解析器规则,您可以将i    32(之间有空格的i)作为输入匹配为type。换句话说:不要在解析器中创建type,而是将其设置为词法分析器规则,并确保在[WORD规则:[[之前
:]]中定义它

type : TYPE | VOID ; VOID : 'void'; TYPE : 'i' NUMBER; NUMBER : '-'* [0-9]+; WORD : [a-zA-Z_.0-9]+; NEWLINE : [\r\n]+; WS : [ \t]+ -> skip;

这将使i32TYPE而不是WORD匹配。如果您还希望在某些情况下将i32匹配为WORD(例如,输入i32 i32也有效),请执行以下操作:

instr : type word ; word : WORD | type ; type : TYPE | VOID ;

© www.soinside.com 2019 - 2024. All rights reserved.