Beispiel #1
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')
Beispiel #2
0
def find(name):
    for l in symTab:
        for e in l:
            if name == e.name: return e
    mark('undefined identifier ' + name)
    undef = Var(Int); undef.lev, undef.adr = 0, 0
    return undef
Beispiel #3
0
def genVar(x):
    # assuming x is ST.Var, ST.Ref, ST.Const
    # for ST.Const: no code, x.val is constant
    # for ST.Var: x.reg is FP for local, 0 for global vars,
    #   x.adr is relative or absolute address
    # for ST.Ref: address is loaded into register
    # returns ST.Var, ST.Const
    if type(x) == Const:
        y = x
    else:
        if x.lev == 0:
            s = R0
        elif x.lev == curlev:
            s = FP
        else:
            mark("level!")
            s = R0
        y = Var(x.tp)
        y.lev = x.lev
        if type(x) == Ref:  # reference is loaded into register
            r = obtainReg()
            putM("lw", r, s, x.adr)
            y.reg, y.adr = r, 0
        elif type(x) == Var:
            y.reg, y.adr = s, x.adr
        else:
            y = x  # error, pass dummy item
    return y
Beispiel #4
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
Beispiel #5
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
Beispiel #6
0
def compileFile(srcfn):
    if srcfn.endswith(".p"):
        with open(srcfn, "r") as f:
            src = f.read()
        dstfn = srcfn[:-2] + ".s"
        compileString(src, dstfn)
    else:
        mark("'.p' file extension expected")
Beispiel #7
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
Beispiel #8
0
def genFormalParams(sc):
    """For list sc with formal procedure parameters, determine the $fp-relative
    address of each parameters; each parameter must be type integer, boolean
    or must be a reference parameter"""
    s = 0 # parameter block size
    for p in reversed(sc):
        if p.tp == Int or p.tp == Bool or type(p) == Ref:
            p.adr, s = s, s + 4
        else: mark('no structured value parameters')
    return s
Beispiel #9
0
def genActualPara(ap, fp, n):
    """Pass parameter, ap is actual parameter, fp is the formal parameter,
    either Ref or Var, n is the parameter number"""
    if type(fp) == Ref:  #  reference parameter, assume p is Var
        if ap.adr != 0:  #  load address in register
            r = obtainReg(); putM('la', r, ap.reg, ap.adr)
        else: r = ap.reg  #  address already in register
        putM('sw', r, SP, - 4 * (n + 1)); releaseReg(r)
    else:  #  value parameter
        if type(ap) != Cond:
            if type(ap) != Reg: ap = loadItem(ap)
            putM('sw', ap.reg, SP, - 4 * (n + 1)); releaseReg(ap.reg)
        else: mark('unsupported parameter type')
Beispiel #10
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
Beispiel #11
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")
Beispiel #12
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)
Beispiel #13
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
Beispiel #14
0
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)
        getSym()
        x = selector(x)
    elif SC.sym == NUMBER:
        x = Const(Int, SC.val)
        x = CG.genConst(x)
        write(str(SC.val))
        getSym()
    elif SC.sym == LPAREN:
        write('(')
        getSym()
        x = expression()
        if SC.sym == RPAREN:
            write(')')
            getSym()
        else:
            mark(") expected")
    elif SC.sym == NOT:
        write('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
Beispiel #15
0
def simpleExpression():
    """
    Parses
        simpleExpression = ["+" «write(' + ')» | "-" «write(' - ')»] term {("+" «write(' + ')» | "-" «write(' - ')» | "or" «write(' or ')») term}.
    Generates code for the simpleExpression if no error is reported
    """
    if SC.sym == PLUS:
        write(' + ')
        getSym()
        x = term()
    elif SC.sym == MINUS:
        write(' - ')
        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()
        if op == OR and type(x) != Const:
            write(' or ')
            x = CG.genUnaryOp(OR, x)
        if op == PLUS: write(' + ')
        if op == MINUS: write(' - ')
        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
Beispiel #16
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
Beispiel #17
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
Beispiel #18
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
Beispiel #19
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)
Beispiel #20
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
Beispiel #21
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)
Beispiel #22
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
Beispiel #23
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
Beispiel #24
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')

        writeHtmlLn()
        writeHtml(l * htmlIndent + '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()
            writeHtml(';')
        else:
            mark("; missing")
        y = statement(l + 1)
        x = CG.genSeq(x, y)
    if SC.sym == END:
        writeln()
        write(l * indent)
        write('end')
        writeln()

        writeHtmlLn()
        writeHtml(l * htmlIndent)
        writeHtml('end')
        writeHtmlLn()

        getSym()
    else:
        mark("'end' expected")
    return x
Beispiel #25
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)
Beispiel #26
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")
Beispiel #27
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")
Beispiel #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
Beispiel #29
0
def declarations(allocVar):
    if SC.sym not in FIRSTDECL | FOLLOWDECL:
        getSym()
        mark("'begin' or declaration expected")
        while SC.sym not in FIRSTDECL | STRONGSYMS | 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:
                newDecl(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()
            newDecl(ident, x)  # x is of type ST.Type
            if SC.sym == SEMICOLON:
                getSym()
            else:
                mark("; expected")
        else:
            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
        newDecl(ident, Proc([]))  # entered without parameters
        sc = topScope()
        CG.genProcStart()
        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)
                else:
                    typedIds(Var)
                while SC.sym == SEMICOLON:
                    getSym()
                    if SC.sym == VAR:
                        getSym()
                        typedIds(Ref)
                    else:
                        typedIds(Var)
            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 = CG.genFormalParams(fp)
        if SC.sym == SEMICOLON:
            getSym()
        else:
            mark("; expected")
        localsize = declarations(CG.genLocalVars)
        CG.genProcEntry(ident, parsize, localsize)
        x = compoundStatement()
        CG.genProcExit(x, parsize, localsize)
        closeScope()  # scope for parameters and body closed
        if SC.sym == SEMICOLON:
            getSym()
        else:
            mark("; expected")
    return varsize
Beispiel #30
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
    """
    global depth
    if SC.sym not in FIRSTDECL | FOLLOWDECL:
        getSym()
        mark("'begin' or declaration expected")
        while SC.sym not in FIRSTDECL | STRONGSYMS | FOLLOWDECL:
            getSym()
    while SC.sym == CONST:
        # attributes
        depth += 1
        write(indent * depth)
        write('const')
        writeln()
        writeHtml(htmlIndent * depth)
        writeHtml('const')
        writeHtmlLn()
        #
        getSym()
        if SC.sym == IDENT:
            # attributes
            depth += 1
            ident = SC.val
            write(indent * depth)
            write(ident)
            writeHtml(htmlIndent * depth)
            # integer constant is upright
            writeHtml(ident)
            #
            getSym()
            if SC.sym == EQ:
                # attribute
                write(' = ')
                writeHtml(' = ')
                #
                getSym()
            else:
                mark("= expected")
            x = expression()
            if type(x) == Const: newObj(ident, x)
            else: mark('expression not constant')
            depth -= 1
        else:
            mark("constant name expected")
        if SC.sym == SEMICOLON:
            # attributes
            write(';')
            writeln()
            writeHtml(';')
            writeHtmlLn()
            #
            getSym()
        else:
            mark("; expected")
        depth -= 1
    while SC.sym == TYPE:
        # attributes
        depth += 1
        write(indent * depth)
        write('type')
        writeln()
        writeHtml(htmlIndent * depth)
        writeHtml('type')
        writeHtmlLn()
        #
        getSym()
        if SC.sym == IDENT:
            # attributes
            depth += 1
            ident = SC.val
            write(indent * depth)
            write(ident)
            writeHtml(htmlIndent * depth)
            writeHtml(ident, _class='ident')
            #
            getSym()
            if SC.sym == EQ:
                # attributes
                write(' = ')
                writeHtml(' = ')
                #
                getSym()
            else:
                mark("= expected")
            # attributes (emulate stack)
            old_depth = depth
            depth += 1
            x = typ()
            depth = old_depth
            #
            newObj(ident, x)  #  x is of type ST.Type
            if SC.sym == SEMICOLON:
                # attribute
                write(';')
                writeln()
                writeHtml(';')
                writeHtmlLn()
                getSym()
                #
            else:
                mark("; expected")
            depth -= 1
        else:
            mark("type name expected")
        depth -= 1
    start = len(topScope())
    while SC.sym == VAR:
        # attributes
        depth += 1
        write(indent * depth)
        write('var')
        writeln()
        writeHtml(htmlIndent * depth)
        writeHtml('var')
        writeHtmlLn()
        depth += 1
        getSym()
        write(indent * depth)
        write(SC.val)
        writeHtml(htmlIndent * depth)
        writeHtml(SC.val)
        #
        typedIds(Var)
        if SC.sym == SEMICOLON:
            #
            write(';')
            writeln()
            writeHtml(';')
            writeHtmlLn()
            getSym()
            #
        else:
            mark("; expected")
        depth -= 2
    varsize = allocVar(topScope(), start)
    while SC.sym == PROCEDURE:
        #
        depth += 1
        write(indent * depth)
        write('procedure ')
        writeHtml(htmlIndent * depth)
        writeHtml('procedure ')
        #
        getSym()
        if SC.sym == IDENT:
            #
            write(SC.val)
            writeHtml(SC.val)
            #
            getSym()
        else:
            mark("procedure name expected")
        ident = SC.val
        newObj(ident, Proc([]))  #  entered without parameters
        sc = topScope()
        CG.procStart()
        openScope()  # new scope for parameters and body
        if SC.sym == LPAREN:
            #
            write('(')
            writeHtml('(')
            #
            getSym()
            if SC.sym in {VAR, IDENT}:
                if SC.sym == VAR:
                    #
                    write('var ')
                    writeHtml('var ')
                    getSym()
                    write(SC.val)
                    writeHtml(SC.val)
                    #
                    typedIds(Ref)
                else:
                    typedIds(Var)
                while SC.sym == SEMICOLON:
                    #
                    write('; ')
                    writeHtml('; ')
                    #
                    getSym()
                    if SC.sym == VAR:
                        #
                        write('var ')
                        writeHtml('var ')
                        getSym()
                        write(SC.val)
                        writeHtml(SC.val)
                        #
                        typedIds(Ref)
                    else:
                        #
                        write(SC.val)
                        writeHtml(SC.val)
                        #
                        typedIds(Var)
            else:
                mark("formal parameters expected")
            fp = topScope()
            sc[-1].par = fp[:]  #  procedure parameters updated
            if SC.sym == RPAREN:
                #
                write(')')
                writeHtml(')')
                #
                getSym()
            else:
                mark(") expected")
        else:
            fp = []
        parsize = CG.genFormalParams(fp)
        if SC.sym == SEMICOLON:
            #
            write(';')
            writeln()
            writeHtml(';')
            writeHtmlLn()
            #
            getSym()
        else:
            mark("; expected")
        depth += 1
        localsize = declarations(CG.genLocalVars)
        CG.genProcEntry(ident, parsize, localsize)
        x = compoundStatement(depth + 1)
        CG.genProcExit(x, parsize, localsize)
        closeScope()  #  scope for parameters and body closed
        if SC.sym == SEMICOLON: getSym()
        else: mark("; expected")
        depth -= 1
    return varsize
Beispiel #31
0
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
Beispiel #32
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
Beispiel #33
0
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
Beispiel #34
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
Beispiel #35
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
Beispiel #36
0
def typedIds():
    if SC.sym == IDENT: tid = [SC.val]; getSym()
    else: mark("identifier expected")
    while SC.sym == COMMA:
        getSym()
        if SC.sym == IDENT: tid.append(SC.val); getSym()
        else: mark('identifier expected')
    if SC.sym == COLON: getSym()
    else: mark("':' expected")
    tp = typ().val
    for i in tid: newDecl(i, Var(tp))
    while SC.sym == COMMA:
        getSym()
        if SC.sym == IDENT: tid = [SC.val]; getSym()
        else: mark("identifier expected")
        while SC.sym == COMMA:
            getSym()
            if SC.sym == IDENT: tid.append(SC.val); getSym()
            else: mark('identifier expected')
        if SC.sym == COLON: getSym()
        else: mark("':' expected")
        tp = typ().val
        for i in tid: newDecl(i, Var(tp))
Beispiel #37
0
def statementBlock():
    x = statementList()
    while SC.sym in FIRSTSTATEMENT:
        if not SC.newline: mark('new line expected')
        y = statementList(); x = CG.genSeq(x, y)
    return x
Beispiel #38
0
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
Beispiel #39
0
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
Beispiel #40
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
Beispiel #41
0
                    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
        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:
Beispiel #42
0
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
Beispiel #43
0
def testRange(x):
    if x.val >= 0x8000 or x.val < -0x8000: mark('value too large')
Beispiel #44
0
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
Beispiel #45
0
def find(name):
    for l in symTab:
        for e in l:
            if name == e.name: return e
    mark('undefined identifier ' + name)
    return Const(None, 0)
Beispiel #46
0
def declarations(allocVar):
    while SC.sym == CONST:
        getSym()
        if SC.sym == IDENT: ident = SC.val; getSym()
        else: mark("constant name expected")
        if SC.sym == EQ: getSym()
        else: mark("= expected")
        x = expression()
        if type(x) == Const: newDecl(ident, x)
        else: mark('expression not constant')
    while SC.sym == TYPE:
        getSym()
        if SC.sym == IDENT: ident = SC.val; getSym()
        else: mark("type name expected")
        if SC.sym == EQ: getSym()
        else: mark("= expected")
        x = typ(); newDecl(ident, x)  #  x is of type ST.Type
    start = len(topScope())
    while SC.sym == VAR:
        getSym(); typedIds()
    var = allocVar(topScope(), start)
    while SC.sym == PROCEDURE:
        getSym()
        if SC.sym == LPAREN:
            getSym()
            if SC.sym == IDENT: r = SC.val; getSym()
            else: mark("identifier expected")
            if SC.sym == COLON: getSym()
            else: mark("':' expected")
            tp = typ().val
            if SC.sym == RPAREN: getSym()
            else: mark(") expected")
        else: r = None
        if SC.sym == IDENT: ident = SC.val; getSym()
        else: mark("procedure name expected")
        newDecl(ident, Proc([], [])) #  entered without parameters
        sc = topScope(); openScope() # new scope for parameters and body
        if r: newDecl(r, Var(tp))
        if SC.sym == LPAREN: getSym()
        else: mark("( expected")
        if SC.sym == IDENT: typedIds()
        fp = topScope()
        if SC.sym == RPAREN: getSym()
        else: mark(") expected")
        d = len(fp)
        if SC.sym == RARROW:
            getSym()
            if SC.sym == LPAREN: getSym()
            else: mark('( expected')
            typedIds()
            if SC.sym == RPAREN: getSym()
            else: mark(') expected')
        sc[-1].par, sc[-1].res = fp[:d], fp[d:] #  procedure parameters updated
        para = CG.genProcStart(ident, fp[:d], fp[d:])
        body(ident, para); closeScope() #  scope for parameters and body closed
    return var
Beispiel #47
0
def compileFile(srcfn):
    if srcfn.endswith('.p'):
        with open(srcfn, 'r') as f: src = f.read()
        dstfn = srcfn[:-2] + '.s'
        compileString(src, dstfn)
    else: mark("'.p' file extension expected")
Beispiel #48
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
Beispiel #49
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
Beispiel #50
0
def obtainReg():
    if len(regs) == 0:
        mark('out of registers')
        return R0
    else:
        return regs.pop()
Beispiel #51
0
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
Beispiel #52
0
def testRange(x):
    """Check if x is suitable for immediate addressing"""
    if x.val >= 0x8000 or x.val < -0x8000:
        mark("value too large")
Beispiel #53
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
Beispiel #54
0
def obtainReg():
    if len(regs) == 0:
        mark("out of registers")
        return R0
    else:
        return regs.pop()
Beispiel #55
0
def newObj(name, entry):
    top, entry.lev, entry.name = symTab[0], len(symTab) - 1, name
    for e in top:
        if e.name == name:
            mark("multiple definition"); return
    top.append(entry)