From 4aedc5d76250fae734af1cd89256ec70e165ab18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benedikt=20B=C3=B6hm?= Date: Mon, 29 Jun 2009 12:28:01 +0200 Subject: fix function_call - function_call is now an expression and a statement - call keyword is required to make lookahead = 1 work --- src/front/parser.py | 103 ++++++++++++++++++---------------------------------- 1 file changed, 35 insertions(+), 68 deletions(-) (limited to 'src/front/parser.py') diff --git a/src/front/parser.py b/src/front/parser.py index 29e300d..610a5bb 100644 --- a/src/front/parser.py +++ b/src/front/parser.py @@ -36,58 +36,41 @@ class Parser: def boolean(self): res = self.join() while self.token.tag == Tag.OPERATOR and self.token.value == "||": - self.move() - res = BinaryExpression(res, "||", self.join()) + res = BinaryExpression(res, self.match(Tag.OPERATOR), self.join(), self.lexer.line) return res - # join = equality { "&&" equality }. + # join = relation { "&&" relation }. def join(self): - res = self.equality() - while self.token.tag == Tag.OPERATOR and self.token.value == "&&": - self.move() - res = BinaryExpression(res, "&&", self.relation()) - return res - - # equality = relation { ( "==" | "!=" ) relation }. - def equality(self): res = self.relation() - while self.token.tag == Tag.OPERATOR and self.token.value in ["==", "!="]: - op = self.match(Tag.OPERATOR) - res = BinaryExpression(res, op, self.relation()) + while self.token.tag == Tag.OPERATOR and self.token.value == "&&": + res = BinaryExpression(res, self.match(Tag.OPERATOR), self.relation(), self.lexer.line) return res - # relation = expression { ( "<" | "<=" | ">=" | ">" ) expression }. + # relation = expression { ( "==" | "!=" | "<" | "<=" | ">=" | ">" ) expression }. def relation(self): res = self.expression() - while self.token.tag == Tag.OPERATOR and self.token.value in ["<", "<=", ">=", ">"]: - op = self.match(Tag.OPERATOR) - res = BinaryExpression(res, op, self.expression()) + while self.token.tag == Tag.OPERATOR and self.token.value in ["==", "!=", "<", "<=", ">=", ">"]: + res = BinaryExpression(res, self.match(Tag.OPERATOR), self.expression(), self.lexer.line) return res # expression = term { ( "+" | "-" ) term }. def expression(self): res = self.term() while self.token.tag == Tag.OPERATOR and self.token.value in ["+", "-"]: - op = self.match(Tag.OPERATOR) - res = BinaryExpression(res, op, self.term()) + res = BinaryExpression(res, self.match(Tag.OPERATOR), self.term(), self.lexer.line) return res # term = unary { ( "*" | "/" | "%" ) unary }. def term(self): res = self.unary() while self.token.tag == Tag.OPERATOR and self.token.value in ["*", "/", "%"]: - op = self.match(Tag.OPERATOR) - res = BinaryExpression(res, op, self.unary()) + res = BinaryExpression(res, self.match(Tag.OPERATOR), self.unary(), self.lexer.line) return res # unary = "!" unary | "-" unary | factor. def unary(self): - if self.token.tag == Tag.OPERATOR and self.token.value == "!": - self.move() - return UnaryExpression("!", self.unary()) - if self.token.tag == Tag.OPERATOR and self.token.value == "-": - self.move() - return UnaryExpression("-", self.unary()) + if self.token.tag == Tag.OPERATOR and self.token.value in ["!", "-"]: + return UnaryExpression(self.match(Tag.OPERATOR), self.unary(), self.lexer.line) return self.factor() # factor = "(" boolean ")" | integer | "true" | "false" | ident | function_call. @@ -98,46 +81,25 @@ class Parser: self.match(Tag.RPAREN) return res if self.token.tag == Tag.NUMBER: - return Constant(self.match(Tag.NUMBER)) + return Constant(self.match(Tag.NUMBER), self.lexer.line) if self.token.tag == Tag.TRUE: self.move() - return Constant(1) + return Constant(1, self.lexer.line) if self.token.tag == Tag.FALSE: self.move() - return Constant(0) - ''' Wegen der Änderung in function_call() kann die Grammatik nicht - mehr mit einem Lookahead von 1 geparst werden. Die Lösung hier - ist, den Aufruf von function_call() zu "inlinen". Muss irgendwann - aber geändert werden. Eine Lösung wäre Funktionen mit call - aufzurufen oder eben auf LL(2) oder LR umzusteigen. - ''' + return Constant(0, self.lexer.line) if self.token.tag == Tag.IDENT: - name = self.match(Tag.IDENT) - if self.token.tag == Tag.LBRAK: # function_call - self.match(Tag.LBRAK) - args = [] if self.token.tag == Tag.RBRAK else self.expression_list() - self.match(Tag.RBRAK) - return FunctionCall(name, args) - return Variable(name)# variable - - error("unknown factor begins with " + self.token.tag) - - # function_call = ident "[" [ expression_list ] "]". - ''' function_call muss eine expression sein sonst geht alles folgende nicht: - foo = bar[] - @foo[bar] - spam[5] + eggs[1] - andererseits ist function_call dann kein statement mehr - exit[] - wäre also falsch. Der Aufruf muss in einem assignment verkapselt werden: - dummy = exit[] - ''' + return Variable(self.match(Tag.IDENT), self.lexer.line) + return self.function_call() + + # function_call = "call" ident "[" [ expression_list ] "]". def function_call(self): + self.match(Tag.CALL) name = self.match(Tag.IDENT) self.match(Tag.LBRAK) args = [] if self.token.tag == Tag.RBRAK else self.expression_list() self.match(Tag.RBRAK) - return FunctionCall(name, args) + return FunctionCall(name, args, self.lexer.line) # ident_list = ident { "," ident }. def ident_list(self): @@ -171,6 +133,7 @@ class Parser: # function = "fun" ident "[" [ ident_list ] "]" nl statement_list "end" nl. def function(self): + line = self.lexer.line self.match(Tag.FUN) name = self.match(Tag.IDENT) self.match(Tag.LBRAK) @@ -180,18 +143,20 @@ class Parser: block = self.statement_list() self.match(Tag.END) self.match(Tag.NEWLINE) - return Function(name, args, block) + return Function(name, args, block, line) - # statement = [ if_statement | while_statement | assign_statement | return_statement ]. + # statement = [ if_statement | while_statement | assign_statement | return_statement | function_call ]. def statement(self): return {Tag.IF: self.if_statement, Tag.WHILE: self.while_statement, Tag.IDENT: self.assignment, - Tag.RETURN: self.return_statement + Tag.RETURN: self.return_statement, + Tag.CALL: self.function_call, }[self.token.tag]() - # if_statement = "if" boolean nl statement_list [ "else" [ nl ] statement_list ] "end" nl. + # if_statement = "if" boolean nl statement_list [ "else" nl statement_list ] "end" nl. def if_statement(self): + line = self.lexer.line self.match(Tag.IF) condition = self.boolean() self.match(Tag.NEWLINE) @@ -199,38 +164,40 @@ class Parser: else_case = [] if self.token.tag == Tag.ELSE: self.move() - if self.token.tag == Tag.NEWLINE: self.move() + self.match(Tag.NEWLINE) else_case = self.statement_list() self.match(Tag.END) self.match(Tag.NEWLINE) - return IfStatement(condition, true_case, else_case) + return IfStatement(condition, true_case, else_case, line) # while_statement = "while" boolean nl statement_list "end" nl. def while_statement(self): + line = self.lexer.line self.match(Tag.WHILE) condition = self.boolean() self.match(Tag.NEWLINE) body = self.statement_list() self.match(Tag.END) self.match(Tag.NEWLINE) - return WhileStatement(condition, body) + return WhileStatement(condition, body, line) # return_statement = "@" boolean nl. def return_statement(self): + line = self.lexer.line self.match(Tag.RETURN) exp = self.boolean() self.match(Tag.NEWLINE) - return ReturnStatement(exp) + return ReturnStatement(exp, line) # assignment = ident "=" boolean nl. def assignment(self): + line = self.lexer.line name = self.match(Tag.IDENT) self.match(Tag.ASSIGNMENT) exp = self.boolean() self.match(Tag.NEWLINE) - return AssignStatement(name, exp) + return AssignStatement(name, exp, line) # program = function_list. def program(self): return Program(self.function_list()) - -- cgit v1.2.3