Example #1
0
def term():
    """
    Parses
        term = factor {("*" | "div" | "mod" | "and") factor}.
    Generates code for the term if no error is reported
    """
    x = factor()
    while SC.sym in {TIMES, DIV, MOD, AND}:
        op = SC.sym
        # attribute
        symbols_of = {TIMES: ' * ', DIV: ' div ', MOD: ' mod ', AND: ' and '}
        write(symbols_of[op])
        writeHtml(symbols_of[op])
        #
        getSym()
        if op == AND and type(x) != Const: x = CG.genUnaryOp(AND, x)
        y = factor()  # x op y
        if x.tp == Int == y.tp and op in {TIMES, DIV, MOD}:
            if type(x) == Const == type(y):  # constant folding
                if op == TIMES: x.val = x.val * y.val
                elif op == DIV: x.val = x.val // y.val
                elif op == MOD: x.val = x.val % y.val
            else: x = CG.genBinaryOp(op, x, y)
        elif x.tp == Bool == y.tp and op == AND:
            if type(x) == Const:  # constant folding
                if x.val: x = y  # if x is true, take y, else x
            else: x = CG.genBinaryOp(AND, x, y)
        else: mark('bad type')
    return x
Example #2
0
def expression():
    """
    Parses
        expression = simpleExpression
                     {("=" | "<>" | "<" | "<=" | ">" | ">=") simpleExpression}.
    Generates code for the expression if no error is reported
    """
    x = simpleExpression()
    while SC.sym in {EQ, NE, LT, LE, GT, GE}:
        op = SC.sym
        # attribute
        symbols_of = {
            EQ: ' = ',
            NE: '<>',
            LT: ' < ',
            LE: ' <= ',
            GT: ' > ',
            GE: ' >= '
        }
        write(symbols_of[op])
        writeHtml(symbols_of[op])
        #
        getSym()
        y = simpleExpression()  # x op y
        if x.tp == Int == y.tp:
            x = CG.genRelation(op, x, y)
        else:
            mark('bad type')
    return x
Example #3
0
def expression():
    """
    Parses
        expression = simpleExpression
                     {("=" | "<>" | "<" | "<=" | ">" | ">=") simpleExpression}.
    Generates code for the expression if no error is reported
    """
    x = simpleExpression()
    while SC.sym in {EQ, NE, LT, LE, GT, GE}:
        op = SC.sym; getSym(); y = simpleExpression() # x op y
        if x.tp == Int == y.tp:
		#============== ADDED CONSTANT FOLDING =============
			if type(x) == Const == type(y):					#
				if op == EQ and x.val != y.val:				#
					x = genSkip()							#	
				elif op == NE and x.val == y.val:			#
					x = genSkip()							#
				elif op == LT and x.val >= y.val:			#
					x = genSkip()							#
				elif op == LE and x.val > y.val:			#
					x = genSkip()							#
				elif op == GT and x.val <= y.val:			#
					x = genSkip()							#
				elif op == GE and x.val < y.val:			#
					x = genSkip()							#
			else:
            	x = genRelation(op, x, y)
        else: mark('bad type')
Example #4
0
def term():
    """
    Parses
        term = factor {("*" «write(' * ')» | "div" «write(' div ')» | "mod" «write(' mod ')» | "and" «write(' and ')») factor}.
    Generates code for the term if no error is reported
    """
    x = factor()
    while SC.sym in {TIMES, DIV, MOD, AND}:
        op = SC.sym
        getSym()
        if op == AND and type(x) != Const:
            write(' and ')
            x = CG.genUnaryOp(AND, x)
        if op == TIMES: write(' * ')
        elif op == DIV: write(' div ')
        elif op == MOD: write(' mod ')
        y = factor()  # x op y
        if x.tp == Int == y.tp and op in {TIMES, DIV, MOD}:
            if type(x) == Const == type(y):  # constant folding
                if op == TIMES: x.val = x.val * y.val
                elif op == DIV: x.val = x.val // y.val
                elif op == MOD: x.val = x.val % y.val
            else: x = CG.genBinaryOp(op, x, y)
        elif x.tp == Bool == y.tp and op == AND:
            if type(x) == Const:  # constant folding
                if x.val: x = y  # if x is true, take y, else x
            else: x = CG.genBinaryOp(AND, x, y)
        else: mark('bad type')
    return x
Example #5
0
def statementSuite():
    if SC.sym in FIRSTSTATEMENT: x = statementList()
    elif SC.sym == INDENT:
        getSym(); x = statementBlock()
        if SC.sym == DEDENT: getSym();
        else: mark('dedent or new line expected')
    else: mark("indented statement expected")
    return x
Example #6
0
def expression():
    x = simpleExpression()
    while SC.sym in {EQ, NE, LT, LE, GT, GE}:
        op = SC.sym
        getSym()
        y = simpleExpression()  # x op y
        if x.tp == Int == y.tp:
            x = CG.genRelation(op, x, y)
        else:
            mark('bad type')
    return x
Example #7
0
def selector(x):
    """
    Parses
        selector = {"." ident | "[" expression "]"}.
    Assumes x is the entry for the identifier in front of the selector;
    generates code for the selector if no error is reported
    """
    while SC.sym in {PERIOD, LBRAK}:
        if SC.sym == PERIOD:  #  x.f
            getSym()
            if SC.sym == IDENT:
                if type(x.tp) == Record:
                    for f in x.tp.fields:
                        if f.name == SC.val:
                            x = genSelect(x, f); break
                    else: mark("not a field")
                    getSym()
                else: mark("not a record")
            else: mark("identifier expected")
        else:  #  x[y]
            getSym(); y = expression()
            if type(x.tp) == Array:
                if y.tp == Int:
                    if type(y) == Const and \
                       (y.val < x.tp.lower or y.val >= x.tp.lower + x.tp.length):
                        mark('index out of bounds')
                    else: x = genIndex(x, y)
                else: mark('index not integer')
            else: mark('not an array')
            if SC.sym == RBRAK: getSym()
            else: mark("] expected")
    return x
Example #8
0
def typedIds(kind, l):
    """
    Parses
        typedIds(l) = ident «write(ident)» {"," «write(', ')» ident «write(ident)»} ":" «write(': ')» type(l).
    Updates current scope of symbol table
    Assumes kind is Var or Ref and applies it to all identifiers
    Reports an error if an identifier is already defined in the current scope
    """
    if SC.sym == IDENT:
        write(SC.val)
        tid = [SC.val]
        getSym()
    else:
        mark("identifier expected")
        tid = []
    while SC.sym == COMMA:
        write(', ')
        getSym()
        if SC.sym == IDENT:
            write(SC.val)
            tid.append(SC.val)
            getSym()
        else:
            mark('identifier expected')
    if SC.sym == COLON:
        write(': ')
        getSym()
        tp = typ(l).tp
        if tp != None:
            for i in tid:
                newObj(i, kind(tp))
    else:
        mark("':' expected")
Example #9
0
def simpleExpression():
    if SC.sym == PLUS:
        getSym()
        x = term()
    elif SC.sym == BAR:
        getSym()
        x = term()
    elif SC.sym == MINUS:
        getSym()
        x = term()
        if x.tp != Int: mark('bad type')
        elif type(x) == Const: x.val = -x.val  # constant folding
        else: x = CG.genUnaryOp(MINUS, x)
    else: x = term()
    while SC.sym in {PLUS, MINUS, OR, BAR}:
        op = SC.sym
        getSym()
        if op == OR and type(x) != Const: x = CG.genUnaryOp(OR, x)
        y = term()  # x op y
        if x.tp == Int == y.tp and op in {PLUS, MINUS, BAR}:
            if type(x) == Const == type(y):  # constant folding
                if op == PLUS: x.val = x.val + y.val
                elif op == MINUS: x.val = x.val - y.val
                elif op == BAR: x.val = x.val | y.val
            else: x = CG.genBinaryOp(op, x, y)
        elif x.tp == Bool == y.tp and op == OR:
            if type(x) == Const:  # constant folding
                if not x.val: x = y  # if x is false, take y, else x
            else: x = CG.genBinaryOp(OR, x, y)
        else: mark('bad type')
    return x
Example #10
0
def selector(x):
    while SC.sym in {LBRAK, PERIOD}:
        if SC.sym == LBRAK:  #  x[y]
            getSym(); y = expression()
            if type(x.tp) == Array:
                if y.tp == Int:
                    if type(y) == Const and (y.val < x.tp.lower or y.val >= x.tp.lower + x.tp.length):
                        mark('index out of bounds')
                    else: x = CG.genIndex(x, y)
                else: mark('index not integer')
            else: mark('not an array')
            if SC.sym == RBRAK: getSym()
            else: mark("] expected")
        else:  #  x.f
            getSym()
            if SC.sym == IDENT:
                if type(x.tp) == Record:
                    for f in x.tp.fields:
                        if f.name == SC.val:
                            x = CG.genSelect(x, f); break
                    else: mark("not a field")
                    getSym()
                else: mark("not a record")
            else: mark("identifier expected")
    return x
Example #11
0
def selector(x):
    """
    Parses
        selector = {"." ident | "[" expression "]"}.
    Assumes x is the entry for the identifier in front of the selector;
    generates code for the selector if no error is reported
    """
    while SC.sym in {PERIOD, LBRAK}:
        if SC.sym == PERIOD:  #  x.f
            # attribute
            write('.')
            writeHtml('.')
            #
            getSym()
            if SC.sym == IDENT:
                # attribute
                write(SC.val)
                writeHtml(SC.val)
                #
                if type(x.tp) == Record:
                    for f in x.tp.fields:
                        if f.name == SC.val:
                            x = CG.genSelect(x, f)
                            break
                    else:
                        mark("not a field")
                    getSym()
                else:
                    mark("not a record")
            else:
                mark("identifier expected")
        else:  #  x[y]
            getSym()
            # attribute
            write('[')
            writeHtml('[')
            #
            y = expression()
            if type(x.tp) == Array:
                if y.tp == Int:
                    if type(y) == Const and \
                       (y.val < x.tp.lower or y.val >= x.tp.lower + x.tp.length):
                        mark('index out of bounds')
                    else:
                        x = CG.genIndex(x, y)
                else:
                    mark('index not integer')
            else:
                mark('not an array')
            if SC.sym == RBRAK:
                getSym()
                # attribute
                write(']')
                writeHtml(']')

            else:
                mark("] expected")
    return x
Example #12
0
def expression():
    """
    Parses
        expression = simpleExpression
                     {("=" | "<>" | "<" | "<=" | ">" | ">=") simpleExpression}.
    Generates code for the expression if no error is reported
    """
    x = simpleExpression()
    while SC.sym in {EQ, NE, LT, LE, GT, GE}:
        op = SC.sym
        getSym()
        y = simpleExpression()  # x op y
        if x.tp == Int == y.tp:
            x = genRelation(op, x, y)
        else:
            mark("bad type")
    return x
Example #13
0
def expression():
    """
    Parses
        expression = simpleExpression
                     {("=" | "<>" | "<" | "<=" | ">" | ">=") simpleExpression}.
    Generates code for the expression if no error is reported
    """
    x = simpleExpression()
    while SC.sym in {EQ, NE, LT, LE, GT, GE}:
        op = SC.sym
        getSym()
        y = simpleExpression()  # x op y
        if x.tp == Int == y.tp:
            x = genRelation(op, x, y)
        else:
            mark('bad type', 16)
    return x
Example #14
0
def program():
    newDecl('boolean', Type(CG.genBool(Bool)))
    newDecl('integer', Type(CG.genInt(Int)))
    newDecl('true', Const(Bool, 1))
    newDecl('false', Const(Bool, 0))
    newDecl('read', StdProc([], [Var(Int)]))
    newDecl('write', StdProc([Var(Int)], []))
    newDecl('writeln', StdProc([], []))
    CG.genProgStart()
    declarations(CG.genGlobalVars)
    if SC.sym == PROGRAM: getSym()
    else: mark("'program' expected")
    ident = SC.val
    if SC.sym == IDENT: getSym()
    else: mark('program name expected')
    openScope(); CG.genProgEntry(ident); x = body(ident, 0)
    closeScope(); x = CG.genProgExit(x)
    return x
Example #15
0
def term():
    """
    Parses
        term = factor {("*" | "div" | "mod" | "and") factor}.
    Generates code for the term if no error is reported
    """
    x = factor()
    while SC.sym in {TIMES, DIV, MOD, AND}:
        op = SC.sym
        getSym()
        if op == AND and type(x) != Const: x = genUnaryOp(AND, x)
        y = factor()  # x op y
        if x.tp == Int == y.tp and op in {TIMES, DIV, MOD}:

            if type(x) == Const == type(y):  # constant folding
                if op == TIMES: x.val = x.val * y.val
                elif op == DIV: x.val = x.val // y.val
                elif op == MOD: x.val = x.val % y.val

            else:
                if type(x) == Const and op == TIMES:
                    # fold 1 * y
                    if x.val == 1:
                        x = y
                    else:
                        # swap x and y for immediate addressing
                        # e.g., 3 * x becomes x * 3
                        x = genBinaryOp(op, y, x)

                # fold x*1, x/1
                elif type(y) == Const and op in {TIMES, DIV} and y.val == 1:
                    pass

                else:
                    x = genBinaryOp(op, x, y)

        elif x.tp == Bool == y.tp and op == AND:
            if type(x) == Const:  # constant folding
                if x.val: x = y  # if x is true, take y, else x
            else: x = genBinaryOp(AND, x, y)
        else: mark('bad type', 13)
    return x
Example #16
0
def term():
    x = factor()
    while SC.sym in {TIMES, DIV, MOD, INTERSECTION, AND}:
        op = SC.sym; getSym();
        if op == AND and type(x) != Const: x = CG.genUnaryOp(AND, x)
        y = factor() # x op y
        if op in {TIMES, DIV, MOD} and x.tp == Int == y.tp:
            if type(x) == Const == type(y): # constant folding
                if op == TIMES: x.val = x.val * y.val
                elif op == DIV: x.val = x.val // y.val
                elif op == MOD: x.val = x.val % y.val
            else: x = CG.genBinaryOp(op, x, y)
        elif op == INTERSECTION and type(x.tp) == Set == type(y.tp):
            x = CG.genBinaryOp(op, x, y)
        elif op == AND and x.tp == Bool == y.tp:
            if type(x) == Const: # constant folding
                if x.val: x = y # if x is true, take y, else x
            else: x = CG.genBinaryOp(AND, x, y)
        else: mark('bad type')
    return x
Example #17
0
def term():
    x = factor()
    while SC.sym in {TIMES, DIV, MOD, AND, AMP}:
        op = SC.sym
        getSym()
        if op == AND and type(x) != Const: x = CG.genUnaryOp(AND, x)
        y = factor()  # x op y
        if x.tp == Int == y.tp and op in {TIMES, DIV, MOD, AMP}:
            if type(x) == Const == type(y):  # constant folding
                if op == TIMES: x.val = x.val * y.val
                elif op == DIV: x.val = x.val // y.val
                elif op == MOD: x.val = x.val % y.val
                elif op == AMP: x.val = x.val & y.val
            else: x = CG.genBinaryOp(op, x, y)
        if x.tp != Int or y.tp != Int and op == AMP: mark('not integer')
        elif x.tp == Bool == y.tp and op == AND:
            if type(x) == Const:  # constant folding
                if x.val: x = y  # if x is true, take y, else x
            else: x = CG.genBinaryOp(AND, x, y)
        else: mark('bad type')
    return x
Example #18
0
def compoundStatement(l):
    """
    Parses
        compoundStatement(l) =
            "begin" «writeln; write(l * indent + 'begin')»
            statement(l + 1) {";" «write(';')» statement(l + 1)}
            "end" «writeln; write(l * ident + 'end')»
    Generates code for the compoundStatement if no error is reported
    """
    if SC.sym == BEGIN:
        writeln()
        write(l * indent + 'begin')
        getSym()
    else:
        mark("'begin' expected")
    x = statement(l + 1)
    while SC.sym == SEMICOLON or SC.sym in FIRSTSTATEMENT:
        if SC.sym == SEMICOLON:
            write(';')
            getSym()
        else:
            mark("; missing")
        y = statement(l + 1)
        x = CG.genSeq(x, y)
    if SC.sym == END:
        writeln()
        write(l * indent + 'end')
        getSym()
    else:
        mark("'end' expected")
    return x
Example #19
0
def term():
    """
    Parses
        term = factor {("*" | "div" | "mod" | "and") factor}.
    Generates code for the term if no error is reported
    """
    x = factor()
    while SC.sym in {TIMES, DIV, MOD, AND}:
        op = SC.sym
        getSym()
        if op == AND and type(x) != Const:
            x = genUnaryOp(AND, x)
        y = factor()  # x op y
        if x.tp == Int == y.tp and op in {TIMES, DIV, MOD}:
            if type(x) == Const == type(y):  # constant folding
                if op == TIMES:
                    x.val = x.val * y.val
                elif op == DIV:
                    x.val = x.val // y.val
                elif op == MOD:
                    x.val = x.val % y.val
            else:
                print("term 2: start optimization op", op)
                if type(x).__name__ == "Const" and x.val == 1:  # check if x=1 for multiplications
                    print("x == 1, do not multiply by 1")
                    x = y
                elif type(y).__name__ == "Const" and y.val == 1:  # check for imediate for multiplications
                    print("y == 1, do not multiply by 1")
                    x = x
                else:
                    x = genBinaryOp(op, x, y)
        elif x.tp == Bool == y.tp and op == AND:
            if type(x) == Const:  # constant folding
                if x.val:
                    x = y  # if x is true, take y, else x
            else:
                x = genBinaryOp(AND, x, y)
        else:
            mark("bad type")
    return x
Example #20
0
def program():
    """
    Parses
        program = "program" ident ";" declarations compoundStatement.
    Generates code if no error is reported
    """
    newObj('boolean', Type(Bool))
    Bool.size = 8  # 64 bit sizes
    newObj('integer', Type(Int))
    Int.size = 8
    newObj('true', Const(Bool, 1))
    newObj('false', Const(Bool, 0))
    newObj('read', StdProc([Ref(Int)]))
    newObj('write', StdProc([Var(Int)]))
    newObj('writeln', StdProc([]))
    progStart()
    if SC.sym == PROGRAM: getSym()
    else: mark("'program' expected", 64)
    ident = SC.val
    if SC.sym == IDENT: getSym()
    else: mark('program name expected', 65)
    if SC.sym == SEMICOLON: getSym()
    else: mark('; expected', 66)
    declarations(genGlobalVars)
    progEntry(ident)
    x = compoundStatement()
    return progExit(x)
Example #21
0
def program():
    newDecl('boolean', Type(CG.genBool(Bool)))
    newDecl('integer', Type(CG.genInt(Int)))
    newDecl('true', Const(Bool, 1))
    newDecl('false', Const(Bool, 0))
    newDecl('read', StdProc([Ref(Int)]))
    newDecl('write', StdProc([Var(Int)]))
    newDecl('writeln', StdProc([]))
    CG.genProgStart()
    if SC.sym == PROGRAM:
        getSym()
    else:
        mark("'program' expected")
    ident = SC.val
    if SC.sym == IDENT:
        getSym()
    else:
        mark('program name expected')
    if SC.sym == SEMICOLON:
        getSym()
    else:
        mark('; expected')
    declarations(CG.genGlobalVars)
    CG.genProgEntry(ident)
    x = compoundStatement()
    return CG.genProgExit(x)
Example #22
0
def simpleExpression():
    if SC.sym == PLUS:
        getSym(); x = term()
    elif SC.sym == MINUS:
        getSym(); x = term()
        if x.tp != Int: mark('bad type')
        elif type(x) == Const: x.val = - x.val # constant folding
        else: x = CG.genUnaryOp(MINUS, x)
    else: x = term()
    while SC.sym in {PLUS, MINUS, UNION, OR}:
        op = SC.sym; getSym()
        if op == OR and type(x) != Const: x = CG.genUnaryOp(OR, x)
        y = term() # x op y
        if op in {PLUS, MINUS} and x.tp == Int == y.tp:
            if type(x) == Const == type(y): # constant folding
                if op == PLUS: x.val = x.val + y.val
                elif op == MINUS: x.val = x.val - y.val
            else: x = CG.genBinaryOp(op, x, y)
        elif op == UNION and type(x.tp) == Set == type(y.tp):
            x = CG.genBinaryOp(UNION, x, y)
        elif op == OR and x.tp == Bool == y.tp:
            if type(x) == Const: # constant folding
                if not x.val: x = y # if x is false, take y, else x
            else: x = CG.genBinaryOp(OR, x, y)
        else: print(x, y); mark('bad type')
    return x
Example #23
0
def program():
    """
    Parses
        program = "program" ident ";" declarations compoundStatement.
    Generates code if no error is reported
    """
    newObj("boolean", Type(Bool))
    Bool.size = 4
    newObj("integer", Type(Int))
    Int.size = 4
    newObj("true", Const(Bool, 1))
    newObj("false", Const(Bool, 0))
    newObj("read", StdProc([Ref(Int)]))
    newObj("write", StdProc([Var(Int)]))
    newObj("writeln", StdProc([]))
    progStart()
    if SC.sym == PROGRAM:
        getSym()
    else:
        mark("'program' expected")
    ident = SC.val
    if SC.sym == IDENT:
        getSym()
    else:
        mark("program name expected")
    if SC.sym == SEMICOLON:
        getSym()
    else:
        mark("; expected")
    declarations(genGlobalVars)
    progEntry(ident)
    x = compoundStatement()
    return progExit(x)
Example #24
0
def simpleExpression():
    """
    Parses
        simpleExpression = ["+" | "-"] term {("+" | "-" | "or") term}.
    Generates code for the simpleExpression if no error is reported
    """
    if SC.sym == PLUS:
        getSym(); x = term()
    elif SC.sym == MINUS:
        getSym(); x = term()
        if x.tp != Int: mark('bad type')
        elif type(x) == Const: x.val = - x.val # constant folding
        else: x = genUnaryOp(MINUS, x)
    else: x = term()
    while SC.sym in {PLUS, MINUS, OR}:
        op = SC.sym; getSym()
        if op == OR and type(x) != Const: x = genUnaryOp(OR, x)
        y = term() # x op y
        if x.tp == Int == y.tp and op in {PLUS, MINUS}:
            if type(x) == Const == type(y): # constant folding
                if op == PLUS: x.val = x.val + y.val
                elif op == MINUS: x.val = x.val - y.val
            else: x = genBinaryOp(op, x, y)
        elif x.tp == Bool == y.tp and op == OR:
            if type(x) == Const: # constant folding
                if not x.val: x = y # if x is false, take y, else x
            else: x = genBinaryOp(OR, x, y)
        else: mark('bad type')
    return x
Example #25
0
def simpleExpression():
    """
    Parses
        simpleExpression = ["+" | "-"] term {("+" | "-" | "or") term}.
    Generates code for the simpleExpression if no error is reported
    """
    if SC.sym == PLUS:
        getSym()
        x = term()
    elif SC.sym == MINUS:
        getSym()
        x = term()
        if x.tp != Int:
            mark("bad type")
        elif type(x) == Const:
            x.val = -x.val  # constant folding
        else:
            x = genUnaryOp(MINUS, x)
    else:
        x = term()
    while SC.sym in {PLUS, MINUS, OR}:
        op = SC.sym
        getSym()
        if op == OR and type(x) != Const:
            x = genUnaryOp(OR, x)  # -----
        y = term()  # x op y
        if x.tp == Int == y.tp and op in {PLUS, MINUS}:  # if (type(x)=int and type(y)=int) and (operator is + or -)
            if type(x) == Const == type(y):  # constant folding
                ## does x + y if they are not zero
                if op == PLUS:
                    x.val = x.val + y.val
                elif op == MINUS:
                    x.val = x.val - y.val
            else:
                print("op", op)
                print("1. simpleExpression")
                if type(x).__name__ == "Const" and x.val == 0:
                    x = y
                    print("x = y")
                    continue
                elif type(y).__name__ == "Const" and y.val == 0:
                    print("x = x")
                    x = x
                    continue
                x = genBinaryOp(op, x, y)  # does the arithmetic + and minus
        elif x.tp == Bool == y.tp and op == OR:  # no changes past here
            if type(x) == Const:  # constant folding
                if not x.val:
                    x = y  # if x is false, take y, else x
            else:
                x = genBinaryOp(OR, x, y)
        else:
            mark("bad type")
    writeln("TEST: ", "SimpleExpression: ", "5. ", "ended")

    # print("--- x: ", dir(x));
    print("function ending x: ", vars(x))
    return x
Example #26
0
def expression():
    """
    Parses
        expression = simpleExpression
                     {("=" «write(' = ')» | "<>" «write(' <> ')» | "<" «write(' < ')» | "<=" «write(' <= ')» | ">" «write(' > ')» | ">=" «write(' >= ')») simpleExpression}.
    Generates code for the expression if no error is reported
    """
    x = simpleExpression()
    while SC.sym in {EQ, NE, LT, LE, GT, GE}:
        op = SC.sym
        if op == EQ: write(' = ')
        elif op == NE: write(' <> ')
        elif op == LT: write(' < ')
        elif op == LE: write(' <= ')
        elif op == GT: write(' > ')
        elif op == GE: write(' >= ')
        getSym()
        y = simpleExpression()  # x op y
        if x.tp == Int == y.tp:
            x = CG.genRelation(op, x, y)
        else:
            mark('bad type')
    return x
Example #27
0
def body(ident, para):
    if SC.sym == INDENT: getSym()
    else: mark('indent expected')
    start = len(topScope())
    local = declarations(CG.genLocalVars)
    CG.genProcEntry(ident, para, local)
    if SC.sym in FIRSTSTATEMENT: x = statementBlock()
    elif SC.sym == INDENT:
        getSym(); x = statementBlock()
        if SC.sym == DEDENT: getSym()
        else: mark('dedent or new line expected')
    else: mark('statement expected')
    CG.genProcExit(x, para, local)
    if SC.sym == DEDENT: getSym()
    else: mark('dedent or new line expected')
    return x
Example #28
0
def expression():
    x = simpleExpression()
    while SC.sym in {EQ, NE, LT, LE, GT, GE, ELEMENT, SUBSET, SUPERSET}:
        op = SC.sym; getSym()
        if op in (EQ, NE, LT, LE, GT, GE):
            y = simpleExpression() # x op y
            if x.tp == y.tp in (Int, Bool):
                if type(x) == Const == type(y): # constant folding
                    if op == EQ: x.val = int(x.val == y.val)
                    elif op == NE: x.val = int(x.val != y.val)
                    elif op == LT: x.val = int(x.val < y.val)
                    elif op == LE: x.val = int(x.val <= y.val)
                    elif op == GT: x.val = int(x.val > y.val)
                    elif op == GE: x.val = int(x.val >= y.val)
                    x.tp = Bool
                else: x = CG.genRelation(op, x, y)
            else: mark('bad type')
        elif (op == ELEMENT and x.tp == Int) or             (op in (SUBSET, SUPERSET) and type(x.tp) == Set):
            x = CG.genUnaryOp(op, x); y = simpleExpression()
            if type(y.tp) == Set: x = CG.genRelation(op, x, y)
            else: mark('set expected')
        else: mark('bad type')
    return x
Example #29
0
def term():
    """
    Parses
        term = factor {("*" | "div" | "mod" | "and") factor}.
    Generates code for the term if no error is reported
    """
    x = factor()
    while SC.sym in {TIMES, DIV, MOD, AND}:
        op = SC.sym; getSym();
        if op == AND and type(x) != Const: x = genUnaryOp(AND, x)
        y = factor() # x op y
        if x.tp == Int == y.tp and op in {TIMES, DIV, MOD}:
            if type(x) == Const == type(y): # constant folding
                if op == TIMES: x.val = x.val * y.val
                elif op == DIV: x.val = x.val // y.val
                elif op == MOD: x.val = x.val % y.val
            else: x = genBinaryOp(op, x, y)
        elif x.tp == Bool == y.tp and op == AND:
            if type(x) == Const: # constant folding
                if x.val: x = y # if x is true, take y, else x
            else: x = genBinaryOp(AND, x, y)
        else: mark('bad type')
    return x
Example #30
0
def typedIds(kind):
    """
    Parses
        typedIds = ident {"," ident} ":" type.
    Updates current scope of symbol table
    Assumes kind is Var or Ref and applies it to all identifiers
    Reports an error if an identifier is already defined in the current scope
    """
    tid = [SC.val]; getSym()
    while SC.sym == COMMA:
        getSym()
        if SC.sym == IDENT: tid.append(SC.val); getSym()
        else: mark('identifier expected')
    if SC.sym == COLON:
        getSym(); tp = typ().tp
        for i in tid: newObj(i, kind(tp))
    else: mark("':' expected")
Example #31
0
def compoundStatement():
    if SC.sym == BEGIN: getSym()
    else: mark("'begin' expected")
    x = statement()
    while SC.sym == SEMICOLON or SC.sym in FIRSTSTATEMENT:
        if SC.sym == SEMICOLON: getSym()
        else: mark("; missing")
        y = statement()
        x = CG.genSeq(x, y)
    if SC.sym == END: getSym()
    else: mark("'end' expected")
    return x
Example #32
0
def simpleExpression():
    """
    Parses
        simpleExpression = ["+" | "-"] term {("+" | "-" | "or") term}.
    Generates code for the simpleExpression if no error is reported
    """
    if SC.sym == PLUS:
        getSym()
        x = term()
    elif SC.sym == MINUS:
        getSym()
        x = term()
        if x.tp != Int: mark('bad type', 14)
        elif type(x) == Const: x.val = -x.val  # constant folding
        else: x = genUnaryOp(MINUS, x)
    else: x = term()
    while SC.sym in {PLUS, MINUS, OR}:
        op = SC.sym
        getSym()
        if op == OR and type(x) != Const: x = genUnaryOp(OR, x)
        y = term()  # x op y
        if x.tp == Int == y.tp and op in {PLUS, MINUS}:

            if type(x) == Const == type(y):  # constant folding
                if op == PLUS: x.val = x.val + y.val
                elif op == MINUS: x.val = x.val - y.val

            else:
                if type(x) == Const:
                    #fold 0 + y, 0 - y
                    if x.val == 0:
                        x = y
                    # change const + y to x + const
                    elif op == PLUS:
                        x = genBinaryOp(op, y, x)

                elif type(y) == Const and y.val == 0:
                    #fold x + 0, x - 0
                    pass

                else:
                    x = genBinaryOp(op, x, y)

        elif x.tp == Bool == y.tp and op == OR:
            if type(x) == Const:  # constant folding
                if not x.val:
                    x = y  # if x is false, take y, else x
            else:
                x = genBinaryOp(OR, x, y)
        else:
            mark('bad type', 15)
    return x
Example #33
0
def typedIds(kind):
    """
    Parses
        typedIds = ident {"," ident} ":" type.
    Updates current scope of symbol table
    Assumes kind is Var or Ref and applies it to all identifiers
    Reports an error if an identifier is already defined in the current scope
    """
    if SC.sym == IDENT:
        tid = [SC.val]
        getSym()
    else:
        mark("identifier expected")
        tid = []
    while SC.sym == COMMA:
        # attribute
        write(', ')
        writeHtml(', ')
        #
        getSym()
        if SC.sym == IDENT:
            # attribute
            write(SC.val)
            writeHtml(SC.val)
            #
            tid.append(SC.val)
            getSym()
        else:
            mark('identifier expected')
    if SC.sym == COLON:
        # attribute
        write(': ')
        writeHtml(': ')
        #
        getSym()
        tp = typ().tp
        if tp != None:
            for i in tid:
                newObj(i, kind(tp))
    else:
        mark("':' expected")
Example #34
0
def selector(x):
    """
    Parses
        selector = {"." ident | "[" expression "]"}.
    Assumes x is the entry for the identifier in front of the selector;
    generates code for the selector if no error is reported
    """
    while SC.sym in {PERIOD, LBRAK}:
        if SC.sym == PERIOD:  #  x.f
            getSym()
            if SC.sym == IDENT:
                if type(x.tp) == Record:  #isinstance(x.tp, Record):#
                    for f in x.tp.fields:
                        if f.name == SC.val:
                            x = genSelect(x, f)
                            break
                    else:
                        mark("not a field", 1)
                    getSym()
                else:
                    mark("not a record", 2)
            else:
                mark("identifier expected", 3)
        else:  #  x[y]
            getSym()
            y = expression()
            if type(x.tp) == Array:  #isinstance(x.tp, Array):#
                if y.tp == Int:
                    if type(y) == Const and \
                       (y.val < x.tp.lower or y.val >= x.tp.lower + x.tp.length):
                        mark('index out of bounds', 4)
                    else:
                        x = genIndex(x, y)
                else:
                    mark('index not integer', 5)
            else:
                mark('not an array', 6)
            if SC.sym == RBRAK: getSym()
            else: mark("] expected", 7)
    return x
Example #35
0
def typedIds(kind):
    if SC.sym == IDENT:
        tid = [SC.val]
        getSym()
    else:
        mark("identifier expected")
        tid = []
    while SC.sym == COMMA:
        getSym()
        if SC.sym == IDENT:
            tid.append(SC.val)
            getSym()
        else:
            mark('identifier expected')
    if SC.sym == COLON:
        getSym()
        tp = typ().val
        if tp != None:
            for i in tid:
                newDecl(i, kind(tp))
    else:
        mark("':' expected")
Example #36
0
def program():
    """
    Parses
        program = "program" «write('program ')» ident «write(ident)»
            ";" «write(';')» declarations compoundStatement(1).
    Generates code if no error is reported
    """
    newObj('boolean', Type(Bool))
    Bool.size = 4
    newObj('integer', Type(Int))
    Int.size = 4
    newObj('true', Const(Bool, 1))
    newObj('false', Const(Bool, 0))
    newObj('read', StdProc([Ref(Int)]))
    newObj('write', StdProc([Var(Int)]))
    newObj('writeln', StdProc([]))
    CG.progStart()
    if SC.sym == PROGRAM:
        #
        write('program ')
        writeHtml('program ')
        #
        getSym()
    else:
        mark("'program' expected")
    ident = SC.val
    if SC.sym == IDENT:
        #
        write(ident)
        writeHtml(ident, _class='ident')
        #
        getSym()
    else:
        mark('program name expected')
    if SC.sym == SEMICOLON:
        getSym()
        #
        write(';')
        writeln()
        writeHtml(';')
        writeHtmlLn()
        #
    else:
        mark('; expected')
    declarations(CG.genGlobalVars)
    CG.progEntry(ident)
    x = compoundStatement(1)
    return CG.progExit(x)
Example #37
0
def compoundStatement():
    """
    Parses
        compoundStatement = "begin" statement {";" statement} "end"
    Generates code for the compoundStatement if no error is reported
    """
    if SC.sym == BEGIN: getSym()
    else: mark("'begin' expected")
    x = statement()
    while SC.sym == SEMICOLON or SC.sym in FIRSTSTATEMENT:
        if SC.sym == SEMICOLON: getSym()
        else: mark("; missing")
        y = statement(); x = genSeq(x, y)
    if SC.sym == END: getSym()
    else: mark("'end' expected")
    return x
Example #38
0
def typedIds(kind):
    """
    Parses
        typedIds = ident {"," ident} ":" type.
    Updates current scope of symbol table
    Assumes kind is Var or Ref and applies it to all identifiers
    Reports an error if an identifier is already defined in the current scope
    """
    tid = [SC.val]
    getSym()
    while SC.sym == COMMA:
        getSym()
        if SC.sym == IDENT:
            tid.append(SC.val)
            getSym()
        else:
            mark('identifier expected', 48)
    if SC.sym == COLON:
        getSym()
        tp = typ().tp
        for i in tid:
            newObj(i, kind(tp))
    else:
        mark("':' expected", 49)
Example #39
0
def compoundStatement():
    """
    Parses
        compoundStatement = "begin" statement {";" statement} "end"
    Generates code for the compoundStatement if no error is reported
    """
    if SC.sym == BEGIN: getSym()
    else: mark("'begin' expected", 17)
    x = statement()
    while SC.sym == SEMICOLON or SC.sym in FIRSTSTATEMENT:
        if SC.sym == SEMICOLON: getSym()
        else: mark("; missing", 18)
        y = statement()
        x = genSeq(x, y)
    if SC.sym == END: getSym()
    else: mark("'end' expected", 19)
    return x
Example #40
0
def simpleExpression():
    """
    Parses
        simpleExpression = ["+" | "-"] term {("+" | "-" | "or") term}.
    Generates code for the simpleExpression if no error is reported
    """
    if SC.sym == PLUS:
        # attribute
        write(' + ')
        writeHtml(' + ')
        #
        getSym()
        x = term()
    elif SC.sym == MINUS:
        # attribute
        write(' - ')
        writeHtml(' - ')
        #
        getSym()
        x = term()
        if x.tp != Int: mark('bad type')
        elif type(x) == Const: x.val = -x.val  # constant folding
        else: x = CG.genUnaryOp(MINUS, x)
    else: x = term()
    while SC.sym in {PLUS, MINUS, OR}:
        op = SC.sym
        getSym()
        symbols_of = {5: ' + ', 6: ' - ', 7: ' or '}
        write(symbols_of[op])
        writeHtml(symbols_of[op])
        if op == OR and type(x) != Const: x = CG.genUnaryOp(OR, x)
        y = term()  # x op y
        if x.tp == Int == y.tp and op in {PLUS, MINUS}:
            if type(x) == Const == type(y):  # constant folding
                if op == PLUS: x.val = x.val + y.val
                elif op == MINUS: x.val = x.val - y.val
            else: x = CG.genBinaryOp(op, x, y)
        elif x.tp == Bool == y.tp and op == OR:
            if type(x) == Const:  # constant folding
                if not x.val: x = y  # if x is false, take y, else x
            else: x = CG.genBinaryOp(OR, x, y)
        else: mark('bad type')
    return x
Example #41
0
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
Example #42
0
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
Example #43
0
            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
        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
Example #44
0
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
Example #45
0
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
Example #46
0
def declarations(allocVar):
    """
    Parses
        declarations =
            {"const" ident "=" expression ";"}
            {"type" ident "=" type ";"}
            {"var" typedIds ";"}
            {"procedure" ident ["(" [["var"] typedIds {";" ["var"] typedIds}] ")"] ";"
                declarations compoundStatement ";"}.
    Updates current scope of symbol table.
    Reports an error if an identifier is already defined in the current scope.
    For each procedure, code is generated
    """
    if SC.sym not in FIRSTDECL | FOLLOWDECL:
        getSym()
        mark("declaration expected")
        while SC.sym not in FIRSTDECL | FOLLOWDECL:
            getSym()
    while SC.sym == CONST:
        getSym()
        if SC.sym == IDENT:
            ident = SC.val
            getSym()
            if SC.sym == EQ:
                getSym()
            else:
                mark("= expected")
            x = expression()
            if type(x) == Const:
                newObj(ident, x)
            else:
                mark("expression not constant")
        else:
            mark("constant name expected")
        if SC.sym == SEMICOLON:
            getSym()
        else:
            mark("; expected")
    while SC.sym == TYPE:
        getSym()
        if SC.sym == IDENT:
            ident = SC.val
            getSym()
            if SC.sym == EQ:
                getSym()
            else:
                mark("= expected")
            x = typ()
            newObj(ident, x)  #  x is of type ST.Type
            if SC.sym == SEMICOLON:
                getSym()
            else:
                mark("; expected")
        else:
            print(SC.sym)
            mark("type name expected")
    start = len(topScope())
    while SC.sym == VAR:
        getSym()
        typedIds(Var)
        if SC.sym == SEMICOLON:
            getSym()
        else:
            mark("; expected")
    varsize = allocVar(topScope(), start)
    while SC.sym == PROCEDURE:
        getSym()
        if SC.sym == IDENT:
            getSym()
        else:
            mark("procedure name expected")
        ident = SC.val
        newObj(ident, Proc([]))  #  entered without parameters
        sc = topScope()
        procStart()
        openScope()  # new scope for parameters and body
        if SC.sym == LPAREN:
            getSym()
            if SC.sym in {VAR, IDENT}:
                if SC.sym == VAR:
                    getSym()
                    typedIds(Ref)  # , procParams)
                else:
                    typedIds(Var)  # , procParams)
                while SC.sym == SEMICOLON:
                    getSym()
                    if SC.sym == VAR:
                        getSym()
                        typedIds(Ref)  # , procParams)
                    else:
                        typedIds(Var)  # , procParams)
            else:
                mark("formal parameters expected")
            fp = topScope()
            sc[-1].par = fp[:]  #  procedure parameters updated
            if SC.sym == RPAREN:
                getSym()
            else:
                mark(") expected")
        else:
            fp = []
        parsize = genFormalParams(fp)
        if SC.sym == SEMICOLON:
            getSym()
        else:
            mark("; expected")
        localsize = declarations(genLocalVars)
        genProcEntry(ident, parsize, localsize)
        x = compoundStatement()
        genProcExit(x, parsize, localsize)
        closeScope()  #  scope for parameters and body closed
        if SC.sym == SEMICOLON:
            getSym()
        else:
            mark("; expected")
    return varsize