如何在ANTLR中实现包含文件?

时间:2019-05-24 09:24:44

标签: antlr antlr4

我正在使用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());

1 个答案:

答案 0 :(得分:0)

由于没有人给出答案,所以让我们滚滚球吧。

过去,当我遇到类似这样的问题时,会想到两个解决方案:

1。 C预处理器

可以使用C编译器随附的C预处理程序,例如gccclang(通常称为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