zoukankan      html  css  js  c++  java
  • 10.JavaCC官方入门指南-例5

    例5:计算器--添加乘除法运算

    1.calculator2.jj

    根据上一个例子,可知要添加乘法和除法运算是很简单的,我们只需在词法描述部分添加如下两个token:

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

      接下来我们修改Expression这个生产式,对它的修改跟上一步添加减号运算所做的修改很相似:

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

      从纯粹的句法角度来看,上面这种方法没有什么错,但是它与我们的计算方法不太吻合,因为它没有认识到乘法和除法应该比加法和减法具有更高的优先级。例如,如果我们计算下式:

    2*3+4*5
    

      那么根据我们的表达式,我们获得的结果就会是((2×3) + 4)×5,结果是50,而不是(2×3) + (4×5)。
      因此,我们将生产式修改成如下:

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

      这样一来,我们就将每个表达式拆分成了一个或多个式子(terms)相加或相减。在我们的例子中,式子(terms)就是两个大括号中的内容:

    [ 2*3 ] +[ 4*5 ]
    

      对Expression来说,它的改变就是修改原先对Primary的引用,把它修改到对Term的引用,如下所示:

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

      而Term的生产式如下所示:

    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文件内容如下:

    /* 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 : "
    " | "
    " | "
    " > }
    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:

    计算 2 * 3.3:

    计算 9. / 3 :

    最后,计算23+45 :

    可以看到,乘除的优先级确实高于加减。

  • 相关阅读:
    大数据总结
    spark_streaming_微批量处理
    spark_sql_解析器
    spark_sql_函数
    spark-sql-04-spark连接hive的几种方式
    spark-sql-04-on_hive
    spark-sql-04-hive
    CF550C Divisibility by Eight
    CF489C Given Length and Sum of Digits...
    CF550A Two Substrings
  • 原文地址:https://www.cnblogs.com/suhaha/p/11733709.html
Copyright © 2011-2022 走看看