Simple Parser

Parsers are interesting. This is a simple arithmetic calculator. Enter various arithmetic expressions.


Math Services Home

keywords: simplest possible programming language, scheme, jscheme, norvig, joy, stack programming language, forth, stack, lang, brainfk, brainf**k

/* scanner.jflex */

import java_cup.runtime.*;
      
%%
   
/* -----------------Options and Declarations Section----------------- */
   
%class Lexer

%line
%column
    
%cup
   
%{      
    private Symbol symbol(int type) {
        return new Symbol(type, yyline, yycolumn);
    }
      
    private Symbol symbol(int type, Object value) {
        return new Symbol(type, yyline, yycolumn, value);
    }
%}
   
  
LineTerminator = \r|\n|\r\n
   
/* White space is a line terminator, space, tab, or line feed. */
WhiteSpace     = {LineTerminator\t\f]
   
dec_int_lit = [1-9][0-9]*
   
dec_int_id = [A-Za-z_][A-Za-z_0-9]*
   
%%

/* ------------------------Lexical Rules Section---------------------- */
      
<YYINITIAL> {
   
    /* Return the token SEMI declared in the class sym that was found. */
    ";"                return symbol(sym.SEMI)}
   
    /* Print the token found that was declared in the class sym and then
       return it. */
    "+"                System.out.print(" + ")return symbol(sym.PLUS)}
    "-"                System.out.print(" - ")return symbol(sym.MINUS)}
    "*"                System.out.print(" * ")return symbol(sym.TIMES)}
    "/"                System.out.print(" / ")return symbol(sym.DIVIDE)}
    "("                System.out.print(" ( ")return symbol(sym.LPAREN)}
    ")"                System.out.print(" ) ")return symbol(sym.RPAREN)}
        
    {dec_int_lit}      { System.out.print(yytext());
                         return symbol(sym.NUMBER, new Integer(yytext()))}
     
    {dec_int_id}       { System.out.print(yytext());
                         return symbol(sym.ID, new Integer(1));}
   
    /* Don't do anything if whitespace is found */
    {WhiteSpace}       { /* just skip what was found, do nothing */ }   
}

/* No token was found for the input so through an error.  Print out an
   Illegal character message with the illegal character that was found. */
[^]                    { throw new Error("Illegal character <"+yytext()+">")}


/* parser.cup  */
/* ----------------------Preliminary Declarations Section--------------------*/
   
import java_cup.runtime.*;
   
parser code {:    

    private final StringBuffer outputResult = new StringBuffer();
     
    public StringBuffer out() {
        return outputResult;
    }
    
    public void report_error(final String message, final Object info) {          
        final StringBuffer m = new StringBuffer("Error");           
        if (info instanceof java_cup.runtime.Symbol) {
            final java_cup.runtime.Symbol s = ((java_cup.runtime.Symbolinfo);              
            if (s.left >= 0) {                 
                m.append(" in line "+(s.left+1));               
                if (s.right >= 0)                    
                    m.append(", column "+(s.right+1));
            }
        }   
        m.append(" : "+message);  
        System.err.println(m);
    }       
    public void report_fatal_error(final String message, final Object info) {
        report_error(message, info);
        System.exit(1);
    }
:};
   
   
/* ------------Declaration of Terminals and Non Terminals Section----------- */
  
terminal           SEMI, PLUS, MINUS, TIMES, DIVIDE, LPAREN, RPAREN;
terminal Integer   NUMBER, ID;
      
non terminal Object     expr_list, expr_part;
non terminal Integer    expr, factor, term;
   
/* ----------------------------Grammar Section-------------------- */
      
expr_list ::= expr_list expr_part
                 |
                 expr_part;
      
expr_part ::= expr:e
                {
                    System.out.println(" = " + e);
                    parser.out().append(String.valueOf(e))
                :}
                 SEMI
                 ;
      
expr      ::= expr:e PLUS factor:f
                 {: RESULT = new Integer(e.intValue() + f.intValue()); :}
                 |
                 expr:e MINUS factor:f
                 {: RESULT = new Integer(e.intValue() - f.intValue()); :}
                 |
                 factor:f
                 {: RESULT = new Integer(f.intValue()); :}
                 ;

factor    ::= factor:f TIMES term:t
                 {: RESULT = new Integer(f.intValue() * t.intValue()); :}
                 |
                 factor:f DIVIDE term:t
                 {: RESULT = new Integer(f.intValue() / t.intValue()); :}
                 |
                 term:t
                 {: RESULT = new Integer(t.intValue()); :}
                 ;
   
term      ::= LPAREN expr:e RPAREN
                 {: RESULT = e; :}
                 |
                 NUMBER:n
                 {: RESULT = n; :}
                 |
                 ID:i
                 {: RESULT = i; :}
                 ;
                 
/* End of File */