//
// An experimental expression grammer by
// Ian Kaplan
//


header {

// include files
#include 
#include 
#include 
#include 
#include "basic_types.hpp"
#include "node_tokens.hpp"
#include "trees.hpp"
#include "tree_fact.hpp"

}


options {
	language="Cpp";
}

class MyExprParser extends Parser;

options {
        k = 2;
        exportVocab=MyExpr;
}


exprlist returns [pNode expr_list]
  { pNode asign; 
    expr_list = factory.make_node( n_expr_list ); 
  }
  : ( asign = assignment_statement { factory.add_child( expr_list, asign ); } )* EOF
  ;

assignment_statement returns [pNode asgn_stmt]
  { pNode a = NULL; }
  : a = assignment SEMICOLON { asgn_stmt = a; }
  ;

assignment returns [pNode asgn]
{ pNode e1 = NULL;
  pNode e2 = NULL; 
  pNode id = NULL; }
  : e1 = expr { asgn = e1; }
  | id = identifier ASSIGN e2 = expr 
    { asgn = factory.build_binary( n_assign, id, e2 ); }
  ;

primary_expr returns [pNode prime_expr]
  { pNode c1 = NULL;
    pNode e1 = NULL;
    pNode id = NULL; }
  : id = identifier   { prime_expr = id; }
  | c1 = constant { prime_expr = c1; }
  | (LPAREN e1 = expr RPAREN )  { prime_expr = e1; }
  ;

identifier returns [pNode rslt_id]
  : id:IDENT { std::string str;
               const char *cstr;

	       str = id->getText();
	       cstr = str.c_str(); 
               rslt_id = factory.make_id_node( cstr ); }
  ;

sign_expr returns [pNode s_expr]
  { pNode b1 = NULL;
    pNode b2 = NULL; 
    pNode minus_op = NULL;
  }
  : b1 = primary_expr { s_expr = b1; }
  | (MINUS { minus_op = factory.build_unary( n_uminus, minus_op ); } )+
    b2 = primary_expr { s_expr = factory.add_child( minus_op, b2 ); }
  ;

mul_expr returns [pNode m_expr]
  { pNode s1 = NULL;
    pNode s2 = NULL;
    pNode op = NULL;
  }
  : s1 = sign_expr { m_expr = s1; } 
    (op = mulop s2 = sign_expr 
     { m_expr = factory.build_binary( op, m_expr, s2 ); } )*
  ;

mulop returns [pNode mul_node]
  : TIMES  { mul_node  = factory.make_node( n_times ); }
  | DIVIDE { mul_node  = factory.make_node( n_divide ); }
  | MOD    { mul_node  = factory.make_node( n_mod ); }
  ;

expr returns [pNode a_expr]
  { pNode m1 = NULL;
    pNode m2 = NULL;
    pNode op = NULL;
  }
  : m1 = mul_expr { a_expr = m1; }
    ( op = addop  m2 = mul_expr
    { a_expr = factory.build_binary( op, a_expr, m2 ); }  )* 
  ;

addop returns [pNode add_node]
  : PLUS { add_node  = factory.make_node( n_plus ); }
  | MINUS { add_node = factory.make_node( n_minus ); }
  ;

constant returns [pNode const_node]
  : icon:ICON  { 
                 std::string str;
                 const char *cstr;

                 str = icon->getText();
	         cstr = str.c_str();
                 assert( cstr != NULL );
                 const val = atoi( cstr );
                 const_node = factory.make_const_node( val ); 
               }
  ;


class MyExprLexer extends Lexer;

options {
	k = 2;
        exportVocab=MyExpr;
}


WS_     :       (' '
        |       '\t'
        |       '\n'
        |       '\r')
                { _ttype = Token::SKIP; }
        ;

IDENT
options {
	paraphrase = "identifier";
}
  :  ('a'..'z' | 'A'..'Z' | '_' ) ( ('a'..'z' | 'A'..'Z' | '_') | ('0'..'9' ))*
  ;

ICON
options {
	paraphrase = "integer constant";
}
  : '0'..'9' ('0'..'9')*
  ;


SEMICOLON
options {
	paraphrase = ";";
}
  : ';'
  ;

LPAREN
options {
	paraphrase = "(";
}
  : '('
  ;

RPAREN
options {
	paraphrase = ")";
}
  : ')'
  ;


PLUS
options {
	paraphrase = "+";
}
  : '+'
  ;

MINUS
options {
	paraphrase = "-";
}
  : '-'
  ;

TIMES
options {
	paraphrase = "*";
}
  : '*'
  ;

DIVIDE
options {
	paraphrase = "/";
}
  : '/'
  ;

MOD
options {
	paraphrase = "%";
}
  : '%'
  ;

ASSIGN
options {
	paraphrase = "=";
}
  : '='
  ;

back to ANTLR examples page