Python Antlr 为什么我的代码没有达到预期的结果?

Python Antlr why isnt my code coming up with the expected outcome?

我需要为一种名为 Decaf 的自定义语言创建一个编译器。我需要一个名为 decaf-lexer.py 的 python 文件,它打印编译器针对给定输入文本检测到的标记列表 文件。这是我在 antlr 中为词法分析器编写的语法:

grammar Decaf;

//********* LEXER ******************

fragment ALPHA : [a-zA-Z];
fragment DIGIT : [0-9];
ID : ALPHA( ALPHA | DIGIT)* ;
NUM: DIGIT(DIGIT)* ;
COMMENTS: '//' ~('\r' | '\n' )*  -> skip;
WS : (' ' | '\n')+  ->skip;

LROUND : '(';
RROUND : ')';
LCURLY : '{';
RCURLY : '}';
LSQUARE: '[' ;
RSQUARE : ']';
SEMI : ';';
CLASS: 'class';
BOOLEAN : 'boolean';
BREAK : 'break';
CALLOUT : 'callout';
CONTINUE : 'continue';
ELSE : 'else';
FALSE : 'false';
FOR : 'for';
IF : 'if';
INT : 'int';
RETURN : 'return';
TRUE : 'true';
VOID : 'void';
CHAR : ALPHA|DIGIT|' '| '#' | '$' | '&' | '.' | ':' | '?' | '@' | '\' | '^' | '_' | '`'| '|' | '~' | '\t'| '\n' ;
COMMA: ',';
COMPARE: '==';
NEQUAL: '!=';
GREQUAL: '>=';
LSEQUAL: '<=';
LS: '<';
GR: '>';
AND: '&&';
OROR: '||';
EQUALS: '=';
PEQUAL: '+=';
MEQUAL: '-=';
PLUS: '+';
MINUS: '-';
TIMES: '*';
DIVIDE: '/';
MOD: '%';
QUOTE: '"';
SQUOTE: '\'';
EXPLANATION: '!';


这里是 python 代码

import antlr4 as ant
from DecafLexer import DecafLexer

filein = open('example_01.decaf', 'r')
lexer = DecafLexer(ant.InputStream(filein.read()))

token = lexer.nextToken()
while token.type != -1:
    print(lexer.symbolicNames[token.type])
    token = lexer.nextToken()

示例文件仅包含:

(x + y)

结果是

LCURLY
COMMENTS
TIMES
COMMENTS
RCURLY

什么时候应该是这样,我哪里错了????

LROUND
ID
PLUS
ID
RROUND

当我运行:

lexer = DecafLexer(ant.InputStream('(x + y)'))

token = lexer.nextToken()
while token.type != -1:
    print(lexer.symbolicNames[token.type])
    token = lexer.nextToken()

打印如下:

LROUND
ID
PLUS
ID
RROUND

我猜你还没有从语法中生成新的解析器和词法分析器类。

还有一件事:尝试标记输入 boolean:您会看到它被标记为 ID。这是因为您在所有关键字(如 booleanfalsevoid 等)之前定义了 ID。如果 F ANTLR 可以匹配多个词法分析器规则(即 2 个或更多规则匹配相同的字符),第一个定义的将 "win"。

解决方法:将ID移到所有关键字下方:

CLASS: 'class';
BOOLEAN : 'boolean';
BREAK : 'break';
CALLOUT : 'callout';
CONTINUE : 'continue';
ELSE : 'else';
FALSE : 'false';
FOR : 'for';
IF : 'if';
INT : 'int';
RETURN : 'return';
TRUE : 'true';
VOID : 'void';

ID : ALPHA( ALPHA | DIGIT)* ;

最后,这条规则:

CHAR : ALPHA|DIGIT|' '| '#' | '$' | '&' | '.' | ':' | '?' | '@' | '\' | '^' | '_' | '`'| '|' | '~' | '\t'| '\n' ;

很奇怪:它可以匹配单个 space-chars,但是您已经指示要更早地跳过 spaces。此外,您告诉它匹配单个 ALPHADIGIT,但它们分别匹配为 IDNUM

there is a T_0 and T_1 created before num ID ect, which is throwing everything off by two, any idea what these are?

如果您在解析器规则中定义文字标记,如下所示:

parser_rule
 : LEXER_RULE ';'
 ;

然后这个 ';' 将由 ANTLR 隐式定义,就像在幕后的 T_... 令牌一样。但是这些 T_... 标记对我的回答中的建议没有影响。

数组 symbolicNames 包含您定义的命名词法分析器规则的名称,这些规则按照您定义它们的顺序排列。但是,它不包含为您在解析器规则中使用的文字隐式定义的词法分析器规则。由于它们的类型编号在命名规则之前,这意味着如果您在语法中使用任何隐式词法分析器规则,则不能使用 token.type 作为 symbolicNames 的索引。

相反,您应该使用 ruleNames,它确实包含隐式标记。因此,对于任何具有适当名称 lexer.ruleNames[token.type] 的标记,将正确地 return 该名称,对于从字符串文字创建的任何标记,它将 return 一个类似于 T__0.[=16= 的字符串]