java程序中空一阁_如何使用JFlex、JavaCUP(详细代码模版) by 踏雪赤兔

撰写本文的目的:

给出使用JFlex、JavaCUP来为一个计算器建立分析器的示例的完整代码,使读者能充分领会JavaCUP的使用方法。虽然本文仅仅给出了计算器的代码,但只要你会写你的语言的翻译模式,则只要照抄这个模版,并改改相应动作就可以了。

引用到的资料:

《CUP User's Manual》,作者:Scott E. Hudson地址为李老师那里下载下来的JavaCUP-11a.rar\CUP-develop.tar.gz\develop\manual.html,有详细的英文说明和示例代码,但有很多错。本文中简称为《手册》。

《使用CUP进行语法分析》,摘自Apollo的博客,貎似是转载的(竟然不注明[转]和真实出处?!,BS之~),作者待考。有详尽的解释,但缺乏示例代码。本文中简称为《语法分析》。

详细步骤:

1、准备工作。

JavaCUP和JFlex一样,压缩包里边有许多的文件夹和文件,我不知道正统的做法是否要求使用javaCUP也像Jflex一样要设置一堆path啊、classpath啊、jflex_home之类的环境变量,但如果你像我一样只打算用它几次,你只要执行下述的两个简单步骤就可以了,它并不需要你设置任何的环境变量(以下假设你的工作目录是work\):

1)   将JavaCUP压缩包里的java-cup-11a.jar解压到work\下。

2)   将JavaCUP压缩包里的CUP-develop.tar.gz\develop\src下的java_cup文件夹整个解压到work\下。

现在你可以使用JavaCUP了。

2、为这个计算器写一个词法分析器。或者用JFlex生成一个词法分析器

两种方法都可以生成词法分析器,其中,直接写分析器的代码如下:

baca3885954afa7bba9fb67d5db26490.gif

353c1fa9cd42287d30310af820b5430d.gifscanner.java17c135a2763225eb253f4ff92e88a664.png//Simple Example Scanner Class 

17c135a2763225eb253f4ff92e88a664.png//scanner.java17c135a2763225eb253f4ff92e88a664.pngimportjava_cup.runtime.*;

17c135a2763225eb253f4ff92e88a664.pngimportjava.io.*;

17c135a2763225eb253f4ff92e88a664.png//import sym;17c135a2763225eb253f4ff92e88a664.png353c1fa9cd42287d30310af820b5430d.gif

baca3885954afa7bba9fb67d5db26490.gifpublicclassscannerimplementsjava_cup.runtime.Scannere2a6613082b46951a97093f596d56b92.gif{

0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gif/**//*single lookahead character*/258e3e26538340eb1c68b7657f2a2de8.gifprotectedstaticintnext_char;

258e3e26538340eb1c68b7657f2a2de8.gif//since cup v11 we use SymbolFactories rather than Symbols258e3e26538340eb1c68b7657f2a2de8.gifprivateSymbolFactory sf=newDefaultSymbolFactory();

258e3e26538340eb1c68b7657f2a2de8.gifprivatestaticFileReader fileReader;

0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gifpublicscanner(FileReader fr)e2a6613082b46951a97093f596d56b92.gif{

258e3e26538340eb1c68b7657f2a2de8.gifthis.fileReader=fr;

6b1eff4d9cb8055b7f54d7b6d5b73a91.gif  }0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gif/**//*advance input by one character*/258e3e26538340eb1c68b7657f2a2de8.gifprotectedstaticvoidadvance()

258e3e26538340eb1c68b7657f2a2de8.gifthrowsjava.io.IOException

0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gife2a6613082b46951a97093f596d56b92.gif{ next_char=fileReader.read(); }258e3e26538340eb1c68b7657f2a2de8.gif

0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gif/**//*initialize the scanner*/258e3e26538340eb1c68b7657f2a2de8.gifpublicstaticvoidinit()

258e3e26538340eb1c68b7657f2a2de8.gifthrowsjava.io.IOException

0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gife2a6613082b46951a97093f596d56b92.gif{ advance(); }258e3e26538340eb1c68b7657f2a2de8.gif

0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gif/**//*recognize and return the next complete token*/258e3e26538340eb1c68b7657f2a2de8.gifpublicSymbol next_token()

258e3e26538340eb1c68b7657f2a2de8.gifthrowsjava.io.IOException

0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gife2a6613082b46951a97093f596d56b92.gif{

258e3e26538340eb1c68b7657f2a2de8.giffor(;;)

258e3e26538340eb1c68b7657f2a2de8.gifswitch(next_char)

0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gife2a6613082b46951a97093f596d56b92.gif{

258e3e26538340eb1c68b7657f2a2de8.gifcase'0':case'1':case'2':case'3':case'4': 

258e3e26538340eb1c68b7657f2a2de8.gifcase'5':case'6':case'7':case'8':case'9': 

0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gif/**//*parse a decimal integer*/258e3e26538340eb1c68b7657f2a2de8.gifinti_val=0;

0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gifdoe2a6613082b46951a97093f596d56b92.gif{

258e3e26538340eb1c68b7657f2a2de8.gif            i_val=i_val*10+(next_char-'0');

258e3e26538340eb1c68b7657f2a2de8.gif            advance();

6b1eff4d9cb8055b7f54d7b6d5b73a91.gif          }while(next_char>='0'&&next_char<='9');

258e3e26538340eb1c68b7657f2a2de8.gifreturnsf.newSymbol("NUMBER",sym.NUMBER,newInteger(i_val));

258e3e26538340eb1c68b7657f2a2de8.gif

258e3e26538340eb1c68b7657f2a2de8.gifcase';': advance();returnsf.newSymbol("SEMI",sym.SEMI);

258e3e26538340eb1c68b7657f2a2de8.gifcase'+': advance();returnsf.newSymbol("PLUS",sym.PLUS);

258e3e26538340eb1c68b7657f2a2de8.gifcase'-': advance();returnsf.newSymbol("MINUS",sym.MINUS);

258e3e26538340eb1c68b7657f2a2de8.gifcase'*': advance();returnsf.newSymbol("TIMES",sym.TIMES);

258e3e26538340eb1c68b7657f2a2de8.gifcase'/': advance();returnsf.newSymbol("DIVIDE",sym.DIVIDE);

258e3e26538340eb1c68b7657f2a2de8.gifcase'%': advance();returnsf.newSymbol("MOD",sym.MOD);

258e3e26538340eb1c68b7657f2a2de8.gifcase'(': advance();returnsf.newSymbol("LPAREN",sym.LPAREN);

258e3e26538340eb1c68b7657f2a2de8.gifcase')': advance();returnsf.newSymbol("RPAREN",sym.RPAREN);

258e3e26538340eb1c68b7657f2a2de8.gif

258e3e26538340eb1c68b7657f2a2de8.gifcase-1:returnsf.newSymbol("EOF",sym.EOF);

258e3e26538340eb1c68b7657f2a2de8.gif

258e3e26538340eb1c68b7657f2a2de8.gifdefault: 

0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gif/**//*in this simple scanner we just ignore everything else*/258e3e26538340eb1c68b7657f2a2de8.gif          advance();

258e3e26538340eb1c68b7657f2a2de8.gifbreak;

6b1eff4d9cb8055b7f54d7b6d5b73a91.gif      }6b1eff4d9cb8055b7f54d7b6d5b73a91.gif    }6bfb8366602b2effefcf17e2749f1731.gif};

以上代码来自《手册》的附录B,但有以下修改:

baca3885954afa7bba9fb67d5db26490.gif

353c1fa9cd42287d30310af820b5430d.gif修改概要17c135a2763225eb253f4ff92e88a664.png注释掉第4行的import sym;

17c135a2763225eb253f4ff92e88a664.png   原文第6行改成public class CalcLex implements java_cup.runtime.Scanner {

17c135a2763225eb253f4ff92e88a664.png因为语法分析器要求其词法分析器必须派生自Scanner类。

17c135a2763225eb253f4ff92e88a664.png   删去原文第23行的static。因为其超类Scanner的next_token()方法不是静态的。

17c135a2763225eb253f4ff92e88a664.png   删掉原文第48行其中一个return(无聊的语法错误!)

17c135a2763225eb253f4ff92e88a664.png   新增加了一个构造函数scanner(FileReader)和静态属性FileReader fr,(当然要import System.io.*;)它们之后将会用到。

17c135a2763225eb253f4ff92e88a664.png   修改了advance()的定义

这时scanner.java还未能通过编译的,因为其需要引用到的sym类还未生成,不用管它,继续下一步。

如果用JFlex来生成一个词法分析器,则要先写一个scanner.flex,代码如下:

baca3885954afa7bba9fb67d5db26490.gif

353c1fa9cd42287d30310af820b5430d.gifscanner.flex17c135a2763225eb253f4ff92e88a664.png//scanner.flex

17c135a2763225eb253f4ff92e88a664.png//用户代码段17c135a2763225eb253f4ff92e88a664.pngimportjava_cup.runtime.*;

17c135a2763225eb253f4ff92e88a664.pngimportjava.io.*;

17c135a2763225eb253f4ff92e88a664.png

17c135a2763225eb253f4ff92e88a664.png%%17c135a2763225eb253f4ff92e88a664.png//参数设置和声明段17c135a2763225eb253f4ff92e88a664.png%classscanner 

17c135a2763225eb253f4ff92e88a664.png%line 

17c135a2763225eb253f4ff92e88a664.png%column 

17c135a2763225eb253f4ff92e88a664.png%cup

17c135a2763225eb253f4ff92e88a664.png%unicode

17c135a2763225eb253f4ff92e88a664.png

353c1fa9cd42287d30310af820b5430d.gif

baca3885954afa7bba9fb67d5db26490.gif%e2a6613082b46951a97093f596d56b92.gif{

0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gifpublicstaticvoidinit()e2a6613082b46951a97093f596d56b92.gif{}/**//*Just为了兼容手写版*/0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gifprivateSymbol symbol(inttype)e2a6613082b46951a97093f596d56b92.gif{

258e3e26538340eb1c68b7657f2a2de8.gifreturnnewSymbol(type,yyline,yycolumn); 

6b1eff4d9cb8055b7f54d7b6d5b73a91.gif    }0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gifprivateSymbol symbol(inttype,Object value)e2a6613082b46951a97093f596d56b92.gif{

258e3e26538340eb1c68b7657f2a2de8.gifreturnnewSymbol(type,yyline,yycolumn,value);

6b1eff4d9cb8055b7f54d7b6d5b73a91.gif    }6bfb8366602b2effefcf17e2749f1731.gif%}17c135a2763225eb253f4ff92e88a664.pngdigit=[0-9]

353c1fa9cd42287d30310af820b5430d.gif

baca3885954afa7bba9fb67d5db26490.gifnumber=e2a6613082b46951a97093f596d56b92.gif{digit}+17c135a2763225eb253f4ff92e88a664.pngLineTerminator=\r|\n|\r\n

353c1fa9cd42287d30310af820b5430d.gif

baca3885954afa7bba9fb67d5db26490.gifWhiteSpace=e2a6613082b46951a97093f596d56b92.gif{LineTerminator}|[ \t\f]

17c135a2763225eb253f4ff92e88a664.png%%17c135a2763225eb253f4ff92e88a664.png//词法规则段353c1fa9cd42287d30310af820b5430d.gif

baca3885954afa7bba9fb67d5db26490.gife2a6613082b46951a97093f596d56b92.gif{

0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gif";"e2a6613082b46951a97093f596d56b92.gif{returnsymbol(sym.SEMI);/**//*case ";"*/}0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gif"+"e2a6613082b46951a97093f596d56b92.gif{returnsymbol(sym.PLUS);/**//*case "+"*/}0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gif"-"e2a6613082b46951a97093f596d56b92.gif{returnsymbol(sym.MINUS);/**//*case "-"*/}0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gif"*"e2a6613082b46951a97093f596d56b92.gif{returnsymbol(sym.TIMES);/**//*case "*"*/}0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gif"/"e2a6613082b46951a97093f596d56b92.gif{returnsymbol(sym.DIVIDE);/**//*case "/"*/}0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gif"%"e2a6613082b46951a97093f596d56b92.gif{returnsymbol(sym.MOD);/**//*case "%"*/}0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gif"("e2a6613082b46951a97093f596d56b92.gif{returnsymbol(sym.LPAREN);/**//*case "("*/}0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gif")"e2a6613082b46951a97093f596d56b92.gif{returnsymbol(sym.RPAREN);/**//*case ")"*/}0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gife2a6613082b46951a97093f596d56b92.gif{number}e2a6613082b46951a97093f596d56b92.gif{returnsymbol(sym.NUMBER,newInteger(yytext()));/**//*case {number}*/}0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gife2a6613082b46951a97093f596d56b92.gif{WhiteSpace}e2a6613082b46951a97093f596d56b92.gif{/**//*case {WhiteSpace}:  do nothing*/}258e3e26538340eb1c68b7657f2a2de8.gif    

6bfb8366602b2effefcf17e2749f1731.gif}353c1fa9cd42287d30310af820b5430d.gif

baca3885954afa7bba9fb67d5db26490.gif.e2a6613082b46951a97093f596d56b92.gif

258e3e26538340eb1c68b7657f2a2de8.gif    System.out.println("Error:"+yytext()+"is illegal!"); 

6bfb8366602b2effefcf17e2749f1731.gif}

3、使用javaCUP生成一个语法分析器。

在这一步里,你需要写一个parser.cup文件,代码如下:

baca3885954afa7bba9fb67d5db26490.gif

353c1fa9cd42287d30310af820b5430d.gifparser.cup17c135a2763225eb253f4ff92e88a664.png//CUP specification for a simple expression evaluator (w/ actions)

17c135a2763225eb253f4ff92e88a664.png//parser.cup17c135a2763225eb253f4ff92e88a664.pngimportjava_cup.runtime.*;

17c135a2763225eb253f4ff92e88a664.png

353c1fa9cd42287d30310af820b5430d.gif

baca3885954afa7bba9fb67d5db26490.gif/**//*Preliminaries to set up and use the scanner.*/353c1fa9cd42287d30310af820b5430d.gif

baca3885954afa7bba9fb67d5db26490.gifinit withe2a6613082b46951a97093f596d56b92.gif{: scanner.init();              :};

353c1fa9cd42287d30310af820b5430d.gif

baca3885954afa7bba9fb67d5db26490.gifscan withe2a6613082b46951a97093f596d56b92.gif{:returngetScanner().next_token(); :};

17c135a2763225eb253f4ff92e88a664.png

353c1fa9cd42287d30310af820b5430d.gif

baca3885954afa7bba9fb67d5db26490.gif/**//*Terminals (tokens returned by the scanner).*/17c135a2763225eb253f4ff92e88a664.pngterminal           SEMI, PLUS, MINUS, TIMES, DIVIDE, MOD;

17c135a2763225eb253f4ff92e88a664.pngterminal           UMINUS, LPAREN, RPAREN;

17c135a2763225eb253f4ff92e88a664.pngterminal Integer   NUMBER;

17c135a2763225eb253f4ff92e88a664.png

353c1fa9cd42287d30310af820b5430d.gif

baca3885954afa7bba9fb67d5db26490.gif/**//*Non-terminals*/17c135a2763225eb253f4ff92e88a664.pngnon terminal            expr_list, expr_part;

17c135a2763225eb253f4ff92e88a664.pngnon terminal Integer    expr;

17c135a2763225eb253f4ff92e88a664.png

353c1fa9cd42287d30310af820b5430d.gif

baca3885954afa7bba9fb67d5db26490.gif/**//*Precedences*/17c135a2763225eb253f4ff92e88a664.pngprecedence left PLUS, MINUS;

17c135a2763225eb253f4ff92e88a664.pngprecedence left TIMES, DIVIDE, MOD;

17c135a2763225eb253f4ff92e88a664.pngprecedence left UMINUS;

17c135a2763225eb253f4ff92e88a664.png

353c1fa9cd42287d30310af820b5430d.gif

baca3885954afa7bba9fb67d5db26490.gif/**//*The grammar*/17c135a2763225eb253f4ff92e88a664.pngexpr_list ::=expr_list expr_part 

17c135a2763225eb253f4ff92e88a664.png|17c135a2763225eb253f4ff92e88a664.png              expr_part;

17c135a2763225eb253f4ff92e88a664.png

17c135a2763225eb253f4ff92e88a664.pngexpr_part ::=expr:e 

353c1fa9cd42287d30310af820b5430d.gif

baca3885954afa7bba9fb67d5db26490.gife2a6613082b46951a97093f596d56b92.gif{: System.out.println("="+e); :}17c135a2763225eb253f4ff92e88a664.png              SEMI              

17c135a2763225eb253f4ff92e88a664.png          ;

17c135a2763225eb253f4ff92e88a664.png

17c135a2763225eb253f4ff92e88a664.pngexpr      ::=expr:e1 PLUS expr:e2    

353c1fa9cd42287d30310af820b5430d.gif

baca3885954afa7bba9fb67d5db26490.gife2a6613082b46951a97093f596d56b92.gif{: RESULT=newInteger(e1.intValue()+e2.intValue()); :}17c135a2763225eb253f4ff92e88a664.png|17c135a2763225eb253f4ff92e88a664.png              expr:e1 MINUS expr:e2    

353c1fa9cd42287d30310af820b5430d.gif

baca3885954afa7bba9fb67d5db26490.gife2a6613082b46951a97093f596d56b92.gif{: RESULT=newInteger(e1.intValue()-e2.intValue()); :}17c135a2763225eb253f4ff92e88a664.png|17c135a2763225eb253f4ff92e88a664.png              expr:e1 TIMES expr:e2 

353c1fa9cd42287d30310af820b5430d.gif

baca3885954afa7bba9fb67d5db26490.gife2a6613082b46951a97093f596d56b92.gif{: RESULT=newInteger(e1.intValue()*e2.intValue()); :}17c135a2763225eb253f4ff92e88a664.png|17c135a2763225eb253f4ff92e88a664.png              expr:e1 DIVIDE expr:e2 

353c1fa9cd42287d30310af820b5430d.gif

baca3885954afa7bba9fb67d5db26490.gife2a6613082b46951a97093f596d56b92.gif{: RESULT=newInteger(e1.intValue()/e2.intValue()); :}17c135a2763225eb253f4ff92e88a664.png|17c135a2763225eb253f4ff92e88a664.png              expr:e1 MOD expr:e2 

353c1fa9cd42287d30310af820b5430d.gif

baca3885954afa7bba9fb67d5db26490.gife2a6613082b46951a97093f596d56b92.gif{: RESULT=newInteger(e1.intValue()%e2.intValue()); :}17c135a2763225eb253f4ff92e88a664.png|17c135a2763225eb253f4ff92e88a664.png              NUMBER:n                 

353c1fa9cd42287d30310af820b5430d.gif

baca3885954afa7bba9fb67d5db26490.gife2a6613082b46951a97093f596d56b92.gif{: RESULT=n; :}17c135a2763225eb253f4ff92e88a664.png|17c135a2763225eb253f4ff92e88a664.png              MINUS expr:e             

353c1fa9cd42287d30310af820b5430d.gif

baca3885954afa7bba9fb67d5db26490.gife2a6613082b46951a97093f596d56b92.gif{: RESULT=newInteger(0-e.intValue()); :}17c135a2763225eb253f4ff92e88a664.png%prec UMINUS

17c135a2763225eb253f4ff92e88a664.png|17c135a2763225eb253f4ff92e88a664.png              LPAREN expr:e RPAREN     

353c1fa9cd42287d30310af820b5430d.gif

baca3885954afa7bba9fb67d5db26490.gife2a6613082b46951a97093f596d56b92.gif{: RESULT=e; :}17c135a2763225eb253f4ff92e88a664.png          ;

17c135a2763225eb253f4ff92e88a664.png

17c135a2763225eb253f4ff92e88a664.png

现在你需要用JavaCUP来分析你的cup文件,请在命令行下输入

17c135a2763225eb253f4ff92e88a664.pngjava-jar java-cup-11a.jarparser.cup

如果屏幕出现以下输出,就说明你已经成功了,这时javaCUP自动生成了parser.java和sym.java两个文件。现在你的scanner.java也可以成功通过编译了。

17c135a2763225eb253f4ff92e88a664.png-------CUP v0.11a beta20060608Parser Generation Summary-------17c135a2763225eb253f4ff92e88a664.png0errors and0warnings

17c135a2763225eb253f4ff92e88a664.png12terminals,4non-terminals, and13productions declared,

17c135a2763225eb253f4ff92e88a664.png  producing24unique parse states.

17c135a2763225eb253f4ff92e88a664.png0terminals declared but not used.

17c135a2763225eb253f4ff92e88a664.png0non-terminals declared but not used.

17c135a2763225eb253f4ff92e88a664.png0productions never reduced.

17c135a2763225eb253f4ff92e88a664.png0conflicts detected (0expected).

17c135a2763225eb253f4ff92e88a664.png  Code written to"parser.java", and"sym.java".

17c135a2763225eb253f4ff92e88a664.png----------------------------------------------------(v0.11a beta20060608)

4、编写主函数。

现在你的计算器的语法分析器已经做好,你还要做的就是编写一个主函数来调用这个分析器。请在work\下新建一个Calc.java,然后输入以下代码:

baca3885954afa7bba9fb67d5db26490.gif

353c1fa9cd42287d30310af820b5430d.gifCalc.java17c135a2763225eb253f4ff92e88a664.png//Calc.java17c135a2763225eb253f4ff92e88a664.pngimportjava.io.*;

353c1fa9cd42287d30310af820b5430d.gif

baca3885954afa7bba9fb67d5db26490.gifpublicclassCalce2a6613082b46951a97093f596d56b92.gif{

0263e0c3f9f3faecf5b4177968c5d64c.gif

163485b2ad506de1bcb3e3ff8e57d8b2.gifpublicstaticvoidmain(String argv[])throwsExceptione2a6613082b46951a97093f596d56b92.gif{

258e3e26538340eb1c68b7657f2a2de8.gif        parser p=newparser(newscanner(newFileReader(argv[0])));

258e3e26538340eb1c68b7657f2a2de8.gif        p.parse();

6b1eff4d9cb8055b7f54d7b6d5b73a91.gif    }6bfb8366602b2effefcf17e2749f1731.gif}

5、测试用例。

你还需要设计一些测试例子来检查你是否已经成功完成了这个计算器。在work\下新建一个test.txt,输入一些数值表达式,例如:

baca3885954afa7bba9fb67d5db26490.gif

353c1fa9cd42287d30310af820b5430d.giftest.txt17c135a2763225eb253f4ff92e88a664.png2*4+6;

17c135a2763225eb253f4ff92e88a664.png7*(5+3);

17c135a2763225eb253f4ff92e88a664.png(5-3)/(2*4+3);

然后在命令行输入:

17c135a2763225eb253f4ff92e88a664.pngjava Calc test.txt

如果屏幕输出:

17c135a2763225eb253f4ff92e88a664.png=1417c135a2763225eb253f4ff92e88a664.png=5617c135a2763225eb253f4ff92e88a664.png=0

这就表示你已经大功告成了

ee62c545c495cce5473613c3155e4c38.png~~

补充两点:

自我贴出这篇博文后,有很多朋友跟我说在输入java Calc test.txt时出现以下输出:

17c135a2763225eb253f4ff92e88a664.pngException in thread "main" java.lang.NoClassDefFoundError: calc

甚至

17c135a2763225eb253f4ff92e88a664.pngException in thread "main" java.lang.NoSuchMethodError: calc

但此前所有的代码生成、编译工作都是成功的。

经过我的分析,这是因为.java文件和.class文件版本不匹配造成的。通常是你用jflex或javaCUP生成了新的.java文件,却没有对它重新编译,因此.class里边的是旧的.java文件的内容,因此在运行的时候就会产生错误。解决方法是在命令行输入del *.class并重新编译,这时java会重新生成所有.class文件。

觉得每次都要手工输入命令去生成代码、编译、运行很慢很麻烦?呵呵~~像我这么懒的人当然不会这么笨啦

8efd5c89e3366ab6689cd05f5ed2aafe.gif~~你可以写一个bat文件去自动帮你完成所有的工作,自然也可以解决上面那个“.NoClassDefFoundError”问题。不懂bat?去google一下“批处理文件”吧。这里再教你一个技巧,就是如何在bat中使用分支:

baca3885954afa7bba9fb67d5db26490.gif

353c1fa9cd42287d30310af820b5430d.gifrun.bat17c135a2763225eb253f4ff92e88a664.pngcall jflex scanner.flex

17c135a2763225eb253f4ff92e88a664.pngif errorlevel 1 goto EXIT

17c135a2763225eb253f4ff92e88a664.pngjava -jar cup.jar parser.cup

17c135a2763225eb253f4ff92e88a664.pngif errorlevel 1 goto EXIT

17c135a2763225eb253f4ff92e88a664.pngjavac scanner.java

17c135a2763225eb253f4ff92e88a664.pngif errorlevel 1 goto EXIT

17c135a2763225eb253f4ff92e88a664.pngjavac parser.java

17c135a2763225eb253f4ff92e88a664.pngif errorlevel 1 goto EXIT

17c135a2763225eb253f4ff92e88a664.pngjavac Calc.java

17c135a2763225eb253f4ff92e88a664.pngif errorlevel 1 goto EXIT

17c135a2763225eb253f4ff92e88a664.pngjava Calc test.txt

17c135a2763225eb253f4ff92e88a664.png:EXIT

17c135a2763225eb253f4ff92e88a664.png

这样你只要轻轻的输入run,然后回车,就可以自动调用Jflex、JavaCUP生成代码、编译、运行了,并且当其中一步出错时,其后所有的步骤都不会被执行。是不是很好玩?

6013f08ac08d84631fe46e22891b1709.gif

posted on 2007-05-09 15:35 踏雪赤兔 阅读(9171) 评论(24)  编辑 收藏 引用 所属分类: 玩转编程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值