JavaCC学习笔记(1)
来源:互联网 发布:法兰西战役知乎 编辑:程序博客网 时间:2024/05/22 20:25
今天刚学,啥也不明白,网罗了一堆文档教程什么的,英文的中文的啥都有了,看了会最简单的,还凑合写出来,看看能说明白不.
看教程上的例子,学着写了一个,还真好使了,就是一个十进制的加法表达式,比如
1+1
呵呵,我知道等于2,可这个小程序不是算结果的,是检验表达式合法不,基本就这样了,得先写个什么.jj文件规范JavaCC的解析器和词法分析器,将会作为JavaCC处理文件的输入.就叫"Adder.jj"吧,跟教程上一样.
- PARSER_BEGIN(Adder)
- public class Adder{
- public static void main(String[] args)
- throws ParseException,TokenMgrError{
- Adder adder = new Adder(System.in);
- adder.start();
- }
- }
- PARSER_END(Adder)
- SKIP:{" "|"/t"|"/n"|"/r"|"/r/n"}
- TOKEN:{
- <PLUS:"+">
- |<NUMBER:(["0"-"9"])+>
- }
- void start():
- {}
- {
- <NUMBER>(<PLUS><NUMBER>)*<EOF>
- }
1.PARSER_BEGIN(Adder)与PARSER_END(Adder)之间的代码是Java语法,这里生成Adder.java的主程序入口,基本就是这种格式,其中要抛出两个异常:
1.1 ParseException : 解析错误,解析器负责检查,Exception的子类.比如输入"1++1",这种就是解析错误,因为它里面的分割符都是我们在TOKEN:中定义的,没有其它字符.
1.2 TokenMgrError : 分割符错误,词法分析器负责检查,Error的子类.比如输入"1-1"就是这种错误,因为TOKEN:中没有定义"-".
这两个类都会自动生成,现在刚研究还不知道为啥一个来之Exception,一个来自Error,以后会明白的.
2.new Adder(System.in),这个构造子这还不是很明白,不知道为啥默认成这型的,就知道是自动产生的,以后再说.
3.start() 方法是解析的主体,是下面需要实现的.
4.
SKIP:{" "|"/t"|"/n"|"/r"|"/r/n"}
这个定义的是忽略的字符,它们虽然构成分割符但不被送给解析器,就是你在输入的时候有这些字符不会发生错误,但它们不会被解析出来.这里定义了5个,基本上就是空格,跳格,回车换行什么的,以为各个操作系统间的回车换行什么的据说不一样,我也不知道都咋回事,都写上吧.各个元素之间用"|"分开,格式就是这样了.
5.
- TOKEN:{
- <PLUS:"+">
- |<NUMBER:(["0"-"9"])+>
- }
这个是说分割符了,就是把一个句子里的什么字符取出来,也就是你这句子里只能有这些规定好的字符,别的不行,这里就是"+"号和0-9十个数字. 两着用"|"分开.
每个分割符是这样规定的,用<>括上,代号和符号用":"隔开,就是用前面的代号代替后面在句子中会出现的元素或元素的集合.这些代号在下面会用到.其中数字用了正则式,就是1个或1个以上的由0-9之间的数字组成的串.
4和5两个部分如果用不到可以没有.
6.
- void start():
- {}
- {
- <NUMBER>
- (<PLUS><NUMBER>)*
- <EOF>
- }
这个就是传说中的解析器了,说是符合什么BNF产生式,基本就这形状了,以后漫漫弄明白吧.里面看起来还像是正则式,就是用符号替换了,是以数字开头,中间跟0个或0个以上的由+和数字组成的序列,这个顺序不能变,最后是结束符,自带定义的.
程序基本上就这么回事了,因为简单,也形式上也没什么.
然后编译吧,设好环境变量什么的,在控制台切换到在Adder.jj所在文件夹:
javacc Adder.jj
成功就会出现提示:
- Java Compiler Compiler Version 4.0beta1 (Parser Generator)
- (type "javacc" with no arguments for help)
- Reading from file Adder.jj . . .
- File "TokenMgrError.java" does not exist. Will create one.
- File "ParseException.java" does not exist. Will create one.
- File "Token.java" does not exist. Will create one.
- File "SimpleCharStream.java" does not exist. Will create one.
- Parser generated successfully.
一共生成了7个.java文件:
- Adder.java : 生成的主程序,里面是程序入口,也是解析器.可以看到片段如下:
- /* Generated By:JavaCC: Do not edit this line. Adder.java */
- public class Adder implements AdderConstants {
- public static void main(String[] args) throws ParseException, TokenMgrError{
- Adder adder = new Adder(System.in);
- adder.start();
- }
- static final public void start() throws ParseException {
- jj_consume_token(NUMBER);
- label_1:
- while (true) {
- switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case PLUS:
- ;
- break;
- default:
- jj_la1[0] = jj_gen;
- break label_1;
- }
- jj_consume_token(PLUS);
- jj_consume_token(NUMBER);
- }
- jj_consume_token(0); }
上面我们定义到:
void start():{}{ <NUMBER>(<PLUS><NUMBER>)*<EOF>}
这里start()方法先消费一个number:jj_consume_token(NUMBER);然后是一个(<PLUS><NUMBER>)*的过程,循环中(jj_ntk==-1)?jj_ntk():jj_ntk来判断下一个未读取的token类型的,感觉从循环体上来看,这个合法的token类型,只能是<PLUS>或<EOF>,因为每次成对的消费PLUS和NUMBER,所以是PLUS就跳出switch,执行20,21行进行消费<PLUS><NUMBER>,如果是其它的,感觉这里只能是0,也就是<EOF>.这个类里还有其它的一些数据,比如几个重载的构造子,一些变量和方法.
-
Token.java : 分割符的信息.里面有一些数据成员和方法,包含了我们定义的那3个token.其中image是我们常在程序中调用的成员,它是一个 public String 类型,记录了 从输入中得到的token,比如我们的"1","+","1",都以字符串的方式存储在image里供人们直接使用.还有一些上面程序片段看到的已经调用过的方法.
-
SimpleCharStream.java : 实现CharStream接口的适配器类,传递字符到词法分析器.貌似只用ASCII,非unicode.
-
AdderConstants.java : 接口.定义了词法分析器和解析器用到的一些常量.这里可以清楚的看到:
- int EOF = 0;
- int PLUS = 6;
- int NUMBER = 7;
- int DEFAULT = 0;
- String[] tokenImage = {
- "<EOF>",
- "/" /"",
- "/"//t/"",
- "/"//n/"",
- "/"//r/"",
- "/"//r//n/"",
- "/"+/"",
- "<NUMBER>",
- };
- AdderTokenManager.java : 词法分析器.
- TokenMgrError.java 和 ParseException.java : 上面说到的异常类.
编译了这些文件:
javac *.java
运行 Adder :
java Adder
这时候控制台等待输入,可以试试拉:
1+1
没提示就是合法,ctrl + c 结束输入
可以试着弄点错误什么的,看看异常类型跟错误的情况是怎么对应的.
都完事了,还挺简单的,呵呵.啊 累死了,下回再说.
- JavaCC学习笔记(1)
- javaCC学习笔记
- 学习JavaCC笔记
- JavaCC学习笔记(2)
- javacc学习笔记
- JavaCC 学习笔记
- JavaCC学习笔记
- JavaCC学习笔记
- jjTree和javaCC学习笔记
- 实验一:javacc学习笔记
- javacc笔记
- javacc笔记2
- javacc笔记3
- javacc笔记4
- javacc笔记5
- javacc学习总结
- javaCC
- javacc
- VC6编译和链接的两个头疼问题
- SqlServer时间字段里自动添加时间格式
- 我对A星算法的理解
- 我的C#窗体
- 提高绘图效率
- JavaCC学习笔记(1)
- 命名规则参考
- VC防止窗口和控件闪烁的方法
- 自绘控件——序
- 此Blog转移到博客园
- 偶感
- 天然水晶挑选全攻略 真假水晶鉴别方法 保养净化
- IIS环境下快速安装、配置和调试PHP5.2.0
- Toad for Oracle