JavaCC(Java Compiler Compiler)是一个用JAVA开发的语法分析生成器。
特点如下:
- LL(k)
- 支持指定长度的 look-ahead
- look-ahead可以内嵌表达式
- 类似YACC,在模板文件中嵌套代码
- 生成后的代码不再依赖任何第三方库
四则运算的语法如下:
1
2
3
|
expr : term | expr ('+' | '-') term
term : pri | term ('*' | '/') pri
pri : INT | '(' expr ')' | -INT
|
上面的语法是左递归的,改成非左递归的如下:
1
2
3
4
5
|
expr : term expr'
expr': ('+' | '-') term expr' | ε
term : pri term'
term': ('*' | '/') pri term' | ε
pri : INT | '(' expr ')' | -INT
|
Calculator.jj 代码如下:
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
options {
STATIC = false;
DEBUG_PARSER = true;
UNICODE_INPUT = true;
JDK_VERSION = "1.8";
}
PARSER_BEGIN(Calculator)
package com.test;
import java.io.*;
public class Calculator {
public Calculator(String expr){
this(new StringReader(expr));
}
}
PARSER_END(Calculator)
SPECIAL_TOKEN : {" "}
TOKEN : {
<ADD : "+" >
| <SUB : "-" >
| <MUL : "*" >
| <DIV : "/" >
}
TOKEN : {
< NUMBER : < DIGITS> | < DIGITS> "." < DIGITS> >
| < #DIGITS : ([ "0"-"9" ])+ >
}
TOKEN : {
< LEFT_PAR : "(">
| < RIGHT_PAR : ")">
}
SPECIAL_TOKEN : { < EOL : "\n" | "\r" | "\r\n"> }
double expr() : {
double left;
double right;
}
{
left = term()
(
< ADD > right = term() { left = left + right; }
| < SUB > right = term() { left = left - right; }
)*
{ return left; }
}
double term() : {
double left = 0D;
double right = 0D;
}
{
left = pri()
(
< MUL > right = pri() { left = left * right;}
| < DIV > right = pri() { left = left / right;}
)*
{ return left;}
}
double pri() : {
Token t;
double val;
}
{
try {
t = < NUMBER > { return Double.parseDouble(t.image); }
| < LEFT_PAR> val = expr() < RIGHT_PAR> { return val;}
| < SUB > val = pri() { return -val;}
} catch(Exception e) {
e.printStackTrace();
}
}
|
编译上述 语法文件,命令如下:
打印输出:
1
2
3
4
5
6
7
8
9
10
|
Java Compiler Compiler Version 7.0.10 (Parser Generator)
(type "javacc" with no arguments for help)
Reading from file Calculator.jj . . .
Note: UNICODE_INPUT option is specified. Please make sure you create the parser/lexer using a Reader with the correct ch
aracter encoding.
File "TokenMgrError.java" is being rebuilt.
File "ParseException.java" is being rebuilt.
File "Token.java" is being rebuilt.
File "SimpleCharStream.java" is being rebuilt.
Parser generated successfully.
|
测试代码:
1
2
3
4
5
6
|
public static void main(String[] args)throws Exception {
String str = "1 + 2 * 3 - (4 + 5 / 6 - 7 * 8) + 9 - 10 \n";
Calculator c = new Calculator(str);
double d = c.expr();
System.out.println("res -> " + d);
}
|
执行结果:
res -> 57.16666666666666