Java ANTLR4忽略标记
我正在为一种语言编写一个编译器,作为大学使用ANTLR4的项目。 我使用Java编写了这个编译器,并采用了Visitor模式,当我到达测试阶段时,我注意到ANTLR忽略了我的部分代码,并生成了它不应该生成的错误 语法:Java ANTLR4忽略标记,java,compiler-construction,antlr,antlr4,grammar,Java,Compiler Construction,Antlr,Antlr4,Grammar,我正在为一种语言编写一个编译器,作为大学使用ANTLR4的项目。 我使用Java编写了这个编译器,并采用了Visitor模式,当我到达测试阶段时,我注意到ANTLR忽略了我的部分代码,并生成了它不应该生成的错误 语法: grammar smallJava; /*----------------- Parser Rules */ start:program; program :imports* classcode EOF; imports :'import' importe
grammar smallJava;
/*-----------------
Parser Rules
*/
start:program;
program
:imports* classcode EOF;
imports
:'import' imported ';';
imported
:classimported=('Small_Java.lang' | 'Small_Java.io');
classcode
:modifier? 'class_SJ' classname '{' declaration* 'main_SJ' '{' statement* '}' '}';
modifier
:'public'
|'protected';
classname
:IDF;
declaration
:type variables=vars ';';
type
:'int_SJ'
|'float_SJ'
|'string_SJ';
vars
:IDF ',' follow=vars #vars_follow
|IDF #vars_end
;
statement
:assign_statement
;
assign_statement
:idf=IDF ':=' right=expression ';';
expression: expressiona; // axiome of "expression"
//left recursion removed using : A -> A alpha / beta <=> A -> beta A' && A' -> alpha A' / epsilon
expressiona
:left=expressiona operator=('+'|'-') right=expressionb #expression_pm
|expressionb #expression_b
;
expressionb
:left=expressionb operator=('*'|'/') right=expressionc #expression_md
|expressionc #expression_c
;
expressionc
:'(' expressiona ')' #expression_parenthesis
|value #expression_value
;
value
:INT #integer
|STRING #string
|FLOAT #float
|IDF #idf
;
/*-----------------
Lexer Rules
*/
fragment DIGIT0: [0-9];
fragment DIGIT1: [1-9];
fragment LETTER: ('A'..'Z')|('a'..'z');
fragment CHAR: LETTER|DIGIT0;
INT: '0'|DIGIT1 DIGIT0*;
FLOAT
:'.' DIGIT0+
|INT '.' DIGIT0*;
STRING: '"' (CHAR|' '|'('|')'|'\\"')*? '"'; //STRING: '"' ('\\"'|.)*? '"';
IDF:LETTER (LETTER|DIGIT0)*;
WS: [ \n\t] -> skip;
当我运行Main时,它显示以下内容:
第1行:0不匹配的输入“导入”应为{,INT,FLOAT,STRING,IDF}
我的语法有什么地方错了吗?如果没有,为什么要这样做?这一行:
ParseTree tree = parser.expression();
告诉解析器对象解析一个表达式,即语法定义的非终端表达式,因此它在看到令牌导入时正确地发出抱怨
假设您的目的是解析程序,在这种情况下,您需要调用程序成员函数:
ParseTree tree = parser.program();
您的开始生产基本上是毫无意义的,因为它所做的只是遵从程序。使用开始规则启动语法是常见的,因为其他一些解析器生成器具有开始规则的概念,这意味着生成的解析器总是尝试解析相同的非终结符。但是Antlr并没有这个概念;您可以使用具有该名称的成员函数接受语法中任何非终结符的顶级匹配。此行:
ParseTree tree = parser.expression();
告诉解析器对象解析一个表达式,即语法定义的非终端表达式,因此它在看到令牌导入时正确地发出抱怨
假设您的目的是解析程序,在这种情况下,您需要调用程序成员函数:
ParseTree tree = parser.program();
您的开始生产基本上是毫无意义的,因为它所做的只是遵从程序。使用开始规则启动语法是常见的,因为其他一些解析器生成器具有开始规则的概念,这意味着生成的解析器总是尝试解析相同的非终结符。但是Antlr并没有这个概念;您可以使用具有该名称的成员函数来接受语法中任何非终结符的顶级匹配。顺便说一句,myVisitor是一个扩展smallJavaBaseVisitor的空类。顺便说一句,myVisitor是一个扩展smallJavaBaseVisitor的空类。这对我来说很有效,我认为在所有情况下都必须编写parser.expression。好的,我会移除start。非常感谢您的帮助。这对我很有用,我想我必须在所有情况下编写parser.expression。好的,我会移除start。非常感谢你的帮助。