def test_assembly_parser_error(symbol_table: f1_t) -> None:
    # unknown token
    test = Parser('FAIL\nADD B #$10\n', symbol_table('FAIL\nADD B #$10\n'))
    with pytest.raises(AssemblerParserError):
        test.take(Mnemonic.T_ADD)
    # unexpected
    test = Parser('ADD B #$10\n', symbol_table('ADD B #$10\n'))
    with pytest.raises(AssemblerParserError):
        test.take(Token.T_VARIABLE)
Exemple #2
0
def operand_state_machine(parser: Parser, operands: Deque[yylex_t],
                          mode_stack: List[AddressingMode]) -> AddressingMode:
    """Get addressing mode and validate instruction operands

    Runs a parser combinator on the operands based on the amount of
    operands for an instruction and the operand types.

    Builds a stack of addressing modes by running on each n operand.
    The final instruction addressing mode is thus determined by the n_0 operand
    since the operand `deque` is provided in reverse order.

    By running for each operand recursively for `n-1` we validate order
    of operands state sets and their respective type and addressing modes
    at once.
    """
    size: int = len(operands)
    if size > 0:
        if size > 1 and operands[1]['token'] == Token.T_COMMA:
            del operands[1]
        test = operands[0]['token']
        mode: Mode_T = match(
            len(operands), 3, lambda k: AddressingMode.IDX
            if operands[0]['token'] == Register.T_X else
            ('error', Register.T_X.name, test), 2, lambda k: match(
                test, Token.T_IMM_UINT8, AddressingMode.IMM, Token.
                T_IMM_UINT16, AddressingMode.IMM, Token.T_DIR_ADDR_UINT8,
                AddressingMode.DIR, Token.T_EXT_ADDR_UINT16, AddressingMode.
                EXT, Register.T_X, AddressingMode.IDX, _, ('error', ', '.join(
                    list(map(lambda x: x.name, Second_Operand_States))), test
                                                           )), 1, lambda k:
            match(test, Token.T_IMM_UINT16, AddressingMode.IMM, Token.
                  T_DIR_ADDR_UINT8, AddressingMode.DIR, Token.T_DISP_ADDR_INT8,
                  AddressingMode.REL, Token.T_EXT_ADDR_UINT16, AddressingMode.
                  EXT, Register.T_A, AddressingMode.ACC, Register.T_B,
                  AddressingMode.ACC, _, ('error', ', '.join(
                      list(map(lambda x: x.name, First_Operand_States))), test
                                          )), 0, lambda k: AddressingMode.INH)
        if not isinstance(mode, AddressingMode):
            parser.error(mode[1], mode[2])
        else:
            operands.popleft()
            mode_stack.append(mode)

        return operand_state_machine(parser, operands, mode_stack)

    return AddressingMode.INH if len(mode_stack) == 0 else mode_stack[0]
Exemple #3
0
 def adc(addr_mode: AddressingMode, operands: Deque[yylex_t],
         registers: Register_T) -> bytearray:
     """The ADC instruction. """
     opcode: bytearray = bytearray()
     data: int = 0
     status: bitarray = registers.SR
     o = operands[0]['data']
     if not isinstance(o, str):
         raise AssemblerParserError(f'Invalid instruction operand')
     # Immediate addressing:
     if addr_mode == AddressingMode.IMM:
         opcode = bytearray.fromhex('89') if operands[-1]['data'] == 'A' \
             else bytearray.fromhex('C9')
         operand = int(Parser.parse_immediate_value(o).hex(), 16)
         if status[0] is True:
             b = bin(operand)
             data = int('0b' + status.to01()[0] + b[2:], 2)
         else:
             data = int(bin(operand), 2)
         registers.AccA += data
     return opcode + bytearray.fromhex(hex(data)[2:])
def test_assembly_parser(symbol_table: f1_t) -> None:
    with open(f'{pathlib.Path(__file__).parent.parent}/etc/fixture.asm') as f:
        source = f.read()
        test = Parser(source, symbol_table(source))
        assert test.line() is True  # variable
        assert test.line() is True  # variable
        assert test.line() is True  # variable
        # note: skips empty lines
        line = test.line()
        if isinstance(line, bool):
            raise AssertionError('failed test')
        # test instruction parsing
        while line is not False:
            expect = expected.popleft()
            instruction, operands = line  # type: ignore
            assert instruction == expect[0]  # type: ignore
            operands.reverse()
            index = 1
            for ops in operands:
                assert ops['token'] == expect[index]  # type: ignore
                index += 1

            line = test.line()
Exemple #5
0
 def _get_parser(source: str) -> Parser:
     parser = Parser(source)
     return parser
Exemple #6
0
def test_parse_immediate_value(parser: f1_t, code: f3_t) -> None:
    assert Parser.parse_immediate_value('#$10') == b'\x10'
    assert Parser.parse_immediate_value('$10') == b'\x10'
Exemple #7
0
 def _get_parser(source: str, symbols: Optional[Symbol_Table]) -> Parser:
     return Parser(source, symbols or Symbol_Table())
Exemple #8
0
"""
    axel is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    axel is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with axel.  If not, see <https://www.gnu.org/licenses/>.
"""
from axel.lexer import Lexer
from axel.parser import Parser

with open('./etc/healthkit.asm') as f:
    source = f.read()
    test = Lexer(source)
    for token in test:
        pass
    test2 = Parser(source, test.symbols)
    line = test2.line()
    print('\nInstructions:')
    while line:
        if not isinstance(line, bool):
            print(line)
        line = test2.line()
    print('\nSymbols:\n', test2.symbols.table)
Exemple #9
0
 def __init__(self, source: str) -> None:
     self.lexer = Optional[Lexer]
     self.symbol_table: Symbol_Table = self._construct_symbol_table(source)
     self.parser: Parser = Parser(source, self.symbol_table)
     self.program: BytesIO = BytesIO()