luence语法解析器 javacc详解

JavaCC是一个词法分析器和语法分析器的生成器。

第一个实例——正整数相加

下面我们来看第一个例子,即能够解析正整数相加的表达式,例如99+42+0+15。

(1) 生成一个adder.jj文件

此文件中写入的即生成词法分析器和语法分析器的规则。

(2) 设定选项,并声明类

 

/* adder.jj Adding up numbers */

options {

  STATIC = false ;

}

PARSER_BEGIN(Adder)

class Adder {

  static void main( String[] args ) throws ParseException, TokenMgrError {

    Adder parser = new Adder( System.in ) ;

    parser.Start() ;

  }

}

PARSER_END(Adder)

STATIC选项默认是true,设为false,使得生成的函数不是static的。

PARSER_BEGIN和PARSER_END之间的java代码部分,此部分不需要通过JavaCC根据规则生成java代码,而是直接拷贝到生成的java代码中的。

(3) 声明一个词法分析器

SKIP : { " " }

SKIP : { "\n" | "\r" | "\r\n" }

TOKEN : { < PLUS : "+" > }

TOKEN : { < NUMBER : (["0"-"9"])+ > }

第一二行表示空格和回车换行是不会传给语法分析器的。

第三行声明了一个Token,名称为PLUS,符号为“+”。

第四行声明了一个Token,名称为NUMBER,符号位一个或多个0-9的数的组合。

如果词法分析器分析的表达式如下:

  • “123 + 456\n”,则分析为NUMBER, PLUS, NUMBER, EOF
  • “123 - 456\n”,则报TokenMgrError,因为“-”不是一个有效的Token.
  • “123 ++ 456\n”,则分析为NUMBER, PLUS, PLUS, NUMBER, EOF,词法分析正确,后面的语法分析将会错误。

(4) 声明一个语法分析器

void Start() :

{}

{

  <NUMBER>

  (

    <PLUS>

    <NUMBER>

  )*

  <EOF>

}

语法分析器使用BNF表达式。

上述声明将生成start函数,称为Adder类的一个成员函数

语法分析器要求输入的语句必须以NUMBER开始,以EOF结尾,中间是零到多个PLUS和NUMBER的组合。

(5) 用javacc编译adder.jj来生成语法分析器和词法分析器

/**
 * JavaCC file
 */
options{
  STATIC = false;
}

PARSER_BEGIN(AddParser)
package add;
public class AddParser{
  public static void main(String args[])throws ParseException{
    AddParser parser = new AddParser(System.in);
    try {
      switch (parser.start()){
        case 0:System.out.println("ok");
        break ;
        case 1:System.out.println("Goodbye.");
        break ;
        default :break ;
      }
    }
    catch (Exception e){
      System.out.println("NOK.");
      System.out.println(e.getMessage());
    }
    catch (Error e){
      System.out.println("Oops.");
      System.out.println(e.getMessage());
    }
  }
}
PARSER_END(AddParser)
SKIP:{
  " "
  | "\n"
  | "\r"
  | "\t"
}
TOKEN:{
  <PLUS:"+">
}
TOKEN:{
  <NUMBER:(["0"-"9"])+>
}
int start():{}{
  add()";"{
    return 0;
  }
  | ""{
    return 1;
  }
}
void add():{}{
  <NUMBER>(<PLUS><NUMBER>)*
}

用JavaCC编译adder.jj生成如下文件:

  • Adder.java:语法分析器。其中的main函数是完全从adder.jj中拷贝的,而start函数是被javacc由adder.jj描述的规则生成的。
  • AdderConstants.java:一些常量,如PLUS, NUMBER, EOF等。
  • AdderTokenManager.java:词法分析器。
  • ParseException.java:用于在语法分析错误的时候抛出。
  • SimpleCharStream.java:用于将一系列字符串传入词法分析器。
  • Token.java:代表词法分析后的一个个Token。Token对象有一个整型域kind,来表示此Token的类型(PLUS, NUMBER, EOF),有一个String类型的域image,来表示此Token的值。
  • TokenMgrError.java:用于在词法分析错误的时候抛出。
/**
 * JavaCC file
 */
options{
  STATIC = false;
}
PARSER_BEGIN(AddParser)
package add;
public class AddParser{
  public static void main(String args[])throws ParseException{
    AddParser parser = new AddParser(System.in);
    try {
      System.out.println(parser.add());
    }
    catch (Exception e){
      System.out.println("NOK.");
      System.out.println(e.getMessage());
    }
    catch (Error e){
      System.out.println("Oops.");
      System.out.println(e.getMessage());
    }
  }
}
PARSER_END(AddParser)
SKIP:{
  " "
}
TOKEN:{
  <PLUS:"+">
}
TOKEN:{
  <EOL:"\n"
  | "\r"
  | "\r\n">
}
TOKEN:{
  <NUMBER:(["0"-"9"])+>
}
int add():{
  int a; //函数的参数值
  int b;
}
{
  a = getNumberValue()//必须用a
  (
  <PLUS>
  b = getNumberValue()
  {
    a+=b;
  }
  )*
  <EOL> //此处输入EOL才会执行return,如果没有EOL则一直不会执行return结果
  {
    return a;
  }
}
/**
*获取输入数字的值
*/
int getNumberValue():{
  Token t;
}
{
  t = <NUMBER>{
    return Integer.parseInt(t.image); //t.image获取string值
  }
}

 

posted @ 2015-09-23 17:13  程序猿进化之路  阅读(816)  评论(0)    收藏  举报