avaCC是一个很不错的词法、语法解析器的生成器,只需要编写规则就可以生成Java语言的词法、语法解析器(新版本的JavaCC还支持C/C++作为目标语言)。JavaCC相当与Yacc/Bison+Lex/Flex很类似。
JavaCC首页:
在首页上下载的JavaCC是最新版的,使用方法和Bison一样,在命令提示符或者终端中执行、获得生成的结果。
也可已用javacc eclipse插件:
http://sourceforge.net/projects/eclipse-javacc/files/
下载插件、解压之后,把plugins和features目录下的文件分别拷贝到eclipse的相应目录中即可。
不论哪种方式,所需编写的规则都是一样的。
通过JavaCC自带的example和文档其实就可以上手了,下面就简单小结一下:
词法和语法规则都写在一个.jj的文件中。这个文件应该这样写:
1、开头:
1
2
3
4
5
|
options
{
JDK_VERSION =
"1.5"
;
STATIC =
false
;
}
|
这个放在.jj文件的开头,JDK_VERSION是所生成代码适用的Jdk版本,1.5、1.6、1.7都可以,STATIC指示是否生成静态的解析器类,还有其他选项,参考文档。
2、主类
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
|
PARSER_BEGIN(Sparql)
package
cn.edu.ruc.iir.sparql;
import
cn.edu.ruc.iir.query.*;
import
cn.edu.ruc.iir.query.model.*;
import
cn.edu.ruc.iir.query.util.*;
import
java.text.*;
public
class
Sparql
{
public
static
void
main(String args [])
throws
ParseException
{
Sparql parser =
new
Sparql(System.in);
int
res =
0
;
while
(
true
)
{
System.out.print(
"MyRDF >"
);
try
{
res = parser.one_query();
if
(res ==
0
)
{}
else
if
(res ==
1
)
{
break
;
}
else
{
System.out.println(
"Please correct your query."
);
}
}
catch
(Exception e)
{
System.out.println(
"NOK."
);
System.out.println(e.getMessage());
parser.ReInit(System.in);
}
catch
(Error e)
{
System.out.println(
"Oops."
);
System.out.println(e.getMessage());
break
;
}
}
}
}
PARSER_END(Sparql)
|
在PARSER_BEGIN和PARSER_END之间定义语法解析器的主类,这是整个解析程序的入口,里面主要有一些引用的包和类以及一个main方法 (其他的方法由JavaCC生成)。由于上面把STATIC设为false了,所这这里需要创建一个parser对象,调用一次 parser.one_query()就进行一条语句的解析并获得解析的结果。
3、定义词法规则
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
|
SKIP :
{
" "
|
"\t"
|
"\r"
|
"\n"
}
TOKEN :
/* OPERATORS */
{
< SELECT :
"select"
|
"SELECT"
>
| < WHERE :
"where"
|
"WHERE"
>
| < OBRACE :
"{"
>
| < CBARCE :
"}"
>
}
TOKEN :
{
< UNKNOWN :
"?"
< KNOWN > >
| < KNOWN : ([
"<"
,
">"
,
"a"
-
"z"
,
"A"
-
"Z"
,
"0"
-
"9"
,
":"
,
"/"
,
"_"
,
"-"
,
"\""
,
"'"
,
"~"
,
"#"
])+ >
| < MISSEDP :
"["
"]"
>
| < EXIT :
"exit"
|
"EXIT"
>
}
|
这部分定义词法解析器的规则,SKIP定义要忽略的字符串,TOKEN定义要识别的字符串。注意,不是说先将输入中符合SKIP规则的都去掉再进行解析, 那样的话是不科学的,正常的词法解析都不会那么干,实际是顺序处理输入串的过程中,通过“大嘴法”识别尽可能长的子串。如果词法规则有二义 性,JavaCC会给出警告,一定不要忽略这些警告。
4、定义语法规则
JavaCC的语法单元形如这样:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
Token subject() :
{
Token token =
null
;
}
{
token = < UNKNOWN >
{
return
token;
}
| token = < KNOWN >
{
Token token1 = token;
}
(
"."
token = < KNOWN >
{
token1.image +=
"."
+ token.image;
}
)*
{
return
token1;
}
}
|
开头是一个声明,包括返回值类型、规则名和一个冒号。对于这样一条语法规则,JavaCC就会在语法分析器类中生成一个同名的方法。紧接着的一对花括号中写一些变量声明。下一对花括号中写该规则的具体内容。
一个语法单元中有多个规则时,用|分开。每个规则都有一系列词法或语法单元组成,每个词法或者语法单元之后跟着一对花括号,里面写处理的代码
基本上就是这样了。
[引用请注明出处:http://blog.csdn.net/bhq2010/article/details/8763920]