summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrederick Yin <fkfd@fkfd.me>2022-08-30 22:26:13 +0800
committerFrederick Yin <fkfd@fkfd.me>2022-08-30 22:26:13 +0800
commit75811ebbd166b3cd271bb730323cc7ab4fdcb3a5 (patch)
treecf176475e6806b1ad200ba61063266aab6e04c2a
parent5b4f3e494c5d12e0b44c232ada41fe2e273b27c0 (diff)
hackc: Subroutine takes care of parens
-rw-r--r--projects/hackc/classes.py53
-rw-r--r--projects/hackc/parser.py1
2 files changed, 39 insertions, 15 deletions
diff --git a/projects/hackc/classes.py b/projects/hackc/classes.py
index 1875ce7..14b3105 100644
--- a/projects/hackc/classes.py
+++ b/projects/hackc/classes.py
@@ -44,23 +44,33 @@ class Class:
tokens_consumed = 3
+ variables = []
while tokens_consumed < tokens_total:
- variables, token_cnt = Variable.from_tokens(
+ variable, token_cnt = Variable.from_tokens(
tokens[tokens_consumed:], context="class"
)
- if variables is None:
+ if variable is None:
break
- variables.print_verbose()
+ variables.append(variable)
tokens_consumed += token_cnt
+ subroutines = []
while tokens_consumed < tokens_total:
subroutine, token_cnt = Subroutine.from_tokens(tokens[tokens_consumed:])
if subroutine is None:
break
- subroutine.print_verbose()
+ subroutines.append(subroutine)
tokens_consumed += token_cnt
- return Class(name, variables, [])
+ return Class(name, variables, subroutines)
+
+ def print_verbose(self):
+ print(f"Define class {self.name}")
+ for variable in self.variables:
+ variable.print_verbose()
+ for subroutine in self.subroutines:
+ subroutine.print_verbose()
+ print(f"End of class {self.name}")
class Variable:
@@ -156,21 +166,20 @@ class ParamList:
"""Construct parameter list of subroutine from tokens.
Format:
- '(' (<type> <name> (, <type> <name>)*)? ')'
+ (<type> <name> (, <type> <name>)*)?
<type> = int | char | boolean | <class>
"""
- if len(tokens) < 2 or tokens[0] != LEFT_PAREN:
+ if not tokens:
return (None, 0)
- if tokens[1] == RIGHT_PAREN:
+ if tokens[0] == RIGHT_PAREN:
# empty param list, i.e. '(' ')'
return (ParamList([]), 2)
- tokens_consumed = 1
+ tokens_consumed = 0
params = []
- for type, name, delim in zip(tokens[1::3], tokens[2::3], tokens[3::3]):
- tokens_consumed += 3
+ for type, name, delim in zip(tokens[0::3], tokens[1::3], tokens[2::3]):
if type not in VAR_TYPES and type.type != "identifier":
raise JackSyntaxError(f"Expected datatype, got `{type}` instead", type)
if not name:
@@ -183,9 +192,11 @@ class ParamList:
if not delim:
raise JackSyntaxError(f"Expected `,` or `{RIGHT_PAREN}`", name)
if delim == ",":
+ tokens_consumed += 3
params.append((type, name))
continue
elif delim == RIGHT_PAREN:
+ tokens_consumed += 2
params.append((type, name))
break
else:
@@ -195,6 +206,11 @@ class ParamList:
return (ParamList(params), tokens_consumed)
+ def print_verbose(self):
+ print(f"Subroutine takes {len(self.params)} parameter(s):")
+ for param in self.params:
+ print(param[0], param[1])
+
class Subroutine:
def __init__(
@@ -211,7 +227,7 @@ class Subroutine:
"""Construct subroutine from tokens.
Format:
- <category> <return type> <name> <paramlist> <body>
+ <category> <return type> <name> '(' <paramlist> ')' '{' <body> '}'
<category> = constructor | method | function
<return type> = int | char | boolean | void | <class>
@@ -233,13 +249,20 @@ class Subroutine:
f"Expected {category} name, got `{name}` instead", name
)
- tokens_consumed = 3
+ if tokens[3] != LEFT_PAREN:
+ raise JackSyntaxError(
+ f"Expected `{LEFT_PAREN}`, got `{tokens[3]}`", tokens[3]
+ )
+
+ tokens_consumed = 4
params, token_cnt = ParamList.from_tokens(tokens[tokens_consumed:])
if params is None:
raise JackSyntaxError("Expected parameter list", tokens[tokens_consumed])
- tokens_consumed += token_cnt
+ # it can be safely assumed that the next token is ')'
+ tokens_consumed += token_cnt + 1
return (Subroutine(category, return_type, name, params, None), tokens_consumed)
def print_verbose(self):
- print(f"Define {self.category} {self.name}, returns {self.type}")
+ print(f"Define {self.category} {self.type} {self.name}")
+ self.params.print_verbose()
diff --git a/projects/hackc/parser.py b/projects/hackc/parser.py
index 2fc30ee..8375d52 100644
--- a/projects/hackc/parser.py
+++ b/projects/hackc/parser.py
@@ -96,6 +96,7 @@ class Parser:
def parse(self):
try:
syntax_tree = Class.from_tokens(self.tokens)
+ syntax_tree.print_verbose()
except JackSyntaxError as err:
print_err(f"{self._fp}:{err.token.line_no + 1}")
print_err(self.lines[err.token.line_no])