from psi.lexer import Lexer, Token __all__ = ['Parser'] class Parser: """ A class representing a parser for Psi code. Args: input: The input code to be parsed. Returns: None Example: ```python parser = Parser(input) parser.parse() ``` """ def __init__(self, input): """ Initializes a Parser object. Args: input: The input code to be parsed. Returns: None """ self.lexer = Lexer(input) self.tokens = iter(self.lexer) self.current_token = next(self.tokens) def parse(self): """ Parses the input code. Returns: The result of the parsing. """ return self.parse_expr() def parse_expr(self): """ Parses an expression in the input code. Returns: The result of the parsing. """ token = self.current_token if token.value == '?': self.eat('?') condition = self.parse_condition() self.eat(':') if condition: result = self.parse_reply() else: result = None return result def parse_condition(self): """ Parses a condition in the input code. Returns: The result of the parsing. """ variable = self.parse_variable() self.eat('==') value = self.parse_value() return variable == value def parse_variable(self): """ Parses a variable in the input code. Returns: The result of the parsing. """ token = self.current_token self.eat('IDENTIFIER') return token.value def parse_value(self): """ Parses a value in the input code. Returns: The result of the parsing. Raises: Exception: Raised when an invalid value is encountered. """ token = self.current_token if token.type == 'INTEGER': self.eat('INTEGER') return token.value else: raise Exception(f'Invalid value: {token.value}') def parse_reply(self): """ Parses a reply in the input code. Returns: The result of the parsing. Raises: Exception: Raised when an invalid reply is encountered. """ self.eat('reply') self.eat(':') token = self.current_token if token.type != 'SEPARATOR': raise Exception(f'Invalid reply: {token.value}') return token.value def eat(self, expected_type): """ Consumes the current token if it matches the expected type. Args: expected_type: The expected type of the token. Returns: None Raises: Exception: Raised when an unexpected token is encountered. """ if self.current_token.type == expected_type: self.current_token = next(self.tokens) else: raise Exception(f'Unexpected token: {self.current_token.value}')