Exemplo n.º 1
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
Exemplo n.º 2
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", 37)
        while SC.sym not in FIRSTTYPE | FOLLOWTYPE | STRONGSYMS:
            getSym()
    if SC.sym == IDENT:
        ident = SC.val
        x = find(ident)
        getSym()
        if type(x) == Type: x = Type(x.tp)
        else: mark('not a type', 38)
    elif SC.sym == ARRAY:
        getSym()
        if SC.sym == LBRAK: getSym()
        else: mark("'[' expected", 39)
        x = expression()
        if type(x) != Const or x.val < 0: mark('bad lower bound', 40)
        if SC.sym == PERIOD: getSym()
        else: mark("'.' expected", 41)
        if SC.sym == PERIOD: getSym()
        else: mark("'.' expected", 42)
        y = expression()
        if type(y) != Const or y.val < x.val: mark('bad upper bound', 43)
        if SC.sym == RBRAK: getSym()
        else: mark("']' expected", 44)
        if SC.sym == OF: getSym()
        else: mark("'of' expected", 45)
        z = typ().tp
        l = y.val - x.val + 1
        x = Type(genArray(Array(z, x.val, l)))
    elif SC.sym == RECORD:
        getSym()
        openScope()
        typedIds(Var)
        while SC.sym == SEMICOLON:
            getSym()
            typedIds(Var)
        if SC.sym == END: getSym()
        else: mark("'end' expected", 46)
        r = topScope()
        closeScope()
        x = Type(genRec(Record(r)))
    else:
        mark("type expected", 47)
        x = Type(None)
    return x
Exemplo n.º 3
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)
        writeHtml(SC.val)
        getSym()
        x = selector(x)
    elif SC.sym == NUMBER:
        x = Const(Int, SC.val)
        x = CG.genConst(x)
        write(str(SC.val))
        writeHtml(str(SC.val))
        getSym()
    elif SC.sym == LPAREN:
        write('(')
        writeHtml('(')
        getSym()
        x = expression()
        if SC.sym == RPAREN:
            write(')')
            writeHtml(')')
            getSym()
        else:
            mark(") expected")
    elif SC.sym == NOT:
        write('not ')
        writeHtml('not ')
        getSym()
        x = factor()
        if x.tp != Bool: mark('not boolean')
        elif type(x) == Const: x.val = 1 - x.val  # constant folding
        else: x = CG.genUnaryOp(NOT, x)
    else: x = Const(None, 0)
    return x
Exemplo n.º 4
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
Exemplo n.º 5
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
Exemplo n.º 6
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
Exemplo n.º 7
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", 8)
        getSym()
        while SC.sym not in FIRSTFACTOR | STRONGSYMS | FOLLOWFACTOR:
            getSym()
    if SC.sym == IDENT:
        x = find(SC.val)
        if type(x) in {Var, Ref}: x = genVar(x)
        elif type(x) == Const:
            x = Const(x.tp, x.val)
            x = genConst(x)
        else:
            mark('variable or constant expected', 9)
        getSym()
        x = selector(x)
    elif SC.sym == NUMBER:
        x = Const(Int, SC.val)
        x = genConst(x)
        getSym()
    elif SC.sym == LPAREN:
        getSym()
        x = expression()
        if SC.sym == RPAREN: getSym()
        else: mark(") expected", 10)
    elif SC.sym == NOT:
        getSym()
        x = factor()
        if x.tp != Bool: mark('not boolean', 11)
        elif type(x) == Const: x.val = 1 - x.val  # constant folding
        else: x = genUnaryOp(NOT, x)
    else:
        mark("factor expected", 12)
        x = None
    return x
Exemplo n.º 8
0
def factor():
    if SC.sym not in FIRSTFACTOR:
        mark("expression expected")
        getSym()
        while SC.sym not in FIRSTFACTOR | STRONGSYMS | FOLLOWFACTOR:
            getSym()
    if SC.sym == IDENT:
        x = find(SC.val)
        if type(x) in {Var, Ref}: x = CG.genVar(x)
        elif type(x) == Const:
            x = Const(x.tp, x.val)
            x = CG.genConst(x)
        else:
            mark('expression expected')
        getSym()
        x = selector(x)
    elif SC.sym == NUMBER:
        x = Const(Int, SC.val)
        x = CG.genConst(x)
        getSym()
    elif SC.sym == LPAREN:
        getSym()
        x = expression()
        if SC.sym == RPAREN: getSym()
        else: mark(") expected")
    elif SC.sym == NOT:
        getSym()
        x = factor()
        if x.tp != Bool: mark('not boolean')
        elif type(x) == Const: x.val = 1 - x.val  # constant folding
        else: x = CG.genUnaryOp(NOT, x)
    elif SC.sym == TILDE:
        getSym()
        x = factor()
        if x.tp != Int: mark('not integer')
        elif type(x) == Const: x.val = ~x.val  # constant folding
        else: x = CG.genUnaryOp(TILDE, x)
    else: x = Const(None, 0)
    return x
Exemplo n.º 9
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
Exemplo n.º 10
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", 20)
        getSym()
        while SC.sym not in FIRSTSTATEMENT | STRONGSYMS | FOLLOWSTATEMENT:
            getSym()
    if SC.sym == IDENT:
        x = find(SC.val)
        getSym()
        x = genVar(x)
        if type(x) in {Var, Ref}:
            x = selector(x)
            if SC.sym == BECOMES:
                getSym()
                y = expression()
                if x.tp == y.tp in {Bool, Int}:
                    if type(x) == Var:
                        x = genAssign(x, y)
                    # else:
                    #     mark('illegal assignment', 21)
                else:
                    mark('incompatible assignment', 22)
            elif SC.sym == EQ:
                mark(':= expected', 23)
                getSym()
                y = expression()
            else:
                mark(':= expected', 24)
        elif type(x) in {Proc, StdProc} and SC.sym == LPAREN:
            getSym()
            fp, i = x.par, 0  #  list of formal parameters
            if SC.sym in FIRSTEXPRESSION:
                y = expression()
                if i < len(fp):
                    if type(fp[i]) == Var or type(y) == Var:
                        if type(x) == Proc:
                            genActualPara(y, fp[i], i)
                        #i = i + 1
                    else:
                        mark('illegal parameter mode', 25)
                    i = i + 1
                else:
                    mark('extra parameter', 26)
                while SC.sym == COMMA:
                    getSym()
                    y = expression()
                    if i < len(fp):
                        if type(fp[i]) == Var or type(y) == Var:
                            if type(x) == Proc:
                                genActualPara(y, fp[i], i)
                            #i = i + 1
                        else:
                            mark('illegal parameter mode', 27)
                        i = i + 1
                    else:
                        mark('extra parameter', 28)
            if i < len(fp): mark('too few parameters', 29)
            #if i > 0: mark('too few parameters')
            if SC.sym == RPAREN: getSym()
            else: mark("')' expected", 30)
            if type(x) == StdProc:
                if x.name == 'read': x = genRead(y)
                elif x.name == 'write': x = genWrite(y)
                elif x.name == 'writeln': x = genWriteln()
            else: x = genCall(x)
        else: mark("variable or procedure expected", 31)
    elif SC.sym == BEGIN: x = compoundStatement()
    elif SC.sym == IF:
        getSym()
        x = expression()
        # if x.tp == Bool: x = genCond(x)
        # else: mark('boolean expected', 32)
        # if SC.sym == THEN: getSym()
        # else: mark("'then' expected", 33)
        # y = statement()
        # if SC.sym == ELSE:
        #     y = genThen(x, y); getSym(); z = statement();
        #     x = genIfElse(x, y, z)
        # else: x = genIfThen(x, y)

        # eliminate dead code resulting from boolean constants
        if x.tp != Bool:
            mark('boolean expected', 32)

        if SC.sym == THEN: getSym()
        else: mark("'then' expected", 33)

        if type(x) == Const and x.val == 1:  # if true then S -> S

            x = statement()

            if SC.sym == ELSE:  # if true then S else T -> S

                getSym()

                CG.emit = False
                statement()  # T
                CG.emit = True

        elif type(x) == Const and x.val == 0:  # if false then S -> skip

            CG.emit = False
            statement()
            CG.emit = True

            if SC.sym == ELSE:  # if false then S else T -> T
                getSym()
                x = statement()  #T

        else:
            # then
            x = genCond(x)
            # S
            y = statement()
            #print("IF S: "+str(y))

            if SC.sym == ELSE:
                y = genThen(x, y)
                getSym()
                z = statement()
                x = genIfElse(x, y, z)

            else:
                #else:
                x = genIfThen(x, y)

    elif SC.sym == WHILE:
        getSym()
        t = genTarget()
        x = expression()
        if x.tp == Bool: x = genCond(x)
        else: mark('boolean expected', 34)
        if SC.sym == DO: getSym()
        else: mark("'do' expected", 35)
        y = statement()
        x = genWhile(t, x, y)
    else:
        mark('invalid statement', 36)
        x = None
    return x
Exemplo n.º 11
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
Exemplo n.º 12
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
Exemplo n.º 13
0
def typ(l):
    """
    Parses
        type(l) = ident «write(ident)» |
               "array" «writeln; write((l + 1) * indent + 'array ')» "[" «write('[')» expression ".." «write(' .. ')» expression "]" «write(']')» "of" «write(' of ')» type(l)|
               "record" «writeln; write((l + 1) * indent + 'record')» typedIds(l) {";" «write(';')» typedIds(l)} "end" «writeln; write((l + 1) * indent + 'end')».
    Returns a type descriptor 
    """
    if SC.sym not in FIRSTTYPE:
        getSym()
        mark("type expected")
        while SC.sym not in FIRSTTYPE | STRONGSYMS | FOLLOWTYPE:
            getSym()
    if SC.sym == IDENT:
        write(SC.val)
        ident = SC.val
        x = find(ident)
        getSym()
        if type(x) == Type: x = Type(x.tp)
        else:
            mark('not a type')
            x = Type(None)
    elif SC.sym == ARRAY:
        writeln()
        write((l + 1) * indent + 'array ')
        getSym()
        if SC.sym == LBRAK:
            write('[')
            getSym()
        else:
            mark("'[' expected")
        x = expression()
        if SC.sym == PERIOD:
            write(' .')
            getSym()
        else:
            mark("'.' expected")
        if SC.sym == PERIOD:
            write('. ')
            getSym()
        else:
            mark("'.' expected")
        y = expression()
        if SC.sym == RBRAK:
            write(']')
            getSym()
        else:
            mark("']' expected")
        if SC.sym == OF:
            write(' of ')
            getSym()
        else:
            mark("'of' expected")
        z = typ(l + 1).tp
        if type(x) != Const or x.val < 0:
            mark('bad lower bound')
            x = Type(None)
        elif type(y) != Const or y.val < x.val:
            mark('bad upper bound')
            y = Type(None)
        else:
            x = Type(CG.genArray(Array(z, x.val, y.val - x.val + 1)))
    elif SC.sym == RECORD:
        writeln()
        write((l + 1) * indent + 'record ')
        writeln()
        write((l + 2) * indent)
        getSym()
        openScope()
        typedIds(Var, l + 2)
        while SC.sym == SEMICOLON:
            write(';')
            writeln()
            write((l + 2) * indent)
            getSym()
            typedIds(Var, l + 2)
        if SC.sym == END:
            writeln()
            write((l + 1) * indent + 'end')
            getSym()
        else:
            mark("'end' expected")
        r = topScope()
        closeScope()
        x = Type(CG.genRec(Record(r)))
    else:
        x = Type(None)
    return x
Exemplo n.º 14
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
Exemplo n.º 15
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
Exemplo n.º 16
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
Exemplo n.º 17
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