def function(self): """ def[kw] fname[id] (arglist) {body} end[kw] """ if (self.parsing_function): raise ParseException(" Nested functions not allowed! ") self.parsing_function = True def_tok = self.dequeue() if (def_tok.kind != Token.DEF): raise ParseException("unmatched 'def' in function " + str(def_tok)) id_tok = self.dequeue() if (id_tok.kind != Token.ID): raise ParseException("expected identifier in function" + str(id_tok)) arglist = self.arglist() self.dbg_msg("finished parsing arglist") body = self.stmtlist() self.match(Token.END) [l, c] = def_tok.get_line_col() fval = Function(id_tok.val, arglist, body, l, c, self.debug) self.parsing_function = False self.dbg_msg("finished parsing function") return fval
def importStmt(self): lead = self.leadComments() cg = ast.CommentGroup(lead, []) l = self._nextTag(IMPORT).location prefix = self.scopePrefix() if self._peekTag() is DOT: self._next() self._nextTag(UNDERSCORE) imp = ast.ImportStatement(prefix, None, cg, self._location(l)) self._tailComment(imp) return imp if len(prefix) == 1: raise ParseException( prefix[0].location, "import statement requires a prefix before symbol to import") lastComponent = prefix.pop() if lastComponent.typeArguments is not None: raise ParseException( lastComponent.location, "type arguments can't be at the end of an import statement") bindings = [] if self._peekTag() is AS: self._next() asName = self.ident() bindings.append( ast.ImportBinding(lastComponent.name, asName, self._location(lastComponent.location))) else: bindings.append( ast.ImportBinding(lastComponent.name, None, lastComponent.location)) while self._peekTag() is COMMA: self._next() name = self.ident() bl = self.location if self._peekTag() is AS: self._next() asName = self.ident() else: asName = None bindings.append(ast.ImportBinding(name, asName, self._location(bl))) imp = ast.ImportStatement(prefix, bindings, cg, self._location(l)) self._tailComment(imp) return imp
def symbol(self): sym = self._nextTag(SYMBOL).text if sym.startswith("`"): sym = tryDecodeString(sym) if sym is None: raise ParseException(self.location, "invalid symbol") return sym
def valuelist(self): """parse: ( expr_1 , expr_2, ... ) """ valueList = list() self.dbg_msg("valuelist: ") lparen_tok = self.match(EzhilToken.LPAREN) while (self.peek().kind != EzhilToken.RPAREN): val = self.expr() if (self.debug): print("val = ", str(val)) ptok = self.peek() if (self.debug): print("ptok = ", str(ptok), str(ptok.kind), str(EzhilToken.ASSIGNOP)) if (ptok.kind in EzhilToken.ASSIGNOP): assign_tok = self.dequeue() rhs = self.expr() [l, c] = assign_tok.get_line_col() lhs = val val = AssignStmt(lhs, assign_tok, rhs, l, c, self.debug) if (self.debug): print("AssignStmt = ", str(val)) ptok = self.peek() else: if (self.debug): print("No-Assign // Expr =", str(val)) self.dbg_msg("valuelist-expr: " + str(val)) valueList.append(val) if (ptok.kind == EzhilToken.RPAREN): break elif (ptok.kind == EzhilToken.COMMA): self.match(EzhilToken.COMMA) else: raise ParseException(" function call argument list " + str(ptok)) self.match(EzhilToken.RPAREN) [l, c] = lparen_tok.get_line_col() return ValueList(valueList, l, c, self.debug)
def expr(self): self.dbg_msg(" EXPR ") val1 = self.term() res = val1 ptok = self.peek() if ptok.kind in EzhilToken.ADDSUB: binop = self.dequeue() if (ptok.kind == EzhilToken.MINUS): val2 = self.term() else: val2 = self.expr() [l, c] = binop.get_line_col() res = Expr(val1, binop, val2, l, c, self.debug) elif ptok.kind == EzhilToken.LPAREN: ## function call if (res.__class__ != Identifier): raise ParseException("invalid function call" + str(ptok)) [l, c] = ptok.get_line_col() vallist = self.valuelist() res = ExprCall(res, vallist, l, c, self.debug) ptok = self.peek() while ptok.kind in EzhilToken.BINOP: binop = self.dequeue() [l, c] = binop.get_line_col() res = Expr(res, binop, self.expr(), l, c, self.debug) ptok = self.peek() return res
def parse(fileName, tokens): parser = Parser(fileName, tokens) module = parser.module() if not parser.atEnd(): raise ParseException(parser.location, "garbage at end of input") ast.addNodeIds(module) return module
def stringLiteral(self): tok = self._nextTag(STRING) value = tryDecodeString(tok.text) if value is None: raise ParseException(tok.location, "could not understand string: %s" % tok.text) return ast.StringLiteral(value, tok.location)
def _parseBinop(self, simpleParser, astCtor, level): if level == 0: termParser = simpleParser else: termParser = lambda: self._parseBinop(simpleParser, astCtor, level - 1) terms = [termParser()] ops = [] tok = self._peek() while tok.tag is OPERATOR and self._precedence(tok.text) == level: self._next() ops.append(tok) terms.append(termParser()) tok = self._peek() if len(terms) == 1: return terms[0] associativity = self._associativity(ops[0].text) if associativity is self.LEFT_ASSOC: e = terms[0] for i, op in enumerate(ops): term = terms[i + 1] if self._associativity(op.text) is not self.LEFT_ASSOC: raise ParseException( op.location, "left and right associative operators are mixed together" ) loc = e.location.combine(term.location) b = astCtor(op.text, e, term, None, loc) self._liftComments(b, e, term) e = b else: e = terms[-1] for i in xrange(len(ops) - 1, -1, -1): op = ops[i] term = terms[i] if self._associativity(op.text) is not self.RIGHT_ASSOC: raise ParseException( op.location, "left and right associative operators are mixed together" ) loc = term.location.combine(e.location) b = astCtor(op.text, term, e, None, loc) self._liftComments(b, term, e) e = b return e
def match(self, kind): ## if match return token, else ParseException tok = self.dequeue() if (tok.kind != kind): raise ParseException(u"cannot find token "+ \ Token.get_name(kind) + u" got " \ + unicode(tok) + u" instead!") return tok
def match(self, kind): ## if match return token, else ParseException tok = self.dequeue() if (tok.kind != kind): raise ParseException("cannot find token "+ \ EzhilToken.get_name(kind) + " got " \ + str(tok) \ + " instead!") return tok
def parseSwitchStmt(self, exp): ## @ <ID/EXPR> SWITCH @( expr ) CASE {stmtlist} @( expr ) CASE {stmtlist} OTHERWISE {stmtlist} END ## implement as an if-elseif-else statement self.dbg_msg("parsing SWITCH statement") sw_tok = self.dequeue() [l, c] = sw_tok.get_line_col() self.inside_if = True lhs = exp[0] # enter this if-statement always ifstmt = IfStmt(Number(1), None, None, l, c, self.debug) self.if_stack.append(ifstmt) self.dbg_msg("parsing SWITCH-body") #self.dbg_msg ptok = self.peek() equality_token = EzhilLexeme("=", EzhilToken.EQUALITY) while (ptok.kind == EzhilToken.ATRATEOF or ptok.kind == EzhilToken.OTHERWISE): self.inside_if = True [l, c] = ptok.get_line_col() if (ptok.kind == EzhilToken.ATRATEOF): # parse elseif branch self.dbg_msg("parsing CASE") self.match(EzhilToken.ATRATEOF) exp = self.valuelist() self.dbg_msg("parsing CASE EXPR") self.match(EzhilToken.CASE) next_stmt = self.stmtlist() expr = Expr(lhs, equality_token, exp[0], l, c, self.debug) self.dbg_msg("building an Expr " + str(expr)) if not ifstmt.body: ifstmt.expr = expr ifstmt.body = next_stmt else: case_stmt = IfStmt(expr, next_stmt, None, l, c, self.debug) ifstmt.append_stmt(case_stmt) elif (ptok.kind == EzhilToken.OTHERWISE): #parse else branch self.dbg_msg("parsing OTHERWISE: ") self.match(EzhilToken.OTHERWISE) self.dbg_msg("parsing OTHERWISE-Body") self.inside_if = False body = self.stmtlist() else_stmt = ElseStmt(body, l, c, self.debug) if not ifstmt.body: ifstmt.body = else_stmt else: ifstmt.append_stmt(else_stmt) break else: self.inside_if = False raise ParseException( "SWITCH-CASE-OTHERWISE statement syntax is messed up") ptok = self.peek() self.dbg_msg("parsing SWITCH-CASE next bits " + str(ptok)) self.match(EzhilToken.END) self.inside_if = False self.dbg_msg("parsing -SWITCH-CASE- complete") return ifstmt
def parseIfStmt(self, exp): ## @ <expression> if { stmtlist } @<expr> ELSEIF {stmtlist} ELSE <stmtlist> END self.dbg_msg("parsing IF statement") if_tok = self.dequeue() [l, c] = if_tok.get_line_col() self.inside_if = True ifstmt = IfStmt(exp[0], None, None, l, c, self.debug) self.if_stack.append(ifstmt) self.dbg_msg("parsing IF-body") body = self.stmtlist() prev_body = body ifstmt.set_body(body) ptok = self.peek() while (ptok.kind == EzhilToken.ATRATEOF or ptok.kind == EzhilToken.ELSE): self.inside_if = True [l, c] = ptok.get_line_col() if (ptok.kind == EzhilToken.ATRATEOF): # parse elseif branch self.dbg_msg("parsing ELSE-IF") self.match(EzhilToken.ATRATEOF) exp = self.valuelist() self.dbg_msg("parsing ELSE-IF EXPR") tok = self.peek() if (tok.kind != EzhilToken.ELSEIF): # maybe another IF statement, SWITCH-CASE or a WHILE loop, DO-WHILE loop etc. next_stmt = self.stmtlist(exp) #pass in the expression prev_body.append(next_stmt) # append to previously scanned body. else: self.dbg_msg("parsing ELSE-IF-body") self.match(EzhilToken.ELSEIF) body = self.stmtlist() prev_body = body next_stmt = IfStmt(exp[0], body, None, l, c, self.debug) ifstmt.append_stmt(next_stmt) elif (ptok.kind == EzhilToken.ELSE): #parse else branch self.dbg_msg("parsing stmt else: ") self.match(EzhilToken.ELSE) self.dbg_msg("parsing ELSE-Body") self.inside_if = False body = self.stmtlist() prev_body = body else_stmt = ElseStmt(body, l, c, self.debug) ifstmt.append_stmt(else_stmt) break else: self.inside_if = False raise ParseException( "If-Else-If statement syntax is messed up") ptok = self.peek() self.dbg_msg("parsing -IF next bits " + str(ptok)) self.match(EzhilToken.END) self.inside_if = False self.dbg_msg("parsing -IF-complete") return ifstmt
def prefixedPattern(self): l = self._peek().location prefix = self.scopePrefix() tag = self._peekTag() if tag is LPAREN: args = self._parseList(self.simplePattern, "pattern arguments", LPAREN, COMMA, RPAREN) ty = None elif tag is COLON: self._next() ty = self.ty() args = None else: args = None ty = None loc = self._location(l) if len(prefix) == 1 and args is None: mayHaveTypeArgs = False result = ast.VariablePattern(prefix[0].name, ty, None, loc) if ty is None: self._tailComment(result) else: self._liftComments(result, None, ty) elif args is None and ty is None: mayHaveTypeArgs = False result = ast.ValuePattern(prefix[:-1], prefix[-1].name, None, loc) self._tailComment(result) elif args is not None: mayHaveTypeArgs = True result = ast.DestructurePattern(prefix, args, None, loc) self._tailComment(result) else: raise ParseException( loc, "invalid variable, value, or destructure pattern") if not mayHaveTypeArgs and prefix[-1].typeArguments is not None: raise ParseException( loc, "can't have type arguments at end of variable or value pattern" ) return result
def factor(self): self.dbg_msg("factor") tok = self.peek() if tok.kind == Token.LPAREN: lparen_tok = self.dequeue() val = self.expr() if self.dequeue().kind != Token.RPAREN: raise SyntaxError("Missing Parens") elif tok.kind == Token.NUMBER: tok_num = self.dequeue() [l, c] = tok_num.get_line_col() val = Number(tok.val, l, c, self.debug) elif tok.kind == Token.ID: tok_id = self.dequeue() [l, c] = tok_id.get_line_col() val = Identifier(tok.val, l, c, self.debug) ptok = self.peek() self.dbg_msg("factor: " + str(ptok) + " / " + str(tok)) if (ptok.kind == Token.LPAREN): ## function call [l, c] = ptok.get_line_col() vallist = self.valuelist() val = ExprCall(val, vallist, l, c, self.debug) elif (ptok.kind == Token.LSQRBRACE): ## array type val = None raise ParseException("arrays not implemented" + str(ptok)) elif tok.kind == Token.STRING: str_tok = self.dequeue() [l, c] = str_tok.get_line_col() val = String(tok.val, l, c, self.debug) else: raise ParseException("Expected Number, found something " + str(tok)) self.dbg_msg("factor-returning: " + str(val)) return val
def expr(self): self.dbg_msg(" EXPR ") val1 = self.term() res = val1 ptok = self.peek() if ptok.kind in Token.ADDSUB: binop = self.dequeue() val2 = self.expr() [l, c] = binop.get_line_col() res = Expr(val1, binop, val2, l, c, self.debug) elif ptok.kind == Token.LPAREN: ## function call -OR- array type. if (res.__class__ != Identifier): raise ParseException("invalid function call" + unicode(ptok)) [l, c] = ptok.get_line_col() vallist = self.valuelist() res = ExprCall(res, vallist, l, c, self.debug) return res
def arglist(self): """parse: ( arg_1, arg_2, ... ) """ self.dbg_msg(" ARGLIST ") args = list() lparen_tok = self.match(Token.LPAREN) while (self.peek().kind != Token.RPAREN): arg_name = self.dequeue() args.append(arg_name.val) ptok = self.peek() if (ptok.kind == Token.RPAREN): break elif (ptok.kind == Token.COMMA): self.match(Token.COMMA) else: raise ParseException(" function definition argument list " + str(ptok)) self.match(Token.RPAREN) [l, c] = lparen_tok.get_line_col() return ArgList(args, l, c, self.debug)
def maybeFunctionType(self): fnTypes = self._parseRepSep(self.simpleType, SMALL_ARROW) ty = fnTypes.pop() while len(fnTypes) > 0: pty = fnTypes.pop() if isinstance(pty, ast.TupleType): if len(pty.flags) > 0: raise ParseException( pty.location, "function parameter list can't be nullable") ptys = pty.types else: ptys = [pty] loc = pty.location.combine(ty.location) fty = ast.FunctionType(ptys, ty, None, loc) self._liftComments(fty, pty, ty) ty = fty return ty
def valuelist(self): """parse: ( expr_1 , expr_2, ... ) """ valueList = list() self.dbg_msg("valuelist: ") lparen_tok = self.match(Token.LPAREN) while (self.peek().kind != Token.RPAREN): val = self.expr() self.dbg_msg("valuelist-expr: " + str(val)) valueList.append(val) ptok = self.peek() if (ptok.kind == Token.RPAREN): break elif (ptok.kind == Token.COMMA): self.match(Token.COMMA) else: raise ParseException(" function call argument list " + str(ptok)) self.match(Token.RPAREN) [l, c] = lparen_tok.get_line_col() return ValueList(valueList, l, c, self.debug)
def _error(self, expected): tok = self._peek() raise ParseException(tok.location, "expected %s but found %s" % (expected, tok.text))
def stmt(self): """ try an assign, print, return, if or eval statement """ self.dbg_msg(" STMT ") ptok = self.peek() self.dbg_msg("stmt: peeking at " + str(ptok)) if (ptok.kind == Token.RETURN): ## return <expression> ret_tok = self.dequeue() [l, c] = ret_tok.get_line_col() rstmt = ReturnStmt(self.expr(), l, c, self.debug) self.dbg_msg("return statement parsed") return rstmt elif (ptok.kind == Token.PRINT): ## print <expression> print_tok = self.dequeue() [l, c] = print_tok.get_line_col() return PrintStmt(self.exprlist(), l, c, self.debug) elif (ptok.kind == Token.IF): ## if <expression> stmtlist end if_tok = self.dequeue() [l, c] = if_tok.get_line_col() exp = self.expr() ifstmt = IfStmt(exp, None, None, l, c, self.debug) self.if_stack.append(ifstmt) body = self.stmtlist() ifstmt.set_body(body) ptok = self.peek() if (ptok.kind in [Token.ELSEIF, Token.ELSE]): self.inside_if = True next_stmt = self.stmtlist() self.inside_if = False ifstmt.append_stmt(next_stmt) self.match(Token.END) return ifstmt elif (ptok.kind == Token.ELSEIF): ## elseif <expression> stmtlist elseif_tok = self.dequeue() [l, c] = elseif_tok.get_line_col() self.check_if_stack() exp = self.expr() elseif_stmt = IfStmt(exp, None, None, l, c, self.debug) ifstmt = self.if_stack[-1] ifstmt.append_stmt(elseif_stmt) self.if_stack.pop() self.if_stack.append(elseif_stmt) body = self.stmtlist() elseif_stmt.set_body(body) return elseif_stmt elif (ptok.kind == Token.ELSE): ## else stmtlist self.check_if_stack() ifstmt = self.if_stack.pop() self.dbg_msg("stmt-else: ") else_tok = self.dequeue() [l, c] = else_tok.get_line_col() body = self.stmtlist() else_stmt = ElseStmt(body, l, c, self.debug) ifstmt.append_stmt(else_stmt) return else_stmt elif (ptok.kind == Token.FOR): ## Fixme : empty for loops not allowed. """ For ( exp1 ; exp2 ; exp3 ) stmtlist end""" self.loop_stack.append(True) self.dbg_msg("for-statement") for_tok = self.dequeue() self.match(Token.LPAREN) lhs = self.expr() init = lhs ptok = self.peek() if (ptok.kind in Token.ASSIGNOP): assign_tok = self.dequeue() [l, c] = assign_tok.get_line_col() rhs = self.expr() init = AssignStmt(lhs, assign_tok, rhs, l, c, self.debug) self.match(Token.COMMA) cond = self.expr() self.match(Token.COMMA) lhs = self.expr() update = lhs ptok = self.peek() if (ptok.kind in Token.ASSIGNOP): assign_tok = self.dequeue() [l, c] = assign_tok.get_line_col() rhs = self.expr() update = AssignStmt(lhs, assign_tok, rhs, l, c, self.debug) self.match(Token.RPAREN) body = self.stmtlist() self.match(Token.END) [l, c] = for_tok.get_line_col() forstmt = ForStmt(init, cond, update, body, l, c, self.debug) self.loop_stack.pop() return forstmt elif (ptok.kind == Token.WHILE): ## while ( expr ) body end self.loop_stack.append(True) self.dbg_msg("while-statement") while_tok = self.dequeue() [l, c] = while_tok.get_line_col() wexpr = self.expr() body = self.stmtlist() self.match(Token.END) whilestmt = WhileStmt(wexpr, body, l, c, self.debug) self.loop_stack.pop() return whilestmt elif (ptok.kind == Token.BREAK): ## break, must be in loop-environment self.dbg_msg("break-statement") break_tok = self.dequeue() [l, c] = break_tok.get_line_col() self.check_loop_stack() ##raises a parse error brkstmt = BreakStmt(l, c, self.debug) return brkstmt elif (ptok.kind == Token.CONTINUE): ## continue, must be in loop-environment self.dbg_msg("continue-statement") cont_tok = self.dequeue() [l, c] = cont_tok.get_line_col() self.check_loop_stack() ##raises a parse error cntstmt = ContinueStmt(l, c, self.debug) return cntstmt else: ## lval := rval ptok = self.peek() [l, c] = ptok.get_line_col() lhs = self.expr() self.dbg_msg("parsing expr: " + str(lhs)) ptok = self.peek() if (ptok.kind in Token.ASSIGNOP): assign_tok = self.dequeue() rhs = self.expr() [l, c] = assign_tok.get_line_col() return AssignStmt(lhs, assign_tok, rhs, l, c, self.debug) return EvalStmt(lhs, l, c, self.debug) raise ParseException("parsing Statement, unkown operators" + str(ptok))
def error(self, token, message): self.nebbdyr.error(token, message) return ParseException()
def continue_statement(self): if self.loop_level <= 0: raise ParseException( self.previous(), "'continue' statement must be inside a loop.") self.consume(TT.NEWLINE, "Expect newline after 'continue' statement.") return stmt.Continue()
def break_statement(self): if self.loop_level <= 0: raise ParseException(self.previous(), "'break' statement must be inside a loop.") self.consume(TT.NEWLINE, "Expect newline after 'break' statement.") return stmt.Break()
def factor(self): self.dbg_msg("factor") tok = self.peek() if tok.kind == EzhilToken.LPAREN: lparen_tok = self.dequeue() val = self.expr() if self.dequeue().kind != EzhilToken.RPAREN: raise SyntaxError("Missing Parens " + str(self.last_token())) elif tok.kind == EzhilToken.NUMBER: tok_num = self.dequeue() [l, c] = tok_num.get_line_col() val = Number(tok.val, l, c, self.debug) elif tok.kind == EzhilToken.LOGICAL_NOT: tok_not = self.dequeue() [l, c] = tok_not.get_line_col() val = UnaryExpr(self.expr(), tok_not, l, c, self.debug) self.dbg_msg("completed parsing unary expression" + str(val)) elif tok.kind == EzhilToken.ID: tok_id = self.dequeue() [l, c] = tok_id.get_line_col() val = Identifier(tok.val, l, c, self.debug) ptok = self.peek() self.dbg_msg("factor: " + str(ptok) + " / " + str(tok)) if (ptok.kind == EzhilToken.LPAREN): ## function call [l, c] = ptok.get_line_col() vallist = self.valuelist() val = ExprCall(val, vallist, l, c, self.debug) elif (ptok.kind == EzhilToken.LSQRBRACE): ## indexing a array type variable or ID val = None raise ParseException("arrays not implemented" + str(ptok)) elif tok.kind == EzhilToken.STRING: str_tok = self.dequeue() [l, c] = str_tok.get_line_col() val = String(tok.val, l, c, self.debug) elif tok.kind in EzhilToken.ADDSUB: unop = self.dequeue() [l, c] = unop.get_line_col() val = Expr(Number(0), unop, self.term(), l, c, self.debug) elif tok.kind == EzhilToken.LSQRBRACE: # creating a list/array expression list_start = self.dequeue() val = Array() while (True): exprval = self.expr() val.append(exprval) if self.debug: print(self.peek().__class__, self.peek()) if (self.peek().kind == EzhilToken.RSQRBRACE): break else: assert (self.peek().kind == EzhilToken.COMMA) self.dequeue() assert (self.peek().kind == EzhilToken.RSQRBRACE) list_end = self.dequeue() else: raise ParseException("Expected Number, found something " + str(tok)) self.dbg_msg("factor-returning: " + str(val)) return val
def ty(self): l = self._peek().location t = self.maybeFunctionType() if isinstance(t, ast.TupleType) and len(t.types) == 0: raise ParseException(l, "expected type but found ()") return t
def check_loop_stack(self): if (len(self.loop_stack) == 0): raise ParseException( "break/continue statement outside any loop, near" + str(self.last_token())) return len(self.loop_stack)
def factor(self): self.dbg_msg("factor") tok = self.peek() if tok.kind == EzhilToken.LPAREN: lparen_tok = self.dequeue() val = self.expr() if self.dequeue().kind != EzhilToken.RPAREN: raise SyntaxError("Missing Parens " + str(self.last_token())) elif tok.kind == EzhilToken.NUMBER: tok_num = self.dequeue() [l, c] = tok_num.get_line_col() val = Number(tok.val, l, c, self.debug) elif tok.kind == EzhilToken.LOGICAL_NOT: tok_not = self.dequeue() [l, c] = tok_not.get_line_col() val = UnaryExpr(self.expr(), tok_not, l, c, self.debug) self.dbg_msg("completed parsing unary expression" + str(val)) elif tok.kind == EzhilToken.ID: tok_id = self.dequeue() [l, c] = tok_id.get_line_col() val = Identifier(tok.val, l, c, self.debug) ptok = self.peek() self.dbg_msg("factor: " + str(ptok) + " / " + str(tok)) if (ptok.kind == EzhilToken.LPAREN): ## function call [l, c] = ptok.get_line_col() vallist = self.valuelist() val = ExprCall(val, vallist, l, c, self.debug) elif (ptok.kind == EzhilToken.LSQRBRACE): ## indexing a array type variable or ID [l, c] = ptok.get_line_col() ## replace with a call to __getitem__ exp = self.factor() if (hasattr(exp, '__getitem__')): VL2 = ValueList([val, exp[0]], l, c, self.debug) else: # when exp is a expression VL2 = ValueList([val, exp], l, c, self.debug) val = ExprCall(Identifier("__getitem__", l, c), VL2, l, c, self.debug) for itr in range(1, len(exp)): VL2 = ValueList([val, exp[itr]], l, c, self.debug) val = ExprCall(Identifier("__getitem__", l, c), VL2, l, c, self.debug) #raise ParseException("array indexing implemented"+str(ptok)); elif (ptok.kind == EzhilToken.LCURLBRACE): val = None raise ParseException("dictionary indexing implemented" + str(ptok)) elif tok.kind == EzhilToken.STRING: str_tok = self.dequeue() [l, c] = str_tok.get_line_col() val = String(tok.val, l, c, self.debug) elif tok.kind in EzhilToken.ADDSUB: unop = self.dequeue() [l, c] = unop.get_line_col() val = Expr(Number(0), unop, self.term(), l, c, self.debug) elif tok.kind == EzhilToken.LCURLBRACE: # creating a list/dictionary expression dict_start = self.dequeue() val = Dict() while (True): if (self.peek().kind == EzhilToken.RCURLBRACE): break exprkey = self.expr() tok_colon = self.match(EzhilToken.COLON) exprval = self.expr() val.update({exprkey: exprval}) if self.debug: print(self.peek().__class__, self.peek()) if (self.peek().kind == EzhilToken.RCURLBRACE): break else: assert (self.peek().kind == EzhilToken.COMMA) self.dequeue() assert (self.peek().kind == EzhilToken.RCURLBRACE) list_end = self.dequeue() elif tok.kind == EzhilToken.LSQRBRACE: # creating a list/array expression list_start = self.dequeue() val = Array() while (True): if (self.peek().kind == EzhilToken.RSQRBRACE): break exprval = self.expr() val.append(exprval) if self.debug: print(self.peek().__class__, self.peek()) if (self.peek().kind == EzhilToken.RSQRBRACE): break else: assert (self.peek().kind == EzhilToken.COMMA) self.dequeue() assert (self.peek().kind == EzhilToken.RSQRBRACE) list_end = self.dequeue() else: raise ParseException("Expected Number, found something " + str(tok)) self.dbg_msg("factor-returning: " + str(val)) return val
def check_if_stack(self): if (len(self.if_stack) == 0): raise ParseException("unmatched else statement, near" + str(self.last_token())) return len(self.if_stack)
def stmt(self, pass_in_ATexpr=None): """ try an assign, print, return, if or eval statement """ self.dbg_msg(" STMT ") ptok = self.peek() self.dbg_msg("stmt: peeking at " + str(ptok)) if (ptok.kind == EzhilToken.RETURN): ## return <expression> self.dbg_msg('enter->return: <expression>') ret_tok = self.dequeue() [l, c] = ret_tok.get_line_col() rstmt = ReturnStmt(self.expr(), l, c, self.debug) self.dbg_msg("return statement parsed") return rstmt elif (ptok.kind == EzhilToken.PRINT): self.currently_parsing.append(ptok) ## print <expression> print_tok = self.dequeue() [l, c] = print_tok.get_line_col() exprlist_val = self.exprlist() self.currently_parsing.pop() return PrintStmt(exprlist_val, l, c, self.debug) elif (ptok.kind == EzhilToken.ATRATEOF or pass_in_ATexpr): ## @ <expression> {if | while | elseif} if not pass_in_ATexpr: at_tok = self.match(EzhilToken.ATRATEOF) self.currently_parsing.append(at_tok) exp = self.valuelist() self.currently_parsing.pop() else: exp = pass_in_ATexpr if (self.debug): print("return from valuelist ", str(exp)) ptok = self.peek() if (ptok.kind == EzhilToken.IF): return self.parseIfStmt(exp) elif (ptok.kind == EzhilToken.WHILE): ## @ ( expr ) while { body } end self.loop_stack.append(True) self.dbg_msg("while-statement") while_tok = self.dequeue() self.currently_parsing.append(while_tok) [l, c] = while_tok.get_line_col() wexpr = exp[0] body = self.stmtlist() self.match(EzhilToken.END) whilestmt = WhileStmt(wexpr, body, l, c, self.debug) self.loop_stack.pop() self.currently_parsing.pop() return whilestmt elif (ptok.kind == EzhilToken.SWITCH): return self.parseSwitchStmt(exp) elif (ptok.kind == EzhilToken.FOREACH): foreach_tok = self.dequeue() self.currently_parsing.append(foreach_tok) [l, c] = foreach_tok.get_line_col() if (self.debug): print("parsing FOREACH stmt") self.loop_stack.append(True) self.dbg_msg("foreach-statement") # convert to a for statement - building Ezhil AST - transformations if not isinstance(exp[1], Identifier): raise ParseError(" FOR-EACH statement " + str(foreach_tok)) foreach_iter = exp[1] iter = Identifier("__" + foreach_iter.id, l=0, c=-1) eq_token = EzhilLexeme("=", EzhilToken.EQUALS) plus_token = EzhilLexeme("+", EzhilToken.PLUS) lt_token = EzhilLexeme("<", EzhilToken.LT) if (self.debug): print("build init assign stmt") init = AssignStmt(iter, eq_token, Number(0), l, c, self.debug) if (self.debug): print("build cond expr") VL1 = ValueList([exp[0]], l, c, self.debug) cond = Expr( iter, lt_token, ExprCall(Identifier("len", l, c), VL1, l, c, self.debug), l, c, self.debug) if (self.debug): print("build plus1 stmt") plus1_iter = Expr(iter, plus_token, Number(1), l, c, self.debug) if (self.debug): print("build equals stmt") update = AssignStmt(iter, eq_token, plus1_iter, l, c, self.debug) body = self.stmtlist() #parse body # and insert artifical update variable in body VL2 = ValueList([exp[0], iter], l, c, self.debug) extract_foreach_iter_from_list = ExprCall( Identifier("__getitem__", l, c), VL2, l, c, self.debug) foreach_iter_Assign = AssignStmt( foreach_iter, eq_token, extract_foreach_iter_from_list, l, c, self.debug) body.List.insert(0, foreach_iter_Assign) # complete FOREACH stmt self.match(EzhilToken.END) self.currently_parsing.pop() foreach_stmt = ForStmt(init, cond, update, body, l, c, self.debug) self.loop_stack.pop() if (self.debug): print("completed parsing FOR-EACH loop", str(foreach_stmt)) return foreach_stmt elif (ptok.kind == EzhilToken.FOR): ## Fixme : empty for loops not allowed. """ For ( exp1 , exp2 , exp3 ) stmtlist end""" if (self.debug): print("parsing FOR stmt") self.loop_stack.append(True) self.dbg_msg("for-statement") for_tok = self.peek() self.currently_parsing.append(for_tok) if (self.debug): print("matching for STMT", str(self.peek())) self.match(EzhilToken.FOR) if (self.debug): print("matched for STMT", str(self.peek())) [l, c] = for_tok.get_line_col() init, cond, update = exp[0], exp[1], exp[2] if (self.debug): print("extract 3 parts", str(init), str(cond), str(update)) body = self.stmtlist() self.match(EzhilToken.END) self.currently_parsing.pop() if (self.debug): print("body of loop", str(body)) forstmt = ForStmt(init, cond, update, body, l, c, self.debug) self.loop_stack.pop() if (self.debug): print("completed parsing FOR loop", str(forstmt)) return forstmt elif (ptok.kind == EzhilToken.DO): if (self.debug): print("parsing DO-WHILE statement") self.loop_stack.append(True) do_tok = self.dequeue() self.currently_parsing.append(do_tok) [l, c] = do_tok.get_line_col() body = self.stmtlist() if (self.debug): print("parsed body") self.match(EzhilToken.DOWHILE) self.match(EzhilToken.ATRATEOF) exp = self.valuelist() if (self.debug): print("parsed EXP", exp[0]) doWhileStmt = DoWhileStmt(exp[0], body, l, c, self.debug) self.loop_stack.pop() self.currently_parsing.pop() return doWhileStmt elif (ptok.kind == EzhilToken.BREAK): ## break, must be in loop-environment self.dbg_msg("break-statement") break_tok = self.dequeue() [l, c] = break_tok.get_line_col() self.check_loop_stack() ##raises a parse error brkstmt = BreakStmt(l, c, self.debug) return brkstmt elif (ptok.kind == EzhilToken.CONTINUE): ## continue, must be in loop-environment self.dbg_msg("continue-statement") cont_tok = self.dequeue() [l, c] = cont_tok.get_line_col() self.check_loop_stack() ##raises a parse error cntstmt = ContinueStmt(l, c, self.debug) return cntstmt else: ## lval := rval ptok = self.peek() self.currently_parsing.append(ptok) [l, c] = ptok.get_line_col() lhs = self.expr() self.dbg_msg("parsing expr: " + str(lhs)) ptok = self.peek() if (ptok.kind in EzhilToken.ASSIGNOP): assign_tok = self.dequeue() rhs = self.expr() [l, c] = assign_tok.get_line_col() self.currently_parsing.pop() return AssignStmt(lhs, assign_tok, rhs, l, c, self.debug) self.currently_parsing.pop() return EvalStmt(lhs, l, c, self.debug) raise ParseException("parsing Statement, unkown operators" + str(ptok))