Beispiel #1
0
def parse_imp(input):
    # parse a string into an element of the abstract representation

    # Grammar:
    #
    # <expr> ::= <integer>
    #            true
    #            false
    #            <identifier>
    #            ( if <expr> <expr> <expr> )
    #            ( function ( <name ... ) <expr> )
    #            ( <expr> <expr> ... )
    #
    # <decl> ::= var name = expr ;
    #
    # <stmt> ::= if <expr> <stmt> else <stmt>
    #            while <expr> <stmt>
    #            name <- <expr> ;
    #            print <expr> ;
    #            <block>
    #
    # <block> ::= { <decl> ... <stmt> ... }
    #
    # <toplevel> ::= <decl>
    #                <stmt>
    #

    idChars = alphas + "_+*-?!=<>+"

    QUOTE = Literal('"')
    INTERNAL_QUOTE = QUOTE.copy().leaveWhitespace()

    pIDENTIFIER = Word(idChars, idChars + "0123456789")
    #### NOTE THE DIFFERENCE
    pIDENTIFIER.setParseAction(
        lambda result: EPrimCall(oper_deref, [EId(result[0])]))

    # A name is like an identifier but it does not return an EId...
    pNAME = Word(idChars,
                 idChars + "0123456789")  #| Keyword("&\"") | Keyword("&\'")

    pNAMES = ZeroOrMore(pNAME)
    pNAMES.setParseAction(lambda result: [result])

    pINTEGER = Word("0123456789")
    pINTEGER.setParseAction(lambda result: EValue(VInteger(int(result[0]))))

    QUOTE = Literal("&\"") | Literal("&\'")
    pSTRING = Literal('"') + ZeroOrMore(
        Combine(Word(idChars + "0123456789'" + " ") | QUOTE)) + Literal('"')
    pSTRING.setParseAction(lambda result: EValue(VString(str(result[1:-1]))))

    pBOOLEAN = Keyword("true") | Keyword("false")
    pBOOLEAN.setParseAction(
        lambda result: EValue(VBoolean(result[0] == "true")))

    pEXPR = Forward()

    pEXPRS = ZeroOrMore(pEXPR)
    pEXPRS.setParseAction(lambda result: [result])

    pIF = "(" + Keyword("if") + pEXPR + pEXPR + pEXPR + ")"
    pIF.setParseAction(lambda result: EIf(result[2], result[3], result[4]))

    def mkFunBody(params, body):
        bindings = [(p, ERefCell(EId(p))) for p in params]
        return ELet(bindings, body)

    def letToFun(result):
        func = result[5]
        binds = result[3]
        params = []
        vals = []
        for p, v in binds:
            params.append(p)
            vals.append(v)
        return ECall(EFunction(params, func), vals)

    pFUN = "(" + Keyword("function") + "(" + pNAMES + ")" + pEXPR + ")"
    pFUN.setParseAction(
        lambda result: EFunction(result[3], mkFunBody(result[3], result[5])))

    pBINDING = "(" + pNAME + pEXPR + ")"
    pBINDING.setParseAction(lambda result: (result[1], result[2]))

    pBINDINGS = OneOrMore(pBINDING)
    pBINDINGS.setParseAction(lambda result: [result])

    pLET = "(" + Keyword("let") + "(" + pBINDINGS + ")" + pEXPR + ")"
    pLET.setParseAction(letToFun)

    pCALL = "(" + pEXPR + pEXPRS + ")"
    pCALL.setParseAction(lambda result: ECall(result[1], result[2]))

    pARRAY = "(" + Keyword("new-array") + pEXPR + ")"
    pARRAY.setParseAction(lambda result: EArray(result[2]))

    pINDEX = Keyword("index") + pINTEGER
    pCALL.setParseAction(lambda result: ECall(result[1], result[2]))

    pWITH = "(" + Keyword("with") + pEXPR + pEXPR + ")"
    pWITH.setParseAction(lambda result: EWithObj(result[2], result[3]))

    pEXPR << (pINTEGER | pARRAY | pSTRING | pWITH | pBOOLEAN | pIDENTIFIER
              | pIF | pLET | pFUN | pCALL)

    pDECL_VAR = "var" + pNAME + "=" + pEXPR + ";"
    pDECL_VAR.setParseAction(lambda result: (result[1], result[3]))

    pSTMT = Forward()

    pDECL_PROCEDURE = "procedure" + pNAME + "(" + pNAMES + ")" + pSTMT
    pDECL_PROCEDURE.setParseAction(lambda result: (result[
        1], EProcedure(result[3], mkFunBody(result[3], result[5]))))

    # hack to get pDECL to match only PDECL_VAR (but still leave room
    # to add to pDECL later)
    pDECL = (pDECL_VAR | pDECL_PROCEDURE | NoMatch() | ";")

    pDECLS = ZeroOrMore(pDECL)
    pDECLS.setParseAction(lambda result: [result])

    pSTMT_IF_1 = "if" + pEXPR + pSTMT + "else" + pSTMT
    pSTMT_IF_1.setParseAction(
        lambda result: EIf(result[1], result[2], result[4]))

    pSTMT_IF_2 = "if" + pEXPR + pSTMT
    pSTMT_IF_2.setParseAction(
        lambda result: EIf(result[1], result[2], EValue(VBoolean(True))))

    pSTMT_WHILE = "while" + pEXPR + pSTMT
    pSTMT_WHILE.setParseAction(lambda result: EWhile(result[1], result[2]))

    pSTMT_FOR = "for" + pDECLS + pEXPR + ";" + pSTMT + pSTMT
    pSTMT_FOR.setParseAction(
        lambda result: EFor(result[1], result[2], result[4], result[5]))

    pSTMT_PRINT = "print" + pEXPR + ";"
    pSTMT_PRINT.setParseAction(
        lambda result: EPrimCall(oper_print, [result[1]]))

    pSTMT_UPDATE_ARR = pNAME + "[" + pINTEGER + "]" + "<-" + pEXPR + ";"
    pSTMT_UPDATE_ARR.setParseAction(lambda result: EPrimCall(
        oper_update_arr, [EId(result[0]), result[2], result[5]]))

    pSTMT_UPDATE = pNAME + "<-" + pEXPR + ";"
    pSTMT_UPDATE.setParseAction(
        lambda result: EPrimCall(oper_update, [EId(result[0]), result[2]]))

    pSTMT_PROCEDURE = pEXPR + "(" + pEXPRS + ")" + ";"
    pSTMT_PROCEDURE.setParseAction(lambda result: ECall(result[0], result[2]))

    pSTMTS = ZeroOrMore(pSTMT)
    pSTMTS.setParseAction(lambda result: [result])

    def mkBlock(decls, stmts):
        bindings = [(n, ERefCell(expr)) for (n, expr) in decls]
        return ELet(bindings, EDo(stmts))

    pSTMT_BLOCK = "{" + pDECLS + pSTMTS + "}"
    pSTMT_BLOCK.setParseAction(lambda result: mkBlock(result[1], result[2]))

    pSTMT << (pSTMT_IF_1 | pSTMT_IF_2 | pWITH | pSTMT_WHILE | pSTMT_FOR
              | pSTMT_PRINT | pSTMT_UPDATE_ARR | pSTMT_UPDATE | pSTMT_PROCEDURE
              | pSTMT_BLOCK)

    # can't attach a parse action to pSTMT because of recursion, so let's duplicate the parser
    pTOP_STMT = pSTMT.copy()
    pTOP_STMT.setParseAction(lambda result: {
        "result": "statement",
        "stmt": result[0]
    })

    pTOP_DECL = pDECL.copy()
    pTOP_DECL.setParseAction(lambda result: {
        "result": "declaration",
        "decl": result[0]
    })

    pABSTRACT = "#abs" + pSTMT
    pABSTRACT.setParseAction(lambda result: {
        "result": "abstract",
        "stmt": result[1]
    })
    pQUIT = Keyword("#quit")
    pQUIT.setParseAction(lambda result: {"result": "quit"})

    pTOP = (pQUIT | pABSTRACT | pTOP_DECL | pTOP_STMT)

    result = pTOP.parseString(input)[0]
    return result  # the first element of the result is the expression
Beispiel #2
0
def parse_imp (input):
    # parse a string into an element of the abstract representation

    # Grammar:
    #
    # <expr> ::= <integer>
    #            true
    #            false
    #            <identifier>
    #            ( if <expr> <expr> <expr> )
    #            ( function ( <name ... ) <expr> )    
    #            ( <expr> <expr> ... )
    #
    # <decl> ::= var name = expr ; 
    #
    # <stmt> ::= if <expr> <stmt> else <stmt>
    #            while <expr> <stmt>
    #            name <- <expr> ;
    #            print <expr> ;
    #            <block>
    #
    # <block> ::= { <decl> ... <stmt> ... }
    #
    # <toplevel> ::= <decl>
    #                <stmt>
    #

    idChars = alphas+"_+*-?!=<>+"

    QUOTE = Literal('"')
    INTERNAL_QUOTE = QUOTE.copy().leaveWhitespace()

    pIDENTIFIER = Word(idChars, idChars+"0123456789")
    #### NOTE THE DIFFERENCE
    pIDENTIFIER.setParseAction(lambda result: EPrimCall(oper_deref,[EId(result[0])]))

    # A name is like an identifier but it does not return an EId...
    pNAME = Word(idChars,idChars+"0123456789") #| Keyword("&\"") | Keyword("&\'")

    pNAMECON = "," + pNAME
    pNAMECON.setParseAction(lambda result: result[1])

    pNAMES = pNAME + ZeroOrMore(pNAMECON) | ZeroOrMore(pNAME)
    pNAMES.setParseAction(lambda result: [result])

    pINTEGER = Word("0123456789")
    pINTEGER.setParseAction(lambda result: EValue(VInteger(int(result[0]))))

    QUOTE = Literal("&\"") | Literal("&\'") 
    pSTRINGSTART = Literal('"') + ZeroOrMore(Word(" ")).leaveWhitespace()
    pSTRINGSTART.setParseAction(lambda result: result[1:])

    pSTRING = pSTRINGSTART + ZeroOrMore(Combine( Word(idChars+"0123456789'"+" ") | QUOTE)) + Literal('"')
    pSTRING.setParseAction(lambda result: EValue(VString(str(result[:-1]))))

    pBOOLEAN = Keyword("true") | Keyword("false")
    pBOOLEAN.setParseAction(lambda result: EValue(VBoolean(result[0]=="true")))

    pEXPR = Forward()
    pEXPR2 = Forward()
    pSTMT_BLOCK = Forward()
    pSTMT = Forward()

    pEXPRS = ZeroOrMore(pEXPR2)
    pEXPRS.setParseAction(lambda result: [result])

    pIF = pEXPR + Keyword("?") + pEXPR + Keyword(':') + pEXPR
    pIF.setParseAction(lambda result: EIf(result[0], result[2], result[4]))


    def mkFunBody (params,body):
        bindings = [ (p,ERefCell(EId(p))) for p in params ]
        return ELet(bindings,body)

    def mkLetBody (bindings,body):
        bindings = [ (p[0],ERefCell(p[1])) for p in bindings ]
        return ELet(bindings,body)

    def multiCallHelper(result, start, i, length):
        if i < length:
            start = ECall(result[1][i][0], [result[1][i][1], start])
            multiCallHelper(result, start, i + 1, length)
        return start

    def multiCall(result):
        start = ECall(result[1][0][0], [result[0], result[1][0][1]])
        return multiCallHelper(result, start, 1, len(result[1]))

    def eFunHelper(variables, expression):
        if len(variables) == 1:
            return EFunction(variables[0], expression)
        else:
            return EFunction(variables[0], eFunHelper(variables[1:], expression))

    def eFunName(result):
        varName = result[1]
        variables = result[3]
        expression = result[-1]
        print variables, expression
        return EFunction(variables, expression, varName)

    pFUN = Keyword("fun") + "(" + pNAMES + ")" + pSTMT
    pFUN.setParseAction(lambda result: EFunction(result[2],mkFunBody(result[2],result[4])))

    pFUNR = Keyword("fun") + pNAME + "(" + pNAMES + ")" + pSTMT
    # pFUNR.setParseAction(eFunName)
    pFUNR.setParseAction(lambda result: EFunction(result[3],mkFunBody(result[3],result[5]), result[1]))

    pEXPR2CAR = "," + pEXPR2
    pEXPR2CAR.setParseAction(lambda result: result[1])

    pEXPR2MULTIALL = pEXPR2 + ZeroOrMore(pEXPR2CAR) | ZeroOrMore(pEXPR2)
    pEXPR2MULTIALL.setParseAction(lambda result: [result])

    pFUNCALL = pEXPR + "(" + pEXPR2MULTIALL + ")"
    pFUNCALL.setParseAction(lambda result: ECall(result[0], result[2]))

    pBINDINGCAR = "," + pNAME + "=" + pEXPR2
    pBINDINGCAR.setParseAction(lambda result: (result[1], result[3]))
    
    pBINDINGCON = pNAME + "=" + pEXPR2
    pBINDINGCON.setParseAction(lambda result: (result[0], result[2]))

    pBINDINGS = pBINDINGCON  + ZeroOrMore(pBINDINGCAR)
    pBINDINGS.setParseAction(lambda result: [result])

    pLET = Keyword("let") + "(" + pBINDINGS + ")" + pEXPR2
    pLET.setParseAction(lambda result: mkLetBody(result[2], result[4]))

    pCALLG = pIDENTIFIER + pEXPR2
    pCALLG.setParseAction(lambda result: (result[0], result[1]))

    pCALL1S = OneOrMore(pCALLG)
    pCALL1S.setParseAction(lambda result: [ result ])

    pCALL =  pEXPR + pCALL1S 
    pCALL.setParseAction(multiCall)

    pCALL1 = pIDENTIFIER + pEXPR2
    pCALL1.setParseAction(lambda result: ECall(result[0], [result[1]]))

    pNOT = "not" + pEXPR2
    pNOT.setParseAction(lambda result: EPrimCall(oper_not, [result[1]]))

    pARRAYITEM = "," + pEXPR2
    pARRAYITEM.setParseAction(lambda result: (result[1]))

    pARRAYITEMS = ZeroOrMore(pARRAYITEM)
    pARRAYITEMS.setParseAction(lambda result: [result])

    pARRAY = "[" + ZeroOrMore(pEXPR2) + pARRAYITEMS + "]"
    pARRAY.setParseAction(lambda result: EArray(result[1],result[2]))

    pDICTPAIR = pNAME + ":" + pEXPR
    pDICTPAIR.setParseAction(lambda result: (result[0],result[2]))

    pDICTPAIRWITHCOMMA = "," + pNAME + ":" + pEXPR
    pDICTPAIRWITHCOMMA.setParseAction(lambda result: (result[1],result[3]))

    pDICTS = ZeroOrMore(pDICTPAIRWITHCOMMA)
    pDICTS.setParseAction(lambda result: [ result ])

    pDICT = "{" + pDICTPAIR + pDICTS + "}"
    pDICT.setParseAction(lambda result:EDict(result[1],result[2]))

    pEXPR2P = "(" + pEXPR2 + ")"
    pEXPR2P.setParseAction(lambda result: result[1])

    pACCESS = pNAME + "[" + pEXPR + "]"
    pACCESS.setParseAction(lambda result: EPrimCall(oper_access_arr,[EId(result[0]),result[2]]))

    pLEN = Keyword("len") + "(" + pNAME + ")"
    pLEN.setParseAction(lambda result: EPrimCall(oper_len,[EId(result[2])]))

    pEXPR << ( pEXPR2P |  pINTEGER | pNOT | pARRAY | pACCESS | pDICT | pSTRING | pBOOLEAN | pIDENTIFIER | pCALL1 | pLEN )

    pEXPR2 << ( pLET | pFUN | pFUNR | pFUNCALL | pIF | pCALL | pEXPR )

    pDECL_VAR_E = "var" + pNAME + ";"
    pDECL_VAR_E.setParseAction(lambda result: (result[1], EValue(VNone)))

    pDECL_VAR = "var" + pNAME + "=" + pEXPR2 + ";"
    pDECL_VAR.setParseAction(lambda result: (result[1],result[3]))

    pDECL_PROCEDURE = "def" + pNAME + "(" + pNAMES + ")" + pSTMT
    pDECL_PROCEDURE.setParseAction(lambda result: (result[1], EProcedure(result[3], mkFunBody(result[3], result[5]))))

    # hack to get pDECL to match only PDECL_VAR (but still leave room
    # to add to pDECL later)
    pDECL = ( pDECL_VAR_E | pDECL_VAR | pDECL_PROCEDURE | NoMatch() | ";" )

    pDECLS = ZeroOrMore(pDECL)
    pDECLS.setParseAction(lambda result: [result])

    pSTMT_IF_1 = "if (" + pEXPR2 + ")" + pSTMT + "else" + pSTMT
    pSTMT_IF_1.setParseAction(lambda result: EIf(result[1],result[3],result[5]))

    pSTMT_IF_2 = "if (" + pEXPR2 + ")" + pSTMT
    pSTMT_IF_2.setParseAction(lambda result: EIf(result[1],result[3],EValue(VBoolean(True))))
   
    pSTMT_WHILE = "while (" + pEXPR2 + ")" + pSTMT
    pSTMT_WHILE.setParseAction(lambda result: EWhile(result[1],result[3]))

    pSTMT_FOR = "for (" + pNAME + "in" + pEXPR2 + ")" + pSTMT
    pSTMT_FOR.setParseAction(lambda result: EFor(result[1], result[3], result[5]))

    pSTMT_PRINT_STMS = "," + pEXPR2
    pSTMT_PRINT_STMS.setParseAction(lambda result: [ result[1] ])

    pSTMT_PRINT_ZERO = ZeroOrMore(pSTMT_PRINT_STMS)
    pSTMT_PRINT_ZERO.setParseAction(lambda result: [ result ])

    def printStmEval(result):
        newArray = []
        newArray.append(result[1])
        for i in result[2]:
            newArray.append(i)
        return EPrimCall(oper_print,newArray)

    pSTMT_PRINT = "print" + pEXPR2 + pSTMT_PRINT_ZERO + ";"
    pSTMT_PRINT.setParseAction(printStmEval)

    pSTMT_UPDATE_ARR = pNAME + "[" + pEXPR +"]" + "=" + pEXPR + ";"
    pSTMT_UPDATE_ARR.setParseAction(lambda result: EPrimCall(oper_update_arr,[EId(result[0]),result[2],result[5]]))

    pSTMT_UPDATE = pNAME + "=" + pEXPR2 + ";"
    pSTMT_UPDATE.setParseAction(lambda result: EPrimCall(oper_update,[EId(result[0]),result[2]]))

    pSTMTS = ZeroOrMore(pSTMT)
    pSTMTS.setParseAction(lambda result: [result])

    def mkBlock (decls,stmts):
        bindings = [ (n,ERefCell(expr)) for (n,expr) in decls ]
        return ELet(bindings,EDo(stmts))
        
    pSTMT_BLOCK = "{" + pDECLS + pSTMTS + "}"
    pSTMT_BLOCK.setParseAction(lambda result: mkBlock(result[1],result[2]))

    pSTMT_pEXPR2 = pEXPR2 + ";"
    pSTMT_pEXPR2.setParseAction(lambda result: result[0])

    pSTMT << ( pSTMT_IF_1 | pSTMT_IF_2 | pSTMT_WHILE | pSTMT_FOR | pSTMT_PRINT | pSTMT_UPDATE_ARR | pSTMT_UPDATE | pSTMT_BLOCK | pSTMT_pEXPR2 | pEXPR2 )

    # can't attach a parse action to pSTMT because of recursion, so let's duplicate the parser
    pTOP_STMT = pSTMT.copy()
    pTOP_STMT.setParseAction(lambda result: {"result":"statement",
                                             "stmt":result[0]})

    pTOP_DECL = pDECL.copy()
    pTOP_DECL.setParseAction(lambda result: {"result":"declaration",
                                             "decl":result[0]})

    pABSTRACT = "#abs" + pSTMT
    pABSTRACT.setParseAction(lambda result: {"result":"abstract",
                                             "stmt":result[1]})
    pQUIT = Keyword("#quit")
    pQUIT.setParseAction(lambda result: {"result":"quit"})

    pTOP =  ZeroOrMore(pTOP_DECL) + ZeroOrMore(pTOP_STMT) 
    return pTOP.parseString(input)