Skoraj koncano, manjka generiranje obj kode
This commit is contained in:
parent
d50c62106e
commit
4b2a7a3cc2
47 changed files with 1034 additions and 0 deletions
0
ass3/zbirnik/README.md
Normal file
0
ass3/zbirnik/README.md
Normal file
18
ass3/zbirnik/poetry.lock
generated
Normal file
18
ass3/zbirnik/poetry.lock
generated
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "ply"
|
||||
version = "3.11"
|
||||
description = "Python Lex & Yacc"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "ply-3.11-py2.py3-none-any.whl", hash = "sha256:096f9b8350b65ebd2fd1346b12452efe5b9607f7482813ffca50c22722a807ce"},
|
||||
{file = "ply-3.11.tar.gz", hash = "sha256:00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3"},
|
||||
]
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.1"
|
||||
python-versions = ">=3.10"
|
||||
content-hash = "aeee2cd18440094d85604201949f31ea16b086488be3992891c1777b5c89b058"
|
||||
21
ass3/zbirnik/pyproject.toml
Normal file
21
ass3/zbirnik/pyproject.toml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
[project]
|
||||
name = "zbirnik"
|
||||
version = "0.1.0"
|
||||
description = ""
|
||||
authors = [
|
||||
{ name = "Timon", email = "timonbub@gmail.com" }
|
||||
]
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
dependencies = [
|
||||
"ply>=3.11,<4.0"
|
||||
]
|
||||
|
||||
[tool.poetry]
|
||||
packages = [
|
||||
{ include = "zbirnik", from = "src" }
|
||||
]
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
6
ass3/zbirnik/src/zbirnik/EmitCtx.py
Normal file
6
ass3/zbirnik/src/zbirnik/EmitCtx.py
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
class EmitContext:
|
||||
def __init__(self, opcodes, registers, symtab):
|
||||
self.opcodes = opcodes
|
||||
self.registers = registers
|
||||
self.symtab = symtab
|
||||
self.base = None
|
||||
0
ass3/zbirnik/src/zbirnik/__init__.py
Normal file
0
ass3/zbirnik/src/zbirnik/__init__.py
Normal file
BIN
ass3/zbirnik/src/zbirnik/__pycache__/EmitCtx.cpython-310.pyc
Normal file
BIN
ass3/zbirnik/src/zbirnik/__pycache__/EmitCtx.cpython-310.pyc
Normal file
Binary file not shown.
BIN
ass3/zbirnik/src/zbirnik/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
ass3/zbirnik/src/zbirnik/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
BIN
ass3/zbirnik/src/zbirnik/__pycache__/adressing.cpython-310.pyc
Normal file
BIN
ass3/zbirnik/src/zbirnik/__pycache__/adressing.cpython-310.pyc
Normal file
Binary file not shown.
7
ass3/zbirnik/src/zbirnik/adressing.py
Normal file
7
ass3/zbirnik/src/zbirnik/adressing.py
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# addressing.py
|
||||
from enum import Enum, auto
|
||||
|
||||
class AddrMode(Enum):
|
||||
SIMPLE = auto()
|
||||
IMMEDIATE = auto()
|
||||
INDIRECT = auto()
|
||||
62
ass3/zbirnik/src/zbirnik/code.py
Normal file
62
ass3/zbirnik/src/zbirnik/code.py
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
from zbirnik.ukazi.node import Node
|
||||
|
||||
class Code:
|
||||
|
||||
REGISTERS = {'A': 0, 'X': 1, 'L': 2, 'B': 3, 'S': 4, 'T': 5, 'F': 6 }
|
||||
|
||||
def __init__(self, name: str | None = None):
|
||||
self.name = name
|
||||
self.nodes = []
|
||||
self.locctr = 0
|
||||
self.symtab = {}
|
||||
self.start_adress = 0
|
||||
self.entry_point = 0
|
||||
self.program_length = 0
|
||||
self.obj = ""
|
||||
|
||||
def add(self, node: Node):
|
||||
self.nodes.append(node)
|
||||
|
||||
def pass1(self):
|
||||
locctr = 0
|
||||
self.start_address = 0
|
||||
self.entry_point = None
|
||||
|
||||
for node in self.nodes:
|
||||
|
||||
# START
|
||||
if node.__class__.__name__ == "directive" and node.name == "START":
|
||||
self.start_address = node.value
|
||||
locctr = self.start_address
|
||||
self.name = node.label
|
||||
node.address = locctr
|
||||
continue
|
||||
|
||||
# naslov node-a
|
||||
node.address = locctr
|
||||
|
||||
# label → SYMTAB
|
||||
if node.label:
|
||||
if node.label in self.symtab:
|
||||
raise ValueError(f"Duplicate symbol: {node.label}")
|
||||
self.symtab[node.label] = locctr
|
||||
|
||||
# END
|
||||
if node.__class__.__name__ == "directive" and node.name == "END":
|
||||
if node.value is not None:
|
||||
self.entry_point = node.value
|
||||
break
|
||||
|
||||
locctr += node.size()
|
||||
|
||||
self.locctr = locctr
|
||||
self.program_length = locctr - self.start_address
|
||||
|
||||
def pass2(self, ctx):
|
||||
output = bytearray()
|
||||
for node in self.nodes:
|
||||
chunk = node.emit(ctx)
|
||||
if chunk:
|
||||
output.extend(chunk)
|
||||
|
||||
return bytes(output)
|
||||
0
ass3/zbirnik/src/zbirnik/mnemoniki/__init__.py
Normal file
0
ass3/zbirnik/src/zbirnik/mnemoniki/__init__.py
Normal file
11
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonic.py
Normal file
11
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonic.py
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
from abc import ABC, abstractmethod
|
||||
|
||||
class Mnemonic(ABC):
|
||||
def __init__(self, name: str, opcode: int | None = None, description: str = ""):
|
||||
self.name = name
|
||||
self.opcode = opcode
|
||||
self.description = description
|
||||
|
||||
@abstractmethod
|
||||
def parse(self, parser):
|
||||
pass
|
||||
8
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicD.py
Normal file
8
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicD.py
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
from zbirnik.ukazi.directive import directive
|
||||
from mnemonic import Mnemonic
|
||||
from zbirnik.parserctx import ParserContext
|
||||
|
||||
class MnemonicD(Mnemonic):
|
||||
def parse(self, parser: ParserContext):
|
||||
return directive(direktiva=self.name, label=parser.label,
|
||||
operand=None)
|
||||
8
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicDn.py
Normal file
8
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicDn.py
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
from zbirnik.ukazi.directive import directive
|
||||
from mnemonic import Mnemonic
|
||||
from zbirnik.parserctx import ParserContext
|
||||
|
||||
class MnemonicDn(Mnemonic):
|
||||
def parse(self, parser: ParserContext):
|
||||
return directive(direktiva=self.name, label=parser.label,
|
||||
operand=parser.read_num_sym())
|
||||
6
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicF1.py
Normal file
6
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicF1.py
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
from mnemonic import Mnemonic
|
||||
from zbirnik.ukazi.f1 import f1
|
||||
|
||||
class MnemonicF1(Mnemonic):
|
||||
def parse(self, parser):
|
||||
return f1(label=parser.label, mnemonic=self.name)
|
||||
9
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicF2.py
Normal file
9
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicF2.py
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
from zbirnik.mnemoniki.mnemonic import Mnemonic
|
||||
from zbirnik.ukazi.f2 import f2
|
||||
from zbirnik.parserctx import ParserContext
|
||||
|
||||
|
||||
class mnemonicF2(Mnemonic):
|
||||
def parse(self, parser: ParserContext):
|
||||
return f2(r1=parser.read_reg(), r2=parser.read_reg(),
|
||||
mnemonic=self.name, label=parser.label)
|
||||
8
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicF2n.py
Normal file
8
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicF2n.py
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
from zbirnik.mnemoniki.mnemonic import Mnemonic
|
||||
from zbirnik.ukazi.f2 import f2
|
||||
from zbirnik.parserctx import ParserContext
|
||||
|
||||
class MnemonicF2n(Mnemonic):
|
||||
def parse(self, parser: ParserContext):
|
||||
return f2(r1=parser.read_reg(), r2 = None,
|
||||
mnemonic=self.name, label=parser.label)
|
||||
9
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicF2r.py
Normal file
9
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicF2r.py
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
from zbirnik.mnemoniki.mnemonic import Mnemonic
|
||||
from zbirnik.ukazi.f2 import f2
|
||||
from zbirnik.parserctx import ParserContext
|
||||
|
||||
|
||||
class MnemonicF2r(Mnemonic):
|
||||
def parse(self, parser: ParserContext):
|
||||
return f2(r1=parser.read_reg(), r2=None,
|
||||
mnemonic=self.name, label=parser.label)
|
||||
8
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicF2rn.py
Normal file
8
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicF2rn.py
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
from zbirnik.mnemoniki.mnemonic import Mnemonic
|
||||
from zbirnik.ukazi.f2 import f2
|
||||
from zbirnik.parserctx import ParserContext
|
||||
|
||||
class MnemonicF2rn(Mnemonic):
|
||||
def parse(self, parser: ParserContext):
|
||||
return f2(r1=parser.read_reg(), r2=parser.read_num_sym()-1,
|
||||
mnemonic=self.name, label=parser.label)
|
||||
9
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicF2rr.py
Normal file
9
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicF2rr.py
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
from zbirnik.mnemoniki.mnemonic import Mnemonic
|
||||
from zbirnik.ukazi.f2 import f2
|
||||
from zbirnik.parserctx import ParserContext
|
||||
|
||||
|
||||
class MnemonicF2rr(Mnemonic):
|
||||
def parse(self, parser: ParserContext):
|
||||
return f2(r1=parser.read_reg(), r2=parser.read_reg(),
|
||||
mnemonic=self.name, label=parser.label)
|
||||
8
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicF3.py
Normal file
8
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicF3.py
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
from zbirnik.mnemoniki.mnemonic import Mnemonic
|
||||
from zbirnik.ukazi.f3 import f3
|
||||
from zbirnik.parserctx import ParserContext
|
||||
|
||||
class MnemonicF3(Mnemonic):
|
||||
def parse(self, parser: ParserContext):
|
||||
return f3(operand=None, adr_mode=None, index=None,
|
||||
mnemonic=self.name, label=parser.label)
|
||||
9
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicF3m.py
Normal file
9
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicF3m.py
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
from zbirnik.mnemoniki.mnemonic import Mnemonic
|
||||
from zbirnik.ukazi.f3 import f3
|
||||
from zbirnik.parserctx import ParserContext
|
||||
|
||||
class MnemonicF3m(Mnemonic):
|
||||
def parse(self, parser: ParserContext):
|
||||
addr_mode, value, indexed = parser.read_addressed_operand()
|
||||
return f3(operand=value, mnemonic=self.name, label=parser.label,
|
||||
adr_mode=addr_mode, index=indexed)
|
||||
10
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicF4m.py
Normal file
10
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicF4m.py
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
from zbirnik.mnemoniki.mnemonic import Mnemonic
|
||||
from zbirnik.ukazi.f4 import f4
|
||||
from zbirnik.parserctx import ParserContext
|
||||
|
||||
class MnemonicF4m(Mnemonic):
|
||||
def parse(self, parser: ParserContext):
|
||||
addr_mode, value, indexed = parser.read_addressed_operand()
|
||||
return f4(operand=value, mnemonic=self.name, label=parser.label,
|
||||
adr_mode=addr_mode, index=indexed)
|
||||
|
||||
7
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicSd.py
Normal file
7
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicSd.py
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
from zbirnik.mnemoniki.mnemonic import Mnemonic
|
||||
from zbirnik.ukazi.storage import storage
|
||||
from zbirnik.parserctx import ParserContext
|
||||
|
||||
class MnemonicSd(Mnemonic):
|
||||
def parse(self, parser: ParserContext):
|
||||
return storage(label=parser.label, name=self.name, val=parser.read_num_sym())
|
||||
8
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicSn.py
Normal file
8
ass3/zbirnik/src/zbirnik/mnemoniki/mnemonicSn.py
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
from zbirnik.mnemoniki.mnemonic import Mnemonic
|
||||
from zbirnik.ukazi.storage import storage
|
||||
from zbirnik.parserctx import ParserContext
|
||||
|
||||
|
||||
class MnemonicSn(Mnemonic):
|
||||
def parse(self, parser: ParserContext):
|
||||
return storage(label=parser.label, name=self.name, val=parser.read_num_sym())
|
||||
70
ass3/zbirnik/src/zbirnik/mnemoniki/mnemoniki_tabela.py
Normal file
70
ass3/zbirnik/src/zbirnik/mnemoniki/mnemoniki_tabela.py
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
from mnemoniki import (
|
||||
mnemonicD, mnemonicDn,
|
||||
mnemonicF1, mnemonicF2n, mnemonicF2r, mnemonicF2rn, mnemonicF2rr,
|
||||
mnemonicF3, mnemonicF3m, mnemonicF4m,
|
||||
mnemonicSd, mnemonicSn
|
||||
)
|
||||
|
||||
# Centralna tabela mnemonikov
|
||||
MNEMONICS = {
|
||||
# Direktive (brez operandov)
|
||||
'NOBASE': mnemonicD('NOBASE'),
|
||||
'LTORG': mnemonicD('LTORG'),
|
||||
# Direktive (en operand)
|
||||
'START': mnemonicDn('START'),
|
||||
'END': mnemonicDn('END'),
|
||||
'BASE': mnemonicDn('BASE'),
|
||||
# Format 1 (brez operandov)
|
||||
'FIX': mnemonicF1('FIX', opcode=0xC4),
|
||||
'FLOAT': mnemonicF1('FLOAT', opcode=0xC0),
|
||||
'HIO': mnemonicF1('HIO', opcode=0xF4),
|
||||
'NORM': mnemonicF1('NORM', opcode=0xC8),
|
||||
'SIO': mnemonicF1('SIO', opcode=0xF0),
|
||||
'TIO': mnemonicF1('TIO', opcode=0xF8),
|
||||
# Format 2
|
||||
# F2 – en številčni operand
|
||||
'SVC': mnemonicF2n('SVC', opcode=0xB0),
|
||||
# F2 – en register
|
||||
'CLEAR': mnemonicF2r('CLEAR', opcode=0xB4),
|
||||
'TIXR': mnemonicF2r('TIXR', opcode=0xB8),
|
||||
# F2 – register + število
|
||||
'SHIFTL': mnemonicF2rn('SHIFTL', opcode=0xA4),
|
||||
'SHIFTR': mnemonicF2rn('SHIFTR', opcode=0xA8),
|
||||
# F2 – dva registra
|
||||
'ADDR': mnemonicF2rr('ADDR', opcode=0x90),
|
||||
'SUBR': mnemonicF2rr('SUBR', opcode=0x94),
|
||||
'MULR': mnemonicF2rr('MULR', opcode=0x98),
|
||||
'DIVR': mnemonicF2rr('DIVR', opcode=0x9C),
|
||||
'COMPR': mnemonicF2rr('COMPR', opcode=0xA0),
|
||||
# Format 3
|
||||
'RSUB': mnemonicF3('RSUB', opcode=0x4C),
|
||||
'LDA': mnemonicF3m('LDA', opcode=0x00),
|
||||
'LDX': mnemonicF3m('LDX', opcode=0x04),
|
||||
'LDL': mnemonicF3m('LDL', opcode=0x08),
|
||||
'STA': mnemonicF3m('STA', opcode=0x0C),
|
||||
'STX': mnemonicF3m('STX', opcode=0x10),
|
||||
'STL': mnemonicF3m('STL', opcode=0x14),
|
||||
'ADD': mnemonicF3m('ADD', opcode=0x18),
|
||||
'SUB': mnemonicF3m('SUB', opcode=0x1C),
|
||||
'MUL': mnemonicF3m('MUL', opcode=0x20),
|
||||
'DIV': mnemonicF3m('DIV', opcode=0x24),
|
||||
'COMP': mnemonicF3m('COMP', opcode=0x28),
|
||||
'J': mnemonicF3m('J', opcode=0x3C),
|
||||
'JEQ': mnemonicF3m('JEQ', opcode=0x30),
|
||||
'JGT': mnemonicF3m('JGT', opcode=0x34),
|
||||
'JLT': mnemonicF3m('JLT', opcode=0x38),
|
||||
'JSUB': mnemonicF3m('JSUB', opcode=0x48),
|
||||
'TD': mnemonicF3m('TD', opcode=0xE0),
|
||||
'RD': mnemonicF3m('RD', opcode=0xD8),
|
||||
'WD': mnemonicF3m('WD', opcode=0xDC),
|
||||
# Format 4 (razširjeni)
|
||||
'+LDA': mnemonicF4m('+LDA', opcode=0x00),
|
||||
'+JSUB': mnemonicF4m('+JSUB', opcode=0x48),
|
||||
# Pomnilniške direktive
|
||||
# podatki
|
||||
'BYTE': mnemonicSd('BYTE'),
|
||||
'WORD': mnemonicSd('WORD'),
|
||||
# rezervacija
|
||||
'RESB': mnemonicSn('RESB'),
|
||||
'RESW': mnemonicSn('RESW'),
|
||||
}
|
||||
219
ass3/zbirnik/src/zbirnik/parser.out
Normal file
219
ass3/zbirnik/src/zbirnik/parser.out
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
Created by PLY version 3.11 (http://www.dabeaz.com/ply)
|
||||
|
||||
Grammar
|
||||
|
||||
Rule 0 S' -> start
|
||||
Rule 1 start -> LABEL command
|
||||
Rule 2 start -> command
|
||||
Rule 3 command -> MNEMONIC
|
||||
Rule 4 command -> MNEMONIC args
|
||||
Rule 5 args -> operand
|
||||
Rule 6 args -> operand COMMA operand
|
||||
Rule 7 operand -> REGISTER
|
||||
Rule 8 operand -> AT address
|
||||
Rule 9 operand -> HASH address
|
||||
Rule 10 operand -> address
|
||||
Rule 11 address -> NUMBER
|
||||
Rule 12 address -> SYMBOL
|
||||
|
||||
Terminals, with rules where they appear
|
||||
|
||||
AT : 8
|
||||
COMMA : 6
|
||||
HASH : 9
|
||||
LABEL : 1
|
||||
MNEMONIC : 3 4
|
||||
NUMBER : 11
|
||||
REGISTER : 7
|
||||
SYMBOL : 12
|
||||
error :
|
||||
|
||||
Nonterminals, with rules where they appear
|
||||
|
||||
address : 8 9 10
|
||||
args : 4
|
||||
command : 1 2
|
||||
operand : 5 6 6
|
||||
start : 0
|
||||
|
||||
Parsing method: LALR
|
||||
|
||||
state 0
|
||||
|
||||
(0) S' -> . start
|
||||
(1) start -> . LABEL command
|
||||
(2) start -> . command
|
||||
(3) command -> . MNEMONIC
|
||||
(4) command -> . MNEMONIC args
|
||||
|
||||
LABEL shift and go to state 2
|
||||
MNEMONIC shift and go to state 4
|
||||
|
||||
start shift and go to state 1
|
||||
command shift and go to state 3
|
||||
|
||||
state 1
|
||||
|
||||
(0) S' -> start .
|
||||
|
||||
|
||||
|
||||
state 2
|
||||
|
||||
(1) start -> LABEL . command
|
||||
(3) command -> . MNEMONIC
|
||||
(4) command -> . MNEMONIC args
|
||||
|
||||
MNEMONIC shift and go to state 4
|
||||
|
||||
command shift and go to state 5
|
||||
|
||||
state 3
|
||||
|
||||
(2) start -> command .
|
||||
|
||||
$end reduce using rule 2 (start -> command .)
|
||||
|
||||
|
||||
state 4
|
||||
|
||||
(3) command -> MNEMONIC .
|
||||
(4) command -> MNEMONIC . args
|
||||
(5) args -> . operand
|
||||
(6) args -> . operand COMMA operand
|
||||
(7) operand -> . REGISTER
|
||||
(8) operand -> . AT address
|
||||
(9) operand -> . HASH address
|
||||
(10) operand -> . address
|
||||
(11) address -> . NUMBER
|
||||
(12) address -> . SYMBOL
|
||||
|
||||
$end reduce using rule 3 (command -> MNEMONIC .)
|
||||
REGISTER shift and go to state 8
|
||||
AT shift and go to state 9
|
||||
HASH shift and go to state 11
|
||||
NUMBER shift and go to state 12
|
||||
SYMBOL shift and go to state 13
|
||||
|
||||
args shift and go to state 6
|
||||
operand shift and go to state 7
|
||||
address shift and go to state 10
|
||||
|
||||
state 5
|
||||
|
||||
(1) start -> LABEL command .
|
||||
|
||||
$end reduce using rule 1 (start -> LABEL command .)
|
||||
|
||||
|
||||
state 6
|
||||
|
||||
(4) command -> MNEMONIC args .
|
||||
|
||||
$end reduce using rule 4 (command -> MNEMONIC args .)
|
||||
|
||||
|
||||
state 7
|
||||
|
||||
(5) args -> operand .
|
||||
(6) args -> operand . COMMA operand
|
||||
|
||||
$end reduce using rule 5 (args -> operand .)
|
||||
COMMA shift and go to state 14
|
||||
|
||||
|
||||
state 8
|
||||
|
||||
(7) operand -> REGISTER .
|
||||
|
||||
COMMA reduce using rule 7 (operand -> REGISTER .)
|
||||
$end reduce using rule 7 (operand -> REGISTER .)
|
||||
|
||||
|
||||
state 9
|
||||
|
||||
(8) operand -> AT . address
|
||||
(11) address -> . NUMBER
|
||||
(12) address -> . SYMBOL
|
||||
|
||||
NUMBER shift and go to state 12
|
||||
SYMBOL shift and go to state 13
|
||||
|
||||
address shift and go to state 15
|
||||
|
||||
state 10
|
||||
|
||||
(10) operand -> address .
|
||||
|
||||
COMMA reduce using rule 10 (operand -> address .)
|
||||
$end reduce using rule 10 (operand -> address .)
|
||||
|
||||
|
||||
state 11
|
||||
|
||||
(9) operand -> HASH . address
|
||||
(11) address -> . NUMBER
|
||||
(12) address -> . SYMBOL
|
||||
|
||||
NUMBER shift and go to state 12
|
||||
SYMBOL shift and go to state 13
|
||||
|
||||
address shift and go to state 16
|
||||
|
||||
state 12
|
||||
|
||||
(11) address -> NUMBER .
|
||||
|
||||
COMMA reduce using rule 11 (address -> NUMBER .)
|
||||
$end reduce using rule 11 (address -> NUMBER .)
|
||||
|
||||
|
||||
state 13
|
||||
|
||||
(12) address -> SYMBOL .
|
||||
|
||||
COMMA reduce using rule 12 (address -> SYMBOL .)
|
||||
$end reduce using rule 12 (address -> SYMBOL .)
|
||||
|
||||
|
||||
state 14
|
||||
|
||||
(6) args -> operand COMMA . operand
|
||||
(7) operand -> . REGISTER
|
||||
(8) operand -> . AT address
|
||||
(9) operand -> . HASH address
|
||||
(10) operand -> . address
|
||||
(11) address -> . NUMBER
|
||||
(12) address -> . SYMBOL
|
||||
|
||||
REGISTER shift and go to state 8
|
||||
AT shift and go to state 9
|
||||
HASH shift and go to state 11
|
||||
NUMBER shift and go to state 12
|
||||
SYMBOL shift and go to state 13
|
||||
|
||||
operand shift and go to state 17
|
||||
address shift and go to state 10
|
||||
|
||||
state 15
|
||||
|
||||
(8) operand -> AT address .
|
||||
|
||||
COMMA reduce using rule 8 (operand -> AT address .)
|
||||
$end reduce using rule 8 (operand -> AT address .)
|
||||
|
||||
|
||||
state 16
|
||||
|
||||
(9) operand -> HASH address .
|
||||
|
||||
COMMA reduce using rule 9 (operand -> HASH address .)
|
||||
$end reduce using rule 9 (operand -> HASH address .)
|
||||
|
||||
|
||||
state 17
|
||||
|
||||
(6) args -> operand COMMA operand .
|
||||
|
||||
$end reduce using rule 6 (args -> operand COMMA operand .)
|
||||
|
||||
92
ass3/zbirnik/src/zbirnik/parser.py
Normal file
92
ass3/zbirnik/src/zbirnik/parser.py
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
import ply.lex
|
||||
import ply.yacc
|
||||
import sys
|
||||
|
||||
# Lexer.
|
||||
tokens = (
|
||||
'AT',
|
||||
'COMMA',
|
||||
'HASH',
|
||||
'LABEL',
|
||||
'REGISTER',
|
||||
'MNEMONIC',
|
||||
'SYMBOL',
|
||||
'NUMBER',
|
||||
'COMMENT',
|
||||
)
|
||||
|
||||
t_AT = r'@'
|
||||
t_COMMA = r','
|
||||
t_HASH = r'\#'
|
||||
t_LABEL = r'^[a-z_0-9]+'
|
||||
t_REGISTER = r'\b[ABFLSTX]\b'
|
||||
t_MNEMONIC = r'\b[A-Z]+\b'
|
||||
t_SYMBOL = r'[a-z_0-9]+'
|
||||
|
||||
def t_NUMBER(t):
|
||||
r'-?\d+'
|
||||
t.value = int(t.value)
|
||||
return t
|
||||
|
||||
def t_COMMENT(t):
|
||||
r'\..*'
|
||||
t.value = t.value[1:].strip()
|
||||
return t
|
||||
|
||||
t_ignore = ' \t\n'
|
||||
|
||||
def t_error(t):
|
||||
print(f'illegal character {t}')
|
||||
t.lexer.skip(1)
|
||||
|
||||
lexer = ply.lex.lex()
|
||||
|
||||
# Parser.
|
||||
def p_start(p):
|
||||
r'''start : LABEL command
|
||||
| COMMENT
|
||||
| command'''
|
||||
if len(p) == 2:
|
||||
if isinstance(p[1], str):
|
||||
p[0] = ('COMMENT', p[1])
|
||||
else:
|
||||
p[0] = (None, p[1])
|
||||
else:
|
||||
p[0] = tuple(p[1:])
|
||||
|
||||
def p_command(p):
|
||||
r'''command : MNEMONIC
|
||||
| MNEMONIC args'''
|
||||
p[0] = p[1:]
|
||||
|
||||
def p_args(p):
|
||||
r'''args : operand
|
||||
| operand COMMA operand'''
|
||||
match len(p):
|
||||
case 2: p[0] = (p[1],)
|
||||
case 4: p[0] = (p[1], p[3])
|
||||
|
||||
def p_operand(p):
|
||||
r'''operand : REGISTER
|
||||
| AT address
|
||||
| HASH address
|
||||
| address'''
|
||||
p[0] = p[1:]
|
||||
|
||||
def p_address(p):
|
||||
r'''address : NUMBER
|
||||
| SYMBOL'''
|
||||
p[0] = p[1]
|
||||
|
||||
def p_error(p):
|
||||
if p:
|
||||
print('Syntax error at token', p)
|
||||
parser.errok()
|
||||
else:
|
||||
print('Syntax error at EOF')
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
parser = ply.yacc.yacc()
|
||||
for line in sys.stdin:
|
||||
print(parser.parse(line))
|
||||
62
ass3/zbirnik/src/zbirnik/parserctx.py
Normal file
62
ass3/zbirnik/src/zbirnik/parserctx.py
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
class ParserContext:
|
||||
|
||||
def __init__(self, parsed):
|
||||
"""
|
||||
parsed je rezultat PLY parserja, npr.:
|
||||
('loop', ('LDA', (('#', 5),)))
|
||||
(None, ('FIX',))
|
||||
('COMMENT', 'to je komentar')
|
||||
"""
|
||||
if isinstance(parsed, tuple) and parsed[0] == 'COMMENT':
|
||||
self.label = None
|
||||
self.mnemonic = 'COMMENT'
|
||||
self.operands = []
|
||||
self.comment = parsed[1]
|
||||
return
|
||||
|
||||
self.label, command = parsed
|
||||
self.mnemonic = command[0]
|
||||
self.operands = list(command[1]) if len(command) > 1 else []
|
||||
self.comment = None
|
||||
|
||||
def has_operand(self) -> bool:
|
||||
return len(self.operands) > 0
|
||||
|
||||
def next_op(self):
|
||||
if not self.operands:
|
||||
raise ValueError("Manjka operand")
|
||||
return self.operands.pop(0)
|
||||
|
||||
def read_reg(self) -> str:
|
||||
op = self.next_op()
|
||||
return op[0]
|
||||
|
||||
def read_num_sym(self):
|
||||
op = self.next_op()
|
||||
if (len(op) == 1):
|
||||
return op[0]
|
||||
return op[1]
|
||||
|
||||
def read_addressed_operand(self):
|
||||
|
||||
from adressing import AddrMode
|
||||
|
||||
indexed = False
|
||||
addr_mode = AddrMode.SIMPLE
|
||||
|
||||
op = self.next_operand()
|
||||
|
||||
# immediate / indirect
|
||||
if len(op) == 2:
|
||||
prefix, value = op
|
||||
addr_mode = {'#': AddrMode.IMMEDIATE, '@': AddrMode.INDIRECT}[prefix]
|
||||
else:
|
||||
value = op[0]
|
||||
|
||||
#indeksiranje
|
||||
if self.operands and self.operands[0] == ('X',):
|
||||
self.operands.pop(0)
|
||||
indexed = True
|
||||
|
||||
return addr_mode, value, indexed
|
||||
|
||||
42
ass3/zbirnik/src/zbirnik/parsetab.py
Normal file
42
ass3/zbirnik/src/zbirnik/parsetab.py
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
|
||||
# parsetab.py
|
||||
# This file is automatically generated. Do not edit.
|
||||
# pylint: disable=W,C,R
|
||||
_tabversion = '3.10'
|
||||
|
||||
_lr_method = 'LALR'
|
||||
|
||||
_lr_signature = 'AT COMMA HASH LABEL MNEMONIC NUMBER REGISTER SYMBOLstart : LABEL command\n | commandcommand : MNEMONIC\n | MNEMONIC argsargs : operand\n | operand COMMA operandoperand : REGISTER\n | AT address\n | HASH address\n | addressaddress : NUMBER\n | SYMBOL'
|
||||
|
||||
_lr_action_items = {'LABEL':([0,],[2,]),'MNEMONIC':([0,2,],[4,4,]),'$end':([1,3,4,5,6,7,8,10,12,13,15,16,17,],[0,-2,-3,-1,-4,-5,-7,-10,-11,-12,-8,-9,-6,]),'REGISTER':([4,14,],[8,8,]),'AT':([4,14,],[9,9,]),'HASH':([4,14,],[11,11,]),'NUMBER':([4,9,11,14,],[12,12,12,12,]),'SYMBOL':([4,9,11,14,],[13,13,13,13,]),'COMMA':([7,8,10,12,13,15,16,],[14,-7,-10,-11,-12,-8,-9,]),}
|
||||
|
||||
_lr_action = {}
|
||||
for _k, _v in _lr_action_items.items():
|
||||
for _x,_y in zip(_v[0],_v[1]):
|
||||
if not _x in _lr_action: _lr_action[_x] = {}
|
||||
_lr_action[_x][_k] = _y
|
||||
del _lr_action_items
|
||||
|
||||
_lr_goto_items = {'start':([0,],[1,]),'command':([0,2,],[3,5,]),'args':([4,],[6,]),'operand':([4,14,],[7,17,]),'address':([4,9,11,14,],[10,15,16,10,]),}
|
||||
|
||||
_lr_goto = {}
|
||||
for _k, _v in _lr_goto_items.items():
|
||||
for _x, _y in zip(_v[0], _v[1]):
|
||||
if not _x in _lr_goto: _lr_goto[_x] = {}
|
||||
_lr_goto[_x][_k] = _y
|
||||
del _lr_goto_items
|
||||
_lr_productions = [
|
||||
("S' -> start","S'",1,None,None,None),
|
||||
('start -> LABEL command','start',2,'p_start','parser.py',41),
|
||||
('start -> command','start',1,'p_start','parser.py',42),
|
||||
('command -> MNEMONIC','command',1,'p_command','parser.py',48),
|
||||
('command -> MNEMONIC args','command',2,'p_command','parser.py',49),
|
||||
('args -> operand','args',1,'p_args','parser.py',53),
|
||||
('args -> operand COMMA operand','args',3,'p_args','parser.py',54),
|
||||
('operand -> REGISTER','operand',1,'p_operand','parser.py',60),
|
||||
('operand -> AT address','operand',2,'p_operand','parser.py',61),
|
||||
('operand -> HASH address','operand',2,'p_operand','parser.py',62),
|
||||
('operand -> address','operand',1,'p_operand','parser.py',63),
|
||||
('address -> NUMBER','address',1,'p_address','parser.py',67),
|
||||
('address -> SYMBOL','address',1,'p_address','parser.py',68),
|
||||
]
|
||||
72
ass3/zbirnik/src/zbirnik/test_emit.py
Normal file
72
ass3/zbirnik/src/zbirnik/test_emit.py
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
OPCODES = {
|
||||
"FIX": 0xC4,
|
||||
"ADDR": 0x90,
|
||||
"LDA": 0x00,
|
||||
"STA": 0x0C,
|
||||
"JSUB": 0x48,
|
||||
}
|
||||
|
||||
REGISTERS = {
|
||||
"A": 0,
|
||||
"X": 1,
|
||||
"L": 2,
|
||||
"B": 3,
|
||||
"S": 4,
|
||||
"T": 5,
|
||||
"F": 6,
|
||||
}
|
||||
|
||||
from zbirnik.ukazi.f1 import f1
|
||||
from zbirnik.EmitCtx import EmitContext
|
||||
|
||||
ctx = EmitContext(OPCODES, REGISTERS, {})
|
||||
|
||||
node = f1("FIX", None)
|
||||
result = node.emit(ctx)
|
||||
|
||||
print(result.hex())
|
||||
|
||||
from zbirnik.ukazi.f2 import f2
|
||||
|
||||
node = f2("A", "X", "ADDR")
|
||||
print(node.emit(ctx).hex())
|
||||
|
||||
from zbirnik.ukazi.f3 import f3
|
||||
from zbirnik.adressing import AddrMode
|
||||
|
||||
#IMMEDIATE
|
||||
node = f3(
|
||||
operand=5,
|
||||
mnemonic="LDA",
|
||||
label=None,
|
||||
index=False,
|
||||
adr_mode=AddrMode.IMMEDIATE
|
||||
)
|
||||
node.address = 0x1000
|
||||
print(node.emit(ctx).hex())
|
||||
|
||||
#PC RELATIVE
|
||||
ctx.symtab["NUM"] = 0x1003
|
||||
|
||||
node = f3(
|
||||
operand="NUM",
|
||||
mnemonic="LDA",
|
||||
label=None,
|
||||
index=False,
|
||||
adr_mode=AddrMode.SIMPLE
|
||||
)
|
||||
node.address = 0x1000
|
||||
print(node.emit(ctx).hex())
|
||||
|
||||
from zbirnik.ukazi.f4 import f4
|
||||
#F4
|
||||
ctx.symtab["SUBR"] = 0x12345
|
||||
node = f4(
|
||||
operand="SUBR",
|
||||
mnemonic="JSUB",
|
||||
label=None,
|
||||
index=False,
|
||||
adr_mode=AddrMode.SIMPLE
|
||||
)
|
||||
print(node.emit(ctx).hex())
|
||||
|
||||
0
ass3/zbirnik/src/zbirnik/ukazi/__init__.py
Normal file
0
ass3/zbirnik/src/zbirnik/ukazi/__init__.py
Normal file
Binary file not shown.
BIN
ass3/zbirnik/src/zbirnik/ukazi/__pycache__/f1.cpython-310.pyc
Normal file
BIN
ass3/zbirnik/src/zbirnik/ukazi/__pycache__/f1.cpython-310.pyc
Normal file
Binary file not shown.
BIN
ass3/zbirnik/src/zbirnik/ukazi/__pycache__/f2.cpython-310.pyc
Normal file
BIN
ass3/zbirnik/src/zbirnik/ukazi/__pycache__/f2.cpython-310.pyc
Normal file
Binary file not shown.
BIN
ass3/zbirnik/src/zbirnik/ukazi/__pycache__/f3.cpython-310.pyc
Normal file
BIN
ass3/zbirnik/src/zbirnik/ukazi/__pycache__/f3.cpython-310.pyc
Normal file
Binary file not shown.
BIN
ass3/zbirnik/src/zbirnik/ukazi/__pycache__/f4.cpython-310.pyc
Normal file
BIN
ass3/zbirnik/src/zbirnik/ukazi/__pycache__/f4.cpython-310.pyc
Normal file
Binary file not shown.
BIN
ass3/zbirnik/src/zbirnik/ukazi/__pycache__/node.cpython-310.pyc
Normal file
BIN
ass3/zbirnik/src/zbirnik/ukazi/__pycache__/node.cpython-310.pyc
Normal file
Binary file not shown.
8
ass3/zbirnik/src/zbirnik/ukazi/comment.py
Normal file
8
ass3/zbirnik/src/zbirnik/ukazi/comment.py
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
from zbirnik.ukazi.node import Node
|
||||
|
||||
class Comment(Node):
|
||||
def __init__(self, text: str):
|
||||
self.text = text
|
||||
|
||||
def size(self):
|
||||
return 0
|
||||
29
ass3/zbirnik/src/zbirnik/ukazi/directive.py
Normal file
29
ass3/zbirnik/src/zbirnik/ukazi/directive.py
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
from zbirnik.ukazi.node import Node
|
||||
|
||||
class directive(Node):
|
||||
def __init__(self, direktiva : str, operand : str | int | None, label : str | None = None):
|
||||
self.direktiva = direktiva
|
||||
super().__init__(label)
|
||||
self.operand = operand
|
||||
|
||||
def size(self) -> int:
|
||||
return 0
|
||||
|
||||
def emit(self, ctx):
|
||||
# BASE directive
|
||||
if self.name == "BASE":
|
||||
if isinstance(self.value, str):
|
||||
ctx.base = ctx.symtab[self.value]
|
||||
elif isinstance(self.value, int):
|
||||
ctx.base = self.value
|
||||
else:
|
||||
raise ValueError("Invalid BASE operand")
|
||||
return None
|
||||
|
||||
# NOBASE directive
|
||||
if self.name == "NOBASE":
|
||||
ctx.base = None
|
||||
return None
|
||||
|
||||
# START, END, LTORG, ...
|
||||
return None
|
||||
13
ass3/zbirnik/src/zbirnik/ukazi/f1.py
Normal file
13
ass3/zbirnik/src/zbirnik/ukazi/f1.py
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
from zbirnik.ukazi.node import Node
|
||||
|
||||
class f1(Node):
|
||||
def __init__(self, mnemnonic : str, label : str | None = None):
|
||||
self.mnemonic = mnemnonic
|
||||
super().__init__(label)
|
||||
|
||||
def size(self) -> int:
|
||||
return 1
|
||||
|
||||
def emit(self, ctx):
|
||||
opcode = ctx.opcodes[self.mnemonic]
|
||||
return bytes([opcode])
|
||||
30
ass3/zbirnik/src/zbirnik/ukazi/f2.py
Normal file
30
ass3/zbirnik/src/zbirnik/ukazi/f2.py
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
from zbirnik.ukazi.node import Node
|
||||
|
||||
class f2(Node):
|
||||
def __init__(self, r1: str, r2: str | None, mnemonic: str, label : str | None = None):
|
||||
self.r1 = r1
|
||||
self.r2 = r2
|
||||
self.mnemonic = mnemonic
|
||||
super().__init__(label)
|
||||
|
||||
def size(self) -> int:
|
||||
return 2
|
||||
|
||||
def emit(self, ctx):
|
||||
opcode = ctx.opcodes[self.mnemonic]
|
||||
|
||||
if isinstance(self.r1, str):
|
||||
r1_val = ctx.registers[self.r1]
|
||||
else:
|
||||
r1_val = self.r1
|
||||
|
||||
if self.r2 is None:
|
||||
r2_val = 0
|
||||
elif isinstance(self.r2, str):
|
||||
r2_val = ctx.registers[self.r2]
|
||||
else:
|
||||
r2_val = self.r2
|
||||
|
||||
byte2 = (r1_val << 4) | r2_val
|
||||
|
||||
return bytes([opcode, byte2])
|
||||
62
ass3/zbirnik/src/zbirnik/ukazi/f3.py
Normal file
62
ass3/zbirnik/src/zbirnik/ukazi/f3.py
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
from zbirnik.ukazi.node import Node
|
||||
from zbirnik.adressing import AddrMode
|
||||
|
||||
class f3(Node):
|
||||
def __init__(self, operand: str | int | None, mnemonic: str, index : bool, adr_mode: str | None, label : str | None = None):
|
||||
super().__init__(label)
|
||||
self.operand = operand
|
||||
self.mnemonic = mnemonic
|
||||
self.index = index
|
||||
self.adr_mode = adr_mode
|
||||
|
||||
def size(self) -> int:
|
||||
return 3
|
||||
|
||||
def emit(self, ctx):
|
||||
opcode = ctx.opcodes[self.mnemonic]
|
||||
base_opcode = opcode & 0b11111100
|
||||
|
||||
if self.adr_mode == AddrMode.SIMPLE:
|
||||
n, i = 1, 1
|
||||
elif self.adr_mode == AddrMode.IMMEDIATE:
|
||||
n, i = 0, 1
|
||||
elif self.adr_mode == AddrMode.INDIRECT:
|
||||
n, i = 1, 0
|
||||
else:
|
||||
raise ValueError("Invalid addressing mode")
|
||||
|
||||
byte1 = base_opcode | (n << 1) | i
|
||||
|
||||
x = 1 if self.index else 0
|
||||
|
||||
if isinstance(self.operand, int):
|
||||
target = self.operand
|
||||
else:
|
||||
target = ctx.symtab[self.operand]
|
||||
|
||||
pc = self.address + 3
|
||||
disp = target - pc
|
||||
b = 0
|
||||
p = 1
|
||||
#PC relativno
|
||||
if -2048 <= disp <= 2047:
|
||||
b = 0
|
||||
p = 1
|
||||
#Bazno relativno
|
||||
elif ctx.base is not None:
|
||||
disp = target - ctx.base
|
||||
if 0 <= disp <= 4095:
|
||||
b = 1
|
||||
p = 0
|
||||
else:
|
||||
raise ValueError("Displacement out of range")
|
||||
|
||||
e = 0
|
||||
|
||||
byte2 = ((x << 7) | (b << 6) | (p << 5) | (e << 4) | ((disp >> 8) & 0x0F))
|
||||
byte3 = disp & 0xFF
|
||||
|
||||
return bytes([byte1, byte2, byte3])
|
||||
|
||||
|
||||
|
||||
51
ass3/zbirnik/src/zbirnik/ukazi/f4.py
Normal file
51
ass3/zbirnik/src/zbirnik/ukazi/f4.py
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
from zbirnik.ukazi.node import Node
|
||||
from zbirnik.adressing import AddrMode
|
||||
|
||||
class f4(Node):
|
||||
def __init__(
|
||||
self,
|
||||
operand: str | int | None,
|
||||
mnemonic: str,
|
||||
label: str | None = None,
|
||||
index: bool = False,
|
||||
adr_mode: AddrMode = AddrMode.SIMPLE
|
||||
):
|
||||
super().__init__(label)
|
||||
self.operand = operand
|
||||
self.mnemonic = mnemonic
|
||||
self.index = index
|
||||
self.adr_mode = adr_mode
|
||||
|
||||
|
||||
def size(self) -> int:
|
||||
return 4
|
||||
|
||||
def emit(self, ctx):
|
||||
opcode = ctx.opcodes[self.mnemonic]
|
||||
base_opcode = opcode & 0b11111100
|
||||
|
||||
if self.adr_mode == AddrMode.SIMPLE:
|
||||
n, i = 1, 1
|
||||
elif self.adr_mode == AddrMode.IMMEDIATE:
|
||||
n, i = 0, 1
|
||||
elif self.adr_mode == AddrMode.INDIRECT:
|
||||
n, i = 1, 0
|
||||
else:
|
||||
raise ValueError("Invalid addressing mode")
|
||||
|
||||
byte1 = base_opcode | (n << 1) | i
|
||||
x = 1 if self.index else 0
|
||||
b = 0
|
||||
p = 0
|
||||
e = 1
|
||||
|
||||
if isinstance(self.operand, int):
|
||||
target = self.operand
|
||||
else:
|
||||
target = ctx.symtab[self.operand]
|
||||
|
||||
byte2 = ((x << 7) | (b << 6) | (p << 5) | (e << 4) | ((target >> 16) & 0x0F))
|
||||
byte3 = (target >> 8) & 0xFF
|
||||
byte4 = target & 0xFF
|
||||
|
||||
return bytes([byte1, byte2, byte3, byte4])
|
||||
9
ass3/zbirnik/src/zbirnik/ukazi/node.py
Normal file
9
ass3/zbirnik/src/zbirnik/ukazi/node.py
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
class Node:
|
||||
def __init__(self, label=None):
|
||||
self.label = label
|
||||
self.address = None
|
||||
|
||||
def size(self):
|
||||
raise NotImplementedError
|
||||
def emit(self):
|
||||
raise NotImplementedError
|
||||
43
ass3/zbirnik/src/zbirnik/ukazi/storage.py
Normal file
43
ass3/zbirnik/src/zbirnik/ukazi/storage.py
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
from zbirnik.ukazi.node import Node
|
||||
|
||||
class storage(Node):
|
||||
def __init__(self, val : str | int, name : str, label : str | None = None):
|
||||
super().__init__(label)
|
||||
self.val = val
|
||||
self.name = name
|
||||
|
||||
def size(self) -> int:
|
||||
return 0
|
||||
|
||||
def emit(self, ctx):
|
||||
if self.name == "WORD":
|
||||
if isinstance(self.value, str):
|
||||
val = ctx.symtab[self.value]
|
||||
else:
|
||||
val = self.value
|
||||
|
||||
val &= 0xFFFFFF # 24-bit signed
|
||||
b1 = (val >> 16) & 0xFF
|
||||
b2 = (val >> 8) & 0xFF
|
||||
b3 = val & 0xFF
|
||||
return bytes([b1, b2, b3])
|
||||
|
||||
if self.name == "BYTE":
|
||||
s = self.value
|
||||
# C'EOF'
|
||||
if s.startswith("C'") and s.endswith("'"):
|
||||
chars = s[2:-1]
|
||||
return bytes(ord(c) for c in chars)
|
||||
# X'F1A3'
|
||||
if s.startswith("X'") and s.endswith("'"):
|
||||
hexstr = s[2:-1]
|
||||
return bytes.fromhex(hexstr)
|
||||
|
||||
raise ValueError("Invalid BYTE constant")
|
||||
|
||||
# RESB / RESW → no code
|
||||
if self.name in ("RESB", "RESW"):
|
||||
return b""
|
||||
|
||||
return b""
|
||||
|
||||
0
ass3/zbirnik/tests/__init__.py
Normal file
0
ass3/zbirnik/tests/__init__.py
Normal file
Loading…
Add table
Add a link
Reference in a new issue