mirror of
https://github.com/BoardWare-Genius/jarvis-models.git
synced 2025-12-13 16:53:24 +00:00
feat: runtime
This commit is contained in:
164
runtime/ast/parser.py
Normal file
164
runtime/ast/parser.py
Normal file
@ -0,0 +1,164 @@
|
||||
|
||||
|
||||
|
||||
from runtime.ast.tokenizer import Tokenizer
|
||||
|
||||
|
||||
class Parser:
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.script = ""
|
||||
self.tokenizer = Tokenizer()
|
||||
self.current_token = None
|
||||
|
||||
def parse(self, script: str):
|
||||
self.script = script
|
||||
self.tokenizer.init(script)
|
||||
self.current_token = self.tokenizer.get_next_token()
|
||||
return self.program()
|
||||
|
||||
def program(self):
|
||||
return {
|
||||
"type": 'Program',
|
||||
"body": {
|
||||
"type": "BlockStatement",
|
||||
"body": self.statement_list()
|
||||
},
|
||||
}
|
||||
|
||||
def return_statement(self):
|
||||
self.eat('return')
|
||||
return {
|
||||
"type": 'ReturnStatement',
|
||||
"value": self.expression_statement(),
|
||||
}
|
||||
|
||||
def statement_list(self):
|
||||
statment_list = [self.statement()]
|
||||
while self.current_token != None:
|
||||
statment_list.append(self.statement())
|
||||
return statment_list
|
||||
|
||||
def statement(self):
|
||||
if self.token_type() == "let":
|
||||
return self.variable_statement()
|
||||
return self.expression_statement()
|
||||
|
||||
def block_statement(self):
|
||||
if self.token_type() != "{":
|
||||
self.eat('{')
|
||||
body = self.statement_list()
|
||||
if self.token_type() != "}":
|
||||
self.eat('}')
|
||||
return {
|
||||
"type": 'BlockStatement',
|
||||
"body": body,
|
||||
}
|
||||
|
||||
def expression_statement(self):
|
||||
if self.token_type() == "return":
|
||||
return self.return_statement()
|
||||
if self._is_literal():
|
||||
return self.literal()
|
||||
if self.token_type() == "IDENTIFIER":
|
||||
identifier = self.identifier()
|
||||
if self.token_type() == "(":
|
||||
return self.call_expression(identifier)
|
||||
if self.token_type() == "SIMPLE_ASSIGN":
|
||||
return self.assignment_expression(identifier)
|
||||
return identifier
|
||||
raise Exception("Unexpected token: " + self.token_type())
|
||||
|
||||
def assignment_expression(self,identifier):
|
||||
self.eat('SIMPLE_ASSIGN')
|
||||
return {
|
||||
"type": 'AssignmentExpression',
|
||||
"identifier": identifier,
|
||||
"value": self.statement(),
|
||||
}
|
||||
|
||||
def call_expression(self, identifier):
|
||||
self.eat('(')
|
||||
arguments = self.argument_list()
|
||||
self.eat(')')
|
||||
return {
|
||||
"type": 'CallExpression',
|
||||
"arguments": arguments,
|
||||
"callee": identifier,
|
||||
}
|
||||
|
||||
def token_type(self):
|
||||
if self.current_token == None:
|
||||
return None
|
||||
return self.current_token["type"]
|
||||
|
||||
def _is_literal(self):
|
||||
return self.current_token["type"] in ["NUMBER", "STRING", "FLOAT"]
|
||||
|
||||
# variable
|
||||
def variable_statement(self):
|
||||
self.eat('let')
|
||||
identifier = self.identifier()
|
||||
self.eat('SIMPLE_ASSIGN')
|
||||
return {
|
||||
"type": 'VariableDeclaration',
|
||||
"identifier": identifier,
|
||||
"value": self.statement(),
|
||||
}
|
||||
|
||||
def eat(self, tokenType):
|
||||
token = self.current_token
|
||||
if token == None:
|
||||
raise Exception("Unexpected EOF")
|
||||
|
||||
if token["type"] != tokenType:
|
||||
raise Exception("Unexpected token: " + token["type"])
|
||||
|
||||
self.current_token = self.tokenizer.get_next_token()
|
||||
return token
|
||||
|
||||
def identifier(self):
|
||||
name = self.eat('IDENTIFIER')
|
||||
return {
|
||||
"type": 'Identifier',
|
||||
"name": name["value"],
|
||||
}
|
||||
|
||||
def literal(self):
|
||||
token_type = self.current_token["type"]
|
||||
if token_type == "NUMBER":
|
||||
return self.numberic_literal()
|
||||
if token_type == "STRING":
|
||||
return self.string_literal()
|
||||
if token_type == "FLOAT":
|
||||
return self.float_literal()
|
||||
raise Exception("Unexpected token: " + token_type)
|
||||
|
||||
def numberic_literal(self):
|
||||
token = self.eat('NUMBER')
|
||||
return {
|
||||
"type": 'NumericLiteral',
|
||||
"value": token["value"],
|
||||
}
|
||||
|
||||
def string_literal(self):
|
||||
token = self.eat('STRING')
|
||||
return {
|
||||
"type": 'StringLiteral',
|
||||
"value": token["value"][1:-1],
|
||||
}
|
||||
|
||||
def float_literal(self):
|
||||
token = self.eat('FLOAT')
|
||||
return {
|
||||
"type": 'FloatLiteral',
|
||||
"value": token["value"],
|
||||
}
|
||||
|
||||
def argument_list(self):
|
||||
args = []
|
||||
while self.token_type() != ")":
|
||||
args.append(self.statement())
|
||||
if self.token_type() == ",":
|
||||
self.eat(',')
|
||||
return args
|
||||
Reference in New Issue
Block a user