aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/psi/parsers.py
diff options
context:
space:
mode:
Diffstat (limited to 'psi/parsers.py')
-rw-r--r--psi/parsers.py144
1 files changed, 144 insertions, 0 deletions
diff --git a/psi/parsers.py b/psi/parsers.py
new file mode 100644
index 0000000..f68f95f
--- /dev/null
+++ b/psi/parsers.py
@@ -0,0 +1,144 @@
+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}')