parser.py (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
from typing import List
from structs import (Token, AST, Program, ExpressionStatement, UnaryExpression, BinaryExpression, Literal, ASTNodeTypes,
TokenTypes)
class Parser:
_tokens: List[Token]
_index: int = 0
@property
def _current(self) -> Token:
return self._tokens[self._index]
@property
def _previous(self) -> Token:
return self._tokens[self._index - 1]
def __init__(self, tokens: List[Token]):
self._tokens = tokens
def parse(self):
ast: Program = Program(ASTNodeTypes.Program, [])
while self._index < len(self._tokens):
ast.body.append(self._plus_minus())
return ast
def _match(self, *args: TokenTypes):
if value := (self._index < len(self._tokens) and self._current.type in args):
self._index += 1
return value
def _plus_minus(self) -> Literal:
expr = self._mult_div()
while self._match(TokenTypes.PLUS, TokenTypes.MINUS):
operator = self._previous
right = self._plus_minus()
expr = BinaryExpression(expr, right, operator)
return expr
def _mult_div(self) -> Literal:
expr = self._unary()
while self._match(TokenTypes.MULT, TokenTypes.DIV):
operator = self._previous
right = self._mult_div()
expr = BinaryExpression(expr, right, operator)
return expr
def _unary(self) -> Literal:
while self._match(TokenTypes.PLUS, TokenTypes.MINUS):
operator = self._previous
value = self._unary()
return UnaryExpression(operator, value)
return self._literal()
def _literal(self) -> Literal:
if self._match(TokenTypes.INT, TokenTypes.FLOAT):
return Literal(self._previous.value)
if self._match(TokenTypes.OPEN_PAREN):
expr = self._plus_minus()
if not self._match(TokenTypes.CLOSE_PAREN):
raise Exception(f'Expected for close parentheses ")" at line {self._previous.line}.')
return expr
|