17 | 17 |
return "%s(%r, %r)" % (self.__class__.__name__, self.ast_node, self.model)
|
18 | 18 |
|
19 | 19 |
|
20 | |
class Parser(object):
|
21 | |
def __init__(self, text, filename):
|
22 | |
self.scanner = Scanner(text, filename)
|
|
20 |
class ParsingContext(object):
|
|
21 |
def __init__(self):
|
23 | 22 |
self.symbols = {} # token -> SymEntry
|
24 | |
self.current_statics = {} # token -> SymEntry
|
|
23 |
self.statics = {} # token -> SymEntry
|
25 | 24 |
self.typedefs = {} # token -> Type AST
|
26 | 25 |
self.consts = {} # token -> Loc
|
|
26 |
|
27 | 27 |
for token in ('a', 'x', 'y'):
|
28 | 28 |
self.symbols[token] = SymEntry(None, LocationRef(TYPE_BYTE, token))
|
29 | 29 |
for token in ('c', 'z', 'n', 'v'):
|
30 | 30 |
self.symbols[token] = SymEntry(None, LocationRef(TYPE_BIT, token))
|
|
31 |
|
|
32 |
def __str__(self):
|
|
33 |
return "Symbols: {}\nStatics: {}\nTypedefs: {}\nConsts: {}".format(self.symbols, self.statics, self.typedefs, self.consts)
|
|
34 |
|
|
35 |
|
|
36 |
class Parser(object):
|
|
37 |
def __init__(self, context, text, filename):
|
|
38 |
self.context = context
|
|
39 |
self.scanner = Scanner(text, filename)
|
31 | 40 |
self.backpatch_instrs = []
|
32 | 41 |
|
33 | 42 |
def syntax_error(self, msg):
|
34 | 43 |
self.scanner.syntax_error(msg)
|
35 | 44 |
|
36 | 45 |
def soft_lookup(self, name):
|
37 | |
if name in self.current_statics:
|
38 | |
return self.current_statics[name].model
|
39 | |
if name in self.symbols:
|
40 | |
return self.symbols[name].model
|
|
46 |
if name in self.context.statics:
|
|
47 |
return self.context.statics[name].model
|
|
48 |
if name in self.context.symbols:
|
|
49 |
return self.context.symbols[name].model
|
41 | 50 |
return None
|
42 | 51 |
|
43 | 52 |
def lookup(self, name):
|
|
57 | 66 |
if self.scanner.on('const'):
|
58 | 67 |
self.defn_const()
|
59 | 68 |
typenames = ['byte', 'word', 'table', 'vector', 'buffer', 'pointer'] # 'routine',
|
60 | |
typenames.extend(self.typedefs.keys())
|
|
69 |
typenames.extend(self.context.typedefs.keys())
|
61 | 70 |
while self.scanner.on(*typenames):
|
62 | 71 |
defn = self.defn()
|
63 | 72 |
name = defn.name
|
64 | |
if name in self.symbols:
|
|
73 |
if name in self.context.symbols:
|
65 | 74 |
self.syntax_error('Symbol "%s" already declared' % name)
|
66 | |
self.symbols[name] = SymEntry(defn, defn.location)
|
|
75 |
self.context.symbols[name] = SymEntry(defn, defn.location)
|
67 | 76 |
defns.append(defn)
|
68 | 77 |
while self.scanner.on('define', 'routine'):
|
69 | 78 |
if self.scanner.consume('define'):
|
|
73 | 82 |
else:
|
74 | 83 |
routine = self.legacy_routine()
|
75 | 84 |
name = routine.name
|
76 | |
if name in self.symbols:
|
|
85 |
if name in self.context.symbols:
|
77 | 86 |
self.syntax_error('Symbol "%s" already declared' % name)
|
78 | |
self.symbols[name] = SymEntry(routine, routine.location)
|
|
87 |
self.context.symbols[name] = SymEntry(routine, routine.location)
|
79 | 88 |
routines.append(routine)
|
80 | 89 |
self.scanner.check_type('EOF')
|
81 | 90 |
|
82 | 91 |
# now backpatch the executable types.
|
83 | |
#for type_name, type_ in self.typedefs.iteritems():
|
|
92 |
#for type_name, type_ in self.context.typedefs.iteritems():
|
84 | 93 |
# type_.backpatch_constraint_labels(lambda w: self.lookup(w))
|
85 | 94 |
for defn in defns:
|
86 | 95 |
defn.location.type.backpatch_constraint_labels(lambda w: self.lookup(w))
|
|
89 | 98 |
for instr in self.backpatch_instrs:
|
90 | 99 |
if instr.opcode in ('call', 'goto'):
|
91 | 100 |
name = instr.location
|
92 | |
if name not in self.symbols:
|
|
101 |
if name not in self.context.symbols:
|
93 | 102 |
self.syntax_error('Undefined routine "%s"' % name)
|
94 | |
if not isinstance(self.symbols[name].model.type, (RoutineType, VectorType)):
|
|
103 |
if not isinstance(self.context.symbols[name].model.type, (RoutineType, VectorType)):
|
95 | 104 |
self.syntax_error('Illegal call of non-executable "%s"' % name)
|
96 | |
instr.location = self.symbols[name].model
|
|
105 |
instr.location = self.context.symbols[name].model
|
97 | 106 |
if instr.opcode in ('copy',) and isinstance(instr.src, basestring):
|
98 | 107 |
name = instr.src
|
99 | |
if name not in self.symbols:
|
|
108 |
if name not in self.context.symbols:
|
100 | 109 |
self.syntax_error('Undefined routine "%s"' % name)
|
101 | |
if not isinstance(self.symbols[name].model.type, (RoutineType, VectorType)):
|
|
110 |
if not isinstance(self.context.symbols[name].model.type, (RoutineType, VectorType)):
|
102 | 111 |
self.syntax_error('Illegal copy of non-executable "%s"' % name)
|
103 | |
instr.src = self.symbols[name].model
|
|
112 |
instr.src = self.context.symbols[name].model
|
104 | 113 |
|
105 | 114 |
return Program(self.scanner.line_number, defns=defns, routines=routines)
|
106 | 115 |
|
|
108 | 117 |
self.scanner.expect('typedef')
|
109 | 118 |
type_ = self.defn_type()
|
110 | 119 |
name = self.defn_name()
|
111 | |
if name in self.typedefs:
|
|
120 |
if name in self.context.typedefs:
|
112 | 121 |
self.syntax_error('Type "%s" already declared' % name)
|
113 | |
self.typedefs[name] = type_
|
|
122 |
self.context.typedefs[name] = type_
|
114 | 123 |
return type_
|
115 | 124 |
|
116 | 125 |
def defn_const(self):
|
117 | 126 |
self.scanner.expect('const')
|
118 | 127 |
name = self.defn_name()
|
119 | |
if name in self.consts:
|
|
128 |
if name in self.context.consts:
|
120 | 129 |
self.syntax_error('Const "%s" already declared' % name)
|
121 | 130 |
loc = self.const()
|
122 | |
self.consts[name] = loc
|
|
131 |
self.context.consts[name] = loc
|
123 | 132 |
return loc
|
124 | 133 |
|
125 | 134 |
def defn(self):
|
|
162 | 171 |
loc = ConstantRef(TYPE_WORD, int(self.scanner.token))
|
163 | 172 |
self.scanner.scan()
|
164 | 173 |
return loc
|
165 | |
elif self.scanner.token in self.consts:
|
166 | |
loc = self.consts[self.scanner.token]
|
|
174 |
elif self.scanner.token in self.context.consts:
|
|
175 |
loc = self.context.consts[self.scanner.token]
|
167 | 176 |
self.scanner.scan()
|
168 | 177 |
return loc
|
169 | 178 |
else:
|
|
214 | 223 |
else:
|
215 | 224 |
type_name = self.scanner.token
|
216 | 225 |
self.scanner.scan()
|
217 | |
if type_name not in self.typedefs:
|
|
226 |
if type_name not in self.context.typedefs:
|
218 | 227 |
self.syntax_error("Undefined type '%s'" % type_name)
|
219 | |
type_ = self.typedefs[type_name]
|
|
228 |
type_ = self.context.typedefs[type_name]
|
220 | 229 |
|
221 | 230 |
return type_
|
222 | 231 |
|
|
272 | 281 |
else:
|
273 | 282 |
statics = self.statics()
|
274 | 283 |
|
275 | |
self.current_statics = self.compose_statics_dict(statics)
|
|
284 |
self.context.statics = self.compose_statics_dict(statics)
|
276 | 285 |
block = self.block()
|
277 | |
self.current_statics = {}
|
|
286 |
self.context.statics = {}
|
278 | 287 |
|
279 | 288 |
addr = None
|
280 | 289 |
location = LocationRef(type_, name)
|
|
288 | 297 |
c = {}
|
289 | 298 |
for defn in statics:
|
290 | 299 |
name = defn.name
|
291 | |
if name in self.symbols or name in self.current_statics:
|
|
300 |
if name in self.context.symbols or name in self.context.statics:
|
292 | 301 |
self.syntax_error('Symbol "%s" already declared' % name)
|
293 | 302 |
c[name] = SymEntry(defn, defn.location)
|
294 | 303 |
return c
|
|
315 | 324 |
return accum
|
316 | 325 |
|
317 | 326 |
def locexpr(self, forward=False):
|
318 | |
if self.scanner.token in ('on', 'off', 'word') or self.scanner.token in self.consts or self.scanner.on_type('integer literal'):
|
|
327 |
if self.scanner.token in ('on', 'off', 'word') or self.scanner.token in self.context.consts or self.scanner.on_type('integer literal'):
|
319 | 328 |
return self.const()
|
320 | 329 |
elif forward:
|
321 | 330 |
name = self.scanner.token
|