-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
342 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
%{ | ||
/* Lab2 Attention: You are only allowed to add code in this file and start at Line 26.*/ | ||
#include <string.h> | ||
#include "util.h" | ||
#include "symbol.h" | ||
#include "errormsg.h" | ||
#include "absyn.h" | ||
#include "y.tab.h" | ||
|
||
int charPos=1; | ||
|
||
int yywrap(void) | ||
{ | ||
charPos=1; | ||
return 1; | ||
} | ||
|
||
void adjust(void) | ||
{ | ||
EM_tokPos=charPos; | ||
charPos+=yyleng; | ||
} | ||
|
||
/* | ||
* Please don't modify the lines above. | ||
* You can add C declarations of your own below. | ||
*/ | ||
|
||
/* @function: getstr | ||
* @input: a string literal | ||
* @output: the string value for the input which has all the escape sequences | ||
* translated into their meaning. | ||
*/ | ||
char *getstr(const char *str) | ||
{ | ||
//optional: implement this function if you need it | ||
return NULL; | ||
} | ||
|
||
static int input(void); | ||
|
||
char *stringToken() { | ||
yyleng = 1; | ||
int maxlen = 128; | ||
char *s = (char *)malloc(maxlen); | ||
int pos = 0; | ||
char c; | ||
while((c = (char)input()) != EOF) { | ||
++yyleng; | ||
if(c == '\"') { | ||
break; | ||
} | ||
if(c == '\n') { | ||
break; | ||
} | ||
if(c == '\\') { | ||
c = (char)input(); | ||
++yyleng; | ||
switch(c) { // still have other conditions | ||
case 'n': | ||
c = '\n'; | ||
break; | ||
case 't': | ||
c = '\t'; | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
if(pos >= maxlen) { | ||
s = (char *)realloc(s, maxlen * 2); | ||
maxlen = maxlen * 2; | ||
} | ||
s[pos] = (char)c; | ||
++pos; | ||
} | ||
s[pos] = '\0'; | ||
return s; | ||
} | ||
|
||
int commentStartCount = 0; | ||
|
||
%} | ||
/* You can add lex definitions here. */ | ||
|
||
%Start COMMENT | ||
%% | ||
/* | ||
* Below is an example, which you can wipe out | ||
* and write reguler expressions and actions of your own. | ||
*/ | ||
|
||
"\n" {adjust(); EM_newline(); continue;} | ||
<INITIAL>(" "|"\t")+ {adjust();} | ||
|
||
<INITIAL>while {adjust(); return WHILE;} | ||
<INITIAL>for {adjust(); return FOR;} | ||
<INITIAL>to {adjust(); return TO;} | ||
<INITIAL>break {adjust(); return BREAK;} | ||
<INITIAL>let {adjust(); return LET;} | ||
<INITIAL>in {adjust(); return IN;} | ||
<INITIAL>end {adjust(); return END;} | ||
<INITIAL>function {adjust(); return FUNCTION;} | ||
<INITIAL>var {adjust(); return VAR;} | ||
<INITIAL>type {adjust(); return TYPE;} | ||
<INITIAL>array {adjust(); return ARRAY;} | ||
<INITIAL>if {adjust(); return IF;} | ||
<INITIAL>then {adjust(); return THEN;} | ||
<INITIAL>else {adjust(); return ELSE;} | ||
<INITIAL>do {adjust(); return DO;} | ||
<INITIAL>of {adjust(); return OF;} | ||
<INITIAL>nil {adjust(); return NIL;} | ||
|
||
<INITIAL>\x22 {yylval.sval=stringToken(); adjust(); return STRING;} | ||
<INITIAL>"/*" {adjust(); ++commentStartCount; BEGIN COMMENT;} | ||
|
||
<INITIAL>":=" {adjust(); return ASSIGN;} | ||
<INITIAL>"," {adjust(); return COMMA;} | ||
<INITIAL>":" {adjust(); return COLON;} | ||
<INITIAL>";" {adjust(); return SEMICOLON;} | ||
<INITIAL>"(" {adjust(); return LPAREN;} | ||
<INITIAL>")" {adjust(); return RPAREN;} | ||
<INITIAL>"[" {adjust(); return LBRACK;} | ||
<INITIAL>"]" {adjust(); return RBRACK;} | ||
<INITIAL>"{" {adjust(); return LBRACE;} | ||
<INITIAL>"}" {adjust(); return RBRACE;} | ||
<INITIAL>"." {adjust(); return DOT;} | ||
<INITIAL>"+" {adjust(); return PLUS;} | ||
<INITIAL>"-" {adjust(); return MINUS;} | ||
<INITIAL>"*" {adjust(); return TIMES;} | ||
<INITIAL>"/" {adjust(); return DIVIDE;} | ||
<INITIAL>"=" {adjust(); return EQ;} | ||
<INITIAL>"!="|"<>" {adjust(); return NEQ;} | ||
<INITIAL>"<=" {adjust(); return LE;} | ||
<INITIAL>"<" {adjust(); return LT;} | ||
<INITIAL>">=" {adjust(); return GE;} | ||
<INITIAL>">" {adjust(); return GT;} | ||
<INITIAL>"&" {adjust(); return AND;} | ||
<INITIAL>"|" {adjust(); return OR;} | ||
|
||
<INITIAL>[A-Za-z][A-Za-z0-9_]* {adjust(); yylval.sval=String(yytext); return ID;} | ||
<INITIAL>[0-9]+ {adjust(); yylval.ival=atoi(yytext); return INT;} | ||
|
||
<INITIAL>. {adjust(); EM_error(charPos, "illegal character");} | ||
|
||
<COMMENT>"/*" {adjust(); ++commentStartCount;} | ||
<COMMENT>"*/" {adjust(); --commentStartCount; if(commentStartCount==0) {BEGIN INITIAL;}} | ||
<COMMENT>(" "|"\t")+ {adjust();} | ||
<COMMENT>. {adjust();} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
%{ | ||
#include <stdio.h> | ||
#include "util.h" | ||
#include "errormsg.h" | ||
#include "symbol.h" | ||
#include "absyn.h" | ||
|
||
int yylex(void); /* function prototype */ | ||
|
||
A_exp absyn_root; | ||
|
||
void yyerror(char *s) | ||
{ | ||
EM_error(EM_tokPos, "%s", s); | ||
} | ||
%} | ||
|
||
|
||
%union { | ||
int pos; | ||
int ival; | ||
string sval; | ||
A_exp exp; | ||
A_expList explist; | ||
A_var var; | ||
A_decList declist; | ||
A_dec dec; | ||
A_efieldList efieldlist; | ||
A_efield efield; | ||
A_namety namety; | ||
A_nametyList nametylist; | ||
A_fieldList fieldlist; | ||
A_field field; | ||
A_fundecList fundeclist; | ||
A_fundec fundec; | ||
A_ty ty; | ||
} | ||
|
||
%token <sval> ID STRING | ||
%token <ival> INT | ||
|
||
%token | ||
COMMA COLON SEMICOLON LPAREN RPAREN LBRACK RBRACK | ||
LBRACE RBRACE DOT | ||
PLUS MINUS TIMES DIVIDE EQ NEQ LT LE GT GE | ||
AND OR ASSIGN | ||
ARRAY IF THEN ELSE WHILE FOR TO DO LET IN END OF | ||
BREAK NIL | ||
FUNCTION VAR TYPE | ||
|
||
%type <exp> exp expseq | ||
%type <explist> actuals nonemptyactuals sequencing sequencing_exps | ||
%type <var> lvalue one oneormore | ||
%type <declist> decs decs_nonempty | ||
%type <dec> decs_nonempty_s vardec | ||
%type <efieldlist> rec rec_nonempty | ||
%type <efield> rec_one | ||
%type <nametylist> tydec | ||
%type <namety> tydec_one | ||
%type <fieldlist> tyfields tyfields_nonempty | ||
%type <ty> ty | ||
%type <fundeclist> fundec | ||
%type <fundec> fundec_one | ||
|
||
%nonassoc ASSIGN | ||
%left OR | ||
%left AND | ||
%nonassoc EQ NEQ LT LE GT GE | ||
%left PLUS MINUS | ||
%left TIMES DIVIDE | ||
%left UMINUS | ||
|
||
%start program | ||
|
||
%% | ||
|
||
program: exp {absyn_root = $1;}; | ||
|
||
exp: lvalue {$$ = A_VarExp(EM_tokPos, $1);} | ||
|NIL {$$ = A_NilExp(EM_tokPos);} | ||
|LPAREN sequencing_exps RPAREN {$$ = A_SeqExp(EM_tokPos, $2);} | ||
|LPAREN exp RPAREN {$$ = $2;} | ||
|INT {$$ = A_IntExp(EM_tokPos, $1);} | ||
|STRING {$$ = A_StringExp(EM_tokPos, $1);} | ||
|MINUS exp %prec UMINUS {$$ = A_OpExp(EM_tokPos, A_minusOp, A_IntExp(EM_tokPos, 0), $2);} | ||
|ID LPAREN actuals RPAREN {$$ = A_CallExp(EM_tokPos, S_Symbol($1), $3);} | ||
|exp PLUS exp {$$ = A_OpExp(EM_tokPos, A_plusOp, $1, $3);} | ||
|exp MINUS exp {$$ = A_OpExp(EM_tokPos, A_minusOp, $1, $3);} | ||
|exp TIMES exp {$$ = A_OpExp(EM_tokPos, A_timesOp, $1, $3);} | ||
|exp DIVIDE exp {$$ = A_OpExp(EM_tokPos, A_divideOp, $1, $3);} | ||
|exp EQ exp {$$ = A_OpExp(EM_tokPos, A_eqOp, $1, $3);} | ||
|exp NEQ exp {$$ = A_OpExp(EM_tokPos, A_neqOp, $1, $3);} | ||
|exp LT exp {$$ = A_OpExp(EM_tokPos, A_ltOp, $1, $3);} | ||
|exp LE exp {$$ = A_OpExp(EM_tokPos, A_leOp, $1, $3);} | ||
|exp GT exp {$$ = A_OpExp(EM_tokPos, A_gtOp, $1, $3);} | ||
|exp GE exp {$$ = A_OpExp(EM_tokPos, A_geOp, $1, $3);} | ||
|exp AND exp {$$ = A_IfExp(EM_tokPos, $1, $3, A_IntExp(EM_tokPos, 0));} | ||
|exp OR exp {$$ = A_IfExp(EM_tokPos, $1, A_IntExp(EM_tokPos, 1), $3);} | ||
|ID LBRACE rec RBRACE {$$ = A_RecordExp(EM_tokPos, S_Symbol($1), $3);} | ||
|ID LBRACK exp RBRACK OF exp {$$ = A_ArrayExp(EM_tokPos, S_Symbol($1), $3, $6);} | ||
|lvalue ASSIGN exp {$$ = A_AssignExp(EM_tokPos, $1, $3);} | ||
|IF exp THEN exp ELSE exp {$$ = A_IfExp(EM_tokPos, $2, $4, $6);} | ||
|IF exp THEN exp {$$ = A_IfExp(EM_tokPos, $2, $4, NULL);} | ||
|WHILE exp DO exp {$$ = A_WhileExp(EM_tokPos, $2, $4);} | ||
|FOR ID ASSIGN exp TO exp DO exp {$$ = A_ForExp(EM_tokPos, S_Symbol($2), $4, $6, $8);} | ||
|BREAK {$$ = A_BreakExp(EM_tokPos);} | ||
|LET decs IN expseq END {$$ = A_LetExp(EM_tokPos, $2, $4);} | ||
; | ||
|
||
expseq : sequencing {$$ = A_SeqExp(EM_tokPos, $1);} | ||
; | ||
|
||
sequencing : {$$ = NULL;} | ||
|exp {$$ = A_ExpList($1, NULL);} | ||
|sequencing_exps {$$ = $1;} | ||
; | ||
|
||
sequencing_exps : exp SEMICOLON exp {$$ = A_ExpList($1, A_ExpList($3, NULL));} | ||
|exp SEMICOLON sequencing_exps {$$ = A_ExpList($1, $3);} | ||
; | ||
|
||
actuals : {$$ = NULL;} | ||
|nonemptyactuals {$$ = $1;} | ||
; | ||
|
||
nonemptyactuals : exp {$$ = A_ExpList($1, NULL);} | ||
|exp COMMA nonemptyactuals {$$ = A_ExpList($1, $3);} | ||
; | ||
|
||
rec : {$$ = NULL;} | ||
|rec_nonempty {$$ = $1;} | ||
; | ||
|
||
rec_nonempty : rec_one {$$ = A_EfieldList($1, NULL);} | ||
|rec_one COMMA rec_nonempty {$$ = A_EfieldList($1, $3);} | ||
; | ||
|
||
rec_one : ID EQ exp {$$ = A_Efield(S_Symbol($1), $3);} | ||
; | ||
|
||
decs : {$$ = NULL;} | ||
|decs_nonempty {$$ = $1;} | ||
; | ||
|
||
decs_nonempty : decs_nonempty_s {$$ = A_DecList($1, NULL);} | ||
|decs_nonempty_s decs_nonempty {$$ = A_DecList($1, $2);} | ||
; | ||
|
||
decs_nonempty_s : tydec {$$ = A_TypeDec(EM_tokPos, $1);} | ||
|vardec {$$ = $1;} | ||
|fundec {$$ = A_FunctionDec(EM_tokPos, $1);} | ||
; | ||
|
||
tydec : tydec_one {$$ = A_NametyList($1, NULL);} | ||
|tydec_one tydec {$$ = A_NametyList($1, $2);} | ||
; | ||
|
||
tydec_one : TYPE ID EQ ty {$$ = A_Namety(S_Symbol($2), $4);} | ||
; | ||
|
||
ty : ID {$$ = A_NameTy(EM_tokPos, S_Symbol($1));} | ||
|LBRACE tyfields RBRACE {$$ = A_RecordTy(EM_tokPos, $2);} | ||
|ARRAY OF ID {$$ = A_ArrayTy(EM_tokPos, S_Symbol($3));} | ||
; | ||
|
||
tyfields : {$$ = NULL;} | ||
|tyfields_nonempty {$$ = $1;} | ||
; | ||
|
||
tyfields_nonempty : ID COLON ID {$$ = A_FieldList(A_Field(EM_tokPos, S_Symbol($1), S_Symbol($3)), NULL);} | ||
|ID COLON ID COMMA tyfields_nonempty {$$ = A_FieldList(A_Field(EM_tokPos, S_Symbol($1), S_Symbol($3)), $5);} | ||
; | ||
|
||
vardec : VAR ID ASSIGN exp {$$ = A_VarDec(EM_tokPos,S_Symbol($2),S_Symbol(""),$4);} | ||
|VAR ID COLON ID ASSIGN exp {$$ = A_VarDec(EM_tokPos,S_Symbol($2),S_Symbol($4),$6);} | ||
; | ||
|
||
fundec : fundec_one {$$ = A_FundecList($1, NULL);} | ||
|fundec_one fundec {$$ = A_FundecList($1, $2);} | ||
; | ||
|
||
fundec_one : FUNCTION ID LPAREN tyfields RPAREN EQ exp {$$ = A_Fundec(EM_tokPos, S_Symbol($2), $4, S_Symbol(""), $7);} | ||
|FUNCTION ID LPAREN tyfields RPAREN COLON ID EQ exp {$$ = A_Fundec(EM_tokPos, S_Symbol($2), $4, S_Symbol($7), $9);} | ||
; | ||
|
||
|
||
lvalue : ID {$$ = A_SimpleVar(EM_tokPos, S_Symbol($1));} | ||
|lvalue DOT ID {$$ = A_FieldVar(EM_tokPos, $1, S_Symbol($3));} | ||
|lvalue LBRACK exp RBRACK {$$ = A_SubscriptVar(EM_tokPos, $1, $3);} | ||
|ID LBRACK exp RBRACK {$$ = A_SubscriptVar(EM_tokPos, A_SimpleVar(EM_tokPos, S_Symbol($1)), $3);} | ||
; | ||
|