我正在使用ANTLR4尝试实现支持包含文件的语言,例如PHP的include
。
var a = 4 + 5; // line a
include "some.inc"; // include statement
var b = 9 * 9; // line b
some.inc 的内容:
a *= 2;
a +== 3; // Typo here (extranous equals sign)
我需要分析树,以便将 some.inc 的内容插入到include
语句的位置。
如何在ANTLR4中做到这一点?
我当然可以构建一个新的字符串并进行一些连接(例如lineA + getContentsOf("some.inc") + lineB
),然后 then 将该字符串传递给词法分析器,但恐怕行号和列号搞砸了,所以我宁愿保留源路径,行和列。
编辑:如果他的代码有误,我想警告目标语言的一段代码的作者。在上面的示例中,作者输入了错误。我想警告用户, some.inc 的第2行出现错误。如果在之前解析(即替换了)包含,则将整个输入传递给词法分析器,则输入流将如下所示:
var a = 4 + 5; // line a
a *= 2;
a +== 3; // Typo here (extranous equals sign)
var b = 9 * 9; // line b
解析器不会知道格式错误的表达式a +== 3
最初来自some.inc的第2行,因此报告了错误的位置。
我当前的代码如下:
CharStream cs = CharStreams.fromPath(mySourceCode);
MyLexer lexer = new MyLexer(cs);
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
MyParser parser = new MyParser(tokenStream);
System.out.println(parser.startRule());
答案 0 :(得分:0)
由于没有人给出答案,所以让我们滚滚球吧。
过去,当我遇到类似这样的问题时,会想到两个解决方案:
1。 C预处理器
可以使用C编译器随附的C预处理程序,例如gcc
或clang
(通常称为cpp
:
/* In file mygrammar.g4 */ var a = 4 + 5; // line a #include "some.inc" // include statement. Note: no ";" var b = 9 * 9; // line b
要运行:
cpp /tmp/mygrammar.g4 | grep -v ^# > /tmp/mygrammar-cpp.g4
需要grep
才能删除行号指令。否则,输出将如下所示:
$ cpp /tmp/mygrammar.g4
# 1 "/tmp/mygrammar.g4"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "/tmp/mygrammar.g4"
var a = 4 + 5;
# 1 "/tmp/some.inc" 1
...
2。 m4宏预处理器
在POSIX系统上,通常会安装m4,这是一个宏处理器,用于处理包含和其他种类的宏。
这里是一个例子:
/* In file mygrammar.g4 */
var a = 4 + 5;
include(`some.inc') // Note `..' to list include filename. Again, no semicolon.
var b = 9 * 9;
并运行:
$ m4 /tmp/mygrammar.g4 > /tmp/mygrammar-m4.g4