Newer
Older
%{
#include <iostream>
#include "node.hpp"
extern int yylex();
void yyerror(const char *s) {
std::cerr << "ERROR: " << s << std::endl;
}
// our root node ;)
Node *rootNode;

Léo Grange
committed
// a very dirty hack for the sake of readibility...
template<typename T>
std::unique_ptr<T> UNIQUE(T *ptr) { return std::unique_ptr<T>(ptr); }
%}
%union {
std::string *str;
Node *node;
NExpression *expr;
NBinaryOperator *cond;
NInteger *integer;
NIdentifier *ident;
NBitfieldVariable *var;
NItemSequence *itemseq;
NItem *item;
NState *state;
NStateSequence *stateseq;
NStatement *stmt;
NStatementSequence *stmtseq;
NWhen *when;
NWhenSequence *whenseq;
}
%token <str> TOK_ID TOK_INT
%token <token> TOK_PLUS TOK_MINUS TOK_MUL TOK_DIV TOK_AND TOK_OR
%token <token> TOK_LSHIFT TOK_RSHIFT
/* comparison operators (binary) */
%token <token> TOK_EQ TOK_NE TOK_GT TOK_GE TOK_LT TOK_LE
/* other operators (~ and !) */
%token <token> TOK_INV TOK_NOT
/* separators... */
%token <token> TOK_LBRAC TOK_RBRAC TOK_LPAR TOK_RPAR
%token <token> TOK_COLUMN
/* language keywords */
%token <token> TOK_AUTO TOK_REG TOK_VAR TOK_CONST TOK_SIGNAL
%token <token> TOK_STATE TOK_WHEN TOK_EXIT TOK_GOTO
%token <token> TOK_IF TOK_THEN TOK_ELSE TOK_END
/* non-terminal types */
%type <ident> ident
%type <integer> literal
%type <itemseq> items
%type <item> item
%type <stmtseq> stmts
%type <stmt> stmt
%type <stateseq> states
%type <state> state
%type <when> when
%type <whenseq> whens
/* may change later */
%type <cond> cond
/*%type <token> unop
%type <token> binop*/
/* precedence to solve shift/reduce conflicts explicitly */
%precedence TOK_THEN
%precedence TOK_ELSE
/* operator associativity to avoid shift/reduce conflicts */
/*
%left TOK_OR
%left TOK_AND
%left TOK_LSHIFT TOK_RSHIFT
%left TOK_PLUS TOK_MINUS
%left TOK_MUL TOK_DIV
*/
%left TOK_OR TOK_AND TOK_LSHIFT TOK_RSHIFT TOK_PLUS TOK_MINUS TOK_MUL TOK_DIV ANY_BINOP
%type <token> binop
%type <token> unop
%right UNARY_MINUS
program : items { rootNode = $1; }
;

Léo Grange
committed
items : items item { $1->addItem(UNIQUE($2)); $$ = $1; }
| item { $$ = new NItemSequence(UNIQUE($1)); }

Léo Grange
committed
item : TOK_REG ident TOK_EQ literal { $$ = new NRegItem(UNIQUE($2), UNIQUE($4)); }

Léo Grange
committed
| TOK_VAR ident { $$ = new NVarItem(UNIQUE($2)); }
| TOK_CONST ident TOK_EQ literal { $$ = new NConstItem(UNIQUE($2), UNIQUE($4)); }
| TOK_SIGNAL ident TOK_EQ ident TOK_LBRAC expr TOK_RBRAC

Léo Grange
committed
{ $$ = new NSignalItem(UNIQUE($2), UNIQUE($4), UNIQUE($6), false); }
| TOK_SIGNAL ident TOK_EQ TOK_NOT ident TOK_LBRAC expr TOK_RBRAC

Léo Grange
committed
{ $$ = new NSignalItem(UNIQUE($2), UNIQUE($5), UNIQUE($7), true); }
| TOK_AUTO ident stmts states state {

Léo Grange
committed
$4->addItem(UNIQUE($5));
$$ = new NAutoItem(UNIQUE($2), UNIQUE($3), UNIQUE($4));
}
;
/* zero or more statements */

Léo Grange
committed
stmts : stmts stmt { $1->addItem(UNIQUE($2)); }
| { $$ = new NStatementSequence(); }
;

Léo Grange
committed
stmt : variable TOK_EQ expr { $$ = new NAssignStatement(UNIQUE($1), UNIQUE($3)); }
| TOK_GOTO ident { $$ = new NGotoStatement(UNIQUE($2)); }
| TOK_EXIT { $$ = new NExitStatement(); }
| TOK_IF cond TOK_THEN stmts stmt TOK_END {

Léo Grange
committed
$4->addItem(UNIQUE($5));
$$ = new NIfStatement(UNIQUE($2), UNIQUE($4));
}
| TOK_IF cond TOK_THEN stmts stmt TOK_ELSE stmts stmt TOK_END {

Léo Grange
committed
$4->addItem(UNIQUE($5));
$7->addItem(UNIQUE($8));
$$ = new NIfStatement(UNIQUE($2), UNIQUE($4), UNIQUE($7));
;
/* zero or more states */

Léo Grange
committed
states : states state { $1->addItem(UNIQUE($2)); }
| { $$ = new NStateSequence(); }
;
state : TOK_STATE ident stmts whens when {

Léo Grange
committed
$4->addItem(UNIQUE($5));
$$ = new NState(UNIQUE($2), UNIQUE($3), UNIQUE($4));
}
;
/* zero or more whens */

Léo Grange
committed
whens : whens when { $1->addItem(UNIQUE($2)); }
| { $$ = new NWhenSequence(); }
when : TOK_WHEN ident stmts stmt {

Léo Grange
committed
$3->addItem(UNIQUE($4));
$$ = new NWhen(UNIQUE($2), UNIQUE($3));
}
;
ident : TOK_ID { $$ = new NIdentifier(*$1); delete $1; }
;
literal : TOK_INT { $$ = new NInteger(*$1); delete $1; }
;
binop : TOK_PLUS | TOK_MINUS | TOK_MUL | TOK_DIV | TOK_AND | TOK_OR
| TOK_LSHIFT | TOK_RSHIFT;
compop : TOK_EQ | TOK_NE | TOK_GT | TOK_GE | TOK_LT | TOK_LE ;
unop : TOK_MINUS | TOK_INV ;

Léo Grange
committed
variable : ident { $$ = new NBitfieldVariable(UNIQUE($1)); }
| ident TOK_LBRAC expr TOK_RBRAC

Léo Grange
committed
{ $$ = new NBitfieldVariable(UNIQUE($1), UNIQUE($3)); }
| ident TOK_LBRAC expr TOK_COLUMN expr TOK_RBRAC

Léo Grange
committed
{ $$ = new NBitfieldVariable(UNIQUE($1), UNIQUE($3), UNIQUE($5)); }
expr : variable { $$ = $1; }
| literal { $$ = $1; }
| unop expr %prec UNARY_MINUS { $$ = new NUnaryOperator($1, UNIQUE($2)); }
| expr binop expr %prec ANY_BINOP { $$ = new NBinaryOperator($2, UNIQUE($1), UNIQUE($3)); }
| TOK_LPAR expr TOK_RPAR { $$ = $2; }

Léo Grange
committed
cond : expr compop expr { $$ = new NBinaryOperator($2, UNIQUE($1), UNIQUE($3)); }