Skip to content

Instantly share code, notes, and snippets.

@saevarb
Created May 1, 2019 20:09
Show Gist options
  • Save saevarb/0b6c740de0c15d70c7ef1605ed321bd0 to your computer and use it in GitHub Desktop.
Save saevarb/0b6c740de0c15d70c7ef1605ed321bd0 to your computer and use it in GitHub Desktop.
%{
#include <stdio.h>
#include <string.h>
#include "tree.h"
extern char *yytext;
extern Body* prgBody;
void yyerror(char *str) {
fprintf(stderr, "%s\n", str);
fprintf(stderr, "syntax error before %s\n",yytext);
}
int yylex();
%}
%union {
int intConst;
int boolConst;
char* stringConst;
Exp* exp;
StmtList* stmtList;
Stmt* stmt;
Decl* decl;
DeclList* declList;
ExpList* expList;
Type* type;
Body* body;
Var *var;
}
%token <intConst> tINTCONST
%token <boolean> tBOOLCONST
%token <stringConst> tIDENTIFIER
%token tPLUS
%token tMINUS
%token tTIMES
%token tDIV
%token tEQUAL
%token tNEQUAL
%token tLT
%token tLTE
%token tGT
%token tGTE
%token tAND
%token tOR
%token tRETURN
%token tWRITE
%token tIF
%token tTHEN
%token tELSE
%token tWHILE
%token tDO
%token tALLOCATE
%token tOF
%token tLENGTH
%token tTRUE
%token tFALSE
%token tNULL
%token tFUNC
%token tEND
%token tVAR
%token tTYPE
%token tBOOL
%token tINT
%token tARRAYOF
%token tRECORDOF
%token tUNIT
%token tINVALID_TOKEN
%type <body> program body
%type <stmtList> statement_list
%type <stmt> statement
%type <decl> var_type
/*declaration has type decList because a single variable declaration can
*declare multiple variable */
%type <declList> decl_list var_decl_list declaration par_decl_list
%type <exp> expression term
%type <expList> act_list
%type <type> type
%type <var> variable
%right tTHEN tELSE
%left tAND tOR
%left tEQUAL tNEQUAL tLT tLTE tGT tGTE
%left tPLUS tMINUS
%left tTIMES tDIV
%start program
%%
program : body { prgBody = $1; }
;
/* body : expression; */
body : decl_list statement_list { $$ = makeProgramBody($1, $2); }
statement_list
: statement { $$ = makeStmtListCons(makeStmtListNil(), $1); }
| statement statement_list { $$ = makeStmtListCons($2, $1); }
;
statement
: tRETURN expression ';'
{ $$ = makeRetStmt($2); }
| tWRITE expression ';'
{ $$ = makeWriteStmt($2); }
| tALLOCATE variable ';'
{ $$ = makeAllocateStmt($2, makeExpIntconst(1)); }
| tALLOCATE variable tOF tLENGTH expression ';'
{ $$ = makeAllocateStmt($2, $5);}
| variable '=' expression ';'
{ $$ = makeAssignmentStmt($1, $3); }
| tIF expression tTHEN statement
{ $$ = makeIfThenStmt($2, $4); }
| tIF expression tTHEN statement tELSE statement
{ $$ = makeIfThenElseStmt($2, $4, $6); }
| tWHILE expression tDO statement
{ $$ = makeWhileLoopStmt($2, $4); }
| '{' statement_list '}'
{ $$ = makeBlockStmt($2); }
;
decl_list
: declaration decl_list { $$ = declListAppend($1, $2); }
| /* epsilon */ { $$ = makeDeclListNil(); }
;
declaration
: tTYPE tIDENTIFIER '=' type ';'
{ $$ = makeDeclListCons(makeDeclListNil(), makeTypeDecl($2, $4)); }
| tFUNC tIDENTIFIER '(' par_decl_list ')' ':' type body tEND tIDENTIFIER
{
if (strcmp($2, $10) != 0) {
char foo[256];
sprintf(foo, "Function declared as '%s' ended with '%s'", $2, $10);
yyerror(foo);
YYERROR;
}
$$ = makeDeclListCons(makeDeclListNil(), makeFuncDecl($2, $4, $7, $8));
}
| tVAR var_decl_list ';'
{$$ = $2;}
;
var_decl_list
: var_type ',' var_decl_list
{$$ = makeDeclListCons($3, $1);}
| var_type
{$$ = makeDeclListCons(makeDeclListNil(), $1);}
;
par_decl_list
: var_decl_list
{$$ = $1;}
| /* epsilon */
{$$ = makeDeclListNil();}
;
var_type
: tIDENTIFIER ':' type
{$$ = makeVarDecl($1, $3);}
;
type
: tIDENTIFIER { $$ = makeTypeCustom($1); }
| tBOOL { $$ = makeTypeBool(); }
| tINT { $$ = makeTypeInt(); }
| tARRAYOF type { $$ = makeTypeArray($2); }
| tUNIT { $$ = makeTypeUnit(); }
| tRECORDOF '{' var_decl_list '}' { $$ = makeTypeRecord($3); }
;
/* TODO: do something like
expression tSOMEOP expression { $$ = makeBinExp($1, $3, $2); }
or just figure out why the exact thing above doesn't work.
*/
expression
: expression tPLUS expression { $$ = makeBinExp($1, $3, tPLUS); }
| expression tMINUS expression { $$ = makeBinExp($1, $3, tMINUS);}
| expression tTIMES expression { $$ = makeBinExp($1, $3, tTIMES);}
| expression tDIV expression { $$ = makeBinExp($1, $3, tDIV);}
| expression tEQUAL expression { $$ = makeBinExp($1, $3, tEQUAL);}
| expression tNEQUAL expression { $$ = makeBinExp($1, $3, tNEQUAL);}
| expression tLT expression { $$ = makeBinExp($1, $3, tLT);}
| expression tLTE expression { $$ = makeBinExp($1, $3, tLTE);}
| expression tGT expression { $$ = makeBinExp($1, $3, tGT);}
| expression tGTE expression { $$ = makeBinExp($1, $3, tGTE);}
| expression tAND expression { $$ = makeBinExp($1, $3, tAND);}
| expression tOR expression { $$ = makeBinExp($1, $3, tOR);}
| term
{$$ = $1;}
;
term
: variable
{$$ = makeExpVar($1);}
| '(' expression ')'
{$$ = $2;}
| tIDENTIFIER '(' act_list ')'
{$$ = makeExpApp($1, $3);}
| '!' term
{$$ = makeExpNot($2);}
| '|' expression '|'
{$$ = makeExpAbs($2);}
| tINTCONST
{$$ = makeExpIntconst($1);}
| tTRUE
{$$ = makeExpTrue();}
| tFALSE
{$$ = makeExpFalse();}
| tNULL
{$$ = makeExpNull();}
;
variable
: variable '[' expression ']'
{$$ = makeVarOffset($1, $3);}
| variable '.' tIDENTIFIER
{$$ = makeVarDot($1, $3);}
| tIDENTIFIER
{$$ = makeVarVar($1);}
;
act_list
: expression ',' act_list
{$$ = makeExpListCons($3, $1);}
| expression
{$$ = makeExpListCons(makeExpListNil(), $1); }
| /* epsilon */
{$$ = makeExpListNil();}
;
%%
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment