/******************************************************/
参考来自于:
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
分享到:
相关推荐
LOOKAHEAD 是 JavaCC 中的一个重要参数,控制着解释器的词法分析能力。语法分析是 JavaCC 的核心功能,使用 BNF 范式和正则表达式来定义语法规则。词法分析是 JavaCC 的重要组成部分,使用正则表达式来描述正则...
- **支持LL(k)算法**: JavaCC允许用户通过调整`lookahead`参数来支持不同级别的前瞻(lookahead),从而支持LL(k)算法,其中k可以是任意正整数。 - **语法树生成**: 新版本的JavaCC提供了如JJTree等工具,帮助开发者...
JavaCC语法文件中定义了几个关键的保留字和结构,例如EOF、IGNORE_CASE、JAVACODE、LOOKAHEAD、MORE、PARSER_BEGIN、PARSER_END、SKIP、SPECIAL_TOKEN、TOKEN、TOKEN_MGR_DECLS。这些关键字有特定的用途,比如PARSER...
- **选择项**:选择项用于设置JavaCC生成代码时的行为,默认情况下LOOKAHEAD设置为1,JAVA_UNICODE_ESCAPE为true。 - **语法分析器类**:定义语法分析器的主要类和方法,实现文法的解析逻辑。 - **词法规则**:定义...
### JAVACC学习心得知识点详解 #### 一、引言 JAVACC是一款强大的解析工具,主要用于构建解析器。本文档旨在分享通过两周多的学习后对JAVACC的理解与心得,主要内容涵盖其工作原理、使用方法及深入认识等方面。 #...
此外,JavaCC允许设置lookahead参数,可以选择生成LL(k)算法,k大于1,这意味着它可以处理更复杂的文法,虽然效率可能较低。对于大多数编程语言,LL(1)算法已经足够,但如果需要,可以通过调整lookahead参数避免修改...
5. **前瞻(Lookahead)**:决定解析器在遇到歧义时如何选择正确的解析路径。 6. **语法文件(Grammar File)**:`.jj`文件,包含JavaCC语法定义和用户动作。 通过深入学习和实践JavaCC,开发者可以构建自己的解析...
- **Lookahead(前瞻)**:决定在遇到歧义时如何选择解析路径。 - **Semantic Actions(语义动作)**:在解析过程中执行的Java代码,通常用于构建解析结果的数据结构。 - **JAVADOC Production(Javadoc生产)**...
在实际编程中,我们可以使用现成的解析库,如ANTLR、JavaCC、Flex和Bison等,它们提供了方便的接口和工具,帮助开发者快速构建语法分析器。同时,现代编程语言和框架也引入了诸如词法作用域、闭包、异步编程等复杂...
LR(Lookahead Rightmost Derivation)解析器在遇到句柄时向右看一个符号,而LALR(Lookahead Left-to-right, Rightmost Derivation)是LR解析器的优化版本,提高了效率并减少了冲突。 4. **抽象语法树**:语法分析...
对于Java实现的语法解析器,开发者可能使用了诸如ANTLR、JavaCC或JFlex这样的工具,这些工具可以自动生成解析器和词法分析器的代码。ANTLR是一个流行的、强大的解析工具,支持多种语言,包括Java,并提供了灵活的...
LR(1)分析法全称为“Lookahead Rightmost Derivation in One Step”,即带有一步前瞻的右递归分析方法。它的核心思想是通过构建一个状态转移表(也称作分析表),根据输入符号和当前状态决定如何进行分析。在LR(1)...