`

javacc Lookahead

阅读更多
/******************************************************/

参考来自于:
  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:
{
}
{
&nbsp; (
&nbsp; &nbsp; < AND >
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; conj=" +";
&nbsp; &nbsp; &nbsp; sb.append(" +");
&nbsp; &nbsp; }
&nbsp; &nbsp;|< NOT>
&nbsp; &nbsp;{
&nbsp; &nbsp; conj=" -";
&nbsp; &nbsp; sb.append(" -");
&nbsp; &nbsp;}
&nbsp; &nbsp;|(
&nbsp; &nbsp; LOOKAHEAD(2)
<span style="white-space:pre"> </span>(< OR>)+ //表示出现一次以上 这个判断很犀利
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp;conj=" OR ";
&nbsp; &nbsp; &nbsp;sb.append(" OR ");
&nbsp; &nbsp; }
&nbsp; &nbsp; |(<OR>)? //表示出现一次或者不出现
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp;conj=" ";
&nbsp; &nbsp; &nbsp;sb.append(" ");
&nbsp; &nbsp; }
&nbsp; &nbsp; )
&nbsp; )
&nbsp; {
&nbsp; &nbsp;expr();
&nbsp; }
}
/******************************************************/
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学习心得

    LOOKAHEAD 是 JavaCC 中的一个重要参数,控制着解释器的词法分析能力。语法分析是 JavaCC 的核心功能,使用 BNF 范式和正则表达式来定义语法规则。词法分析是 JavaCC 的重要组成部分,使用正则表达式来描述正则...

    javaCC入门文档

    - **支持LL(k)算法**: JavaCC允许用户通过调整`lookahead`参数来支持不同级别的前瞻(lookahead),从而支持LL(k)算法,其中k可以是任意正整数。 - **语法树生成**: 新版本的JavaCC提供了如JJTree等工具,帮助开发者...

    JavaCC语法文件中文版 V2.0_静水71

    JavaCC语法文件中定义了几个关键的保留字和结构,例如EOF、IGNORE_CASE、JAVACODE、LOOKAHEAD、MORE、PARSER_BEGIN、PARSER_END、SKIP、SPECIAL_TOKEN、TOKEN、TOKEN_MGR_DECLS。这些关键字有特定的用途,比如PARSER...

    JavaCC学习与应用

    - **选择项**:选择项用于设置JavaCC生成代码时的行为,默认情况下LOOKAHEAD设置为1,JAVA_UNICODE_ESCAPE为true。 - **语法分析器类**:定义语法分析器的主要类和方法,实现文法的解析逻辑。 - **词法规则**:定义...

    javacc 学习心得

    ### JAVACC学习心得知识点详解 #### 一、引言 JAVACC是一款强大的解析工具,主要用于构建解析器。本文档旨在分享通过两周多的学习后对JAVACC的理解与心得,主要内容涵盖其工作原理、使用方法及深入认识等方面。 #...

    使用JavaCC做语法分析

    此外,JavaCC允许设置lookahead参数,可以选择生成LL(k)算法,k大于1,这意味着它可以处理更复杂的文法,虽然效率可能较低。对于大多数编程语言,LL(1)算法已经足够,但如果需要,可以通过调整lookahead参数避免修改...

    JavaCC Grammar File && Tutorial File

    5. **前瞻(Lookahead)**:决定解析器在遇到歧义时如何选择正确的解析路径。 6. **语法文件(Grammar File)**:`.jj`文件,包含JavaCC语法定义和用户动作。 通过深入学习和实践JavaCC,开发者可以构建自己的解析...

    lucene配置必备文件JAVA-CC

    - **Lookahead(前瞻)**:决定在遇到歧义时如何选择解析路径。 - **Semantic Actions(语义动作)**:在解析过程中执行的Java代码,通常用于构建解析结果的数据结构。 - **JAVADOC Production(Javadoc生产)**...

    编译原理之语法分析程序

    在实际编程中,我们可以使用现成的解析库,如ANTLR、JavaCC、Flex和Bison等,它们提供了方便的接口和工具,帮助开发者快速构建语法分析器。同时,现代编程语言和框架也引入了诸如词法作用域、闭包、异步编程等复杂...

    编译原理—词法分析和语法分析 实验报告

    LR(Lookahead Rightmost Derivation)解析器在遇到句柄时向右看一个符号,而LALR(Lookahead Left-to-right, Rightmost Derivation)是LR解析器的优化版本,提高了效率并减少了冲突。 4. **抽象语法树**:语法分析...

    Yufa.rar_语法解析

    对于Java实现的语法解析器,开发者可能使用了诸如ANTLR、JavaCC或JFlex这样的工具,这些工具可以自动生成解析器和词法分析器的代码。ANTLR是一个流行的、强大的解析工具,支持多种语言,包括Java,并提供了灵活的...

    精选_毕业设计_基于Java实现的LR(1)分析法语法分析程序_完整源码

    LR(1)分析法全称为“Lookahead Rightmost Derivation in One Step”,即带有一步前瞻的右递归分析方法。它的核心思想是通过构建一个状态转移表(也称作分析表),根据输入符号和当前状态决定如何进行分析。在LR(1)...

Global site tag (gtag.js) - Google Analytics