java antlr.Tool mygrammar.g  
 

JavaCC Installation:

                                            java JavaCC0_8pre1
                                           JavaCC mygrammar.jj
       
 
      1. Create a new file and call it "alc.g" (the name has no influence on the grammar)
      2. Enter a header, although we do not need it for our parser, I just include it as an example:
      3. header

        {

        import java.lang.*;

        }
         

      4. I will write the lexer rules, to define the terminals or the tokens for our calc grammar:
      5. class CalcLexer extends Lexer;options{

        // a lookahed of 2

        k=2;

        }

        // white space, these will be skipped by the lexer:WS: ( ' ' | '\t' | '\r') { _ttype = Token.SKIP; };

        // terminals:

        EOL       : '\n' ;
        LPAREN    : '(' ;
        RPAREN    : ')' ;
        PLUS      : '+' ;
        MINUS     : '-' ;
        MULTIPLY  : '*' ;
        DIVIDE    : '/' ;
        INT       : (DIGIT)+ ;

        // protected rules, can not be accessed from the parser, can be used
        // only from other lexer rules:

        protected
        DIGIT : '0'..'9' ;

        Unless changed manually, each lexer rule returns a token.
         

      6. Now we will write the rules for the parser:
      7. class CalcParser extends Parser;
        expr returns [float f]
        {
           f=0;
        }
        :
             f=sum
             ( EOL )*
             EOF
        ;

        sum returns [float f]
        {
           f=0;
        }
        :
           term
           (
              ( PLUS term | MINUS term )
           )*
        ;

        term returns [float f]

        {
           f=0;
        }
        :
            element
            (
              ( MULTIPLY element | DIVIDE element )
            )*
        ;

        element returns [float f]
        {
           f=0;
        }
        :
            INT | LPAREN sum RPAREN
        ;
         

      8. Provide actions in the parser rules, to handle the calculation of the expression:
      9. For example:

        sum returns [float f]
        {
            f=0; float f2=0;
        }
        :
            f=term //assign to f the value returned by the rule term
            (
               (    PLUS f2=term { f += f2; }
                 | MINUS f2=term { f -= f2; }
               )
            )*
        ;
         

        Notice that at the end of the rule, you do not need to explicitly return the value f, it will be done by antlr.

         

      10. The rest of the modification to the other rules is very similar to the sum rule, The complete file is listed here:
      11. class CalcParser extends Parser;

        expr returns [float f]
        {
           f=0;
        }
        :
            f=sum
            ( EOL )*
            EOF
        ;

        sum returns [float f]
        {
           f=0;
           float f2=0;
        }
        :
           f=term
           (
              (    PLUS f2=term { f += f2; }
                | MINUS f2=term { f -= f2; }
               )
            )*
        ;

        term returns [float f]
        {
           f=0;
           float f2=0;
        }
        :
            f=element
            (
               ( MULTIPLY f2=element { f *= f2; }
                 | DIVIDE f2=element { f /= f2; }
               )
            )*
        ;

        element returns [float f]
        {
           f=0;
           Float x;
        }
        :
            d:INT { x = new Float(d.getText());
                    f = x.floatValue();
                  }
            |
              LPAREN f=sum RPAREN
        ;

         

        class CalcLexer extends Lexer;
        options
        {
           k=1;
        }

        WS: ( ' ' | '\t' | '\r')
           {
              _ttype = Token.SKIP;
           }
        ;

        EOL      : '\n' ;
        LPAREN   : '(' ;
        RPAREN   : ')' ;
        PLUS     : '+' ;
        MINUS    : '-' ;
        MULTIPLY : '*' ;
        DIVIDE   : '/' ;
        INT      : (DIGIT)+ ;

        protected
        DIGIT : '0'..'9' ;

         

      12. To generate the Parser and Lexer code, we need to run antlr.
      13. On the command line, type the following command:

        Java antlr.Tool calc.g

        I am assuming that your path is pointing to the directory where java is installed, if not then just add the following path to your PATH environment variable:

        Q:\WINDOWS\jdk-w32\bin
         

      14. antlr should terminate generating few java files. To compile them , run javac, example:
      15. javac *.java

        this will produce the class files.
         

      16. The following program, shows how can we use the lexer and the parser:
       
        import java.io.*;
        import antlr.*;

        class Calc
        {
            public static void main(String[] args)
            {
              try
              {
                CalcLexer lexer =  new CalcLexer(new DataInputStream(System.in));
                CalcParser parser = new CalcParser(lexer);

                // Parse the input expression
                System.out.print("Enter Expression: ");
                System.out.flush();

                float res = parser.expr();

                System.out.println("Result: " + res);
              }
              catch(IOException e)
              {
                 System.err.println("IOException: " + e);
              }
              catch(ParserException e)
              {
                 System.err.println("ParseException: " + e);
              }
           }
        }

      Put the above code into a file called "Cal.java", compile it and run it using the java command:

      Java Calc