我刚刚开始使用ANTLR v4而且我有点困惑......
我使用C语法文件从ANTLR项目在这里与C的下列位工作:
#include <stdio.h>
int main()
{
printf("Hello");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
(保存为C:\ Users\Public\tc).
我生成了C解析器,如下所示:
java -cp lib/antlr-4.4-complete.jar org.antlr.v4.Tool -o src/cparser src/C.g4
Run Code Online (Sandbox Code Playgroud)
我编辑了生成的文件,将包语句放在顶部.
然后,我启动了一个包含这些生成文件的Java项目,引用antlr-runtime-4.4.jar了一个主类,如下所示:
package antlrtest;
import java.io.IOException;
import org.antlr.v4.runtime.ANTLRFileStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import cparser.CLexer;
import cparser.CParser;
import cparser.CParser.CompilationUnitContext;
public class AntlrTestMain {
public static void main(String[] arguments) {
try {
CParser parser = new CParser(
new CommonTokenStream(
new CLexer(
new ANTLRFileStream("C:\\Users\\Public\\t.c"))));
parser.setBuildParseTree(true);
// This line prints the error
CompilationUnitContext ctx = parser.compilationUnit();
MyListener listener = new MyListener();
ParseTreeWalker.DEFAULT.walk(listener, ctx);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)
并且为了完整性,虽然我认为它不重要,但听众看起来像这样(只是空的,我打算在这里放一些东西):
package antlrtest;
import cparser.CBaseListener;
public class MyListener extends CBaseListener {
}
Run Code Online (Sandbox Code Playgroud)
现在当我运行时会发生什么,当我调用compilationUnit方法时,我将以下错误打印到控制台:
line 1:0 token recognition error at: '#i'
line 1:9 no viable alternative at input 'nclude<'
Run Code Online (Sandbox Code Playgroud)
我很确定C代码是有效的,我根本没有编辑过C.g4文件所以我在这里做错了 - 为什么我会收到这些错误?
正在调用compilationUnit()错误的事情也许这样做,如果是的话我怎么称呼通入树遍历?
问题是:
除非先对文件进行预处理,否则一般不能解析文件.这可能就是为什么预处理器的东西只包含在非常有限的范围内.一些简单的例子:
#define FOO if (a
void main ()
{
int a;
FOO );
}
Run Code Online (Sandbox Code Playgroud)
所以你必须先创建一个预处理器语法.我做了类似的事情并且这样做了:
if,a,().你能做的是以下几点:
将包含规则添加到文件末尾的语法文件中(如果可能,将匹配其他预处理器内容):
SomePreprocessorStuff
: '#' ~[\r\n]*
-> skip
;
Run Code Online (Sandbox Code Playgroud)
ANTLR项目随附的C语法需要预处理的源文件作为输入。该语法不执行任何文件包含,宏扩展或预处理器提供的任何其他功能。如果在使用此语法之前未执行预处理,则它生成的解析树将不能正确表示编译单元。
请注意,跳过“预处理器内容”不是预先使用预处理器的替代方法,因为文件包含只是预处理器的一部分。