diff --git a/src/sixtypical/parser.py b/src/sixtypical/parser.py index 6905280..832885e 100644 --- a/src/sixtypical/parser.py +++ b/src/sixtypical/parser.py @@ -19,6 +19,7 @@ class Parser(object): def __init__(self, text): self.scanner = Scanner(text) self.symbols = {} # token -> SymEntry + self.typedefs = {} # token -> Type AST for token in ('a', 'x', 'y'): self.symbols[token] = SymEntry(None, LocationRef(TYPE_BYTE, token)) for token in ('c', 'z', 'n', 'v'): @@ -35,7 +36,11 @@ class Parser(object): def program(self): defns = [] routines = [] - while self.scanner.on('byte', 'word', 'table', 'vector', 'buffer', 'pointer'): # 'routine', + while self.scanner.on('typedef'): + typedef = self.typedef() + typenames = ['byte', 'word', 'table', 'vector', 'buffer', 'pointer'] # 'routine', + typenames.extend(self.typedefs.keys()) + while self.scanner.on(*typenames): defn = self.defn() name = defn.name if name in self.symbols: @@ -78,6 +83,15 @@ class Parser(object): return Program(defns=defns, routines=routines) + def typedef(self): + self.scanner.expect('typedef') + type_ = self.defn_type() + name = self.defn_name() + if name in self.typedefs: + raise SyntaxError('Type "%s" already declared' % name) + self.typedefs[name] = type_ + return type_ + def defn(self): type_ = self.defn_type() name = self.defn_name() @@ -131,9 +145,14 @@ class Parser(object): elif self.scanner.consume('buffer'): size = self.defn_size() return BufferType(size) - else: - self.scanner.expect('pointer') + elif self.scanner.consume('pointer'): return PointerType() + else: + type_name = self.scanner.token + self.scanner.scan() + if type_name not in self.typedefs: + raise SyntaxError("Undefined type '%s'" % type_name) + return self.typedefs[type_name] def defn_name(self): self.scanner.check_type('identifier') diff --git a/tests/SixtyPical Syntax.md b/tests/SixtyPical Syntax.md index 256d510..1410942 100644 --- a/tests/SixtyPical Syntax.md +++ b/tests/SixtyPical Syntax.md @@ -153,6 +153,26 @@ Tables of different types. | } = ok +Typedefs of different types. + + | typedef byte octet + | typedef table[256] octet twokay + | typedef routine trashes a game_routine + | vector game_routine start_game + | + | routine main { + | } + = ok + +Can't have two typedefs with the same name. + + | typedef byte frank + | typedef word frank + | + | routine main { + | } + ? SyntaxError + Explicit memory address. | byte screen @ 1024