program : YPROGRAM decls YBEGIN stmts YEND {$2.symtab = {["integer", "type", "integer"], ...}; $4.symtab = $2.symtab'; $$.type = $4.type;} ; decls : /* empty */ {$$.symtab' = $$.symtab;} | decl ';' decls {$1.symtab = $$.symtab; $3.symtab = $1.symtab'; $$.symtab' = $3.symtab'; ; decl : vardecl {$1.symtab = $$.symtab; $$.symtab' = $$.symtab U $1.symtab';} | procdecl {$1.symtab = $$.symtab; $$.symtab' = $$.symtab U $1.symtab';} ; vardecl : YVAR vars ':' type {$2.type = $4.type; $2.class = "var"; $4.symtab = $$.symtab; $$.symtab' = $2.symtab';} ; type : Yidentifier {$$.type = Lookup($$.symtab, $1.text)[3];} ; vars : var {/** OLD: Enter($1.text, $$.class, $$.type); **/ $$.symtab' = {[$1.text, $$.class, $$.type]};} | var ',' vars {/** OLD: Enter($1.text, $$.class, $$.type); **/ $$.symtab' = {[$1.text, $$.class, $$.type]} U $3.symtab';} ; var : Yidentifier {$$.text = $1;} /* The lexer provides Yidentifier as a string */ ; ... stmts : stmt ';' {$$.type = $1.type; $1.symtab = $$.symtab;} | stmt ';' stmts {$$.type = if ($1.type = "OK" and $3.type = "OK") then "OK" else "ERROR"; $1.symtab = $$.symtab; $3.symtab = $$.symtab;} ; stmt : /* empty */ | var YASSMNT_OP expr {$3.symtab = $$.symtab; $$.type = (if Lookup($$.symtab, $1.text)[3] = $3.type then "OK" else "ERROR"; } ... ; expr : number {$$.type = $1.type;} | char {$$.type = $1.type;} | bool {$$.type = $1.type;} | var {$$.type = Lookup($$.symtab, $1.text);} ... ;