Moved all AST nodes to a separate module and fixed a bug with unary + operator

This commit is contained in:
2023-04-17 18:36:18 -04:00
parent 70cd50b087
commit 092e2d311e
2 changed files with 146 additions and 138 deletions

164
aurora.py
View File

@@ -12,6 +12,7 @@ Purpose: Main implementation of Aurora
# Imports # Imports
import string import string
from exceptions import core as exceptions from exceptions import core as exceptions
from internal import nodes
#################### ####################
# CONSTANTS # CONSTANTS
@@ -21,12 +22,6 @@ LETTERS = string.ascii_letters
LETTERS_DIGITS = LETTERS + DIGITS LETTERS_DIGITS = LETTERS + DIGITS
####################
# ERRORS
####################
#################### ####################
# POSITION # POSITION
#################### ####################
@@ -311,119 +306,6 @@ class Lexer:
return Token(token_type, pos_start=pos_start, pos_end=self.pos) return Token(token_type, pos_start=pos_start, pos_end=self.pos)
####################
# NODES
####################
class NumberNode:
def __init__(self, token):
self.token = token
self.pos_start = self.token.pos_start
self.pos_end = self.token.pos_end
def __repr__(self):
return f"{self.token}"
class StringNode:
def __init__(self, token):
self.token = token
self.pos_start = self.token.pos_start
self.pos_end = self.token.pos_end
def __repr__(self):
return f'{self.token}'
class VarAccessNode:
def __init__(self, var_name_token):
self.var_name_token = var_name_token
self.pos_start = self.var_name_token.pos_start
self.pos_end = self.var_name_token.pos_end
class VarAssignNode:
def __init__(self, var_name_token, value_node):
self.var_name_token = var_name_token
self.value_node = value_node
self.pos_start = self.var_name_token.pos_start
self.pos_end = self.var_name_token.pos_end
class BinaryOperationNode:
def __init__(self, left_node, operation, right_node):
self.left_node = left_node
self.operation = operation
self.right_node = right_node
self.pos_start = self.left_node.pos_start
self.pos_end = self.right_node.pos_end
def __repr__(self):
return f"({self.left_node}, {self.operation}, {self.right_node})"
class UnaryOperationNode:
def __init__(self, operation, node):
self.operation = operation
self.node = node
self.pos_start = self.operation.pos_start
self.pos_end = self.node.pos_end
def __repr__(self):
return f'({self.operation}, {self.node})'
class IfNode:
def __init__(self, cases, else_case):
self.cases = cases
self.else_case = else_case
self.pos_start = self.cases[0][0].pos_start
self.pos_end = (self.else_case or self.cases[len(self.cases) - 1][0]).pos_end
class ForNode:
def __init__(self, var_name_token, start_value_node, end_value_node, step_value_node, body_node):
self.var_name_token = var_name_token
self.start_value_node = start_value_node
self.end_value_node = end_value_node
self.step_value_node = step_value_node
self.body_node = body_node
self.pos_start = self.var_name_token.pos_start
self.pos_end = self.body_node.pos_end
class WhileNode:
def __init__(self, condition_node, body_node):
self.condition_node = condition_node
self.body_node = body_node
self.pos_start = condition_node.pos_start
self.pos_end = body_node.pos_end
class FunDefNode:
def __init__(self, var_name_token, arg_name_tokens, body_node):
self.var_name_token = var_name_token
self.arg_name_tokens = arg_name_tokens
self.body_node = body_node
if self.var_name_token:
self.pos_start = self.var_name_token.pos_start
elif len(self.arg_name_tokens) > 0:
self.pos_start = self.arg_name_tokens[0].pos_start
else:
self.pos_start = self.body_node.pos_start
self.pos_end = self.body_node.pos_end
class CallNode:
def __init__(self, node_to_call, arg_nodes):
self.node_to_call = node_to_call
self.arg_nodes = arg_nodes
self.pos_start = self.node_to_call.pos_start
if len(self.arg_nodes) > 0:
self.pos_end = self.arg_nodes[len(self.arg_nodes) - 1].pos_end
else:
self.pos_end = self.node_to_call.pos_end
#################### ####################
# PARSER RESULT # PARSER RESULT
#################### ####################
@@ -545,7 +427,7 @@ class Parser:
result.register_advancement() result.register_advancement()
self.advance() self.advance()
return result.success(CallNode(atom, arg_nodes)) return result.success(nodes.CallNode(atom, arg_nodes))
return result.success(atom) return result.success(atom)
def atom(self): def atom(self):
@@ -555,15 +437,15 @@ class Parser:
if token.type in (TT_INT, TT_FLOAT): if token.type in (TT_INT, TT_FLOAT):
result.register_advancement() result.register_advancement()
self.advance() self.advance()
return result.success(NumberNode(token)) return result.success(nodes.NumberNode(token))
elif token.type == TT_STRING: elif token.type == TT_STRING:
result.register_advancement() result.register_advancement()
self.advance() self.advance()
return result.success(StringNode(token)) return result.success(nodes.StringNode(token))
elif token.type == TT_IDENTIFIER: elif token.type == TT_IDENTIFIER:
result.register_advancement() result.register_advancement()
self.advance() self.advance()
return result.success(VarAccessNode(token)) return result.success(nodes.VarAccessNode(token))
elif token.type == TT_LPAREN: elif token.type == TT_LPAREN:
result.register_advancement() result.register_advancement()
self.advance() self.advance()
@@ -619,7 +501,7 @@ class Parser:
factor = result.register(self.factor()) factor = result.register(self.factor())
if result.error: if result.error:
return result return result
return result.success(UnaryOperationNode(token, factor)) return result.success(nodes.UnaryOperationNode(token, factor))
return self.power() return self.power()
@@ -640,7 +522,7 @@ class Parser:
node = result.register(self.com_expr()) node = result.register(self.com_expr())
if result.error: if result.error:
return result return result
return result.success(UnaryOperationNode(operation, node)) return result.success(nodes.UnaryOperationNode(operation, node))
node = result.register(self.binary_operation(self.ar_expr, (TT_EE, TT_NE, TT_LT, TT_GT, TT_LTE, TT_GTE))) node = result.register(self.binary_operation(self.ar_expr, (TT_EE, TT_NE, TT_LT, TT_GT, TT_LTE, TT_GTE)))
if result.error: if result.error:
@@ -682,7 +564,7 @@ class Parser:
expr = result.register(self.expr()) expr = result.register(self.expr())
if result.error: if result.error:
return result return result
return result.success(VarAssignNode(var_name, expr)) return result.success(nodes.VarAssignNode(var_name, expr))
node = result.register(self.binary_operation(self.com_expr, ((TT_KEYWORD, "and"), (TT_KEYWORD, "or")))) node = result.register(self.binary_operation(self.com_expr, ((TT_KEYWORD, "and"), (TT_KEYWORD, "or"))))
if result.error: if result.error:
@@ -757,7 +639,7 @@ class Parser:
else_case = result.register(self.expr()) else_case = result.register(self.expr())
if result.error: if result.error:
return result return result
return result.success(IfNode(cases, else_case)) return result.success(nodes.IfNode(cases, else_case))
def for_expr(self): def for_expr(self):
result = ParsedResult() result = ParsedResult()
@@ -834,7 +716,7 @@ class Parser:
if result.error: if result.error:
return result return result
return result.success(ForNode(var_name, start_value, end_value, step_value, body)) return result.success(nodes.ForNode(var_name, start_value, end_value, step_value, body))
def while_expr(self): def while_expr(self):
result = ParsedResult() result = ParsedResult()
@@ -867,7 +749,7 @@ class Parser:
if result.error: if result.error:
return result return result
return result.success(WhileNode(condition, body)) return result.success(nodes.WhileNode(condition, body))
def fun_def(self): def fun_def(self):
result = ParsedResult() result = ParsedResult()
@@ -958,7 +840,7 @@ class Parser:
if result.error: if result.error:
return result return result
return result.success(FunDefNode( return result.success(nodes.FunDefNode(
var_name_token, var_name_token,
arg_name_tokens, arg_name_tokens,
node_to_return node_to_return
@@ -980,7 +862,7 @@ class Parser:
right = result.register(rfunc()) right = result.register(rfunc())
if result.error: if result.error:
return result return result
left = BinaryOperationNode(left, operation, right) left = nodes.BinaryOperationNode(left, operation, right)
return result.success(left) return result.success(left)
@@ -1311,7 +1193,7 @@ class Interpreter:
Number(node.token.value).set_context(context).set_pos(node.pos_start, node.pos_end) Number(node.token.value).set_context(context).set_pos(node.pos_start, node.pos_end)
) )
def visit_StringNode(self, node: StringNode, context: Context): def visit_StringNode(self, node: nodes.StringNode, context: Context):
return RuntimeResult().success( return RuntimeResult().success(
String(node.token.value).set_context(context).set_pos(node.pos_start, node.pos_end) String(node.token.value).set_context(context).set_pos(node.pos_start, node.pos_end)
) )
@@ -1383,7 +1265,7 @@ class Interpreter:
return rt_result.failure(error) return rt_result.failure(error)
return rt_result.success(result.set_pos(node.pos_start, node.pos_end)) return rt_result.success(result.set_pos(node.pos_start, node.pos_end))
def visit_UnaryOperationNode(self, node: UnaryOperationNode, context): def visit_UnaryOperationNode(self, node: nodes.UnaryOperationNode, context):
result = RuntimeResult() result = RuntimeResult()
number = result.register(self.visit(node.node, context)) number = result.register(self.visit(node.node, context))
if result.error: if result.error:
@@ -1393,12 +1275,18 @@ class Interpreter:
number, error = number.multiplied_by(Number(-1)) number, error = number.multiplied_by(Number(-1))
elif node.operation.matches(TT_KEYWORD, 'not'): elif node.operation.matches(TT_KEYWORD, 'not'):
number, error = number.not_op() number, error = number.not_op()
else:
return result.failure(exceptions.InvalidSyntaxErr(
node.pos_start,
node.pos_end,
"This unary operation is not valid in this context."
))
if error: if error:
return result.failure(error) return result.failure(error)
return result.success(number.set_pos(node.pos_start, node.pos_end)) return result.success(number.set_pos(node.pos_start, node.pos_end))
def visit_IfNode(self, node: IfNode, context): def visit_IfNode(self, node: nodes.IfNode, context):
result = RuntimeResult() result = RuntimeResult()
for condition, expr, in node.cases: for condition, expr, in node.cases:
@@ -1422,7 +1310,7 @@ class Interpreter:
return result.success(None) return result.success(None)
def visit_ForNode(self, node: ForNode, context: Context): def visit_ForNode(self, node: nodes.ForNode, context: Context):
result = RuntimeResult() result = RuntimeResult()
start_value = result.register(self.visit(node.start_value_node, context)) start_value = result.register(self.visit(node.start_value_node, context))
@@ -1456,7 +1344,7 @@ class Interpreter:
return result.success(None) return result.success(None)
def visit_WhileNode(self, node: WhileNode, context: Context): def visit_WhileNode(self, node: nodes.WhileNode, context: Context):
result = RuntimeResult() result = RuntimeResult()
while True: while True:
@@ -1473,7 +1361,7 @@ class Interpreter:
return result.success(None) return result.success(None)
def visit_FunDefNode(self, node: FunDefNode, context: Context): def visit_FunDefNode(self, node: nodes.FunDefNode, context: Context):
result = RuntimeResult() result = RuntimeResult()
fun_name = node.var_name_token.value if node.var_name_token else None fun_name = node.var_name_token.value if node.var_name_token else None
@@ -1486,7 +1374,7 @@ class Interpreter:
return result.success(fun_value) return result.success(fun_value)
def visit_CallNode(self, node: CallNode, context: Context): def visit_CallNode(self, node: nodes.CallNode, context: Context):
result = RuntimeResult() result = RuntimeResult()
args = [] args = []

120
internal/nodes.py Normal file
View File

@@ -0,0 +1,120 @@
# d888888
# d88P aaa 888 888 888d88 .d88b. 888d88 8888b.
# d88P aaa 888 888 888P d88^^88b 888P 88b
# d88P aaa 888 888 888 888 888 888 .d888888
# d8888888888 Y88b 888 888 Y88..88P 888 888 888
# d88P aaa Y88888 888 Y88P 888 Y888888
# -- Copyright © 2023 Zandercraft. All rights reserved. --
"""
Purpose: Contains all node types for the AST of the language.
"""
class NumberNode:
def __init__(self, token):
self.token = token
self.pos_start = self.token.pos_start
self.pos_end = self.token.pos_end
def __repr__(self):
return f"{self.token}"
class StringNode:
def __init__(self, token):
self.token = token
self.pos_start = self.token.pos_start
self.pos_end = self.token.pos_end
def __repr__(self):
return f'{self.token}'
class VarAccessNode:
def __init__(self, var_name_token):
self.var_name_token = var_name_token
self.pos_start = self.var_name_token.pos_start
self.pos_end = self.var_name_token.pos_end
class VarAssignNode:
def __init__(self, var_name_token, value_node):
self.var_name_token = var_name_token
self.value_node = value_node
self.pos_start = self.var_name_token.pos_start
self.pos_end = self.var_name_token.pos_end
class BinaryOperationNode:
def __init__(self, left_node, operation, right_node):
self.left_node = left_node
self.operation = operation
self.right_node = right_node
self.pos_start = self.left_node.pos_start
self.pos_end = self.right_node.pos_end
def __repr__(self):
return f"({self.left_node}, {self.operation}, {self.right_node})"
class UnaryOperationNode:
def __init__(self, operation, node):
self.operation = operation
self.node = node
self.pos_start = self.operation.pos_start
self.pos_end = self.node.pos_end
def __repr__(self):
return f'({self.operation}, {self.node})'
class IfNode:
def __init__(self, cases, else_case):
self.cases = cases
self.else_case = else_case
self.pos_start = self.cases[0][0].pos_start
self.pos_end = (self.else_case or self.cases[len(self.cases) - 1][0]).pos_end
class ForNode:
def __init__(self, var_name_token, start_value_node, end_value_node, step_value_node, body_node):
self.var_name_token = var_name_token
self.start_value_node = start_value_node
self.end_value_node = end_value_node
self.step_value_node = step_value_node
self.body_node = body_node
self.pos_start = self.var_name_token.pos_start
self.pos_end = self.body_node.pos_end
class WhileNode:
def __init__(self, condition_node, body_node):
self.condition_node = condition_node
self.body_node = body_node
self.pos_start = condition_node.pos_start
self.pos_end = body_node.pos_end
class FunDefNode:
def __init__(self, var_name_token, arg_name_tokens, body_node):
self.var_name_token = var_name_token
self.arg_name_tokens = arg_name_tokens
self.body_node = body_node
if self.var_name_token:
self.pos_start = self.var_name_token.pos_start
elif len(self.arg_name_tokens) > 0:
self.pos_start = self.arg_name_tokens[0].pos_start
else:
self.pos_start = self.body_node.pos_start
self.pos_end = self.body_node.pos_end
class CallNode:
def __init__(self, node_to_call, arg_nodes):
self.node_to_call = node_to_call
self.arg_nodes = arg_nodes
self.pos_start = self.node_to_call.pos_start
if len(self.arg_nodes) > 0:
self.pos_end = self.arg_nodes[len(self.arg_nodes) - 1].pos_end
else:
self.pos_end = self.node_to_call.pos_end