/******************************************************/
参考来自于:
heir\javacc-5.0\examples\Lookahead\
README.txt
/******************************************************/
/******************************************************/
0.概要
lookahead的作用不是很好用文字表达其实有很多问题都
可以避开它进行一个解决,但是如果你能够掌握他那么说明
你的javacc学的很不错了,因为这方面的学习资料大部分
都是英文,我例举一个java的多重条件结构来描述一下
lookahead的真正含义。
>举例代码:
如果有几个前缀相似的英文字母需要对这些不同的英文字母
做出不同的动作,关键是如何去区分这些英文。
void whatIsLookAhead():
{}
{
(
LOOKAHEAD(2)
"A" "B" "C"
{
System.out.println("shit");
}
|
"D" "E"
|
"A" "E"
{
System.out.println("xxxxxxxxx");
}
)
}
>分析:
上面的代码相当于:
//jj_scan_token(token_kind)作用:
//jj_scan_token(token_kind)从TokenManager取得一个Token对象,
//如果该token的类型和我传入的类型
//相匹配那么就说明符合语法要求
if (如果调用两次jj_scan_token(token_kind)
如果都符合要求那么返回true条件成立) {
"A" "B" "C"
} else if (next token is "D") {
"D" "E"
} else if (next token is "A") {
"A" "E"
} else {
produce an error message
}
// 为什么要这么做因为如果我输入的字符是
// AE并且没有用lookahead的话那么他将进入第一个
// 条件判断并且会抛出语法解析异常的错误这是
// 因为我输入的字符本来是要去匹配第三个条件判断的
// 如果采用lookahead的话这个错就不会报了
// 很明显这样的东西可以想很多的办法不用lookahead
>反向生成的java代码
if (jj_2_1(2)) {// 向前扫描两个指定了类型的token也就是17和18
// 为什么是17和18因为这里扫描的时候是根据第一个条件下面
// 需要消费的token而确定的
jj_consume_token(17);//>扫描的第一个token的类型17
jj_consume_token(18);//>扫描的第二个token的类型18
jj_consume_token(19);
System.out.println("shit");
} else {
switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) {
case 20:
jj_consume_token(20);
jj_consume_token(21);
break;
case 17:
//因为上面已经区分了两者的区别
//所以这里就很方便了就直接判断一个记号
//的类型就行了
jj_consume_token(17);
jj_consume_token(21);
System.out.println("xxxxxxxxx");
break;
default:
jj_la1[0] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
}
/******************************************************/
//(< LBRACE>)
//#MULTI(>1) 表示在栈中有ASTMULTI这个节点大于一的时候将当前节点压入栈顶
//否则丢弃
//jjtree.closeNodeScope(jjtn001, jjtree.nodeArity() > 1)
//ASTMULTI.java
void conj_elem()#void:
{
}
{
(
< AND >
{
conj=" +";
sb.append(" +");
}
|< NOT>
{
conj=" -";
sb.append(" -");
}
|(
LOOKAHEAD(2)
<span style="white-space:pre"> </span>(< OR>)+ //表示出现一次以上 这个判断很犀利
{
conj=" OR ";
sb.append(" OR ");
}
|(<OR>)? //表示出现一次或者不出现
{
conj=" ";
sb.append(" ");
}
)
)
{
expr();
}
}
/******************************************************/
1.全局LOOKAHEAD
LOOKAHEAD的全局效果默认为1也就是在判断的时候
默认向前多判断一个字符进行冲突判断
/******************************************************/
/******************************************************/
2.局部LOOKAHEAD
//这个方法是动态生成的并且是根据你的LOOKAHEAD(需要扫描几个)
//用的地方的第一个条件判断指定数量个token的类型的数字来生成
//这个方法也是对应到每一个局部的LOOKAHEAD的使用
static private boolean jj_2_1(int xla) {
jj_la = xla;
jj_lastpos = jj_scanpos = token;
try {
return !jj_3_1();
} catch (LookaheadSuccess ls) {
return true;
} finally {
jj_save(0, xla);
}
}
//这个方法是根据你的指定要送啊面的
//数量而生成的条件判断的方法
static private boolean jj_3_1() {
if (jj_scan_token(17))
return true;
if (jj_scan_token(18))
return true;
return false;
}
非原创,转自:http://blog.csdn.net/zyb243380456/article/details/7242796
分享到:
相关推荐
javacc 名词解释 如token,specialToken,lookahead
javacc-4.0以及 javacc-5.0下载
javacc eclipse 插件
javacc语法分析
cmm javacc 对CMM语言的词法语法分析器的自动实现
简介javacc ,列举javacc案例
JavaCC JavaCompilerCompiler 是一个用JAVA开发的最受欢迎的语法分析生成器 这个分析生成器工具可以读取上下文无关且有着特殊意义的语法并把它转换成可以识别且匹配该语法的JAVA程序 JavaCC可以在Java虚拟机 JVM V1 ...
具体使用方法:假如我们要创建一个a.jj,在项目图标上点右键->new->other->javacc目录下的javacc template file即可 对于创建好的a.jj 在其图标上点击右键compile with javacc 即可生成.java文件
该文档为自学JAVACC的笔记,以实例为例,具有较为详尽的介绍
javacc-5.0.rar
eclipse javacc
javacc构造编译器的方法 javacc代码生成器的基本介绍.
JavaCC附源码详细教程,对快速了解和学习JavaCC有很大帮助,结合实例讲角,通俗易懂
自己写的javacc学习心得,希望对大家能有帮助,说实话,我觉得写的还不错。
对一句话的关键词进行分析,挑出关键词的一种工具
javacc是专门用于设计编译器的eclipse插件!主要介绍了javacc的基本语法,以及基本的使用教程!
很详细的JAVACC对于初学者可以学到很多!
通过javacc来设计一个小型编译器,思路清晰,功能完善
最新的javacc,语法分器,生成器,含例子,帮助您更好的学习
javacc 编译器 有实例 用法:javacc xxx.jj javac *.java java ***