summaryrefslogtreecommitdiffstats
path: root/src/front/parser.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/front/parser.py')
-rw-r--r--src/front/parser.py103
1 files changed, 35 insertions, 68 deletions
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())
-