-
Notifications
You must be signed in to change notification settings - Fork 4
/
project_10.py
150 lines (104 loc) · 4.59 KB
/
project_10.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# Compiler I: Syntax Analysis
#
# See https://www.nand2tetris.org/project10
"""On parsers:
nand.parsing provides a collection of primitive parsers which can be assembled into the parsers
you need to implement here. That module includes a tutorial on the basics and documentation for
each combinator.
Each component parser can act as a function taking a parse location and returning a result value
and a new location (if it succeeds). If a parser doesn't recognize the tokens at the given location,
it raises ParseFailure.
Each component parser also provides `parse(tokens)`, which can be called directly to parse a program
fragment.
For example:
>>> KeywordConstantP.parse([('keyword', 'true')])
KeywordConstant(value=True)
>>> ExpressionP.parse([('identifier', 'a'), ('symbol', '+'), ('integerConstant', '1')])
BinaryExpression(left=VarRef(name='a'), op=Op(symbol='+'), right=IntegerConstant(value=1))
"""
from nand.parsing import *
from nand import jack_ast
# SOLVERS: remove this import to get started
from nand.solutions import solved_10
# a label for each token type:
KEYWORD = 'keyword'
SYMBOL = 'symbol'
INT = 'integerConstant'
STR = 'stringConstant'
IDENTIFIER = 'identifier'
def lex(string):
"""Break the text of Jack source code into a list of tokens.
White space and comments are ignored. Each token is converted to a tuple of (token-type, value).
>>> lex("a + 1")
[('identifier', 'a'), ('symbol', '+'), ('integerConstant', '1')]
"""
# SOLVERS: replace this with code to break the input string into a sequence of tokens
tokens = solved_10.lex(string)
return tokens
def parse_class(string):
"""Convenience function which just applies the lexer and then the ClassP parser implemented below.
"""
return ClassP.parse(lex(string))
#
# Simple Values:
#
# Example: match one of the keywords that represents a simple constant value (or the "this" reference)
KeywordConstantP = (
TokenP(("keyword", "true"), jack_ast.KeywordConstant(True))
| TokenP(("keyword", "false"), jack_ast.KeywordConstant(False))
| TokenP(("keyword", "null"), jack_ast.KeywordConstant(None))
| TokenP(("keyword", "this"), jack_ast.KeywordConstant("this")))
# SOLVERS: replace this with a parser of jack_ast.Op
UnaryOpP = solved_10.UnaryOpP
# SOLVERS: replace this with a parser of jack_ast.Op
BinaryOpP = solved_10.BinaryOpP
# SOLVERS: replace this with a parser of jack_ast.IntegerConstant
IntegerConstantP = solved_10.IntegerConstantP
# SOLVERS: replace this with a parser of jack_ast.StringConstant
StringConstantP = solved_10.StringConstantP
# SOLVERS: replace this with a parser of jack_ast.VarRef
# Note the name discrepancy: the grammar defines `varName` and uses it twice. The AST has `VarRef` and
# `ArrayRef` for the two cases.
VarNameP = solved_10.VarNameP
#
# Complex Expressions:
#
# Tricky: the grammar for expressions is recursive, so need a way to refer to this parser before
# actually giving its own definition.
ExpressionP = DeferP("ExpressionP")
# SOLVERS: replace this with a parser of jack_ast.ArrayRef
# Note the name discrepancy: the grammar defines `varName` and uses it twice. The AST has `VarRef` and
# `ArrayRef` for the two cases.
VarNameAndArrayIndexP = solved_10.VarNameAndArrayIndexP
# SOLVERS: replace this with a parser of jack_ast.Expression
ExpressionP.set(solved_10.ExpressionP)
#
# Statements:
#
# Tricky: the grammar for statements is recursive, so need a way to refer to this parser before
# actually giving its own definition.
StatementP = DeferP("StatementP")
# SOLVERS: replace this with a parser of jack_ast.DoStatement
DoStatementP = solved_10.DoStatementP
# SOLVERS: replace this with a parser of jack_ast.ReturnStatement
ReturnStatementP = solved_10.ReturnStatementP
# SOLVERS: replace this with a parser of jack_ast.LetStatement
LetStatementP = solved_10.LetStatementP
# SOLVERS: replace this with a parser of jack_ast.IfStatement
IfStatementP = solved_10.IfStatementP
# SOLVERS: replace this with a parser of jack_ast.WhileStatement
WhileStatementP = solved_10.WhileStatementP
StatementP.set(LetStatementP | IfStatementP | WhileStatementP | DoStatementP | ReturnStatementP)
#
# Program Structure:
#
# SOLVERS: replace this with a parser of jack_ast.Type (aka str)
TypeP = solved_10.TypeP
# SOLVERS: replace this with a parser of jack_ast.jack_ast.VarDec
VarDecP = solved_10.VarDecP
# SOLVERS: replace this with a parser of jack_ast.SubroutineDec
SubroutineDecP = solved_10.SubroutineDecP
# SOLVERS: replace this with a parser of jack_ast.ClassVarDec
ClassVarDecP = solved_10.ClassVarDecP
# SOLVERS: replace this with a parser of jack_ast.Class
ClassP = solved_10.ClassP