def statement(): """ Parses statement = ident selector ":=" expression | ident "(" [expression {"," expression}] ")" | compoundStatement | "if" expression "then" Statement ["else" Statement] | "while" expression "do" Statement. Generates code for the statement if no error is reported """ if SC.sym not in FIRSTSTATEMENT: mark("statement expected") getSym() while SC.sym not in FIRSTSTATEMENT | STRONGSYMS | FOLLOWSTATEMENT: getSym() if SC.sym == IDENT: x = find(SC.val) getSym() x = genVar(x) if type(x) in {Var, Ref}: x = selector(x) if SC.sym == BECOMES: getSym() y = expression() if x.tp == y.tp in {Bool, Int}: # if type(x) == Var: x = genAssign(x, y) if type(x) == Var: print("x: ", x, "y: ", y) x = genAssign2(x, y) else: mark("illegal assignment") else: mark("incompatible assignment") elif SC.sym == EQ: mark(":= expected") getSym() y = expression() else: mark(":= expected") elif type(x) in {Proc, StdProc} and SC.sym == LPAREN: getSym() fp, i = x.par, 0 # list of formal parameters if SC.sym in FIRSTEXPRESSION: y = expression() if i < len(fp): if type(fp[i]) == Var or type(y) == Var: # fp[i] == Ref and ty if type(x) == Proc: genActualPara(y, fp[i], i) i = i + 1 else: mark("illegal parameter mode") else: mark("extra parameter") while SC.sym == COMMA: getSym() y = expression() if i < len(fp): if type(fp[i]) == Var or type(y) == Var: if type(x) == Proc: genActualPara(y, fp[i], i) i = i + 1 else: mark("illegal parameter mode") else: mark("extra parameter") if i < len(fp): mark("too few parameters") if SC.sym == RPAREN: getSym() else: mark("')' expected") if type(x) == StdProc: if x.name == "read": x = genRead(y) elif x.name == "write": x = genWrite(y) elif x.name == "writeln": x = genWriteln() else: x = genCall(x) else: mark("variable or procedure expected") elif SC.sym == BEGIN: x = compoundStatement() elif SC.sym == IF: getSym() x = expression() if x.tp == Bool: x = genCond(x) else: mark("boolean expected") if SC.sym == THEN: getSym() else: mark("'then' expected") y = statement() if SC.sym == ELSE: y = genThen(x, y) getSym() z = statement() x = genIfElse(x, y, z) else: x = genIfThen(x, y) elif SC.sym == WHILE: getSym() t = genTarget() x = expression() if x.tp == Bool: x = genCond(x) else: mark("boolean expected") if SC.sym == DO: getSym() else: mark("'do' expected") y = statement() x = genWhile(t, x, y) else: mark("invalid statement") x = None return x
elif x.name == 'writeln': x = genWriteln() else: x = genCall(x) else: mark("variable or procedure expected") elif SC.sym == BEGIN: x = compoundStatement() elif SC.sym == IF: getSym(); x = expression(); q=1; if x.tp == Bool: x = genCond(x) elif x.tp == Int: q = 0 # if we skipped genrelation, prepare to skip following statement else: mark('boolean expected') if SC.sym == THEN: getSym() else: mark("'then' expected") if q=1: y = statement() # if (FALSE (q=0)) skip if SC.sym == ELSE and q=1: # if (TRUE (q=1)) then perform THEN y = genThen(x, y); getSym(); z = statement(); x = genIfElse(x, y, z) else: x = genIfThen(x, y) elif SC.sym == WHILE: getSym(); t = genTarget(); x = expression() if x.tp == Bool: x = genCond(x) else: mark('boolean expected') if SC.sym == DO: getSym() else: mark("'do' expected") y = statement(); x = genWhile(t, x, y) else: mark('invalid statement'); x = None return x #=============================================== def typ(): """ Parses