• JavaCC


    项目中用的JavaCC做查询编译,在这里小结一下,作为备忘。

    JavaCC是一个很不错的词法、语法解析器的生成器,只需要编写规则就可以生成Java语言的词法、语法解析器(新版本的JavaCC还支持C/C++作为目标语言)。JavaCC相当与Yacc/Bison+Lex/Flex很类似。

    JavaCC首页:

    http://javacc.java.net/

    在首页上下载的JavaCC是最新版的,使用方法和Bison一样,在命令提示符或者终端中执行、获得生成的结果。

    也可已用javacc eclipse插件:

    http://sourceforge.net/projects/eclipse-javacc/files/

    下载插件、解压之后,把plugins和features目录下的文件分别拷贝到eclipse的相应目录中即可。

    不论哪种方式,所需编写的规则都是一样的。

    通过JavaCC自带的example和文档其实就可以上手了,下面就简单小结一下:

    词法和语法规则都写在一个.jj的文件中。这个文件应该这样写:

    1、开头:

    options
    {
      JDK_VERSION = "1.5";
      STATIC = false;
    }

    这个放在.jj文件的开头,JDK_VERSION是所生成代码适用的Jdk版本,1.5、1.6、1.7都可以,STATIC指示是否生成静态的解析器类,还有其他选项,参考文档。

    2、主类

    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)

    3、定义词法规则

    SKIP :
    {
    " "
    | " "
    | " "
    | " "
    }

    TOKEN : /* OPERATORS */
    {
    < SELECT :
    "select"
    | "SELECT" >
    | < WHERE :
    "where"
    | "WHERE" >
    | < OBRACE : "{" >
    | < CBARCE : "}" >
    }

    TOKEN :
    {
    < EXIT :
    | "exit"
    | "EXIT" >
    | < UNKNOWN : "?" < KNOWN > >
    | < KNOWN : ([ "<", ">", "a"-"z", "A"-"Z", "0"-"9", ":", "/", "_", "-", """, "'", "~", "#" ])+ >
    | < MISSEDP : "[" "]" >

    }

    这部分定义词法解析器的规则,SKIP定义要忽略的字符串,TOKEN定义要识别的字符串。注意,不是说先将输入中符合SKIP规则的都去掉再进行解析,那样的话是不科学的,正常的词法解析都不会那么干,实际是顺序处理输入串的过程中,通过“大嘴法”识别尽可能长的子串。如果词法规则有二义性,JavaCC会给出警告,一定不要忽略这些警告。此外,JavaCC只对开头存在二义性的词法给出警告(一个字符可以作为两个词法规则的第一个字符),有些词法上的冲突是需要我们自己去注意的,比如要在词法解析时识别一些关键词,这些关键词同时也符合一般标识符的规则,那么在JavaCC中就要把关键词的定义写在标识符定义之前,写在前面的,JavaCC会优先识别。

     

    4、定义语法规则

    JavaCC的语法单元形如这样:

    Token subject() :
    {
    Token token = null;
    }
    {
    token = < UNKNOWN >
    {
    return token;
    }
    | token = < KNOWN >
    {
    Token token1 = token;
    }
    (
    "." token = < KNOWN >
    {
    token1.image += "."+ token.image;
    }
    )*
    {
    return token1;
    }
    }

    开头是一个声明,包括返回值类型、规则名和一个冒号。对于这样一条语法规则,JavaCC就会在语法分析器类中生成一个同名的方法。紧接着的一对花括号中写一些变量声明。下一对花括号中写该规则的具体内容。

     

    一个语法单元中有多个规则时,用|分开。每个规则都有一系列词法或语法单元组成,每个词法或者语法单元之后跟着一对花括号,里面写处理的代码。

  • 相关阅读:
    63.C++异常
    62.C++文件操作list实现内存检索,实现两千万数据秒查
    61.C++文件操作实现硬盘检索
    ios之数据持久化
    ios NSRange
    安排
    接口隔离原则
    Liskon替换原则
    开放封闭原则
    单一职责原则
  • 原文地址:https://www.cnblogs.com/xmzzp/p/6284305.html
Copyright © 2020-2023  润新知