ANTLR 4翻译器

1 翻译器

Since 4.2。

对于较小的解析任务,使用翻译器更加简便。

2 动作代码

因为不会使用生成的词法器和解析器,因此无法使用动作代码和谓词。

3 Java 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// 从代码加载
LexerGrammar lg = new LexerGrammar(
"lexer grammar L;\n" +
"A : 'a' ;\n" +
"B : 'b' ;\n" +
"C : 'c' ;\n");
Grammar g = new Grammar(
"parser grammar T;\n" +
"s : (A|B)* C ;\n",
lg);
LexerInterpreter lexEngine =
lg.createLexerInterpreter(new ANTLRInputStream(input));
CommonTokenStream tokens = new CommonTokenStream(lexEngine);
ParserInterpreter parser = g.createParserInterpreter(tokens);
ParseTree t = parser.parse(g.rules.get(startRule).index);


// 从文件中加载结合的语法文件
public static ParseTree parse(String fileName,
String combinedGrammarFileName,
String startRule)
throws IOException
{
final Grammar g = Grammar.load(combinedGrammarFileName);
LexerInterpreter lexEngine = g.createLexerInterpreter(CharStreams.fromPath(Paths.get(fileName)));
CommonTokenStream tokens = new CommonTokenStream(lexEngine);
ParserInterpreter parser = g.createParserInterpreter(tokens);
ParseTree t = parser.parse(g.getRule(startRule).index);
System.out.println("parse tree: "+t.toStringTree(parser));
return t;
}
// then
ParseTree t = parse("T.om", MantraGrammar, "compilationUnit");


// 从文件中分别加载词法器和解析器
public static ParseTree parse(String fileNameToParse,
String lexerGrammarFileName,
String parserGrammarFileName,
String startRule)
throws IOException
{
final LexerGrammar lg = (LexerGrammar) Grammar.load(lexerGrammarFileName);
final Grammar pg = Grammar.load(parserGrammarFileName, lg);
CharStream input = CharStreams.fromPath(Paths.get(fileNameToParse));
LexerInterpreter lexEngine = lg.createLexerInterpreter(input);
CommonTokenStream tokens = new CommonTokenStream(lexEngine);
ParserInterpreter parser = pg.createParserInterpreter(tokens);
ParseTree t = parser.parse(pg.getRule(startRule).index);
System.out.println("parse tree: " + t.toStringTree(parser));
return t;
}
// then
ParseTree t = parse(fileName, XMLLexerGrammar, XMLParserGrammar, "document");

详见:TestParserInterpreter.java.

4 非Java配置

运行时不包含语法解析的类,其包含在工具包中。因此不能使用LexerGrammar或Grammar为解析器翻译语法。

可以直接初始化LexerInterpreter和ParserInterpreter对象。其需要的数据来源于代码生成的*.interpre文件。

文件读取可以使用InterpreterDataReader。

以下为C++示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* sourceFileName - name of the file with content to parse
* lexerName - the name of your lexer (arbitrary, that's what is used in error messages)
* parserName - ditto for the parser
* lexerDataFileName - the lexer interpeter data file name (e.g. `<path>/ExprLexer.interp`)
* parserDataFileName - ditto for the parser (e.g. `<path>/Expr.interp`)
* startRule - the name of the rule to start parsing at
*/
void parse(std::string const& sourceFileName,
std::string const& lexerName, std::string const& parserName,
std::string const& lexerDataFileName, std::string const& parserDataFileName,
std::string const& startRule) {

InterpreterData lexerData = InterpreterDataReader::parseFile(lexerDataFileName);
InterpreterData parserData = InterpreterDataReader::parseFile(parserDataFileName);

ANTLRFileStream input(sourceFileName);
LexerInterpreter lexEngine(lexerName, lexerData.vocabulary, lexerData.ruleNames,
lexerData.channels, lexerData.modes, lexerData.atn, &input);
CommonTokenStream tokens(&lexEngine);

/* Remove comment to print the tokens.
tokens.fill();
std::cout << "INPUT:" << std::endl;
for (auto token : tokens.getTokens()) {
std::cout << token->toString() << std::endl;
}
*/

ParserInterpreter parser(parserName, parserData.vocabulary, parserData.ruleNames,
parserData.atn, &tokens);
tree::ParseTree *tree = parser.parse(parser.getRuleIndex(startRule));

std::cout << "parse tree: " << tree->toStringTree(&parser) << std::endl;
}

参考资料