Skip to content
parser.y 4.86 KiB
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;

// 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); }

	Node *node;
	NExpression *expr;
	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

/* binary operators */
%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 <var> variable

%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*/
%type <token> compop
/* 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

%start program
program : items { rootNode = $1; }
	 ;

items : items item { $1->addItem(UNIQUE($2)); $$ = $1; }
	 | item { $$ = new NItemSequence(UNIQUE($1)); }
item : TOK_REG ident TOK_EQ literal { $$ = new NRegItem(UNIQUE($2), UNIQUE($4)); }
	/* TODO var const signal*/
	| 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
		{ $$ = new NSignalItem(UNIQUE($2), UNIQUE($4), UNIQUE($6), false); }
	| TOK_SIGNAL ident TOK_EQ TOK_NOT ident TOK_LBRAC expr TOK_RBRAC
		{ $$ = new NSignalItem(UNIQUE($2), UNIQUE($5), UNIQUE($7), true); }
	| TOK_AUTO ident stmts states state {
		$4->addItem(UNIQUE($5));
		$$ = new NAutoItem(UNIQUE($2), UNIQUE($3), UNIQUE($4));
	}
	;

/* zero or more statements */
stmts : stmts stmt { $1->addItem(UNIQUE($2)); }
	  | { $$ = new NStatementSequence(); }
	  ;

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 {
			$4->addItem(UNIQUE($5));
			$$ = new NIfStatement(UNIQUE($2), UNIQUE($4));
		}
	 | TOK_IF cond TOK_THEN stmts stmt TOK_ELSE stmts stmt TOK_END {
			$4->addItem(UNIQUE($5));
			$7->addItem(UNIQUE($8));
			$$ = new NIfStatement(UNIQUE($2), UNIQUE($4), UNIQUE($7));
	 ;

/* zero or more states */
states : states state { $1->addItem(UNIQUE($2)); }
	   | { $$ = new NStateSequence(); }
	   ;

state : TOK_STATE ident stmts whens when {
	  		$4->addItem(UNIQUE($5));
	  		$$ = new NState(UNIQUE($2), UNIQUE($3), UNIQUE($4));
whens : whens when { $1->addItem(UNIQUE($2)); }
	  | { $$ = new NWhenSequence(); }
when : TOK_WHEN ident stmts stmt {
	 		$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 ;

variable : ident { $$ = new NBitfieldVariable(UNIQUE($1)); }
	 	 | ident TOK_LBRAC expr TOK_RBRAC
			{ $$ = new NBitfieldVariable(UNIQUE($1), UNIQUE($3)); }
	 	 | ident TOK_LBRAC expr TOK_COLUMN expr TOK_RBRAC
		 	{ $$ = 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; }
cond : expr compop expr { $$ = new NBinaryOperator($2, UNIQUE($1), UNIQUE($3)); }