1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2024-05-31 21:41:29 +00:00

Parse byte table declarations and indexing modifiers.

This commit is contained in:
Chris Pressey 2015-10-18 17:40:53 +01:00
parent 41432b5cb3
commit 4287bf81c1
3 changed files with 35 additions and 12 deletions

View File

@ -1,7 +1,7 @@
SixtyPical
==========
This document describes the SixtyPical programming language version 0.4,
This document describes the SixtyPical programming language version 0.5-PRE,
both its execution aspect and its static analysis aspect (even though
these are, technically speaking, separate concepts.)
@ -325,7 +325,7 @@ Grammar
-------
Program ::= {Defn} {Routine}.
Defn ::= "byte" NewIdent.
Defn ::= "byte" ["table"] NewIdent ["@" WordConst].
Routine ::= "routine" NewIdent
["inputs" LocExprs] ["outputs" LocExprs] ["trashes" LocExprs]
(Block | "@" WordConst).
@ -336,8 +336,8 @@ Grammar
LitByte ::= "0" ... "255".
LitWord ::= "0" ... "65535".
Block ::= "{" {Instr} "}".
Instr ::= "ld" LocExpr "," LocExpr
| "st" LocExpr "," LocExpr
Instr ::= "ld" LocExpr "," LocExpr ["+" LocExpr]
| "st" LocExpr "," LocExpr ["+" LocExpr]
| "add" LocExpr "," LocExpr
| "sub" LocExpr "," LocExpr
| "cmp" LocExpr "," LocExpr

View File

@ -4,7 +4,8 @@ import re
from sixtypical.ast import Program, Defn, Routine, Block, Instr
from sixtypical.model import (
TYPE_BIT, TYPE_BYTE, LocationRef, ConstantRef
TYPE_BIT, TYPE_BYTE, TYPE_BYTE_TABLE,
LocationRef, ConstantRef
)
@ -32,7 +33,7 @@ class Scanner(object):
self.token = None
self.type = 'EOF'
return
if self.scan_pattern(r'\,|\@|\{|\}', 'operator'):
if self.scan_pattern(r'\,|\@|\+|\{|\}', 'operator'):
return
if self.scan_pattern(r'\d+', 'integer literal'):
return
@ -99,8 +100,8 @@ class Parser(object):
defn = self.defn()
name = defn.name
if name in self.symbols:
raise SyntaxError(name)
self.symbols[name] = SymEntry(defn, LocationRef(TYPE_BYTE, name))
raise SyntaxError('Symbol "%s" already declared' % name)
self.symbols[name] = SymEntry(defn, LocationRef(defn.type, name))
defns.append(defn)
while self.scanner.on('routine'):
routine = self.routine()
@ -113,7 +114,11 @@ class Parser(object):
return Program(defns=defns, routines=routines)
def defn(self):
type = TYPE_BYTE
self.scanner.expect('byte')
if self.scanner.consume('table'):
type = TYPE_BYTE_TABLE
self.scanner.check_type('identifier')
name = self.scanner.token
self.scanner.scan()
addr = None
@ -121,7 +126,7 @@ class Parser(object):
self.scanner.check_type('integer literal')
addr = int(self.scanner.token)
self.scanner.scan()
return Defn(name=name, addr=addr)
return Defn(name=name, type=type, addr=addr)
def routine(self):
self.scanner.expect('routine')
@ -208,14 +213,20 @@ class Parser(object):
dest = self.locexpr()
self.scanner.expect(',')
src = self.locexpr()
return Instr(opcode=opcode, dest=dest, src=src)
index = None
if self.scanner.consume('+'):
index = self.locexpr()
return Instr(opcode=opcode, dest=dest, src=src, index=index)
elif self.scanner.token in ("st",):
opcode = self.scanner.token
self.scanner.scan()
src = self.locexpr()
self.scanner.expect(',')
dest = self.locexpr()
return Instr(opcode=opcode, dest=dest, src=src)
index = None
if self.scanner.consume('+'):
index = self.locexpr()
return Instr(opcode=opcode, dest=dest, src=src, index=index)
elif self.scanner.token in ("shl", "shr", "inc", "dec"):
opcode = self.scanner.token
self.scanner.scan()
@ -229,4 +240,4 @@ class Parser(object):
# TODO: check that is has been defined
return Instr(opcode=opcode, name=name, dest=None, src=None)
else:
raise ValueError('bad opcode')
raise ValueError('bad opcode "%s"' % self.scanner.token)

View File

@ -166,3 +166,15 @@ Can't define two routines with the same name.
| ld y, 1
| }
? SyntaxError
Declaring a byte table memory location.
| byte table tab
|
| routine main {
| ld x, 0
| ld y, 0
| ld a, tab + x
| st a, tab + y
| }
= ok