/* grammar.y */ %{ #include #include #include #include "project.h" %} /* Tokens have semantic values that are either integers or strings */ %union { unsigned val; char* str; } /* This grammar has 40 shift/reduce conflicts */ %expect 40 /* A stmt_list eventually expands to the entire program */ %start stmt_list %token INT /* Constant integer value */ %token ID /* Any string */ %type expr /* Anything that evaluates to an integer */ /* Define operator precedence */ %left IOR %left AND %left '^' %left '&' %left EQV NEQ %left '<' LEQ '>' GEQ %left SHL SHR %left '+' '-' %left '*' '/' '%' %right NEG '~' '!' %right '?' %left ':' ';' ',' %% /* List of label declarations and expressions */ stmt_list: /* empty */ | stmt_list stmt ; /* A single statement is either a label declaration or something that evaluates * down to a 32-bit value */ stmt: ID ':' {asm_label_decl($1); } | error ':' {yyerrok; } | expr ';' {asm_expr($1); } | error ';' {yyerrok; } ; /* An expression always evaluates down to a constant unsigned 32-bit number */ expr: INT {$$ = $1; } | '$' ID {$$ = asm_reg($2); } | ID '(' expr ',' expr ',' expr ')' {$$ = asm_insn($1, $3, $5, $7); } | '@' ID {$$ = asm_label($2); } | expr '?' expr ':' expr {$$ = $1 ? $3 : $5; } | expr IOR expr {$$ = $1 || $3; } | expr AND expr {$$ = $1 && $3; } | expr '|' expr {$$ = $1 | $3; } | expr '^' expr {$$ = $1 ^ $3; } | expr '&' expr {$$ = $1 & $3; } | expr EQV expr {$$ = $1 == $3; } | expr NEQ expr {$$ = $1 != $3; } | expr '<' expr {$$ = $1 < $3; } | expr LEQ expr {$$ = $1 <= $3; } | expr '>' expr {$$ = $1 > $3; } | expr GEQ expr {$$ = $1 >= $3; } | expr SHL expr {$$ = $1 << $3; } | expr SHR expr {$$ = $1 >> $3; } | expr '+' expr {$$ = $1 + $3; } | expr '-' expr {$$ = $1 - $3; } | expr '*' expr {$$ = $1 * $3; } | expr '/' expr {$$ = $1 / $3; } | expr '%' expr {$$ = $1 % $3; } | '-' expr %prec NEG {$$ = ~$2 + 1; } | '~' expr {$$ = ~$2; } | '!' expr {$$ = !$2; } | '(' expr ')' {$$ = $2; } ; /* That wasn't so hard, now was it? */ %% /* EOF */