Skip to content

Latest commit

History

History
113 lines (93 loc) · 3.8 KB

File metadata and controls

113 lines (93 loc) · 3.8 KB

Chapter 4: Parser Implementation

Back: Parser Layout | Chapters | Next: AST Nodes Parsing


Parsing starts in parse_expression. From there we need to figure out which kind of AST node comes next in out input. Let's gather some indicators by which we could differentiate them.

Class (extending AST)Indicator
Valuestarts with numeric digit
Variablestarts with alphabetic digit or underscore
FuncCallstarts with variable, differentiation later!
BinaryOpstarts with any AST node, differentiation later!
UnaryOpstarts with operator (+/-)

While there is no AST node for bracketed expressions, we still need to parse it, so we also need to check for (.

Now that we more or less know what we are dealing with, we can switch to the correct node parser function accordingly.

Parser
classParser:
...
defparse_expression(self) ->AST:
c=self.current()
ifc=='(':
self.next() # skip opening bracketexpr=self.parse_expression() # parse innerifself.current() !=')':
raiseParseException('Expected closing bracket', self)
self.next() # skip closing bracketelifc.isnumeric():
expr=self.parse_value()
elifc.isalpha() orc=='_':
expr=self.parse_variable()
# TODO: check for function callelifcin'+-':
expr=self.parse_unary_op()
else:
raiseParseException('Unimplemented!', self)
# TODO: check for binary opreturnexpr

Now we can address the two nodes which we could not detect immediately.

FuncCall

If the variable name is followed by (, its a function call. If not, its just a variable.

parse_func_call
classParser:
...
defparse_expression(self) ->AST:
...
elifc.isalpha() orc=='_':
expr=self.parse_variable()
# TODO: check for function callifself.has_current() andself.current() =='(':
# expr is a variable, so we can get the name, since we already parsed that.expr=self.parse_func_call(expr.name)
...
...
# this also means we need to adjust the signature heredefparse_func_call(self, name: str) ->FuncCall:
raiseParseException('Unimplemented!', self)

BinaryOp

The binary operator is similar. If the current expression is followed by an operator, we parse it and immediately parse the next expression afterwards as the righhand value.

parse_binary_op
classParser:
...
defparse_expression(self) ->AST:
else:
raiseParseException('Unimplemented!', self)
# TODO: check for binary opifself.has_current() andself.current() in'+-*/%':
op=self.current()
self.next()
expr=self.parse_binary_op(expr, op)
returnexpr
...
# this again means we need to adjust the signature heredefparse_binary_op(self, left: AST, op: str) ->BinaryOp:
raiseParseException('Unimplemented!', self)

And with that we already did most of the hard work! All that is left to do now that we have the branching (for parsing at least) is implemented, is coding all the more or less linear functions which implement the nodes.


Back: Parser Layout | Chapters | Next: AST Nodes Parsing