diff --git a/compiler/lexer.py b/compiler/lexer.py index f8060c6..4c9feba 100644 --- a/compiler/lexer.py +++ b/compiler/lexer.py @@ -44,6 +44,7 @@ class Tokens(enum.Enum): Equal = re.compile(r"=") Colon = re.compile(r":") Semicolon = re.compile(r";") + Comma = re.compile(r",") Newline = re.compile(r"\n", flags=re.MULTILINE) EOF = re.compile(r"\Z") diff --git a/compiler/parser.py b/compiler/parser.py index 48c3eda..1015af6 100644 --- a/compiler/parser.py +++ b/compiler/parser.py @@ -6,7 +6,7 @@ from .errors import CompilationError, UnexpectedTokenError from .lexer import Tokens, Token from .logger import Logger, Tracer, LogLevel from .nodes import Float, Sum, Value, Product, Node, Division, Sub, Integer, Expression, Identifier, Assignment, \ - Variable, Statement, PseudoNode, Block, Definition + Variable, Statement, PseudoNode, Block, Definition, Call logger = Logger(__name__) tracer = Tracer(logger, level=LogLevel.Debug) @@ -108,12 +108,14 @@ class Parser: @tracer.trace_method def factor(self, mandatory: bool = False) -> Value: if self.accept(Tokens.Parens_Left): - v = self.expression() + v = self.expression(mandatory=True) self.expect(Tokens.Parens_Right) return v - elif num := self.number(): + elif num := self.number(mandatory=False): return num - elif variable := self.variable(): + elif call := self.call(mandatory=False): + return call + elif variable := self.variable(mandatory=False): return variable elif mandatory: raise UnexpectedTokenError(self.token, "parenthesized expression, number or variable") @@ -141,6 +143,22 @@ class Parser: elif mandatory: raise UnexpectedTokenError(self.token, "assignment") + @tracer.trace_method + def call(self, mandatory: bool = False) -> Call: + if self.peek_several(Tokens.Identifier, Tokens.Parens_Left): + ident = self.identifier(mandatory=True) + lparens = self.expect(Tokens.Parens_Left) + expressions: list[Expression] = [] + if expr := self.expression(mandatory=False): + expressions += [expr] + while self.accept(Tokens.Comma): + expressions += [self.expression(mandatory=True)] + rparens = self.expect(Tokens.Parens_Right) + return Call(identifier=ident, arguments=expressions, + pseudo_nodes=[PseudoNode(lparens), PseudoNode(rparens)]) + elif mandatory: + raise UnexpectedTokenError(self.token, "function call") + @tracer.trace_method def definition(self, mandatory: bool = False) -> Definition: if let_kw := self.accept(Tokens.KwLet):