如何使用JFlex、JavaCUP(详细代码模版)

openkk 13年前
     编译原理的实验要求我们用JFlex和JavaCUP来对语言进行分析处理,JavaCUP有一个User's Manual教你怎样做,上面还有一个简单的计算器作为例子,但一试之下,却发现那个例子有不少错误,结果改了我n久才完成~当然马上就决定写一篇博客告诉大家怎样做才是正确的,以免像我那样白走许多弯路。我也不知是不是我找的那份不好,如果你有更好的manual,记得告诉我。    <br />    <br />    <strong><u>撰写本文的目的</u></strong>:    <br /> 给出使用JFlex、JavaCUP来为一个计算器建立分析器的示例的完整代码,使读者能充分领会JavaCUP的使用方法。虽然本文仅仅给出了计算器的代码,但只要你会写你的语言的翻译模式,则只要照抄这个模版,并改改相应动作就可以了。    <br />    <br />    <strong><u>引用到的资料</u></strong>:    <ul>     <li>《CUP User's Manual》,作者:<a href="/misc/goto?guid=4959500124418784036"><u><span style="color:#0000ff;">Scott E. Hudson</span></u></a>地址为李老师那里下载下来的JavaCUP-11a.rar\CUP-develop.tar.gz\develop\manual.html,有详细的英文说明和示例代码,但有很多错。本文中简称为《手册》。 </li>     <li><a href="/misc/goto?guid=4959500124507711725">《使用CUP进行语法分析》</a>,摘自Apollo的博客,貎似是转载的(竟然不注明[转]和真实出处?!,BS之~),作者待考。有详尽的解释,但缺乏示例代码。本文中简称为《语法分析》。 </li>    </ul>    <p><u><strong>详细步骤</strong></u>:<br /> 1、准备工作。<br /> JavaCUP和JFlex一样,压缩包里边有许多的文件夹和文件,我不知道正统的做法是否要求使用javaCUP也像Jflex一样要设置一堆path啊、classpath啊、jflex_home 之类的环境变量,但如果你像我一样只打算用它几次,你只要执行下述的两个简单步骤就可以了,它并不需要你设置任何的环境变量(以下假设你的工作目录是 work\):<br /> 1)   将JavaCUP压缩包里的java-cup-11a.jar解压到work\下。<br /> 2)   将JavaCUP压缩包里的CUP-develop.tar.gz\develop\src下的java_cup文件夹整个解压到work\下。<br /> 现在你可以使用JavaCUP了。<br /> <br /> 2、为这个计算器写一个词法分析器。或者用JFlex生成一个词法分析器</p> 两种方法都可以生成词法分析器,其中,直接写分析器的代码如下:    <pre class="brush:java; toolbar: true; auto-links: false;">// Simple Example Scanner Class  // scanner.java import java_cup.runtime.*; import java.io.*; //import sym;  public class scanner implements java_cup.runtime.Scanner {   /* single lookahead character */   protected static int next_char;   // since cup v11 we use SymbolFactories rather than Symbols   private SymbolFactory sf = new DefaultSymbolFactory();   private static FileReader fileReader;   public scanner(FileReader fr){       this.fileReader=fr;   }   /* advance input by one character */   protected static void  advance()     throws java.io.IOException     { next_char = fileReader.read(); }    /* initialize the scanner */   public static void init()     throws java.io.IOException     { advance(); }    /* recognize and return the next complete token */   public Symbol next_token()     throws java.io.IOException     {       for (;;)         switch (next_char)       {         case '0': case '1': case '2': case '3': case '4':          case '5': case '6': case '7': case '8': case '9':            /* parse a decimal integer */           int i_val = 0;           do {             i_val = i_val * 10 + (next_char - '0');             advance();           } while (next_char >= '0' && next_char <= '9');         return sf.newSymbol("NUMBER",sym.NUMBER, new Integer(i_val));          case ';': advance(); return sf.newSymbol("SEMI",sym.SEMI);         case '+': advance(); return sf.newSymbol("PLUS",sym.PLUS);         case '-': advance(); return sf.newSymbol("MINUS",sym.MINUS);         case '*': advance(); return sf.newSymbol("TIMES",sym.TIMES);         case '/': advance(); return sf.newSymbol("DIVIDE",sym.DIVIDE);         case '%': advance(); return sf.newSymbol("MOD",sym.MOD);         case '(': advance(); return sf.newSymbol("LPAREN",sym.LPAREN);         case ')': advance(); return sf.newSymbol("RPAREN",sym.RPAREN);          case -1: return sf.newSymbol("EOF",sym.EOF);          default:            /* in this simple scanner we just ignore everything else */           advance();         break;       }     } };</pre>