您的位置:首页 > 其它

The Definitive Antlr 4 第4章学习笔记

2016-05-09 23:47 393 查看
The Definitive Antlr 4 Reference 2nd Edition 第4章第一小节 学习笔记

匹配算数表达式语言



本例中,只使用基本的算数运算(加,减,乘,除),括号表达式,整数,及变量。例如有如下的表达式。

193
a = 5
b = 6
a+b*2
(1+2)*3


在这里介绍的表达式语言,是由换行符所分割的一组语句构成。语句可以是表达式、赋值运算、或是一个空行。下面是用于解析上述语句及表达式的Antlr文法。

grammar expr;
prog : stat+;

stat : expr NEWLINE
| ID '=' expr NEWLINE
| NEWLINE
;

expr: expr ('*' | '/') expr
| expr ('+' | '-') expr
| INT
| ID
| '(' expr ')'
;

ID : [a-zA-Z]+;
INT : [0-9]+;
NEWLINE: '\r'?'\n';


首先说明Antlr文法概念中的一些关键概念。

文法由一组描述语法的规则组成。其中包括词法与语法规则。
语法规则是以小写字母组成。如prog,stat。
词法规则由大写字母组成。如ID:[a-zA-Z]+。
通过使用 | 运算符来将不同的规则分割,还可以使用括号构成子规则。例如(‘*’ | ‘/’)会匹配多个乘号或除号。

上面的文法中 –> skip是一个指示符,用来告诉词法分析器来匹配,并丢弃这些空白符。

此外Antlr v4 的一个重要的特性是能够处理大多数的左递归规则。(Antlr4可以处理直接左递归,但无法处理间接左递归)

文法文件写完后 鼠标右键文法文件 -> Generate Antlr...... 随后会在指定的目录下生成XXparser 与 XXLexer文件。通过这些文件就可以完成分析任务了。

public class Main {

public static void main(String[] args) {
String expr = "(1+2*3/2-7))";
ANTLRInputStream input = new ANTLRInputStream(expr);
exprLexer lexer = new exprLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
exprParser parser = new exprParser(tokens);
ParseTree tree = parser.prog();
System.out.println(tree.toStringTree(parser));
}
}


代码中创建了字符输入流对象,用作创建词法分析对象的输入。随后创建词法(ExprLexer)分析对象、符号流对象(CommonTokenStream)、及语法(ExprParser)分析对象。CommonTokenStream将ExprParser与ExprLexer串联在了一起。代码最后打印出分析树。

导入文法

若将所有内容写在一个文件内,则不便于管理,因此可以将文法文件分解。其中一种办法是将文法与词法分开定义。通过lexer grammar定义词法文件,最后在语法文件中用import关键字将词法定义导入。

定义文法文件,该文件内的词法定义已经移入CommonLexerRules.g4文件中,并通过import导入该文件内容。

expr.g4文件

grammar expr;
import CommonLexerRules;
prog : stat+;

stat : expr NEWLINE
| ID '=' expr NEWLINE
| NEWLINE
;

expr: expr ('*' | '/') expr
| expr ('+' | '-') expr
| INT
| ID
| '(' expr ')'
;
CommonLexerRules.g4
lexer grammar CommonLexerRules;

ID : [a-zA-Z]+;
INT : [0-9]+;
NEWLINE: '\r'?'\n';
WS : [\t]+ -> skip;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: