10.JavaCC官方入門指南-例5

例5:計算器--添加乘除法運算

1.calculator2.jj

根據上一個例子,可知要添加乘法和除法運算是很簡單的,咱們只需在詞法描述部分添加以下兩個token:java

TOKEN : { < TIMES : "*" > }
TOKEN : { < DIVIDE : "/" > }

  接下來咱們修改Expression這個生產式,對它的修改跟上一步添加減號運算所作的修改很類似:測試

Expression --> Primary (PLUS Primary | MINUS Primary | TIMES Primary | DIVIDE Primary)*

  從純粹的句法角度來看,上面這種方法沒有什麼錯,可是它與咱們的計算方法不太吻合,由於它沒有認識到乘法和除法應該比加法和減法具備更高的優先級。例如,若是咱們計算下式:code

2*3+4*5

  那麼根據咱們的表達式,咱們得到的結果就會是((2×3) + 4)×5,結果是50,而不是(2×3) + (4×5)。
  所以,咱們將生產式修改爲以下:orm

Expression --> Term (PLUS Term | MINUS Term)*
Term --> Primary (TIMES Primary | DIVIDE Primary)*

  這樣一來,咱們就將每一個表達式拆分紅了一個或多個式子(terms)相加或相減。在咱們的例子中,式子(terms)就是兩個大括號中的內容:blog

[ 2*3 ] +[ 4*5 ]

  對Expression來講,它的改變就是修改原先對Primary的引用,把它修改到對Term的引用,以下所示:token

double Expression() throws NumberFormatException :
{
    double i ;
    double value ;
}
{
    value = Term()
    (
        <PLUS>
        i = Term()
        { value += i ; }
      | <MINUS>
        i = Term()
        { value -= i ; }
    )*
    { return value ; }
}

  而Term的生產式以下所示:io

double Term() throws NumberFormatException :
{
    double i ;
    double value ;
}
{
    value = Primary()
    (
        <TIMES>
        i = Primary()
        { value *= i ; }
      | <DIVIDE>
        i = Primary()
        { value /= i ; }
    )*
    { return value ; }
}

2.測試

  根據上面的修改,最終獲得的calculator2.jj文件內容以下:class

/* calculator0.jj An interactive calculator. */
options {
    STATIC = false ;
}
PARSER_BEGIN(Calculator)
    import java.io.PrintStream ;
    class Calculator {
        public static void main( String[] args )
            throws ParseException, TokenMgrError, NumberFormatException {
            Calculator parser = new Calculator( System.in ) ;
            parser.Start( System.out ) ;
        }
        double previousValue = 0.0 ;
    }
PARSER_END(Calculator)


SKIP : { " " }
TOKEN : { < EOL : "\n" | "\r" | "\r\n" > }
TOKEN : { < PLUS : "+" > }
TOKEN : { < MINUS : "-" > }
TOKEN : { < TIMES : "*" > }
TOKEN : { < DIVIDE : "/" > }
TOKEN : { < NUMBER : <DIGITS>
                   | <DIGITS> "." <DIGITS>
                   | <DIGITS> "."
                   | "."<DIGITS> >
        }
TOKEN : { < #DIGITS : (["0"-"9"])+ > }


void Start(PrintStream printStream) throws NumberFormatException :
{}
{
    (
        previousValue = Expression()
        <EOL> { printStream.println( previousValue ) ; }
    )*
    <EOF>
}

double Expression() throws NumberFormatException :
{
    double i ;
    double value ;
}
{
    value = Term()
    (
        <PLUS>
        i = Term()
        { value += i ; }
      | <MINUS>
        i = Term()
        { value -= i ; }
    )*
    { return value ; }
}

double Term() throws NumberFormatException :
{
    double i ;
    double value ;
}
{
    value = Primary()
    (
        <TIMES>
        i = Primary()
        { value *= i ; }
      | <DIVIDE>
        i = Primary()
        { value /= i ; }
    )*
    { return value ; }
}

double Primary() throws NumberFormatException :
{
    Token t ;
}
{
    t = <NUMBER>
    { return Double.parseDouble( t.image ) ; }
}

先來測試1+2:
import

計算 2 * 3.3:
引用

計算 9. / 3 :

最後,計算23+45 :

能夠看到,乘除的優先級確實高於加減。

相關文章
相關標籤/搜索