匹配算数表达式语言

 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文法概念中的一些关键概念。

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

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

此外Antlr v4 的一个重要的特性是能够处理大多数的左递归规则。

文法文件写完后 鼠标右键文法文件 -> 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;


你可能感兴趣的:(antlr,算数表达式)