summaryrefslogtreecommitdiff
path: root/projects/hackc/syntax.py
diff options
context:
space:
mode:
Diffstat (limited to 'projects/hackc/syntax.py')
-rw-r--r--projects/hackc/syntax.py146
1 files changed, 0 insertions, 146 deletions
diff --git a/projects/hackc/syntax.py b/projects/hackc/syntax.py
deleted file mode 100644
index 281bd17..0000000
--- a/projects/hackc/syntax.py
+++ /dev/null
@@ -1,146 +0,0 @@
-from .tokens import Token
-from .utils import *
-
-SCOPES = ["static", "field", "var"]
-PRIMITIVE_TYPES = ["int", "char", "boolean"]
-
-
-class Class:
- def __init__(self, name: Token, variables: list, subroutines: list):
- self.name = name
- self.variables = variables
- self.subroutines = subroutines
-
- @classmethod
- def from_tokens(cls, tokens: list):
- """Construct a class from a list of tokens.
-
- In standard Jack, one file is exactly one class.
-
- Format:
- class <name> {
- <zero or more class variable declarations>
- <zero or more subroutines>
- }
- """
- if len(tokens) < 4:
- return None
- if tokens[0] != "class":
- raise JackSyntaxError(
- f"Expected `class`, got `{tokens[0]}` instead", tokens[0]
- )
-
- name = tokens[1]
- if name.type != "identifier":
- raise JackSyntaxError(f"You cannot name a class `{name}`", name)
-
- if tokens[2] != LEFT_BRACE:
- raise JackSyntaxError(
- f"Expected `{LEFT_BRACE}`, got `{tokens[2]}` instead", tokens[2]
- )
-
- tokens_consumed = 3
-
- while True:
- variables, token_cnt = Variable.from_tokens(
- tokens[tokens_consumed:], context="class"
- )
- if variables is None:
- break
- variables.print_verbose()
- tokens_consumed += token_cnt
-
- return Class(name, variables, [])
-
-
-class Variable:
- def __init__(self, scope: Token, type: Token, names: list[Token]):
- self.scope = scope
- self.type = type
- self.names = names
-
- @classmethod
- def from_tokens(cls, tokens: list, context: str) -> tuple:
- """Construct variable declaration statement from a list of tokens.
- Return a tuple of an instance of Variable and number of tokens consumed.
- When `tokens` does not begin with a variable declaration, return (None, 0).
-
- context -- "class" (<scope> = static | field) or "subroutine" (<scope> = var)
-
- Format:
- <scope> <type> <one or more names, joined with a comma>;
-
- <scope> = static | field | var
- <type> = int | char | boolean | <class name>
- """
- if len(tokens) < 4 or tokens[0] not in SCOPES:
- # not variable declaration
- return (None, 0)
-
- scope = tokens[0]
- if scope in ["static", "field"] and context != "class":
- raise JackSyntaxError(
- f"You cannot declare a {scope} variable in a subroutine", scope
- )
- if scope == "var" and context != "subroutine":
- raise JackSyntaxError(
- f"You cannot declare a local variable outside of a subroutine",
- scope,
- )
-
- type = tokens[1]
- if type not in PRIMITIVE_TYPES and type.type != "identifier":
- raise JackSyntaxError(f"Expected datatype, got `{tokens[1]}` instead", type)
-
- tokens_consumed = 2
- names = [] # names of variables
- expecting_identifier = True
-
- for token in tokens[2:]:
- tokens_consumed += 1
- if token.type == "identifier":
- if expecting_identifier:
- names.append(token)
- expecting_identifier = False
- else:
- raise JackSyntaxError(f"Expected `,`, got `{token}` instead", token)
- elif token == ",":
- if not expecting_identifier:
- expecting_identifier = True
- else:
- raise JackSyntaxError(
- f"Expected variable name, got `,` instead", token
- )
- elif token == ";":
- if expecting_identifier:
- raise JackSyntaxError(
- f"Expected variable name, got `;` instead", token
- )
- break
- else:
- expected = "variable name" if expecting_identifier else "`,` or `;`"
- raise JackSyntaxError(
- f"Expected {expected}, got `{token}` instead", token
- )
-
- return (Variable(scope, type, names), tokens_consumed)
-
- def print_verbose(self):
- print(f"Declare {len(self.names)} variable(s):")
- for name in self.names:
- print(self.scope, self.type, name)
-
-
-class Subroutine:
- def __init__(self):
- pass
-
-
-class Statement:
- def __init__(self):
- super().__init__()
-
-
-class IfStatement(Statement):
- def __init__(self):
- super().__init__()