我正在为一种语言编写一个编译器,作为大学使用ANTLR4的项目。我使用Java编写了这个编译器,并采用了Visitor模式,当我到达测试阶段时,我注意到ANTLR忽略了我的部分代码,并生成了它不应该生成的错误。
语法:
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;
以下是我的主要观点:
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
public class Main {
public static void main(String[] args) {
String test =
"import Small_Java.lang;\n" +
"public class_SJ Test{\n" +
"\tint_SJ varTest;\n" +
"\tmain_SJ{\n" +
"\t\tvarTest := 1+1;\n" +
"\t}\n" +
"}";
ANTLRInputStream input = new ANTLRInputStream(test);
smallJavaLexer lexer = new smallJavaLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
smallJavaParser parser = new smallJavaParser(tokens);
ParseTree tree = parser.expression();
myVisitor v = new myVisitor();
v.visit(tree);
}
}
当我运行Main时,它显示:
第1行:0不匹配的输入'import'应为{(',INT,FLOAT,STRING,IDF}
我的语法有什么地方错了吗?如果没有,为什么要这样做?
这一行:
ParseTree tree = parser.expression();
告诉解析器
对象解析一个表达式
(即语法定义的非终端表达式
),因此当它看到标记导入
时,它会正确地发牢骚。
大概您的意图是解析程序
,在这种情况下,您需要调用程序
成员函数:
ParseTree tree = parser.program();
您的start
生产本质上是毫无意义的,因为它所做的只是服从程序
。使用start
规则启动语法很常见,因为其他一些解析器生成器具有“start规则”的概念,这意味着生成的解析器总是尝试解析相同的非终端。但是Antlr真的没有这个概念;您可以使用具有该名称的成员函数接受语法中任何非终端的顶级匹配。
问题内容: 我正在开发一个使用Spring-boot,关系数据库和Elasticsearch的应用程序。 我在代码的2个不同位置使用JSON序列化: 在REST API的响应中。 当代码与Elasticsearch交互时。 我在Elasticsearch中需要一些属性,但我想向应用程序用户隐藏(例如,来自关系数据库的内部ID)。 这是一个实体的例子: 问题 :当对象持久化在Elasticsearc
我们如何才能让他们识别lexer规则?所有、和规则都可能与匹配。那么我在测试它的时候应该使用什么类型。 我的意思是: 一般来说,我想了解如何知道的类型?
问题内容: 我正在某个网站上插入一些标题中的换行符。假设我无法编辑源HTML,是否有CSS可以忽略这些中断的方法? 我正在移动网站的优化,所以我真的不想使用JavaScript。 问题答案: 使用css,您可以“隐藏” br标签,它们不会起作用: 如果只想在特定的标题类型中隐藏某些内容,只需使CSS更具体即可。
我的语法在很大程度上必须忽略空格,除非在某些上下文中。这个问题的答案建议定义特定的lexer规则来处理我想要的异常。 问题是(我认为)我不能在lexer级别处理这种情况,因为它们似乎是在解析器级别被触发的。 更具体地说:我想认识一些东西,比如 记住我有一个WS- 在Xtext中,规则可以在规则范围的基础上指定在规则范围内应用哪些隐藏令牌: 但是我对antlr4一无所知。