aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/psi
diff options
context:
space:
mode:
Diffstat (limited to 'src/psi')
-rw-r--r--src/psi/__init__.py45
-rw-r--r--src/psi/execution.py35
-rw-r--r--src/psi/interpreter.py49
-rw-r--r--src/psi/lexer.py96
-rw-r--r--src/psi/parsers.py79
5 files changed, 301 insertions, 3 deletions
diff --git a/src/psi/__init__.py b/src/psi/__init__.py
index 1c274e2..3652c6d 100644
--- a/src/psi/__init__.py
+++ b/src/psi/__init__.py
@@ -8,19 +8,64 @@ __all__ = ['psi']
from psi.execution import Execution
class Psi:
+ """
+ A class representing a Psi object.
+
+ Args:
+ input: The input value for the Psi object.
+
+ Returns:
+ None
+
+ Example:
+ ```python
+ obj = Psi("example")
+ ```
+ """
+
def __init__(self, input):
+ """
+ Initializes a Psi object.
+
+ Args:
+ input: The input value for the Psi object.
+
+ Returns:
+ None
+ """
self.input = input
self.execution = Execution(input)
self.result = None
def execute(self):
+ """
+ Executes the Psi object.
+
+ Returns:
+ The result of the execution.
+ """
self.result = self.execution.execute()
return self.result
def get_result(self):
+ """
+ Retrieves the result of the Psi object.
+
+ Returns:
+ The result of the execution.
+ """
return self.result
def set_input(self, input):
+ """
+ Sets the input value for the Psi object.
+
+ Args:
+ input: The new input value.
+
+ Returns:
+ None
+ """
self.input = input
self.execution = Execution(input)
self.result = None
diff --git a/src/psi/execution.py b/src/psi/execution.py
index 052f7ab..0abdf2c 100644
--- a/src/psi/execution.py
+++ b/src/psi/execution.py
@@ -4,14 +4,43 @@ from psi.interpreter import Interpreter
__all__ = ['Execution']
class Execution:
+ """
+ A class representing the execution of Psi code.
+
+ Args:
+ input: The input code to be executed.
+
+ Returns:
+ None
+
+ Example:
+ ```python
+ execution = Execution("print('Hello, World!')")
+ execution.execute()
+ ```
+ """
+
def __init__(self, input):
+ """
+ Initializes an Execution object.
+
+ Args:
+ input: The input code to be executed.
+
+ Returns:
+ None
+ """
self.input = input
def execute(self):
+ """
+ Executes the input code.
+
+ Returns:
+ The result of the execution.
+ """
parser = Parser(self.input)
ast = parser.parse()
interpreter = Interpreter(ast)
- result = interpreter.interpret()
-
- return result
+ return interpreter.interpret()
diff --git a/src/psi/interpreter.py b/src/psi/interpreter.py
index f98a777..8aa8fad 100644
--- a/src/psi/interpreter.py
+++ b/src/psi/interpreter.py
@@ -4,13 +4,53 @@ from psi.lexer import Token
__all__ = ['Interpreter']
class Interpreter:
+ """
+ A class representing an interpreter for Psi code.
+
+ Args:
+ ast: The abstract syntax tree (AST) of the code to be interpreted.
+
+ Returns:
+ None
+
+ Example:
+ ```python
+ interpreter = Interpreter(ast)
+ interpreter.interpret()
+ ```
+ """
+
def __init__(self, ast):
+ """
+ Initializes an Interpreter object.
+
+ Args:
+ ast: The abstract syntax tree (AST) of the code to be interpreted.
+
+ Returns:
+ None
+ """
self.ast = ast
def interpret(self):
+ """
+ Interprets the code represented by the AST.
+
+ Returns:
+ The result of the interpretation.
+ """
return self.interpret_expr(self.ast)
def interpret_expr(self, node):
+ """
+ Interprets an expression node in the AST.
+
+ Args:
+ node: The expression node to be interpreted.
+
+ Returns:
+ The result of the interpretation.
+ """
if isinstance(node, Token):
return node.value
elif isinstance(node, list):
@@ -20,6 +60,15 @@ class Interpreter:
return result
def interpret_condition(self, node):
+ """
+ Interprets a condition node in the AST.
+
+ Args:
+ node: The condition node to be interpreted.
+
+ Returns:
+ The result of the interpretation.
+ """
variable = self.interpret_expr(node[0])
value = self.interpret_expr(node[2])
diff --git a/src/psi/lexer.py b/src/psi/lexer.py
index 2fce0eb..d2c6f68 100644
--- a/src/psi/lexer.py
+++ b/src/psi/lexer.py
@@ -56,22 +56,97 @@ print([t['type'] for t in lexer])
__all__ = ['Token', 'Lexer']
class Token(dict):
+ """
+ A class representing a token in the lexer.
+
+ Args:
+ type: The type of the token.
+ value: The value of the token.
+ position: The position of the token.
+
+ Returns:
+ None
+
+ Example:
+ ```python
+ token = Token("identifier", "x", (1, 5))
+ ```
+ """
+
def __init__(self, type, value, position):
+ """
+ Initializes a Token object.
+
+ Args:
+ type: The type of the token.
+ value: The value of the token.
+ position: The position of the token.
+
+ Returns:
+ None
+ """
super().__init__(type=type, value=value, position=position)
def __getattr__(self, name):
+ """
+ Retrieves the value of an attribute from the Token object.
+
+ Args:
+ name: The name of the attribute.
+
+ Returns:
+ The value of the attribute.
+
+ Raises:
+ AttributeError: Raised when the attribute does not exist.
+ """
try:
return self[name]
except KeyError:
raise AttributeError(f"'Token' object has no attribute '{name}'")
+
class Lexer:
+ """
+ A class representing a lexer for Psi code.
+
+ Args:
+ input: The input code to be lexed.
+
+ Returns:
+ None
+
+ Example:
+ ```python
+ lexer = Lexer("x = 10")
+ for token in lexer:
+ print(token)
+ ```
+ """
def __init__(self, input):
+ """
+ Initializes a Lexer object.
+
+ Args:
+ input: The input code to be lexed.
+
+ Returns:
+ None
+ """
self.input = input
self.position = 0
self.tokens = []
def get_next_token(self):
+ """
+ Retrieves the next token from the input code.
+
+ Returns:
+ The next token.
+
+ Raises:
+ Exception: Raised when an unknown character is encountered.
+ """
while self.position < len(self.input):
current_char = self.input[self.position]
@@ -144,10 +219,31 @@ class Lexer:
return token
def __iter__(self):
+ """
+ Returns an iterator over the tokens.
+
+ Returns:
+ An iterator over the tokens.
+ """
return iter(self.tokens)
def __getitem__(self, index):
+ """
+ Retrieves the token at the specified index.
+
+ Args:
+ index: The index of the token.
+
+ Returns:
+ The token at the specified index.
+ """
return self.tokens[index]
def __len__(self):
+ """
+ Returns the number of tokens.
+
+ Returns:
+ The number of tokens.
+ """
return len(self.tokens) \ No newline at end of file
diff --git a/src/psi/parsers.py b/src/psi/parsers.py
index db3e52c..f68f95f 100644
--- a/src/psi/parsers.py
+++ b/src/psi/parsers.py
@@ -4,15 +4,52 @@ 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('?')
@@ -29,6 +66,12 @@ class Parser:
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()
@@ -36,11 +79,26 @@ class Parser:
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')
@@ -49,6 +107,15 @@ class Parser:
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(':')
@@ -59,6 +126,18 @@ class Parser:
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: