我需要为一种名为Decaf的自定义语言创建一个编译器,我需要一个名为Decaf-lexer.py的python文件。我需要一个名为decaf-lexer.py的python文件,它可以打印出编译器检测到的给定输入文本文件的标记列表。这是我在antlr中为Lexer编写的语法。
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
数组 symbolicNames
包含了您按照定义顺序所定义的命名的词法规则的名称,但不包含您在解析规则中为字元隐式定义的词法规则。然而,它并不包含在解析器规则中隐式定义的字元的词法规则。因为这些规则的类型号会在命名规则的类型号之前,这意味着你不能使用 token.type
作为索引进入 symbolicNames
如果你在语法中使用了任何隐性词法规则。
相反,您应该使用 ruleNames
,其中确实包括隐式标记。因此,对于任何一个名字为 lexer.ruleNames[token.type]
将正确地返回该名称,对于任何从字符串字面数创建的标记,它将返回一个字符串,如 T__0
.
当我运行时。
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
. 这是因为你已经定义了 ID
在所有关键词前(如 boolean
, false
, void
,等等)。) 如果F ANTLR可以匹配多个词法规则(即2个或更多的规则匹配相同的字符),先定义的规则将 "获胜"。
解决方案:移动 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' ;
是很奇怪的:它可以匹配单个空格字符,但你已经在前面指示跳过空格。另外,你告诉它要匹配单个 ALPHA
或 DIGIT
但这些都是作为一个 ID
或 NUM
分别。
在num ID之前有一个T_0和T_1的创建,这让所有的东西都偏离了两个,你知道这些是什么吗?
如果你在解析器规则里面定义文字标记,像这样。
parser_rule
: LEXER_RULE ';'
;
那么这个 ';'
将会被ANTLR隐式地定义为像这样一个 T_...
背后的信物。但这些 T_...
不过代币对我回答的建议没有影响。