fixed some scope issues and added label and line reference support to the AST
This commit is contained in:
@@ -43,6 +43,15 @@ class FunctionNode:
|
||||
parent: FunctionNode | RootNode
|
||||
return_type: Optional[str] = None
|
||||
name: Optional[str] = None
|
||||
@dataclass
|
||||
class LabelDecNode:
|
||||
name: str
|
||||
@dataclass
|
||||
class LabelRefNode:
|
||||
name: str
|
||||
@dataclass
|
||||
class LineRefNode:
|
||||
line: int
|
||||
|
||||
def generate_ast(tokens: list[Token], code: str) -> RootNode:
|
||||
root_node = RootNode([])
|
||||
@@ -55,7 +64,7 @@ def generate_ast(tokens: list[Token], code: str) -> RootNode:
|
||||
# todo: this is the absolute WORST way i could do this, but i could not care less lmao
|
||||
# its not even performant......
|
||||
for token in tokens:
|
||||
print(token)
|
||||
#print(token.type)
|
||||
if token.type == TokenType.INSTRUCTION:
|
||||
if current_node:
|
||||
scope.statements.append(current_node)
|
||||
@@ -68,9 +77,15 @@ def generate_ast(tokens: list[Token], code: str) -> RootNode:
|
||||
current_node_type = "inst"
|
||||
|
||||
if current_node.instruction == "endfun":
|
||||
scope = scope.parent # go up one scope
|
||||
if scope == root_node:
|
||||
traceback(code, "ScopeError", "You can't use endfun from global scope, did you mean to use the \"end\" instruction?")
|
||||
|
||||
current_node.parent = scope
|
||||
scope = scope.parent # go up one scope
|
||||
current_node.parent = scope
|
||||
scope.statements.append(current_node)
|
||||
current_node = scope
|
||||
else:
|
||||
current_node.parent = scope
|
||||
else:
|
||||
current_node = FunctionNode([], [], scope)
|
||||
current_node_type = "func"
|
||||
@@ -88,11 +103,22 @@ def generate_ast(tokens: list[Token], code: str) -> RootNode:
|
||||
else:
|
||||
traceback(code, "SyntaxError", "Expected instruction, not number.")
|
||||
|
||||
elif token.type == TokenType.LINE_REFERENCE:
|
||||
if current_node_type == "inst":
|
||||
current_node.arguments.append(LineRefNode(token.value))
|
||||
else:
|
||||
traceback(code, "SyntaxError", "Expected instruction, not line reference")
|
||||
|
||||
elif token.type == TokenType.LABEL_REFERENCE:
|
||||
if current_node_type == "inst":
|
||||
current_node.arguments.append(LabelRefNode(token.value))
|
||||
else:
|
||||
traceback(code, "SyntaxError", "Expected instruction, not label reference")
|
||||
|
||||
elif token.type == TokenType.VARIABLE_POINTER:
|
||||
if current_node_type == "inst":
|
||||
current_node.arguments.append(VarPointerNode(token.value))
|
||||
elif last_token and last_token.type == TokenType.TYPE and current_node_type == "func":
|
||||
print(current_node)
|
||||
current_node.args[-1].name = token.value
|
||||
else:
|
||||
traceback(code, "SyntaxError", "Expected instruction, not variable pointer.")
|
||||
@@ -126,6 +152,9 @@ def generate_ast(tokens: list[Token], code: str) -> RootNode:
|
||||
else:
|
||||
traceback(code, "SyntaxError", "Expected instruction or function return type, got function reference.")
|
||||
|
||||
elif token.type == TokenType.LABEL_DECLERATION:
|
||||
scope.statements.append(LabelDecNode(token.value))
|
||||
|
||||
elif token.type == TokenType.EOF:
|
||||
root_node.statements.append(current_node)
|
||||
last_token = token
|
||||
|
@@ -5,8 +5,8 @@ fun -list !split -string &str -string &determiner
|
||||
set &x 2
|
||||
set &y 5
|
||||
add $x $y &x
|
||||
stdlnout $x
|
||||
return $x
|
||||
endfun
|
||||
|
||||
# should error
|
||||
stdlnout $x
|
||||
@myLabel
|
||||
jump %myLabel
|
Reference in New Issue
Block a user