def factor(): """ Parses factor = ident selector | integer | "(" expression ")" | "not" factor. Generates code for the factor if no error is reported """ if SC.sym not in FIRSTFACTOR: mark("factor expected"); getSym() while SC.sym not in FIRSTFACTOR | STRONGSYMS | FOLLOWFACTOR: getSym() if SC.sym == IDENT: x = find(SC.val) if type(x) in {Var, Ref}: x = genVar(x) elif type(x) == Const: x = Const(x.tp, x.val); x = genConst(x) else: mark('variable or constant expected') getSym(); x = selector(x) elif SC.sym == NUMBER: x = Const(Int, SC.val); x = genConst(x); getSym() elif SC.sym == LPAREN: getSym(); x = expression() if SC.sym == RPAREN: getSym() else: mark(") expected") elif SC.sym == NOT: getSym(); x = factor() if x.tp != Bool: mark('not boolean') elif type(x) == Const: x.val = 1 - x.val # constant folding else: x = genUnaryOp(NOT, x) else: mark("factor expected"); x = None return x
def typ(): """ Parses type = ident | "array" "[" expression ".." expression "]" "of" type | "record" typedIds {";" typedIds} "end". Returns a type descriptor """ if SC.sym not in FIRSTTYPE: getSym() mark("type expected", 37) while SC.sym not in FIRSTTYPE | FOLLOWTYPE | STRONGSYMS: getSym() if SC.sym == IDENT: ident = SC.val x = find(ident) getSym() if type(x) == Type: x = Type(x.tp) else: mark('not a type', 38) elif SC.sym == ARRAY: getSym() if SC.sym == LBRAK: getSym() else: mark("'[' expected", 39) x = expression() if type(x) != Const or x.val < 0: mark('bad lower bound', 40) if SC.sym == PERIOD: getSym() else: mark("'.' expected", 41) if SC.sym == PERIOD: getSym() else: mark("'.' expected", 42) y = expression() if type(y) != Const or y.val < x.val: mark('bad upper bound', 43) if SC.sym == RBRAK: getSym() else: mark("']' expected", 44) if SC.sym == OF: getSym() else: mark("'of' expected", 45) z = typ().tp l = y.val - x.val + 1 x = Type(genArray(Array(z, x.val, l))) elif SC.sym == RECORD: getSym() openScope() typedIds(Var) while SC.sym == SEMICOLON: getSym() typedIds(Var) if SC.sym == END: getSym() else: mark("'end' expected", 46) r = topScope() closeScope() x = Type(genRec(Record(r))) else: mark("type expected", 47) x = Type(None) return x
def factor(): """ Parses factor = ident «write(ident)» selector | integer «write(integer)» | "(" «write('(')» expression ")" «write(')')» | "not" «write('not ') factor. Generates code for the factor if no error is reported """ if SC.sym not in FIRSTFACTOR: mark("expression expected") getSym() while SC.sym not in FIRSTFACTOR | STRONGSYMS | FOLLOWFACTOR: getSym() if SC.sym == IDENT: x = find(SC.val) if type(x) in {Var, Ref}: x = CG.genVar(x) elif type(x) == Const: x = Const(x.tp, x.val) x = CG.genConst(x) else: mark('expression expected') write(SC.val) writeHtml(SC.val) getSym() x = selector(x) elif SC.sym == NUMBER: x = Const(Int, SC.val) x = CG.genConst(x) write(str(SC.val)) writeHtml(str(SC.val)) getSym() elif SC.sym == LPAREN: write('(') writeHtml('(') getSym() x = expression() if SC.sym == RPAREN: write(')') writeHtml(')') getSym() else: mark(") expected") elif SC.sym == NOT: write('not ') writeHtml('not ') getSym() x = factor() if x.tp != Bool: mark('not boolean') elif type(x) == Const: x.val = 1 - x.val # constant folding else: x = CG.genUnaryOp(NOT, x) else: x = Const(None, 0) return x
def typ(): if SC.sym not in FIRSTTYPE: getSym() mark("type expected") while SC.sym not in FIRSTTYPE | STRONGSYMS | FOLLOWTYPE: getSym() if SC.sym == IDENT: ident = SC.val x = find(ident) getSym() if type(x) == Type: x = Type(x.val) else: mark('not a type') x = Type(None) elif SC.sym == ARRAY: getSym() if SC.sym == LBRAK: getSym() else: mark("'[' expected") x = expression() if SC.sym == PERIOD: getSym() else: mark("'.' expected") if SC.sym == PERIOD: getSym() else: mark("'.' expected") y = expression() if SC.sym == RBRAK: getSym() else: mark("']' expected") if SC.sym == OF: getSym() else: mark("'of' expected") z = typ().val if type(x) != Const or x.val < 0: mark('bad lower bound') x = Type(None) elif type(y) != Const or y.val < x.val: mark('bad upper bound') x = Type(None) else: x = Type(CG.genArray(Array(z, x.val, y.val - x.val + 1))) elif SC.sym == RECORD: getSym() openScope() typedIds(Var) while SC.sym == SEMICOLON: getSym() typedIds(Var) if SC.sym == END: getSym() else: mark("'end' expected") r = topScope() closeScope() x = Type(CG.genRec(Record(r))) else: x = Type(None) return x
def typ(): """ Parses type = ident | "array" "[" expression ".." expression "]" "of" type | "record" typedIds {";" typedIds} "end". Returns a type descriptor """ if SC.sym not in FIRSTTYPE: getSym(); mark("type expected") while SC.sym not in FIRSTTYPE | FOLLOWTYPE |STRONGSYMS: getSym() if SC.sym == IDENT: ident = SC.val; x = find(ident); getSym() if type(x) == Type: x = Type(x.tp) else: mark('not a type') elif SC.sym == ARRAY: getSym() if SC.sym == LBRAK: getSym() else: mark("'[' expected") x = expression() if type(x) != Const or x.val < 0: mark('bad lower bound') if SC.sym == PERIOD: getSym() else: mark("'.' expected") if SC.sym == PERIOD: getSym() else: mark("'.' expected") y = expression() if type(y) != Const or y.val < x.val: mark('bad upper bound') if SC.sym == RBRAK: getSym() else: mark("']' expected") if SC.sym == OF: getSym() else: mark("'of' expected") z = typ().tp; l = y.val - x.val + 1 x = Type(genArray(Array(z, x.val, l))) elif SC.sym == RECORD: getSym(); openScope(); typedIds(Var) while SC.sym == SEMICOLON: getSym(); typedIds(Var) if SC.sym == END: getSym() else: mark("'end' expected") r = topScope(); closeScope() x = Type(genRec(Record(r))) else: mark("type expected"); x = Type(None) return x
def typ(): if SC.sym == IDENT: ident = SC.val; x = find(ident) if type(x) == Type: x = Type(x.val); getSym() else: mark('type identifier expected') elif SC.sym == LBRAK: getSym(); x = expression() if SC.sym == DOTDOT: getSym() else: mark("'..' expected") y = expression() if SC.sym == RBRAK: getSym() else: mark("']' expected") if SC.sym == RARROW: getSym() else: mark("'→' expected") z = typ().val; if type(x) != Const or x.val < 0: mark('bad lower bound') elif type(y) != Const or y.val < x.val: mark('bad upper bound') else: x = Type(CG.genArray(Array(z, x.val, y.val - x.val + 1))) elif SC.sym == LPAREN: getSym(); openScope(); typedIds() if SC.sym == RPAREN: getSym() else: mark("')' expected") r = topScope(); closeScope() x = Type(CG.genRec(Record(r))) elif SC.sym == FULLPAREN: pass elif SC.sym == SET: getSym(); if SC.sym == LBRAK: getSym() else: mark ("'[' expected") x = expression() if SC.sym == DOTDOT: getSym() else: mark("'..' expected") y = expression() if SC.sym == RBRAK: getSym() else: mark("']' expected") if type(x) != Const: mark('bad lower bound') elif type(y) != Const or y.val < x.val: mark('bad upper bound') else: x = Type(CG.genSet(Set(x.val, y.val - x.val + 1))) else: mark('type expected') return x
def factor(): """ Parses factor = ident selector | integer | "(" expression ")" | "not" factor. Generates code for the factor if no error is reported """ if SC.sym not in FIRSTFACTOR: mark("factor expected", 8) getSym() while SC.sym not in FIRSTFACTOR | STRONGSYMS | FOLLOWFACTOR: getSym() if SC.sym == IDENT: x = find(SC.val) if type(x) in {Var, Ref}: x = genVar(x) elif type(x) == Const: x = Const(x.tp, x.val) x = genConst(x) else: mark('variable or constant expected', 9) getSym() x = selector(x) elif SC.sym == NUMBER: x = Const(Int, SC.val) x = genConst(x) getSym() elif SC.sym == LPAREN: getSym() x = expression() if SC.sym == RPAREN: getSym() else: mark(") expected", 10) elif SC.sym == NOT: getSym() x = factor() if x.tp != Bool: mark('not boolean', 11) elif type(x) == Const: x.val = 1 - x.val # constant folding else: x = genUnaryOp(NOT, x) else: mark("factor expected", 12) x = None return x
def factor(): if SC.sym not in FIRSTFACTOR: mark("expression expected") getSym() while SC.sym not in FIRSTFACTOR | STRONGSYMS | FOLLOWFACTOR: getSym() if SC.sym == IDENT: x = find(SC.val) if type(x) in {Var, Ref}: x = CG.genVar(x) elif type(x) == Const: x = Const(x.tp, x.val) x = CG.genConst(x) else: mark('expression expected') getSym() x = selector(x) elif SC.sym == NUMBER: x = Const(Int, SC.val) x = CG.genConst(x) getSym() elif SC.sym == LPAREN: getSym() x = expression() if SC.sym == RPAREN: getSym() else: mark(") expected") elif SC.sym == NOT: getSym() x = factor() if x.tp != Bool: mark('not boolean') elif type(x) == Const: x.val = 1 - x.val # constant folding else: x = CG.genUnaryOp(NOT, x) elif SC.sym == TILDE: getSym() x = factor() if x.tp != Int: mark('not integer') elif type(x) == Const: x.val = ~x.val # constant folding else: x = CG.genUnaryOp(TILDE, x) else: x = Const(None, 0) return x
def factor(): if SC.sym == IDENT: x = find(SC.val) if type(x) == Var: x = CG.genVar(x); getSym() elif type(x) == Const: x = Const(x.tp, x.val); x = CG.genConst(x); getSym() else: mark('variable or constant identifier expected') x = selector(x) elif SC.sym == NUMBER: x = Const(Int, SC.val); x = CG.genConst(x); getSym() elif SC.sym == LPAREN: getSym(); x = expression() if SC.sym == RPAREN: getSym() else: mark(') expected') elif SC.sym == LBRACE: getSym() if SC.sym in FIRSTEXPRESSION: y = expression() if y.tp == Int: x = CG.genUnaryOp(SET, y) else: mark('not integer') while SC.sym == COMMA: getSym(); y = expression() if y.tp == Int: y = CG.genUnaryOp(SET, y) else: mark("not integer") x = CG.genBinaryOp(UNION, x, y) else: x = Const(Set(0, 32), 0); x = CG.genConst(x) if SC.sym == RBRACE: getSym() else: mark('} expected') elif SC.sym == NOT: getSym(); x = factor() if x.tp != Bool: mark('not boolean') elif type(x) == Const: x.val = 1 - x.val # constant folding else: x = CG.genUnaryOp(NOT, x) elif SC.sym in {CARD, COMPLEMENT}: op = SC.sym; getSym(); x = factor() if type(x.tp) == Set: x = CG.genUnaryOp(op, x) else: mark('set expected') else: mark('expression expected') return x
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", 20) 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) # else: # mark('illegal assignment', 21) else: mark('incompatible assignment', 22) elif SC.sym == EQ: mark(':= expected', 23) getSym() y = expression() else: mark(':= expected', 24) 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: if type(x) == Proc: genActualPara(y, fp[i], i) #i = i + 1 else: mark('illegal parameter mode', 25) i = i + 1 else: mark('extra parameter', 26) 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', 27) i = i + 1 else: mark('extra parameter', 28) if i < len(fp): mark('too few parameters', 29) #if i > 0: mark('too few parameters') if SC.sym == RPAREN: getSym() else: mark("')' expected", 30) 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", 31) elif SC.sym == BEGIN: x = compoundStatement() elif SC.sym == IF: getSym() x = expression() # if x.tp == Bool: x = genCond(x) # else: mark('boolean expected', 32) # if SC.sym == THEN: getSym() # else: mark("'then' expected", 33) # y = statement() # if SC.sym == ELSE: # y = genThen(x, y); getSym(); z = statement(); # x = genIfElse(x, y, z) # else: x = genIfThen(x, y) # eliminate dead code resulting from boolean constants if x.tp != Bool: mark('boolean expected', 32) if SC.sym == THEN: getSym() else: mark("'then' expected", 33) if type(x) == Const and x.val == 1: # if true then S -> S x = statement() if SC.sym == ELSE: # if true then S else T -> S getSym() CG.emit = False statement() # T CG.emit = True elif type(x) == Const and x.val == 0: # if false then S -> skip CG.emit = False statement() CG.emit = True if SC.sym == ELSE: # if false then S else T -> T getSym() x = statement() #T else: # then x = genCond(x) # S y = statement() #print("IF S: "+str(y)) if SC.sym == ELSE: y = genThen(x, y) getSym() z = statement() x = genIfElse(x, y, z) else: #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', 34) if SC.sym == DO: getSym() else: mark("'do' expected", 35) y = statement() x = genWhile(t, x, y) else: mark('invalid statement', 36) x = None return x
def statement(): if SC.sym == IDENT: # x := y, y(...), x ← y(...) # type(x) == Proc, StdProc: check no result parameters needed; call, y := true, x # type(x) ≠ Proc, StdProc: x := selector(): # sym == BECOMES: assignment; call := false # sym == LARROW: check result paramter match, type(y) is Proc, StdProc, x = find(SC.val) if type(x) in {Proc, StdProc}: # procedure call without result if x.res != []: mark('variable for result expected') getSym(); call, xs, y = True, [], x elif type(x) == Var: # assignment or procedure call with result x = find(SC.val); x = CG.genVar(x); getSym() if SC.sym in FIRSTSELECTOR: xs = [CG.genLeftAssign(selector(x))] # array or field update else: # multiple assignment or procedure call with result xs = [CG.genLeftAssign(x)] while SC.sym == COMMA: getSym(); if SC.sym == IDENT: x = find(SC.val) if x.name not in {x.name for x in xs}: if type(x) == Var: xs += [CG.genLeftAssign(CG.genVar(x))]; getSym() else: mark('variable identifier expected') else: mark('duplicate variable identifier') else: mark('identifier expected') if SC.sym == BECOMES: getSym(); call = False; ys = [CG.genRightAssign(expression())] # xs := ys while SC.sym == COMMA: getSym(); ys += [CG.genRightAssign(expression())] if len(xs) == len(ys): for x, y in zip(reversed(xs), reversed(ys)): if compatible(x.tp, y.tp): x = CG.genAssign(x, y) else: mark('incompatible assignment') else: mark('unbalanced assignment') elif SC.sym == LARROW: getSym() if SC.sym == IDENT: y = find(SC.val); getSym(); call = True else: mark('procedure identifier expected') if type(y) in {Proc, StdProc}: if len(xs) == len(y.res): for x, r in zip(xs, y.res): if not compatible(x.tp, r.tp): mark('incompatible call') else: mark('unbalanced call') else: mark('procedure expected') else: mark(':= or ← expected') else: mark("variable or procedure expected") if call: # call y(ap) or xs ← y(ap) fp, ap, i = y.par, [], 0 # list of formals, list of actuals if SC.sym == LPAREN: getSym() else: mark("'(' expected") if SC.sym in FIRSTEXPRESSION: a = expression() if i < len(fp): if compatible(fp[i].tp, a.tp): ap.append(CG.genActualPara(a, fp[i], i)) else: mark('incompatible parameter') else: mark('extra parameter') i = i + 1 while SC.sym == COMMA: getSym() a = expression() if i < len(fp): if compatible(fp[i].tp, a.tp): ap.append(CG.genActualPara(a, fp[i], i)) else: mark('incompatible parameter') else: mark('extra parameter') i = i + 1 if SC.sym == RPAREN: getSym() else: mark("')' expected") if i < len(fp): mark('too few parameters') elif type(y) == StdProc: if y.name == 'read': x = CG.genRead(x) elif y.name == 'write': x = CG.genWrite(a) elif y.name == 'writeln': x = CG.genWriteln() else: x = CG.genCall(xs, y, ap) elif SC.sym == IF: getSym(); x = expression(); if x.tp == Bool: x = CG.genThen(x) else: mark('boolean expected') if SC.sym == THEN: getSym() else: mark("'then' expected") y = statementSuite() if SC.sym == ELSE: getSym() y = CG.genElse(x, y) z = statementSuite() x = CG.genIfElse(x, y, z) else: x = CG.genIfThen(x, y) elif SC.sym == WHILE: getSym(); t = CG.genWhile(); x = expression() if x.tp == Bool: x = CG.genDo(x) else: mark('boolean expected') if SC.sym == DO: getSym() else: mark("'do' expected") y = statementSuite() x = CG.genWhileDo(t, x, y) else: mark('statement expected') return x
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) 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(); q=1; if x.tp == Bool: x = genCond(x) elif x.tp == Int: q = 0 # if we skipped genrelation, prepare to skip following statement
def typ(l): """ Parses type(l) = ident «write(ident)» | "array" «writeln; write((l + 1) * indent + 'array ')» "[" «write('[')» expression ".." «write(' .. ')» expression "]" «write(']')» "of" «write(' of ')» type(l)| "record" «writeln; write((l + 1) * indent + 'record')» typedIds(l) {";" «write(';')» typedIds(l)} "end" «writeln; write((l + 1) * indent + 'end')». Returns a type descriptor """ if SC.sym not in FIRSTTYPE: getSym() mark("type expected") while SC.sym not in FIRSTTYPE | STRONGSYMS | FOLLOWTYPE: getSym() if SC.sym == IDENT: write(SC.val) ident = SC.val x = find(ident) getSym() if type(x) == Type: x = Type(x.tp) else: mark('not a type') x = Type(None) elif SC.sym == ARRAY: writeln() write((l + 1) * indent + 'array ') getSym() if SC.sym == LBRAK: write('[') getSym() else: mark("'[' expected") x = expression() if SC.sym == PERIOD: write(' .') getSym() else: mark("'.' expected") if SC.sym == PERIOD: write('. ') getSym() else: mark("'.' expected") y = expression() if SC.sym == RBRAK: write(']') getSym() else: mark("']' expected") if SC.sym == OF: write(' of ') getSym() else: mark("'of' expected") z = typ(l + 1).tp if type(x) != Const or x.val < 0: mark('bad lower bound') x = Type(None) elif type(y) != Const or y.val < x.val: mark('bad upper bound') y = Type(None) else: x = Type(CG.genArray(Array(z, x.val, y.val - x.val + 1))) elif SC.sym == RECORD: writeln() write((l + 1) * indent + 'record ') writeln() write((l + 2) * indent) getSym() openScope() typedIds(Var, l + 2) while SC.sym == SEMICOLON: write(';') writeln() write((l + 2) * indent) getSym() typedIds(Var, l + 2) if SC.sym == END: writeln() write((l + 1) * indent + 'end') getSym() else: mark("'end' expected") r = topScope() closeScope() x = Type(CG.genRec(Record(r))) else: x = Type(None) return x
def statement(): 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() if type(x) in {Var, Ref}: x = CG.genVar(x) x = selector(x) if SC.sym == BECOMES: getSym() y = expression() if x.tp == y.tp in {Bool, Int}: x = CG.genAssign(x, y) else: mark('incompatible assignment') elif SC.sym == EQ: mark(':= expected') getSym() y = expression() else: mark(':= expected') elif type(x) in {Proc, StdProc}: fp, ap, i = x.par, [], 0 # list of formals, list of actuals if SC.sym == LPAREN: getSym() if SC.sym in FIRSTEXPRESSION: y = expression() if i < len(fp): if (type(fp[i]) == Var or type(y) == Var) and \ fp[i].tp == y.tp: if type(x) == Proc: ap.append(CG.genActualPara(y, fp[i], i)) else: mark('illegal parameter mode') else: mark('extra parameter') i = i + 1 while SC.sym == COMMA: getSym() y = expression() if i < len(fp): if (type(fp[i]) == Var or type(y) == Var) and \ fp[i].tp == y.tp: if type(x) == Proc: ap.append(CG.genActualPara(y, fp[i], i)) else: mark('illegal parameter mode') else: mark('extra parameter') i = i + 1 if SC.sym == RPAREN: getSym() else: mark("')' expected") if i < len(fp): mark('too few parameters') elif type(x) == StdProc: if x.name == 'read': x = CG.genRead(y) elif x.name == 'write': x = CG.genWrite(y) elif x.name == 'writeln': x = CG.genWriteln() else: x = CG.genCall(x, ap) else: mark("variable or procedure expected") elif SC.sym == BEGIN: x = compoundStatement() elif SC.sym == IF: getSym() x = expression() if x.tp == Bool: x = CG.genCond(x) else: mark('boolean expected') if SC.sym == THEN: getSym() else: mark("'then' expected") y = statement() if SC.sym == ELSE: if x.tp == Bool: y = CG.genThen(x, y) getSym() z = statement() if x.tp == Bool: x = CG.genIfElse(x, y, z) else: if x.tp == Bool: x = CG.genIfThen(x, y) elif SC.sym == WHILE: getSym() t = CG.genTarget() x = expression() if x.tp == Bool: x = CG.genCond(x) else: mark('boolean expected') if SC.sym == DO: getSym() else: mark("'do' expected") y = statement() if x.tp == Bool: x = CG.genWhile(t, x, y) else: x = None return x
def typ(): """ Parses type = ident | "array" "[" expression ".." expression "]" "of" type | "record" typedIds {";" typedIds} "end". Returns a type descriptor """ global depth if SC.sym not in FIRSTTYPE: getSym() mark("type expected") while SC.sym not in FIRSTTYPE | STRONGSYMS | FOLLOWTYPE: getSym() if SC.sym == IDENT: # attribute ident = SC.val write(ident) writeHtml(ident, _class='ident') # x = find(ident) getSym() if type(x) == Type: x = Type(x.tp) else: mark('not a type') x = Type(None) elif SC.sym == ARRAY: depth += 1 # attribute writeln() write(indent * depth) write('array ') writeHtmlLn() writeHtml(htmlIndent * depth) writeHtml('array ') # getSym() if SC.sym == LBRAK: # attribute write('[') writeHtml('[') # getSym() else: mark("'[' expected") x = expression() if SC.sym == PERIOD: # attribute write(' .') writeHtml(' .') # getSym() else: mark("'.' expected") if SC.sym == PERIOD: # attribute write('. ') writeHtml('. ') # getSym() else: mark("'.' expected") y = expression() if SC.sym == RBRAK: # attribute write('] ') writeHtml('] ') # getSym() else: mark("']' expected") if SC.sym == OF: # attribute write('of') writeHtml('of') # getSym() else: mark("'of' expected") z = typ().tp if type(x) != Const or x.val < 0: mark('bad lower bound') x = Type(None) elif type(y) != Const or y.val < x.val: mark('bad upper bound') y = Type(None) else: x = Type(CG.genArray(Array(z, x.val, y.val - x.val + 1))) depth -= 1 elif SC.sym == RECORD: # attributes depth += 1 writeln() write(indent * depth) write('record') writeln() writeHtmlLn() writeHtml(htmlIndent * depth) writeHtml('record') writeHtmlLn() depth += 1 # getSym() # attributes write(indent * depth) write(SC.val) writeHtml(htmlIndent * depth) writeHtml(SC.val) # openScope() typedIds(Var) while SC.sym == SEMICOLON: # attributes write(';') writeln() writeHtml(';') writeHtmlLn() # getSym() # attributes write(indent * depth) write(SC.val) writeHtml(htmlIndent * depth) writeHtml(SC.val) # typedIds(Var) # attributes writeln() writeHtmlLn() depth -= 1 write(indent * depth) writeHtml(htmlIndent * depth) # if SC.sym == END: # attributes write('end') writeHtml('end') # getSym() else: mark("'end' expected") r = topScope() closeScope() x = Type(CG.genRec(Record(r))) depth -= 1 else: x = Type(None) return x
def statement(l): """ Parses statement = EDIT LINE ident selector ":=" expression | ident «write(l * indent + ident)» "(" «write('(')» [expression {"," «write(', ')» expression}] ")" «write(')')» | compoundStatement(l) | "if" «writeln; write(l * indent + 'if ')» expression "then" «write(' then')» statement(l + 1) ["else" «writeln; write(l * indent + 'else')» statement(l + 1)] | EDIT LINE "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) writeln() write(l * indent + SC.val) getSym() writeHtmlLn() writeHtml(l * htmlIndent + SC.val) x = CG.genVar(x) if type(x) in {Var, Ref}: x = selector(x) if SC.sym == BECOMES: write(' := ') writeHtml(' := ') getSym() y = expression() if x.tp == y.tp in { Bool, Int }: # and not SC.error: type(y) could be Type #if type(x) == Var: ### and type(y) in {Var, Const}: incomplete, y may be Reg x = CG.genAssign(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}: fp, i = x.par, 0 # list of formals, count of actuals if SC.sym == LPAREN: write('(') getSym() writeHtml('(') if SC.sym in FIRSTEXPRESSION: y = expression() if i < len(fp): if (type(fp[i]) == Var or type(y) == Var) and \ fp[i].tp == y.tp: if type(x) == Proc: CG.genActualPara(y, fp[i], i) i = i + 1 else: mark('illegal parameter mode') else: mark('extra parameter') while SC.sym == COMMA: write(', ') getSym() writeHtml(', ') y = expression() if i < len(fp): if (type(fp[i]) == Var or type(y) == Var) and \ fp[i].tp == y.tp: if type(x) == Proc: CG.genActualPara(y, fp[i], i) i = i + 1 else: mark('illegal parameter mode') else: mark('extra parameter') if SC.sym == RPAREN: write(')') getSym() writeHtml(')') else: mark("')' expected") if i < len(fp): mark('too few parameters') if type(x) == StdProc: if x.name == 'read': x = CG.genRead(y) elif x.name == 'write': x = CG.genWrite(y) elif x.name == 'writeln': x = CG.genWriteln() else: x = CG.genCall(x) else: mark("variable or procedure expected") elif SC.sym == BEGIN: x = compoundStatement(l + 1) elif SC.sym == IF: writeln() write(l * indent + 'if ') writeHtmlLn() writeHtml(l * htmlIndent + 'if ') getSym() x = expression() if x.tp == Bool: x = CG.genCond(x) else: mark('boolean expected') if SC.sym == THEN: write(' then') writeHtml(' then') getSym() else: mark("'then' expected") y = statement(l + 1) if SC.sym == ELSE: if x.tp == Bool: y = CG.genThen(x, y) writeln() write(l * indent + 'else') writeHtmlLn() writeHtml(l * htmlIndent + ' else') getSym() z = statement(l + 1) if x.tp == Bool: x = CG.genIfElse(x, y, z) else: if x.tp == Bool: x = CG.genIfThen(x, y) elif SC.sym == WHILE: writeln() write(indent * (l + 1)) write('while ') writeHtmlLn() writeHtml(htmlIndent * (l + 1)) writeHtml('while ') getSym() t = CG.genTarget() x = expression() if x.tp == Bool: x = CG.genCond(x) else: mark('boolean expected') if SC.sym == DO: write(' do') writeHtml(' do') getSym() else: mark("'do' expected") y = statement(l + 2) if x.tp == Bool: x = CG.genWhile(t, x, y) else: x = None return x
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