AST is working!!!!
This commit is contained in:
116
plasma_parser.py
116
plasma_parser.py
@@ -3,6 +3,11 @@ from lexer_token import Token, TokenType
|
||||
from typing import Callable
|
||||
from enum import Enum, auto
|
||||
|
||||
from AST import Statement, Expression, Program
|
||||
from AST import ExpressionStatement
|
||||
from AST import InfixExpression
|
||||
from AST import IntegerLiteral, FloatLiteral
|
||||
|
||||
class PrecedenceType(Enum):
|
||||
P_LOWEST = 0
|
||||
P_EQUALS = auto()
|
||||
@@ -32,8 +37,23 @@ class Parser:
|
||||
self.current_token: Token = None
|
||||
self.peek_token: Token = None
|
||||
|
||||
self.prefix_parse_functions: dict[Token, Callable] = {} # -1
|
||||
self.infix_parse_functions: dict[Token, Callable] = {} # 5 + 5
|
||||
self.prefix_parse_functions: dict[Token, Callable] = { # -1
|
||||
|
||||
TokenType.INT: self.__parse_int_literal,
|
||||
TokenType.FLOAT: self.__parse_float_literal,
|
||||
TokenType.LPAREN: self.__parse_grouped_expression
|
||||
|
||||
}
|
||||
self.infix_parse_functions: dict[Token, Callable] = { # 5 + 5
|
||||
|
||||
TokenType.PLUS: self.__parse_infix_expression,
|
||||
TokenType.MINUS: self.__parse_infix_expression,
|
||||
TokenType.SLASH: self.__parse_infix_expression,
|
||||
TokenType.ASTERISK: self.__parse_infix_expression,
|
||||
TokenType.POW: self.__parse_infix_expression,
|
||||
TokenType.MODULUS: self.__parse_infix_expression
|
||||
|
||||
}
|
||||
|
||||
self.__next_token()
|
||||
self.__next_token()
|
||||
@@ -74,4 +94,94 @@ class Parser:
|
||||
# endregion
|
||||
|
||||
def parse_program(self) -> None:
|
||||
pass
|
||||
program: Program = Program()
|
||||
|
||||
while self.current_token.type != TokenType.EOF:
|
||||
stmt: Statement = self.__parse_statement()
|
||||
|
||||
if stmt is not None:
|
||||
program.statements.append(stmt)
|
||||
|
||||
self.__next_token()
|
||||
|
||||
return program
|
||||
|
||||
# region Statement Methods
|
||||
def __parse_statement(self) -> Statement:
|
||||
return self.__parse_expression_statement()
|
||||
|
||||
def __parse_expression_statement(self) -> ExpressionStatement:
|
||||
expr = self.__parse_expression(PrecedenceType.P_LOWEST)
|
||||
|
||||
if self.__peek_token_is(TokenType.SEMICOLON):
|
||||
self.__next_token()
|
||||
|
||||
stmt: ExpressionStatement = ExpressionStatement(expr=expr)
|
||||
|
||||
return stmt
|
||||
# endregion
|
||||
|
||||
# region Expression Methods
|
||||
def __parse_expression(self, precedence: PrecedenceType) -> Expression:
|
||||
prefix_func: Callable | None = self.prefix_parse_functions.get(self.current_token.type)
|
||||
if prefix_func is None:
|
||||
self.__no_prefix_parse_function_error(self.current_token.type)
|
||||
return None
|
||||
|
||||
left_expr: Expression = prefix_func()
|
||||
while not self.__peek_token_is(TokenType.SEMICOLON) and precedence.value < self.__peek_precedence().value:
|
||||
infix_func: Callable | None = self.infix_parse_functions.get(self.peek_token.type)
|
||||
if infix_func is None:
|
||||
return left_expr
|
||||
|
||||
self.__next_token()
|
||||
|
||||
left_expr = infix_func(left_expr)
|
||||
|
||||
return left_expr
|
||||
|
||||
def __parse_infix_expression(self, left_node: Expression) -> Expression:
|
||||
infix_expr: Expression = InfixExpression(left_node=left_node, operator=self.current_token.literal)
|
||||
|
||||
precedence = self.__current_precedence()
|
||||
|
||||
self.__next_token()
|
||||
|
||||
infix_expr.right_node = self.__parse_expression(precedence)
|
||||
|
||||
return infix_expr
|
||||
|
||||
def __parse_grouped_expression(self) -> Expression:
|
||||
self.__next_token()
|
||||
|
||||
expr: Expression = self.__parse_expression(PrecedenceType.P_LOWEST)
|
||||
|
||||
if not self.__expect_peek(TokenType.RPAREN):
|
||||
return None
|
||||
|
||||
return expr
|
||||
# endregion
|
||||
|
||||
# region Prefix Methods
|
||||
def __parse_int_literal(self) -> Expression:
|
||||
int_lit: IntegerLiteral = IntegerLiteral()
|
||||
|
||||
try:
|
||||
int_lit.value = int(self.current_token.literal)
|
||||
except:
|
||||
self.errors.append(f"Could not parse \"{self.current_token.literal}\" as an integer.")
|
||||
return None
|
||||
|
||||
return int_lit
|
||||
|
||||
def __parse_float_literal(self) -> Expression:
|
||||
float_lit: FloatLiteral = FloatLiteral()
|
||||
|
||||
try:
|
||||
float_lit.value = float(self.current_token.literal)
|
||||
except:
|
||||
self.errors.append(f"Could not parse \"{self.current_token.literal}\" as an float.")
|
||||
return None
|
||||
|
||||
return float_lit
|
||||
# endregion
|
||||
Reference in New Issue
Block a user