libcas - Grammar File (for YACC/bison)

/*
 (C) Christoph Lehner 2012
*/
%skeleton "lalr1.cc"
%define namespace "cas"
%define parser_class_name "InputGrammar"

%code requires {
#include "libcas.hh"
namespace cas { class Input; }
}

%union {
 char *s;
 int i;
 Expression* e;
 Arguments* a;
}

%code {
#define yylex(v,l,i) i->lex(v,l)
}

%locations
%parse-param { cas::Input* input }
%lex-param { cas::Input* input }
%token                  END     0       "end of input"
%token                  INVALID         "invalid token"
%token <i>              INTEGER         "integer"
%token <s>              NAME            "name"
%type  <e>              exp
%type  <a>              arglist
%left '+'
%left '-'
%left '*'
%left '/'
%left NEG POS
%right '^'

%destructor { } <i>
%destructor { delete $$; } <*>

%%
input:
exp { input->e = $1; }
;

exp:
INTEGER                 { $$ = new Integer($1); }
| NAME                  { $$ = new Symbol($1); }
| NAME '(' arglist ')'  { $$ = new Function($1,$3);        }
| NAME '(' ')'          { $$ = new Function($1,0);      }
| exp '+' exp           { Arguments* a = new Arguments(); a->add($1); a->add($3);  $$ = new Operator('+',a); }
| exp '-' exp           { Arguments* a = new Arguments(); a->add($1); a->add($3);  $$ = new Operator('-',a); }
| exp '*' exp           { Arguments* a = new Arguments(); a->add($1); a->add($3);  $$ = new Operator('*',a); }
| exp '/' exp           { Arguments* a = new Arguments(); a->add($1); a->add($3);  $$ = new Operator('/',a); }
| '-' exp  %prec NEG    { if ($2->getType()==Expression::INTEGER) { ((Integer*)$2)->i *= -1; $$ = $2; } else { Arguments* a = new Arguments(); a->add($2); $$ = new Operator('-',a); } }
| '+' exp  %prec POS    { $$ = $2;                         }
| exp '^' exp           { Arguments* a = new Arguments(); a->add($1); a->add($3);  $$ = new Operator('^',a); }
| '(' exp ')'           { $$ = $2;                         }
;

arglist:
exp                     { Arguments* a = new Arguments(); a->add($1); $$ = a; }
| arglist ',' exp       { $1->add($3); $$ = $1; }
;
%%