打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
javacc运行这个例子

1.2.5         运行这个例子

再看看Adder类的main方法:

static void main( String[] args )

throws ParseException, TokenMgrError {

Adder parser = new Adder( System.in ) ;

parser.Start() ;

}

首先请注意main方法可能会抛出Throwable类的两个子类,这样写不是好的风格,我们确实应该捕捉这些异常,但是,这样做可以让第一个例子变得简短。

第一条语句创建了一个新的对象parser,其构造方法是自动生成的,带一个参数InputStream,第一个参数还可以是Reader。构造方法会生成类SimpleCharacterStream的一个实例,还会生成词法分析类AdderTokenManager的一个对象。这样,词法分析器通过SimpleCharacterStream对象从System.in读取到字符串,然后再传递到语法分析器。

第二条语句调用Start方法。对每个BNF产生式,JavaCC都会在解析类中生成相应的方法。这个方法试图找出与输入描述相匹配的输入序列。在这个例子中,语法分析器调用Start方法来找出符合输入描述的一系列标记符,该输入描述如下:

<NUMBER> (<PLUS> <NUMBER>)* <EOF>

准备好合适的输入文件后,我们就可以运行这个程序了,执行如下命令:

D:\home\JavaCC-Book\adder>java Adder <input.txt

程序执行后,会出现以下三种情况之一:

1 发现词法错误。在本例中,仅当输入中出现未预料的字符时才会出现该错误。输入为以下字符串可以产生一个词法错误:

123 - 456\n”

程序会抛出一个TokenMgrError异常,该异常类的成员变量message如下:Exception in thread ”main” TokenMgrError: Lexical error at line 1,

column 5.Encountered: ”-” (45), after : ””

2 发现语法错误。当输入不符合Start的规范时会出现该错误。当输入为“123 ++ 456\n” 123 456\n”或者“\n”时都会抛出一个ParseException异常,对第一个,该异常的message变量为:

Exception inthread ”main” ParseException: Encountered ”+” at

line 1, column6.

Was expecting:

<NUMBER>...

 

3 输入字符串符合Start的规范。这种情况下,程序正常执行,没有异常抛出。

目前这个语法分析器仅仅能检验输入字串是否合法,在接下来的部分,我们会作些修改使它更有用处。

 

1.2.6        生成的代码

为了能理解JavaCC生成语法分析器的工作机理,看看生成的代码是有益的。

final public void Start() throws ParseException {

ij_consume_token(NUMBER);

label 1:

while (true) {

ij_consume_token (PLUS);

ij_consume_token (NUMBER);

switch ((jj_ntk == -1) ? jj_ntk () : jj_ntk) {

case PLUS:;

break;

default:

jj_la1[0] = jj_gen;

break label 1;

}

}

jj_consume_token(0);

}

           jj_consume_token方法使用Token类型作为其传入参数,试图从词法分析器中得到该类型的标记符;如果得不到,会抛出异常。该表达式

(jj_ntk == -1) ? jj_ntk() : jj_ntk

        计算下一个未读的标记符。最后一行会尝试获得0类型的标记符,在JavaCC中,0类型代表EOF标记符。

1.2.7         语法分析器的增强

           JavaCC按照BNF产生式生成的方法Start只能简单的检查输入是否符合规范,我们可以通过在生成的方法中加入Java代码来增强BNF产生式。JavaCC提供了一个框架,需要我们来填充。

        我们对规范文件作些小的改动得到adder1.jj。在BNF产生式的类Start中添加一些声明和java代码。添加或者修改的部分用粗体表示:

int Start() throws NumberFormatException :

{

Token t ;

int i ;

int value ;

}{

t = <NUMBER>

{ i = Integer.parseInt( t.image ) ; }

{ value = i ; } (

<PLUS>

t = <NUMBER>

{ i = Integer.parseInt( t.image ) ; }

{ value += i ; }

)*

<EOF>

{ return value ; }

}

       首先,BNF产生式所生成的函数代码的返回值,从void变成了int,我们声明该方法可能抛出NumberFormatException异常。我们声明了三个变量,Token类型的t,类型Token是一个由JavaCC生成的代表标记符的类;Token类的image变量,代表解析到的字符串。当一个标记符符合BNF产生式时,我们可以记录这个Token对象并用如下的行来引用它:

t = <NUMBER>

       在BNF产生式的花括号内,我们可以添加任何所需的Java代码,这些代码会一字不落的复制到生成的方法中。

       由于生成的方法Start有了返回值,我们必须修改main方法,如下

static void main( String[] args )

throws ParseException, TokenMgrError, NumberFormatException {

Adder parser = new Adder( System.in ) ;

int val = parser.Start() ;

System.out.println(val);

}

       本例还可以有一个小的改进,这两行

t = <NUMBER>

{ i = Integer.parseInt( t.image ) ; }

       出现了两次,虽然在本例中不会有什么明显的差异,毕竟只是两行代码,但这类重复的代码可能导致以后维护的困难。所以我们把这两行重构到一个BNF产生式中,称为Primary。同上,最新的修改用粗体标记。

int Start() throws NumberFormatException :

{

int i ;

int value ;

}{

value = Primary()

(

<PLUS>

i = Primary()

{ value += i ; }

)*

<EOF>

{ return value ; }

}

int Primary() throws NumberFormatException :

{

Token t ;

}{

t=<NUMBER>

{ return Integer.parseInt( t.image ) ; }

}

    来看看生成的方法,展示了JavaCC是如何把Java声明和表达式集成到生成的方法的框架中的。

final public int Start() throws ParseException, NumberFormatException {

int i ;

int value ;

value = Primary();

label 1:

while (true) {

switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {

case PLUS:;

break;

default:

jj_la1[0] = jj_gen;

break label 1;

}

jj_consume_token(PLUS);

i = Primary();

value += i ;

}

jj_consume_token(0);

{if (true) return value ;}

throw new Error(”Missing return statement in function”);

}

final public int Primary() throws ParseException, NumberFormatException {

Token t ;

t = jj_consume_token(NUMBER);

{if (true) return Integer.parseInt( t.image ) ;}

throw new Error(”Missing return statement in function”);

}

      在后面还可以看到,可以在BNF产生式中传参数。

http://laitysoft.blog.sohu.com/40344497.html

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
把字符串表达的颜色值转换成java.awt.Color 实例
Java 十进制和十六制之间的转化(负数的处理)
JDK源码学习阅读
身份证号码验证(15位和18位且最后一位是X时不区分大小写)
JR 精品文章 - 使用JavaCC做语法分析[转]
传统武术健身精华
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服