Calcite JavaCC简单介绍及使用

  • Post author:
  • Post category:java



JavaCC

使用递归降低语法解析,LL(k)。其中,第一个L表示从左到右扫描输入;第二个L表示每次都进行最左推导(在推导语法树的过程当中每次都替换句型中最左的非终结符为终结符。相似还有最右推导);k表示的是每次向前探索(lookahead)k个终结符


语法描述文件

options {
    JavaCC的选项
}

PARSER_BEGIN(解析器类名)
package 包名;
import 库名;

public class 解析器类名 {
    任意的Java代码
}
PARSER_END(解析器类名)

扫描器的描述

解析器的描述


JavaCC类介绍


SimpleCharStream:词法分析器的输入流

// SimpleCharStream    词法分析器的输入流

// 构造函数种类 ,能够接受Reader和InputStream
public class SimpleCharStream {
   public SimpleCharStream(java.io.Reader dstream, int startline, int startcolumn, int buffersize);
   public SimpleCharStream(java.io.Reader dstream, int startline, int startcolumn);   
   public SimpleCharStream(java.io.Reader dstream); 
   public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException;  
   public SimpleCharStream(java.io.InputStream dstream, int startline, int startcolumn, int buffersize);
   public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, int startcolumn) throws java.io.UnsupportedEncodingException;                    
   public SimpleCharStream(java.io.InputStream dstream, int startline, int startcolumn);
   public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException;
   public SimpleCharStream(java.io.InputStream dstream);
}


XXXXXConstants:Token常量,SKIP TOKEN和TOKEN

// 忽略的字符
SKIP:{
    " "
}

// 关键字
TOKEN:{
    <PLUS :"+">
}

// 和常量申明对应
public interface XXXXXConstants {
  int EOF = 0;
  int PLUS = 2;
  int DEFAULT = 0;

  String[] tokenImage = {
    // EOF 文件结尾
    "<EOF>",
    // 忽律字符串
    "\" \"",
    // PLUSA
    "\"+\"",
  };
}


XXXXXTokenManager:词法分析器

// 常见方法说明
public class XXXXXTokenManager implements XXXXXConstants {
    protected SimpleCharStream input_stream;             // 输入流
    public XXXXXTokenManager(SimpleCharStream stream);   // 构造函数
    public Token getNextToken();                         // 获取下一个Token
}


Token:Token类函数

public class Token {
    public int kind;                                          // Constants.java的种类
    public int beginLine, beginColumn, endLine, endColumn;    // 开始行和开始列,结束行和结束列
    public String image;                                      // token的字符串
    public Token next;                                        // 下一个token
    public Token specialToken;                                // 特殊令牌
    public String toString() {
        return image;
    }
}


XXXXX:解析类入口


ParseException:语法解析异常


TokenMgrError:语法错误提示


JavaCC工作原理


语法二义性解决

void S():{}
{
    IFStat()
    |
    E();
}
void IFStat():{}
{
    "if" "(" E() ")"
    S()
    (
        "else" S();
    )?
}

if E if E S else S  中存在两种解释:
    if E
       if E
         S
       else
         S 
       
    if E
       if E
         S
    else
       S

能够借助LOOKAHEAD(K)关键字解决;
// 词法分析执行完if-S以后先找slse, 找到则匹配最近的if,不然执行后面的语句
void S():{}
{
    IFStat()
    |
    E();
}
void IFStat():{}
{
    "if" "(" E() ")"
    S()
    (
        LOOKAHEAD(1)
        "else" S();
    )?
}


JavaCC语法


Java代码:java代码块用{}声明

// 定义java代码块
void javaCodeDemo():
{ local variable...... }
{
    {
        int i = 0;
        System.out.println(i);
    }
}


JAVA函数:须要用JAVACODE声明

JAVACODE void print(Token t){
    System.out.println(t);
}


条件:if语句 if-else语句

// if语句
void ifExpr():
{}
{
    [
        <SELECT>
        {
            System.out.println("if select");
        }
    ]
    // 循环,出现一次
    (<SELECT>)?
}

// if - else
void ifElseExpr():
{}
{
    (
        <SELECT> {System.out.println("if else select");}
        |
        <UPDATE>  {System.out.println("if else update");}
        |
        <DELETE>  {System.out.println("if else delete");}
        |
        {
           System.out.println("other");
        }
    )
}


循环:while 0~n while 1~n

// while 0~n
void while1Expr():
{}
{
    (<SELECT>)*
}

// while 1~n
void while2Expr():
{}
{
    (<SELECT>)+
}


正则表达式

  1. [] 内容可选
  2. + 内容出现一次或者屡次
  3. * 内容出现0次或者屡次
  4. ? 内容出现0次或者一次
  5. | 或
  6. () 优先级改变或者总体操做


代码示例

简单计算器 Maven编译:mvn javacc:javacc

PARSER_BEGIN(Calculator)
package com.meton.test.parser.javacc.calc;

import java.io.* ;

public class Calculator {
    public Calculator(String expr) {
        this((Reader)(new StringReader(expr)));
    }

    public static void main(String[] args) throws Exception  {
       Calculator calc = new Calculator(args[0]);
       System.out.println(calc.calc());
    }
}
PARSER_END(Calculator)


// 忽律的字符
SKIP:{
    " "
    | "\t"
    | "\n"
    | "\r"
    | "\r\n"
}

// 关键字
TOKEN:{
    <ADD :"+">
    | <SUB :"-">
    | <MUL :"*">
    | <DIV :"/">
    | <NUMBER :
            <DIGITS>
            | <DIGITS> "." <DIGITS>
            | <DIGITS> "."
            | "." <DIGITS>
      >
    | <#DIGITS : (["0"-"9"])+ >
}

// 计算
double calc():
{
    Double value ;
    Double result = 0.0;
}
{
  result = term()
  // 加减
  (
      <ADD>
      value = term()
      {result += value;}
      |
      <SUB>
      value =term()
      {result -= value;}
  )*
  {return result;}
}

// 乘除
double term():
{
    double value;
    double result;
}
{
    result = getNumber()
    (
       <MUL>
        value = getNumber()
        {result *= value;}
       |
       <DIV>
       value = getNumber()
       {result /= value;}
    )*
    {return result;}

}

// 获取字符串
double getNumber():
{
    double number;
    Token t;
}
{
    t = <NUMBER>
    {number = Double.parseDouble(t.image);
    return number;}
}


简单语法示例

// javacc编译设置
options {
    STATIC = false;
    IGNORE_CASE = true;
    UNICODE_INPUT = true;
}

// 解析类
PARSER_BEGIN(JavaCCGrammar)
package com.meton.test.parser.javacc.grammar;
public class JavaCCGrammar{
    public static void main(String[] args) throws Exception  {
       JavaCCGrammar grammar = new JavaCCGrammar(System.in);
       grammar.function1();
    }
}
PARSER_END(JavaCCGrammar)

// 忽律的字符
SKIP:{
    " "
    | "\t"
    | "\n"
    | "\r"
    | "\r\n"
}

// token关键字
TOKEN:{
      <SELECT :"select">
    | <UPDATE :"update">
    | <DELETE :"delete">
    | <COMMA:",">
    | <FORM:"form">
    | <AS:"as">
    | <WHERE:"where">
    | <EQUAL:"=">
    | <OPEN_PAR: "(">
    | <CLOSE_PAR: ")">
}

// 定义java代码块
void javaCodeDemo():
{}
{
    {
        int i = 0;
        System.out.println(i);
    }
}

// 函数
void function1():
{
    int i=0;    // 定义局部变量
}
{
    {return;}
}

// 返回值
double function2():
{
    int i=0;
}
{
    {return i;}  // 带返回值
}

// 函数调用
double function3():
{
    double i;
}
{
   {i = function2();}
   {return i;}
}

// token复制
void tokenAssignment() :
{
    Token st;
    Token dt;
}
{
     st = <SELECT>
     dt = <DELETE>
}

// if语句
void ifExpr():
{}
{
    [
        <SELECT>
        {
            System.out.println("if select");
        }
    ]
    (<SELECT>)?   // 循环,出现一次
}

// if - else
void ifElseExpr():
{}
{
    (
        <SELECT> {System.out.println("if else select");}
        |
        <UPDATE>  {System.out.println("if else update");}
        |
        <DELETE>  {System.out.println("if else delete");}
        |
        {
           System.out.println("other");
        }
    )
}

// while 0~n
void while1Expr():
{}
{
    (<SELECT>)*
}

// while 1~n
void while2Expr():
{}
{
    (<SELECT>)+
}

// Java代码
JAVACODE void print(Token t){
    System.out.println(t);
}