From 8740fe2e21b6b810b0ed22baffca14bc09417938 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Thu, 17 Oct 2024 10:25:37 +0900 Subject: [PATCH] Expose all parsers --- src/asm_base.h | 1 - src/asm_cdp1802.cpp | 89 +------- src/asm_cdp1802.h | 3 +- src/asm_f3850.cpp | 8 +- src/asm_i8051.cpp | 7 +- src/asm_i8086.cpp | 4 +- src/asm_i8096.cpp | 7 +- src/asm_ins8060.cpp | 43 ---- src/asm_ins8070.cpp | 42 ---- src/asm_mc68000.cpp | 10 - src/asm_mn1610.cpp | 14 +- src/asm_mos6502.cpp | 31 --- src/asm_ns32000.cpp | 27 --- src/asm_pdp8.cpp | 55 ----- src/asm_scn2650.cpp | 22 +- src/asm_tlcs90.cpp | 8 +- src/asm_tms32010.cpp | 18 -- src/asm_z8.cpp | 11 +- src/asm_z80.cpp | 6 +- src/asm_z8000.cpp | 11 +- src/comment_parser.h | 46 +++- src/function_table.h | 59 ++++++ src/letter_parser.h | 69 +++++- src/number_parser.h | 60 ++++-- src/operators.cpp | 140 +++++++++++-- src/operators.h | 16 +- src/parsers.cpp | 395 ++++++++++++++++++++++++++--------- src/parsers.h | 20 +- src/symbol_parser.h | 102 ++++++--- src/value_parser.cpp | 91 ++------ src/value_parser.h | 16 +- test/test_asm_scn2650.cpp | 4 +- test/test_expr_fairchild.cpp | 9 +- test/test_expr_zilog.cpp | 8 +- 34 files changed, 764 insertions(+), 688 deletions(-) create mode 100644 src/function_table.h diff --git a/src/asm_base.h b/src/asm_base.h index 4ce206ec..6a0f872f 100644 --- a/src/asm_base.h +++ b/src/asm_base.h @@ -24,7 +24,6 @@ #include "error_reporter.h" #include "insn_base.h" #include "option_base.h" -#include "parsers.h" #include "pseudos.h" #include "symbol_table.h" #include "value_parser.h" diff --git a/src/asm_cdp1802.cpp b/src/asm_cdp1802.cpp index b36d94eb..5205b54f 100644 --- a/src/asm_cdp1802.cpp +++ b/src/asm_cdp1802.cpp @@ -39,61 +39,9 @@ constexpr Pseudo PSEUDOS[] PROGMEM = { // clang-format on PROGMEM constexpr Pseudos PSEUDO_TABLE{ARRAY_RANGE(PSEUDOS)}; -/** - * RCA style numbers are the same as IBM plus '#hh' for hexadecimal. - */ -struct RcaNumberParser final : NumberParser, Singleton { - Error parseNumber(StrScanner &scan, Value &val, Radix defaultRadix) const override { - auto p = scan; - if (*p == '#' && isxdigit(p[1])) { - const auto error = val.read(++p, RADIX_16); - if (error == OK) - scan = p; - return error; - } - return _ibm.parseNumber(scan, val, defaultRadix); - } - -private: - const IbmNumberParser _ibm{'X', 'B', 0, 'D'}; -}; - -struct RcaCommentParser final : CommentParser, Singleton { - bool commentLine(StrScanner &scan) const override { - static constexpr char TEXT_DOTDOT[] PROGMEM = ".."; - return scan.iexpectText_P(TEXT_DOTDOT) || endOfLine(scan); - } - bool endOfLine(StrScanner &scan) const override { - return SemicolonCommentParser::singleton().endOfLine(scan); - } -}; - -struct RcaSymbolParser final : SymbolParser, Singleton { - bool functionNameLetter(char c) const override { return symbolLetter(c) || c == '.'; } - bool instructionLetter(char c) const override { - return SymbolParser::instructionLetter(c) || c == '='; - } - bool instructionTerminator(char c) const override { return c == '='; } -}; - -struct RcaLetterParser final : LetterParser, Singleton { - bool letterPrefix(StrScanner &scan) const override { - scan.iexpect('T'); // optional - return true; - } - bool stringPrefix(StrScanner &scan) const override { - scan.iexpect('T'); // optional - return true; - } -}; - -struct RcaFunctionTable final : FunctionTable, Singleton { - const Functor *lookupFunction(const StrScanner &name) const override; -}; - } // namespace -const ValueParser::Plugins &AsmCdp1802::defaultPlugins() { +const ValueParser::Plugins &defaultPlugins() { static const struct final : ValueParser::Plugins { const NumberParser &number() const override { return RcaNumberParser::singleton(); } const CommentParser &comment() const override { return RcaCommentParser::singleton(); } @@ -123,41 +71,6 @@ Error AsmCdp1802::setUseReg(bool enable) { namespace { -const struct : Functor { - int_fast8_t nargs() const override { return 1; } - Error eval(ValueStack &stack, ParserContext &, uint_fast8_t) const override { - // Mark that this is 2 bytes value. - stack.pushUnsigned((stack.pop().getUnsigned() & UINT16_MAX) | UINT32_C(0x1000'0000)); - return OK; - } -} FN_A; - -const struct : Functor { - int_fast8_t nargs() const override { return 1; } - Error eval(ValueStack &stack, ParserContext &, uint_fast8_t) const override { - stack.pushUnsigned(stack.pop().getUnsigned() & UINT8_MAX); - return OK; - } -} FN_A0; - -const struct : Functor { - int_fast8_t nargs() const override { return 1; } - Error eval(ValueStack &stack, ParserContext &, uint_fast8_t) const override { - stack.pushUnsigned((stack.pop().getUnsigned() >> 8) & UINT8_MAX); - return OK; - } -} FN_A1; - -const Functor *RcaFunctionTable::lookupFunction(const StrScanner &name) const { - if (name.iequals_P(PSTR("A.0"))) - return &FN_A0; - if (name.iequals_P(PSTR("A.1"))) - return &FN_A1; - if (name.iequals_P(PSTR("A"))) - return &FN_A; - return nullptr; -} - constexpr Config::opcode_t BR = 0x30; constexpr Config::opcode_t LBR = 0xC0; diff --git a/src/asm_cdp1802.h b/src/asm_cdp1802.h index 915689c9..9b9895d6 100644 --- a/src/asm_cdp1802.h +++ b/src/asm_cdp1802.h @@ -24,6 +24,8 @@ namespace libasm { namespace cdp1802 { +const ValueParser::Plugins &defaultPlugins(); + struct AsmCdp1802 final : Assembler, Config { AsmCdp1802(const ValueParser::Plugins &plugins = defaultPlugins()); @@ -44,7 +46,6 @@ struct AsmCdp1802 final : Assembler, Config { Error encodeImpl(StrScanner &scan, Insn &insn) const override; const ConfigBase &config() const override { return *this; } ConfigSetter &configSetter() override { return *this; } - static const ValueParser::Plugins &defaultPlugins(); }; } // namespace cdp1802 diff --git a/src/asm_f3850.cpp b/src/asm_f3850.cpp index b94f2ee6..99d8c1e4 100644 --- a/src/asm_f3850.cpp +++ b/src/asm_f3850.cpp @@ -43,7 +43,13 @@ PROGMEM constexpr Pseudos PSEUDO_TABLE{ARRAY_RANGE(PSEUDOS)}; } // namespace const ValueParser::Plugins &AsmF3850::defaultPlugins() { - return ValueParser::Plugins::fairchild(); + static const struct final : ValueParser::Plugins { + const NumberParser &number() const override { return FairchildNumberParser::singleton(); } + const SymbolParser &symbol() const override { return FairchildSymbolParser::singleton(); } + const CommentParser &comment() const override { return StarCommentParser::singleton(); } + const LetterParser &letter() const override { return FairchildLetterParser::singleton(); } + } PLUGINS{}; + return PLUGINS; } AsmF3850::AsmF3850(const ValueParser::Plugins &plugins) diff --git a/src/asm_i8051.cpp b/src/asm_i8051.cpp index b1e1d80e..edb2f00a 100644 --- a/src/asm_i8051.cpp +++ b/src/asm_i8051.cpp @@ -40,12 +40,7 @@ PROGMEM constexpr Pseudos PSEUDO_TABLE{ARRAY_RANGE(PSEUDOS)}; } // namespace const ValueParser::Plugins &AsmI8051::defaultPlugins() { - static struct final : ValueParser::IntelPlugins { - const SymbolParser &symbol() const override { - return UnderQuestionSymbolParser::singleton(); - } - } PLUGINS; - return PLUGINS; + return ValueParser::Plugins::intel(); } AsmI8051::AsmI8051(const ValueParser::Plugins &plugins) diff --git a/src/asm_i8086.cpp b/src/asm_i8086.cpp index 57d6a1e6..91832fa0 100644 --- a/src/asm_i8086.cpp +++ b/src/asm_i8086.cpp @@ -58,10 +58,8 @@ struct I8086SymbolParser final : SimpleSymbolParser, Singleton { - const Functor *lookupFunction(const StrScanner &) const override; -}; - } // namespace const ValueParser::Plugins &AsmIns8060::defaultPlugins() { @@ -58,45 +54,6 @@ AsmIns8060::AsmIns8060(const ValueParser::Plugins &plugins) reset(); } -namespace { - -const struct : Functor { - int_fast8_t nargs() const override { return 1; } - Error eval(ValueStack &stack, ParserContext &, uint_fast8_t) const override { - stack.pushUnsigned((stack.pop().getUnsigned() >> 8) & 0xFF); - return OK; - } -} FN_HIGH; - -const struct : Functor { - int_fast8_t nargs() const override { return 1; } - Error eval(ValueStack &stack, ParserContext &, uint_fast8_t) const override { - stack.pushUnsigned(stack.pop().getUnsigned() & 0xFF); - return OK; - } -} FN_LOW; - -const struct : Functor { - int_fast8_t nargs() const override { return 1; } - Error eval(ValueStack &stack, ParserContext &, uint_fast8_t) const override { - const auto v = stack.pop().getUnsigned(); - stack.pushUnsigned(page(v) | offset(v - 1)); - return OK; - } -} FN_ADDR; - -const Functor *Ins8060FunctionTable::lookupFunction(const StrScanner &name) const { - if (name.iequals_P(TEXT_FN_H)) - return &FN_HIGH; - if (name.iequals_P(TEXT_FN_L)) - return &FN_LOW; - if (name.iequals_P(TEXT_FN_ADDR)) - return &FN_ADDR; - return nullptr; -} - -} // namespace - void AsmIns8060::encodeRel8(AsmInsn &insn, const Operand &op) const { Config::ptrdiff_t delta; if (op.mode == M_DISP) { diff --git a/src/asm_ins8070.cpp b/src/asm_ins8070.cpp index a2a542f0..26c39b0c 100644 --- a/src/asm_ins8070.cpp +++ b/src/asm_ins8070.cpp @@ -38,10 +38,6 @@ constexpr Pseudo PSEUDOS[] PROGMEM = { // clang-format on PROGMEM constexpr Pseudos PSEUDO_TABLE{ARRAY_RANGE(PSEUDOS)}; -struct Ins8070FunctionTable final : FunctionTable, Singleton { - const Functor *lookupFunction(const StrScanner &) const override; -}; - } // namespace const ValueParser::Plugins &AsmIns8070::defaultPlugins() { @@ -58,44 +54,6 @@ AsmIns8070::AsmIns8070(const ValueParser::Plugins &plugins) reset(); } -namespace { - -const struct : Functor { - int_fast8_t nargs() const override { return 1; } - Error eval(ValueStack &stack, ParserContext &, uint_fast8_t) const override { - stack.pushUnsigned((stack.pop().getUnsigned() >> 8) & 0xFF); - return OK; - } -} FN_HIGH; - -const struct : Functor { - int_fast8_t nargs() const override { return 1; } - Error eval(ValueStack &stack, ParserContext &, uint_fast8_t) const override { - stack.pushUnsigned(stack.pop().getUnsigned() & 0xFF); - return OK; - } -} FN_LOW; - -const struct : Functor { - int_fast8_t nargs() const override { return 1; } - Error eval(ValueStack &stack, ParserContext &, uint_fast8_t) const override { - stack.pushUnsigned((stack.pop().getUnsigned() - 1) & 0xFFFF); - return OK; - } -} FN_ADDR; - -const Functor *Ins8070FunctionTable::lookupFunction(const StrScanner &name) const { - if (name.iequals_P(TEXT_FN_H)) - return &FN_HIGH; - if (name.iequals_P(TEXT_FN_L)) - return &FN_LOW; - if (name.iequals_P(TEXT_FN_ADDR)) - return &FN_ADDR; - return nullptr; -} - -} // namespace - void AsmIns8070::emitAbsolute(AsmInsn &insn, const Operand &op) const { // PC will be +1 before fetching instruction. const auto target = op.getError() ? 0 : op.val.getUnsigned() - 1; diff --git a/src/asm_mc68000.cpp b/src/asm_mc68000.cpp index 165977a1..bc1f5482 100644 --- a/src/asm_mc68000.cpp +++ b/src/asm_mc68000.cpp @@ -65,16 +65,6 @@ constexpr Pseudo PSEUDOS[] PROGMEM = { // clang-format on PROGMEM constexpr Pseudos PSEUDO_TABLE{ARRAY_RANGE(PSEUDOS)}; -struct Mc68000SymbolParser final : PrefixSymbolParser, Singleton { - Mc68000SymbolParser() : PrefixSymbolParser(PSTR_DOT, PSTR_UNDER_DOT_DOLLAR) {} - bool locationSymbol(StrScanner &scan) const override { - return SymbolParser::locationSymbol(scan, '*'); - } - bool instructionLetter(char c) const override { - return PrefixSymbolParser::instructionLetter(c) || c == '.'; - } -}; - } // namespace const ValueParser::Plugins &AsmMc68000::defaultPlugins() { diff --git a/src/asm_mn1610.cpp b/src/asm_mn1610.cpp index c6b44899..674923ea 100644 --- a/src/asm_mn1610.cpp +++ b/src/asm_mn1610.cpp @@ -39,22 +39,12 @@ constexpr Pseudo PSEUDOS[] PROGMEM = { // clang-format on PROGMEM constexpr Pseudos PSEUDO_TABLE{ARRAY_RANGE(PSEUDOS)}; -struct Mn1610NumberParser final : IbmNumberParser, Singleton { - Mn1610NumberParser() : IbmNumberParser('X', 0, 0, 0) {} -}; - -struct Mn1610SymbolParser final : SymbolParser, Singleton { - bool locationSymbol(StrScanner &scan) const override { - return SymbolParser::locationSymbol(scan, '*'); - } -}; - } // namespace const ValueParser::Plugins &AsmMn1610::defaultPlugins() { static const struct final : ValueParser::Plugins { - const NumberParser &number() const override { return Mn1610NumberParser::singleton(); } - const SymbolParser &symbol() const override { return Mn1610SymbolParser::singleton(); } + const NumberParser &number() const override { return PanasonicNumberParser::singleton(); } + const SymbolParser &symbol() const override { return PanasonicSymbolParser::singleton(); } const CommentParser &comment() const override { return StarCommentParser::singleton(); } const LetterParser &letter() const override { return IbmLetterParser::singleton(); } } PLUGINS{}; diff --git a/src/asm_mos6502.cpp b/src/asm_mos6502.cpp index 579a3325..eb650b52 100644 --- a/src/asm_mos6502.cpp +++ b/src/asm_mos6502.cpp @@ -45,37 +45,6 @@ constexpr Pseudo PSEUDOS[] PROGMEM = { // clang-format on PROGMEM constexpr Pseudos PSEUDO_TABLE{ARRAY_RANGE(PSEUDOS)}; -struct MostekCommentParser final : CommentParser, Singleton { - bool commentLine(StrScanner &scan) const override { - return SemicolonCommentParser::singleton().commentLine(scan); - } - bool endOfLine(StrScanner &scan) const override { - return StarCommentParser::singleton().endOfLine(scan) || - SemicolonCommentParser::singleton().endOfLine(scan); - } -}; - -struct MostekSymbolParser final : SimpleSymbolParser, Singleton { - MostekSymbolParser() : SimpleSymbolParser(PSTR_UNDER) {} - bool locationSymbol(StrScanner &scan) const override { - return SymbolParser::locationSymbol(scan, '*'); - } - bool instructionLetter(char c) const override { - return SymbolParser::instructionLetter(c) || c == '.' || c == '=' || c == '*' || c == ':'; - } - bool instructionTerminator(char c) const override { return c == '='; } -}; - -struct MostekLetterParser final : LetterParser, Singleton { - Error parseLetter(StrScanner &scan, char &letter) const { - return MotorolaLetterParser::singleton().parseLetter(scan, letter); - } - char stringDelimiter(StrScanner &scan) const { - const auto c = scan.expect('\''); - return c ? c : scan.expect('"'); - } -}; - } // namespace const ValueParser::Plugins &AsmMos6502::defaultPlugins() { diff --git a/src/asm_ns32000.cpp b/src/asm_ns32000.cpp index f73123de..780c5a04 100644 --- a/src/asm_ns32000.cpp +++ b/src/asm_ns32000.cpp @@ -64,33 +64,6 @@ constexpr Pseudo PSEUDOS[] PROGMEM = { // clang-format on PROGMEM constexpr Pseudos PSEUDO_TABLE{ARRAY_RANGE(PSEUDOS)}; -struct Ns32000NumberParser final : NationalNumberParser, Singleton { - Ns32000NumberParser() : NationalNumberParser(/* 'X','H' */ 0, 'B', /* 'O' or */ 'Q', 'D') {} -}; - -struct Ns32000SymbolParser final : SimpleSymbolParser, Singleton { - Ns32000SymbolParser() : SimpleSymbolParser(PSTR_UNDER_DOT) {} - bool locationSymbol(StrScanner &scan) const override { - return SymbolParser::locationSymbol(scan, '.') || SymbolParser::locationSymbol(scan, '*'); - } - bool instructionLetter(char c) const override { - return SimpleSymbolParser::instructionLetter(c) || c == '.'; - } -}; - -struct Ns32000LetterParser final : LetterParser, Singleton { - char stringDelimiter(StrScanner &scan) const override { return scan.expect('"'); } - char readLetter(StrScanner &scan, ErrorAt &error, char delim) const override { - auto c = *scan++; - if (c == '\\' && *scan) { - c = *scan++; - } else if (c == delim) { - error.setErrorIf(ILLEGAL_CONSTANT); - } - return c; - } -}; - } // namespace const ValueParser::Plugins &AsmNs32000::defaultPlugins() { diff --git a/src/asm_pdp8.cpp b/src/asm_pdp8.cpp index 480d754b..f64e9bca 100644 --- a/src/asm_pdp8.cpp +++ b/src/asm_pdp8.cpp @@ -45,61 +45,6 @@ constexpr Pseudo PSEUDOS[] PROGMEM = { // clang-format on PROGMEM constexpr Pseudos PSEUDO_TABLE{ARRAY_RANGE(PSEUDOS)}; -struct Pdp8SymbolParser final : SymbolParser, Singleton { - bool locationSymbol(StrScanner &scan) const override { - return SymbolParser::locationSymbol(scan, '.') || SymbolParser::locationSymbol(scan, '$'); - } - bool labelDelimitor(StrScanner &scan) const override { return scan.expect(','); } - bool instructionLetter(char c) const override { - return SymbolParser::symbolLetter(c) || c == '*' || c == '='; - } - bool instructionTerminator(char c) const override { return c == '*' || c == '='; } -}; - -struct Pdp8LetterParser final : LetterParser, Singleton { - Error parseLetter(StrScanner &scan, char &letter) const override { - if (*scan == '\'') - return LetterParser::parseLetter(scan, letter); - auto p = scan; - if (p.expect('"')) { - ErrorAt error; - letter = readLetter(p, error, 0); - if (error.isOK()) { - scan = p; - return OK; - } - return ILLEGAL_CONSTANT; - } - return NOT_AN_EXPECTED; - } - - char readLetter(StrScanner &scan, ErrorAt &error, char delim) const override { - UNUSED(delim); - const auto c = *scan; - if (c == 0 || (c >= 0x60 && c < 0x7F)) { - error.setErrorIf(ILLEGAL_CONSTANT); // no lowercase letter - return 0; - } - ++scan; - return c + 0x80; // convert to DEC 8-Bit form. - } -}; - -struct Pdp8CommentParser final : CommentParser, Singleton { - bool endOfLine(StrScanner &scan) const override { - return *scan == 0 || *scan == '/' || *scan == ';'; - }; -}; - -struct Pdp8OperatorParser final : OperatorParser, Singleton { - const Operator *readInfix( - StrScanner &scan, ValueStack &stack, ParserContext &context) const override { - if (scan.expect('!')) - return &Operator::OP_BITWISE_OR; - return CStyleOperatorParser::singleton().readInfix(scan, stack, context); - } -}; - } // namespace const ValueParser::Plugins &AsmPdp8::defaultPlugins() { diff --git a/src/asm_scn2650.cpp b/src/asm_scn2650.cpp index 604d6909..951dbd3a 100644 --- a/src/asm_scn2650.cpp +++ b/src/asm_scn2650.cpp @@ -42,18 +42,6 @@ constexpr Pseudo PSEUDOS[] PROGMEM = { // clang-format on PROGMEM constexpr Pseudos PSEUDO_TABLE{ARRAY_RANGE(PSEUDOS)}; -/** - * Signetics style numbers are the same as IBM except H'hh' for hexadecimal. - */ -struct SigneticsNumberParser final : IbmNumberParser, Singleton { - SigneticsNumberParser() : IbmNumberParser('H', 'B', 'O', 'D') {} -}; - -struct SigneticsLetterParser final : LetterParser, Singleton { - bool letterPrefix(StrScanner &scan) const override { return scan.iexpect('A'); } - bool stringPrefix(StrScanner &scan) const override { return scan.iexpect('A'); } -}; - } // namespace const ValueParser::Plugins &AsmScn2650::defaultPlugins() { @@ -61,6 +49,9 @@ const ValueParser::Plugins &AsmScn2650::defaultPlugins() { const NumberParser &number() const override { return SigneticsNumberParser::singleton(); } const CommentParser &comment() const override { return StarCommentParser::singleton(); } const LetterParser &letter() const override { return SigneticsLetterParser::singleton(); } + const OperatorParser &operators() const override { + return SigneticsOperatorParser::singleton(); + } } PLUGINS{}; return PLUGINS; } @@ -90,14 +81,13 @@ Error AsmScn2650::parseOperand(StrScanner &scan, Operand &op) const { return OK; } - const auto bop = p.expect([](char c) { return c == '<' || c == '>'; }); op.indir = p.expect('*'); op.val = parseInteger(p.skipSpaces(), op); if (op.hasError()) return op.getError(); if (p.expect(',')) { op.reg = parseRegName(p.skipSpaces()); - if (op.reg == REG_UNDEF || bop) + if (op.reg == REG_UNDEF) return op.setError(UNKNOWN_OPERAND); if (p.skipSpaces().expect(',')) { op.sign = p.skipSpaces().expect([](char c) { return c == '+' || c == '-'; }); @@ -115,10 +105,6 @@ Error AsmScn2650::parseOperand(StrScanner &scan, Operand &op) const { if (op.indir) { op.mode = M_AB15; } else { - if (bop == '<') - op.val.setUnsigned(op.val.getUnsigned() & 0xFF); // LSB - if (bop == '>') - op.val.setUnsigned((op.val.getUnsigned() >> 8) & 0xFF); // MSB; op.mode = M_IMM8; } scan = p; diff --git a/src/asm_tlcs90.cpp b/src/asm_tlcs90.cpp index 26f7ae2b..6206e18a 100644 --- a/src/asm_tlcs90.cpp +++ b/src/asm_tlcs90.cpp @@ -46,13 +46,7 @@ AsmTlcs90::AsmTlcs90(const ValueParser::Plugins &plugins) } const ValueParser::Plugins &AsmTlcs90::defaultPlugins() { - static const struct final : ValueParser::Plugins { - const NumberParser &number() const override { return IntelNumberParser::singleton(); } - const SymbolParser &symbol() const override { - return UnderQuestionSymbolParser::singleton(); - } - } PLUGINS{}; - return PLUGINS; + return ValueParser::Plugins::intel(); } namespace { diff --git a/src/asm_tms32010.cpp b/src/asm_tms32010.cpp index d6eb3676..d99965db 100644 --- a/src/asm_tms32010.cpp +++ b/src/asm_tms32010.cpp @@ -41,24 +41,6 @@ constexpr Pseudo PSEUDOS[] PROGMEM = { // clang-format on PROGMEM constexpr Pseudos PSEUDO_TABLE{ARRAY_RANGE(PSEUDOS)}; -struct Tms32010CommentParser final : CommentParser, Singleton { - bool commentLine(StrScanner &scan) const override { return *scan == '*'; } - bool endOfLine(StrScanner &scan) const override { - return SemicolonCommentParser::singleton().endOfLine(scan); - } -}; - -struct Tms32010SymbolParser final : SimpleSymbolParser, Singleton { - Tms32010SymbolParser() : SimpleSymbolParser(PSTR_UNDER_DOLLAR) {} - bool instructionLetter(char c) const override { - return SimpleSymbolParser::instructionLetter(c) || c == '.'; - } -}; - -struct Tms32010LetterParser final : LetterParser, Singleton { - char stringDelimiter(StrScanner &scan) const override { return scan.expect('"'); } -}; - } // namespace const ValueParser::Plugins &AsmTms32010::defaultPlugins() { diff --git a/src/asm_z8.cpp b/src/asm_z8.cpp index 243b6a55..ea489e1f 100644 --- a/src/asm_z8.cpp +++ b/src/asm_z8.cpp @@ -49,20 +49,11 @@ constexpr Pseudo PSEUDOS[] PROGMEM = { // clang-format on PROGMEM constexpr Pseudos PSEUDO_TABLE{ARRAY_RANGE(PSEUDOS)}; -struct Z8SymbolParser final : SimpleSymbolParser, Singleton { - Z8SymbolParser() : SimpleSymbolParser(PSTR_UNDER_DOT_DOLLAR_QUESTION) {} -}; - } // namespace const ValueParser::Plugins &AsmZ8::defaultPlugins() { - static const struct final : ValueParser::Plugins { - const NumberParser &number() const override { return ZilogNumberParser::singleton(); } + static const struct final : ValueParser::ZilogPlugins { const SymbolParser &symbol() const override { return Z8SymbolParser::singleton(); } - const LetterParser &letter() const override { return ZilogLetterParser::singleton(); } - const OperatorParser &operators() const override { - return ZilogOperatorParser::singleton(); - } } PLUGINS{}; return PLUGINS; } diff --git a/src/asm_z80.cpp b/src/asm_z80.cpp index f3b5a510..459ae91a 100644 --- a/src/asm_z80.cpp +++ b/src/asm_z80.cpp @@ -45,11 +45,7 @@ PROGMEM constexpr Pseudos PSEUDO_TABLE{ARRAY_RANGE(PSEUDOS)}; } // namespace const ValueParser::Plugins &AsmZ80::defaultPlugins() { - static const struct final : ValueParser::Plugins { - const NumberParser &number() const override { return IntelNumberParser::singleton(); } - const SymbolParser &symbol() const override { - return UnderQuestionSymbolParser::singleton(); - } + static const struct final : ValueParser::IntelPlugins { const OperatorParser &operators() const override { return ZilogOperatorParser::singleton(); } diff --git a/src/asm_z8000.cpp b/src/asm_z8000.cpp index 38f19d75..da40862d 100644 --- a/src/asm_z8000.cpp +++ b/src/asm_z8000.cpp @@ -45,20 +45,11 @@ constexpr Pseudo PSEUDOS[] PROGMEM = { // clang-format on PROGMEM constexpr Pseudos PSEUDO_TABLE{ARRAY_RANGE(PSEUDOS)}; -struct Z8000SymbolParser final : PrefixSymbolParser, Singleton { - Z8000SymbolParser() : PrefixSymbolParser(nullptr, PSTR_UNDER) {} -}; - } // namespace const ValueParser::Plugins &AsmZ8000::defaultPlugins() { - static const struct final : ValueParser::Plugins { - const NumberParser &number() const override { return ZilogNumberParser::singleton(); } + static const struct final : ValueParser::ZilogPlugins { const SymbolParser &symbol() const override { return Z8000SymbolParser::singleton(); } - const LetterParser &letter() const override { return ZilogLetterParser::singleton(); } - const OperatorParser &operators() const override { - return ZilogOperatorParser::singleton(); - } } PLUGINS{}; return PLUGINS; } diff --git a/src/comment_parser.h b/src/comment_parser.h index 1e9dd91d..467380f1 100644 --- a/src/comment_parser.h +++ b/src/comment_parser.h @@ -26,28 +26,58 @@ namespace libasm { * Comment parser */ struct CommentParser { + /** Return if |scan| points line comment. */ virtual bool commentLine(StrScanner &scan) const { return endOfLine(scan); } + /** Return if |scan| points comment. */ virtual bool endOfLine(StrScanner &scan) const = 0; }; struct SemicolonCommentParser final : CommentParser, Singleton { + /** A comment starts with ";". */ + bool endOfLine(StrScanner &scan) const override; +}; + +struct SharpCommentParser final : CommentParser, Singleton { + /** A comment starts with ";" or "#". */ + bool endOfLine(StrScanner &scan) const override; +}; + +struct StarCommentParser final : CommentParser, Singleton { + /** A comment line starts with "*" or ";". */ + bool commentLine(StrScanner &scan) const override; + /** If a comment starts with " " then skip spaces, otherwise starts with ";". */ + bool endOfLine(StrScanner &scan) const override; +}; + +struct RcaCommentParser final : CommentParser, Singleton { + /** A comment line starts with ".." or ";". */ + bool commentLine(StrScanner &scan) const override; + /** A comment starts with ";". */ bool endOfLine(StrScanner &scan) const override { - return *scan.skipSpaces() == 0 || *scan == ';'; + return SemicolonCommentParser::singleton().endOfLine(scan); } }; -struct SharpCommentParser final : CommentParser, Singleton { +struct MostekCommentParser final : CommentParser, Singleton { + /** A comment line starts with ";". */ + bool commentLine(StrScanner &scan) const override { + return SemicolonCommentParser::singleton().commentLine(scan); + } + /** If a comment starts with " " then skip spaces, otherwise starts with ";". */ bool endOfLine(StrScanner &scan) const override { - return SemicolonCommentParser::singleton().endOfLine(scan) || *scan == '#'; + return StarCommentParser::singleton().endOfLine(scan); } }; -struct StarCommentParser final : CommentParser, Singleton { - bool commentLine(StrScanner &scan) const override { return *scan == '*' || *scan == ';'; } +struct Pdp8CommentParser final : CommentParser, Singleton { + /** A comment starts with "/" or ";". */ + bool endOfLine(StrScanner &scan) const override; +}; + +struct Tms32010CommentParser final : CommentParser, Singleton { + bool commentLine(StrScanner &scan) const override { return *scan == '*'; } bool endOfLine(StrScanner &scan) const override { - const auto end = (*scan == 0 || *scan == ' '); - scan.skipSpaces(); - return end || SemicolonCommentParser::singleton().endOfLine(scan); + return SemicolonCommentParser::singleton().endOfLine(scan); } }; diff --git a/src/function_table.h b/src/function_table.h new file mode 100644 index 00000000..354a65d1 --- /dev/null +++ b/src/function_table.h @@ -0,0 +1,59 @@ +/* + * Copyright 2024 Tadashi G. Takaoka + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LIBASM_FUNCTION_TABLE_H__ +#define __LIBASM_FUNCTION_TABLE_H__ + +#include "operators.h" +#include "str_scanner.h" + +namespace libasm { + +/** + * Pre-defined function table. + */ +struct FunctionTable { + /** + * Look up |name| and returns a Functor pointer for a function, otherwise return nullptr. + */ + virtual const Functor *lookupFunction(const StrScanner &) const { return nullptr; } +}; + +struct RcaFunctionTable final : FunctionTable, Singleton { + /** A(), A.0(), A.1() */ + const Functor *lookupFunction(const StrScanner &name) const override; +}; + +struct Ins8060FunctionTable final : FunctionTable, Singleton { + /** H(), L(), ADDR() */ + const Functor *lookupFunction(const StrScanner &) const override; +}; + +struct Ins8070FunctionTable final : FunctionTable, Singleton { + /** H(), L(), ADDR() */ + const Functor *lookupFunction(const StrScanner &) const override; +}; + +} // namespace libasm + +#endif + +// Local Variables: +// mode: c++ +// c-basic-offset: 4 +// tab-width: 4 +// End: +// vim: set ft=cpp et ts=4 sw=4: diff --git a/src/letter_parser.h b/src/letter_parser.h index 70ce27d3..b5f87951 100644 --- a/src/letter_parser.h +++ b/src/letter_parser.h @@ -70,39 +70,86 @@ struct LetterParser { }; struct CStyleLetterParser final : LetterParser, Singleton { - /** C-style letter is 'c' where c is [:print:], \['"?\btnt], \x[0-9A-Fa-f]+, \[0-7]+ */ + /** A letter is 'c' where c is [:print:], \['"?\btnt], \x[0-9A-Fa-f]+, \[0-7]+ */ char readLetter(StrScanner &scan, ErrorAt &error, char delim) const override; - /** C-style string is "str". */ + /** A string is "str". */ char stringDelimiter(StrScanner &scan) const override { return scan.expect('"'); } }; struct MotorolaLetterParser final : LetterParser, Singleton { /** - * Motorola style letter is followed after a single quote and optionally closed with another - * single quote + * A letter is followed after a single quote and optionally closed with + * another single quote. */ Error parseLetter(StrScanner &scan, char &letter) const override; }; struct ZilogLetterParser final : LetterParser, Singleton { /** - * Zilog style letter is followed after a single quote and hexadecimal escape sequence with - * '%hh'. Also a single quote is expressed as %Q. + * A letter is followed after a single quote and hexadecimal escape sequence + * with '%hh'. Also a single quote is expressed as %Q. */ char readLetter(StrScanner &scan, ErrorAt &error, char delim) const override; }; -struct IbmLetterParser final : LetterParser, Singleton { - /** IBM style letter constant is C'c'. */ +struct PrefixLetterParser : LetterParser { + PrefixLetterParser(char prefix) : _prefix(prefix) {} + /** A letter constant is [prefix]'[:print:]', and [prefix] is optional. */ bool letterPrefix(StrScanner &scan) const override { - scan.iexpect('C'); // optional + scan.iexpect(_prefix); return true; } - /** IBM style string constant is C'str'. */ + + /** A string constant is [prefix]'[:print:]', and [prefix] is optional. */ bool stringPrefix(StrScanner &scan) const override { - scan.iexpect('C'); // optional + scan.iexpect(_prefix); return true; } + +private: + const char _prefix; +}; + +struct IbmLetterParser final : PrefixLetterParser, Singleton { + IbmLetterParser() : PrefixLetterParser('C') {} +}; + +struct RcaLetterParser final : PrefixLetterParser, Singleton { + RcaLetterParser() : PrefixLetterParser('T') {} +}; + +struct FairchildLetterParser final : LetterParser, Singleton { + /** A letter is C'[:print:]', #[:print:], '[:print:]'? */ + Error parseLetter(StrScanner &scan, char &letter) const override; + /** A string constant is C'str'. */ + bool stringPrefix(StrScanner &scan) const override; +}; + +struct MostekLetterParser final : LetterParser, Singleton { + Error parseLetter(StrScanner &scan, char &letter) const override { + return MotorolaLetterParser::singleton().parseLetter(scan, letter); + } + /** A strinf constant is 'str' or "str". */ + char stringDelimiter(StrScanner &scan) const override; +}; + +struct SigneticsLetterParser final : LetterParser, Singleton { + bool letterPrefix(StrScanner &scan) const override { return scan.iexpect('A'); } + bool stringPrefix(StrScanner &scan) const override { return scan.iexpect('A'); } +}; + +struct Ns32000LetterParser final : LetterParser, Singleton { + char stringDelimiter(StrScanner &scan) const override { return scan.expect('"'); } + char readLetter(StrScanner &scan, ErrorAt &error, char delim) const override; +}; + +struct Pdp8LetterParser final : LetterParser, Singleton { + Error parseLetter(StrScanner &scan, char &letter) const override; + char readLetter(StrScanner &scan, ErrorAt &error, char delim) const override; +}; + +struct Tms32010LetterParser final : LetterParser, Singleton { + char stringDelimiter(StrScanner &scan) const override { return scan.expect('"'); } }; } // namespace libasm diff --git a/src/number_parser.h b/src/number_parser.h index 912c4156..b6ce5a12 100644 --- a/src/number_parser.h +++ b/src/number_parser.h @@ -49,7 +49,8 @@ struct NumberParser { * Base for character prefixed number parser. */ struct PrefixNumberParser : NumberParser { - PrefixNumberParser(char hex, char bin, char oct, char dec); + PrefixNumberParser(char hex, char bin, char oct, char dec) + : _hex(hex), _bin(bin), _oct(oct), _dec(dec) {} Error parseNumber(StrScanner &scan, Value &val, Radix defaultRadix) const override; @@ -87,7 +88,18 @@ struct IntelNumberParser final : NumberParser, Singleton { Error parseNumber(StrScanner &scan, Value &val, Radix defaultRadix) const override; Error parseNumber(StrScanner &scan, Value &val, Radix radix, StrScanner &end) const; - static Radix hasSuffix(StrScanner &scan, Radix defaultRadix); + static Radix hasSuffix(StrScanner &scan); +}; + +/** + * Motorola style numbers are + * - Decimal: "{&}[0-9]+" + * - Hexadecimal: "$[0-9A-Fa-f]+" + * - Octal: "@[0-7]+" + * - Binary: "%[01]+" + */ +struct MotorolaNumberParser final : PrefixNumberParser, Singleton { + MotorolaNumberParser() : PrefixNumberParser('$', '%', '@', '&') {} }; /** @@ -105,14 +117,12 @@ struct ZilogNumberParser final : NumberParser, Singleton { }; /** - * Motorola style numbers are - * - Decimal: "{&}[0-9]+" - * - Hexadecimal: "$[0-9A-Fa-f]+" - * - Octal: "@[0-7]+" - * - Binary: "%[01]+" + * Texas Instrument style numbers is: + * - '>hh' as hexadecimal. + * - '?bb' as binary. */ -struct MotorolaNumberParser final : PrefixNumberParser, Singleton { - MotorolaNumberParser() : PrefixNumberParser('$', '%', '@', '&') {} +struct TexasNumberParser final : PrefixNumberParser, Singleton { + TexasNumberParser() : PrefixNumberParser('>', '?', 0, 0) {} }; /** @@ -128,6 +138,29 @@ struct IbmNumberParser : PrefixNumberParser { Error parseNumber(StrScanner &scan, Value &val, Radix defaultRadix) const override; }; +/** RCA style numbers are the same as IBM plus '#hh' for hexadecimal. */ +struct RcaNumberParser final : IbmNumberParser, Singleton { + RcaNumberParser() : IbmNumberParser('X', 'B', 0, 'D') {} + Error parseNumber(StrScanner &scan, Value &val, Radix defaultRadix) const override; +}; + +/** + * Fairchild style numbers are the same as IBM plus '$hh' for hexadecimal. + */ +struct FairchildNumberParser final : IbmNumberParser, Singleton { + FairchildNumberParser() : IbmNumberParser('H', 'B', 'O', 'D') {} + Error parseNumber(StrScanner &scan, Value &val, Radix defaultRadix) const override; +}; + +struct PanasonicNumberParser final : IbmNumberParser, Singleton { + PanasonicNumberParser() : IbmNumberParser('X', 0, 0, 0) {} +}; + +/** A numbers are the same as IBM except H'hh' for hexadecimal. */ +struct SigneticsNumberParser final : IbmNumberParser, Singleton { + SigneticsNumberParser() : IbmNumberParser('H', 'B', 'O', 'D') {} +}; + /** * National style numbers are * - Decimal: "[0-9]+|[dD]'[0-9]+'?" @@ -148,13 +181,8 @@ struct Ins80xxNumberParser final : NationalNumberParser, Singletonhh' as hexadecimal. - * - '?bb' as binary. - */ -struct TexasNumberParser final : PrefixNumberParser, Singleton { - TexasNumberParser() : PrefixNumberParser('>', '?', 0, 0) {} +struct Ns32000NumberParser final : NationalNumberParser, Singleton { + Ns32000NumberParser() : NationalNumberParser(/* 'X','H' */ 0, 'B', /* 'O' or */ 'Q', 'D') {} }; } // namespace libasm diff --git a/src/operators.cpp b/src/operators.cpp index b7ad2faa..f7c173c8 100644 --- a/src/operators.cpp +++ b/src/operators.cpp @@ -17,10 +17,15 @@ #include "operators.h" #include #include +#include "function_table.h" +#include "reg_ins8060.h" #include "str_scanner.h" +#include "text_common.h" namespace libasm { +using namespace text::common; + bool Operator::isHigher(const Operator &o) const { return _prec < o._prec || (_prec == o._prec && o._assoc == LEFT); } @@ -352,37 +357,37 @@ static Error logical_shift_right_16bit(ValueStack &stack, ParserContext &) { } // clang-format off -static const Operator MC68_EXPONENTIAL( 5, R, 2, exponential); -static const Operator MC68_ROTATE_LEFT( 5, L, 2, rotate_left_16bit); -static const Operator MC68_ROTATE_RIGHT(5, L, 2, rotate_right_16bit); -static const Operator MC68_SHIFT_LEFT( 5, L, 2, logical_shift_left_16bit); -static const Operator MC68_SHIFT_RIGHT( 5, L, 2, logical_shift_right_16bit); -static const Operator MC68_BITWISE_AND( 5, L, 2, bitwise_and); -static const Operator MC68_BITWISE_XOR( 5, L, 2, bitwise_xor); -static const Operator MC68_BITWISE_OR( 5, L, 2, bitwise_or); +static const Operator MOTOROLA_EXPONENTIAL( 5, R, 2, exponential); +static const Operator MOTOROLA_ROTATE_LEFT( 5, L, 2, rotate_left_16bit); +static const Operator MOTOROLA_ROTATE_RIGHT(5, L, 2, rotate_right_16bit); +static const Operator MOTOROLA_SHIFT_LEFT( 5, L, 2, logical_shift_left_16bit); +static const Operator MOTOROLA_SHIFT_RIGHT( 5, L, 2, logical_shift_right_16bit); +static const Operator MOTOROLA_BITWISE_AND( 5, L, 2, bitwise_and); +static const Operator MOTOROLA_BITWISE_XOR( 5, L, 2, bitwise_xor); +static const Operator MOTOROLA_BITWISE_OR( 5, L, 2, bitwise_or); // clang-format on -const Operator *Mc68xxOperatorParser::readInfix( +const Operator *MotorolaOperatorParser::readInfix( StrScanner &scan, ValueStack &stack, ParserContext &context) const { auto p = scan; const Operator *opr = nullptr; if (p.expect('!')) { if (p.expect('.')) { - opr = &MC68_BITWISE_AND; + opr = &MOTOROLA_BITWISE_AND; } else if (p.expect('+')) { - opr = &MC68_BITWISE_OR; + opr = &MOTOROLA_BITWISE_OR; } else if (p.expect('X') && !isalnum(*p)) { - opr = &MC68_BITWISE_XOR; + opr = &MOTOROLA_BITWISE_XOR; } else if (p.expect('^')) { - opr = &MC68_EXPONENTIAL; + opr = &MOTOROLA_EXPONENTIAL; } else if (p.expect('<')) { - opr = &MC68_SHIFT_LEFT; + opr = &MOTOROLA_SHIFT_LEFT; } else if (p.expect('>')) { - opr = &MC68_SHIFT_RIGHT; + opr = &MOTOROLA_SHIFT_RIGHT; } else if (p.expect('L') && !isalnum(*p)) { - opr = &MC68_ROTATE_LEFT; + opr = &MOTOROLA_ROTATE_LEFT; } else if (p.expect('R') && !isalnum(*p)) { - opr = &MC68_ROTATE_RIGHT; + opr = &MOTOROLA_ROTATE_RIGHT; } } if (opr) { @@ -503,8 +508,6 @@ const Operator *IntelOperatorParser::readInfix( } // clang-format off -static const Operator ZILOG_HIGH16( 3, R, 1, most_siginificant_word); -static const Operator ZILOG_LOW16( 3, R, 1, least_significant_word); static const Operator ZILOG_SHIFT_RIGHT(5, L, 1, logical_shift_right_16bit); static const Operator ZILOG_SHIFT_LEFT( 5, L, 1, logical_shift_left_16bit); static const Operator ZILOG_BITWISE_AND(5, L, 2, bitwise_and); @@ -526,9 +529,9 @@ const Operator *ZilogOperatorParser::readPrefix( } else if (name.iequals_P(PSTR("LOW"))) { opr = &INTEL_LOW; } else if (name.iequals_P(PSTR("HIGH16"))) { - opr = &ZILOG_HIGH16; + opr = &INTEL_MSW; } else if (name.iequals_P(PSTR("LOW16"))) { - opr = &ZILOG_LOW16; + opr = &INTEL_LSW; } if (opr) { scan = p; @@ -564,6 +567,101 @@ const Operator *ZilogOperatorParser::readInfix( return CStyleOperatorParser::singleton().readInfix(scan, stack, context); } +const Operator *SigneticsOperatorParser::readPrefix( + StrScanner &scan, ValueStack &stack, ParserContext &context) const { + if (scan.expect('<')) { + return &INTEL_LOW; + } else if (scan.expect('>')) { + return &INTEL_HIGH; + } + return CStyleOperatorParser::singleton().readPrefix(scan, stack, context); +} + +const Operator *Pdp8OperatorParser::readInfix( + StrScanner &scan, ValueStack &stack, ParserContext &context) const { + if (scan.expect('!')) + return &Operator::OP_BITWISE_OR; + return CStyleOperatorParser::singleton().readInfix(scan, stack, context); +} + +const struct : Functor { + int_fast8_t nargs() const override { return 1; } + Error eval(ValueStack &stack, ParserContext &, uint_fast8_t) const override { + stack.pushUnsigned(stack.pop().getUnsigned() & UINT8_MAX); + return OK; + } +} FN_LOW; + +const struct : Functor { + int_fast8_t nargs() const override { return 1; } + Error eval(ValueStack &stack, ParserContext &, uint_fast8_t) const override { + stack.pushUnsigned((stack.pop().getUnsigned() >> 8) & UINT8_MAX); + return OK; + } +} FN_HIGH; + +namespace rca { +const struct : Functor { + int_fast8_t nargs() const override { return 1; } + Error eval(ValueStack &stack, ParserContext &, uint_fast8_t) const override { + // Mark that this is 2 bytes value. + stack.pushUnsigned((stack.pop().getUnsigned() & UINT16_MAX) | UINT32_C(0x1000'0000)); + return OK; + } +} FN_A; +} // namespace rca + +const Functor *RcaFunctionTable::lookupFunction(const StrScanner &name) const { + if (name.iequals_P(PSTR("A.0"))) + return &FN_LOW; + if (name.iequals_P(PSTR("A.1"))) + return &FN_HIGH; + if (name.iequals_P(PSTR("A"))) + return &rca::FN_A; + return nullptr; +} + +namespace ins8060 { +const struct : Functor { + int_fast8_t nargs() const override { return 1; } + Error eval(ValueStack &stack, ParserContext &, uint_fast8_t) const override { + const auto v = stack.pop().getUnsigned(); + stack.pushUnsigned(reg::page(v) | reg::offset(v - 1)); + return OK; + } +} FN_ADDR; +} // namespace ins8060 + +const Functor *Ins8060FunctionTable::lookupFunction(const StrScanner &name) const { + if (name.iequals_P(TEXT_FN_H)) + return &FN_HIGH; + if (name.iequals_P(TEXT_FN_L)) + return &FN_LOW; + if (name.iequals_P(TEXT_FN_ADDR)) + return &ins8060::FN_ADDR; + return nullptr; +} + +namespace ins8070 { +const struct : Functor { + int_fast8_t nargs() const override { return 1; } + Error eval(ValueStack &stack, ParserContext &, uint_fast8_t) const override { + stack.pushUnsigned((stack.pop().getUnsigned() - 1) & 0xFFFF); + return OK; + } +} FN_ADDR; +} // namespace ins8070 + +const Functor *Ins8070FunctionTable::lookupFunction(const StrScanner &name) const { + if (name.iequals_P(TEXT_FN_H)) + return &FN_HIGH; + if (name.iequals_P(TEXT_FN_L)) + return &FN_LOW; + if (name.iequals_P(TEXT_FN_ADDR)) + return &ins8070::FN_ADDR; + return nullptr; +} + } // namespace libasm // Local Variables: diff --git a/src/operators.h b/src/operators.h index f4176469..18564d4f 100644 --- a/src/operators.h +++ b/src/operators.h @@ -18,7 +18,6 @@ #define __LIBASM_OPERATORS_H__ #include - #include "error_reporter.h" #include "stack.h" #include "value.h" @@ -145,20 +144,29 @@ struct CStyleOperatorParser final : OperatorParser, Singleton { +struct IntelOperatorParser final : OperatorParser, Singleton { + const Operator *readPrefix(StrScanner &, ValueStack &, ParserContext &) const override; const Operator *readInfix(StrScanner &, ValueStack &, ParserContext &) const override; }; -struct IntelOperatorParser final : OperatorParser, Singleton { - const Operator *readPrefix(StrScanner &, ValueStack &, ParserContext &) const override; +struct MotorolaOperatorParser final : OperatorParser, Singleton { const Operator *readInfix(StrScanner &, ValueStack &, ParserContext &) const override; }; +struct SigneticsOperatorParser final : OperatorParser, Singleton { + const Operator *readPrefix(StrScanner &, ValueStack &, ParserContext &) const override; +}; + struct ZilogOperatorParser final : OperatorParser, Singleton { const Operator *readPrefix(StrScanner &, ValueStack &, ParserContext &) const override; const Operator *readInfix(StrScanner &, ValueStack &, ParserContext &) const override; }; +struct Pdp8OperatorParser final : OperatorParser, Singleton { + const Operator *readInfix( + StrScanner &scan, ValueStack &stack, ParserContext &context) const override; +}; + } // namespace libasm #endif diff --git a/src/parsers.cpp b/src/parsers.cpp index edeef9d1..bf31039c 100644 --- a/src/parsers.cpp +++ b/src/parsers.cpp @@ -14,30 +14,34 @@ * limitations under the License. */ -#include "parsers.h" #include +#include "comment_parser.h" #include "config_base.h" +#include "function_table.h" +#include "letter_parser.h" +#include "number_parser.h" +#include "symbol_parser.h" #include "text_common.h" -using namespace libasm::text::common; - namespace libasm { +using namespace text::common; + namespace { -bool isoctal(char c) { +bool is_octal(char c) { return c >= '0' && c < '8'; } -bool isbinary(char c) { +bool is_binary(char c) { return c == '0' || c == '1'; } -uint8_t tonumbert(char c) { +uint8_t to_digit(char c) { return isdigit(c) ? c - '0' : toupper(c) - 'A' + 10; } -bool isValidDigit(const char c, const Radix radix) { +bool is_digit(const char c, const Radix radix) { if (radix == RADIX_16) return isxdigit(c); return c >= '0' && c < '0' + uint8_t(radix); @@ -45,8 +49,82 @@ bool isValidDigit(const char c, const Radix radix) { } // namespace -PrefixNumberParser::PrefixNumberParser(char hex, char bin, char oct, char dec) - : _hex(hex), _bin(bin), _oct(oct), _dec(dec) {} +Error NumberParser::scanNumberEnd(StrScanner &scan, Radix radix, char suffix) { + auto p = scan; + if (radix == RADIX_2 && suffix == 'B') { + // Check whether Intel binary or C-style binary, '010b' vs '0b10' + if (p.expect('0') && p.iexpect('B') && is_binary(*p)) + return NOT_AN_EXPECTED; + p = scan; + } + if (is_digit(*p, radix)) { + if (radix == RADIX_16 && !is_digit(*p, RADIX_10)) + return NOT_AN_EXPECTED; + p.trimStart([radix](char c) { return is_digit(c, radix); }); + if (suffix == 0) { + if (!isalnum(*p)) { + scan = p; + return OK; + } + } else if (p.iexpect(suffix)) { + scan = p; + return OK; + } + } + return NOT_AN_EXPECTED; +} + +Radix CStyleNumberParser::hasPrefix(StrScanner &scan, Radix defaultRadix) const { + if (scan.iexpectText_P(PSTR_ZERO_X)) + return RADIX_16; + if (scan.iexpectText_P(PSTR_ZERO_B)) + return RADIX_2; + if (*scan == '0' && is_octal(scan[1])) + return RADIX_8; + if (is_digit(*scan, defaultRadix)) + return defaultRadix; + return RADIX_NONE; +} + +Error CStyleNumberParser::parseNumber(StrScanner &scan, Value &val, Radix defaultRadix) const { + auto p = scan; + const auto radix = hasPrefix(p, defaultRadix); + if (radix == RADIX_NONE) + return NOT_AN_EXPECTED; + + const auto error = val.read(p, radix); + if (error != NOT_AN_EXPECTED) + scan = p; + return error; +} + +Radix IntelNumberParser::hasSuffix(StrScanner &scan) { + if (scanNumberEnd(scan, RADIX_16, 'H') == OK) + return RADIX_16; + if (scanNumberEnd(scan, RADIX_8, 'O') == OK || scanNumberEnd(scan, RADIX_8, 'Q') == OK) + return RADIX_8; + if (scanNumberEnd(scan, RADIX_2, 'B') == OK) + return RADIX_2; + if (scanNumberEnd(scan, RADIX_10, 'D') == OK) + return RADIX_10; + return RADIX_NONE; +} + +Error IntelNumberParser::parseNumber(StrScanner &scan, Value &val, Radix defaultRadix) const { + auto end = scan; + const auto radix = hasSuffix(end); + if (radix == RADIX_NONE) + return CStyleNumberParser::singleton().parseNumber(scan, val, defaultRadix); + return parseNumber(scan, val, radix, end); +} + +Error IntelNumberParser::parseNumber( + StrScanner &scan, Value &val, Radix radix, StrScanner &end) const { + const auto error = val.read(scan, radix); + if (error != NOT_AN_EXPECTED) + scan = end; + return error; +} Radix PrefixNumberParser::hasPrefix(StrScanner &scan) const { if (_hex && scan.iexpect(_hex)) @@ -71,13 +149,35 @@ Error PrefixNumberParser::parseNumber(StrScanner &scan, Value &val, Radix defaul return error; } +Radix ZilogNumberParser::hasPrefix(StrScanner &scan) const { + if (scan.iexpectText_P(PSTR_PERCENT_8)) + return RADIX_8; + if (scan.iexpectText_P(PSTR_PERCENT_2)) + return RADIX_2; + if (scan.expect('%') && isxdigit(*scan)) + return RADIX_16; + return RADIX_NONE; +} + +Error ZilogNumberParser::parseNumber(StrScanner &scan, Value &val, Radix defaultRadix) const { + auto p = scan; + const auto radix = hasPrefix(p); + if (radix == RADIX_NONE) + return IntelNumberParser::singleton().parseNumber(scan, val, defaultRadix); + + const auto error = val.read(p, radix); + if (error != NOT_AN_EXPECTED) + scan = p; + return error; +} + Error IbmNumberParser::parseNumber(StrScanner &scan, Value &val, Radix defaultRadix) const { auto p = scan; const auto radix = hasPrefix(p); if (radix == RADIX_NONE) return IntelNumberParser::singleton().parseNumber(scan, val, defaultRadix); - if (!p.expect('\'') || !isValidDigit(*p, radix)) + if (!p.expect('\'') || !is_digit(*p, radix)) return NOT_AN_EXPECTED; const auto error = val.read(p, radix); @@ -88,6 +188,17 @@ Error IbmNumberParser::parseNumber(StrScanner &scan, Value &val, Radix defaultRa return MISSING_CLOSING_QUOTE; } +Error RcaNumberParser::parseNumber(StrScanner &scan, Value &val, Radix defaultRadix) const { + auto p = scan; + if (*p == '#' && isxdigit(p[1])) { + const auto error = val.read(++p, RADIX_16); + if (error == OK) + scan = p; + return error; + } + return IbmNumberParser::parseNumber(scan, val, defaultRadix); +} + Radix NationalNumberParser::hasPrefix(StrScanner &scan) const { if (_hex == 0 && (scan.iexpect('X') || scan.iexpect('H'))) return RADIX_16; @@ -102,7 +213,7 @@ Error NationalNumberParser::parseNumber(StrScanner &scan, Value &val, Radix defa if (radix == RADIX_NONE) return IntelNumberParser::singleton().parseNumber(scan, val, defaultRadix); - if (!p.expect('\'') || !isValidDigit(*p, radix)) + if (!p.expect('\'') || !is_digit(*p, radix)) return NOT_AN_EXPECTED; const auto error = val.read(p, radix); @@ -112,103 +223,95 @@ Error NationalNumberParser::parseNumber(StrScanner &scan, Value &val, Radix defa return error; } -Radix CStyleNumberParser::hasPrefix(StrScanner &scan, Radix defaultRadix) const { - if (scan.iexpectText_P(PSTR_ZERO_X)) - return RADIX_16; - if (scan.iexpectText_P(PSTR_ZERO_B)) - return RADIX_2; - if (*scan == '0' && isoctal(scan[1])) - return RADIX_8; - if (isValidDigit(*scan, defaultRadix)) - return defaultRadix; - return RADIX_NONE; +Error FairchildNumberParser::parseNumber(StrScanner &scan, Value &val, Radix defaultRadix) const { + auto p = scan; + if (*p == '$' && isxdigit(p[1])) { + const auto error = val.read(++p, RADIX_16); + if (error != NOT_AN_EXPECTED) + scan = p; + return error; + } + return IbmNumberParser::parseNumber(scan, val, defaultRadix); } -Error CStyleNumberParser::parseNumber(StrScanner &scan, Value &val, Radix defaultRadix) const { - auto p = scan; - const auto radix = hasPrefix(p, defaultRadix); - if (radix == RADIX_NONE) - return NOT_AN_EXPECTED; +bool SymbolParser::symbolLetter(char c, bool headOfSymbol) const { + return isalpha(c) || (!headOfSymbol && isdigit(c)) || c == '_'; +} - const auto error = val.read(p, radix); - if (error != NOT_AN_EXPECTED) +bool SymbolParser::locationSymbol(StrScanner &scan, char location) const { + auto p = scan; + if (p.expect(location) && !symbolLetter(*p)) { scan = p; - return error; + return true; + } + return false; } -Radix IntelNumberParser::hasSuffix(StrScanner &scan, Radix defaultRadix) { - if (scanNumberEnd(scan, RADIX_16, 'H') == OK) - return RADIX_16; - if (scanNumberEnd(scan, RADIX_8, 'O') == OK || scanNumberEnd(scan, RADIX_8, 'Q') == OK) - return RADIX_8; - if (scanNumberEnd(scan, RADIX_2, 'B') == OK) - return RADIX_2; - if (scanNumberEnd(scan, RADIX_10, 'D') == OK) - return RADIX_10; - return RADIX_NONE; +bool SimpleSymbolParser::symbolLetter(char c, bool headOfSymbol) const { + return SymbolParser::symbolLetter(c, headOfSymbol) || (c && strchr_P(_extra_P, c)); } -Error IntelNumberParser::parseNumber(StrScanner &scan, Value &val, Radix defaultRadix) const { - auto end = scan; - const auto radix = hasSuffix(end, defaultRadix); - if (radix == RADIX_NONE) - return CStyleNumberParser::singleton().parseNumber(scan, val, defaultRadix); - return parseNumber(scan, val, radix, end); +bool PrefixSymbolParser::symbolLetter(char c, bool headOfSymbol) const { + if (SymbolParser::symbolLetter(c, headOfSymbol)) + return true; + if (headOfSymbol && _prefix_P) + return c && strchr_P(_prefix_P, c); + if (_extra_P) + return c && strchr_P(_extra_P, c); + return false; } -Error IntelNumberParser::parseNumber( - StrScanner &scan, Value &val, Radix radix, StrScanner &end) const { - const auto error = val.read(scan, radix); - if (error != NOT_AN_EXPECTED) - scan = end; - return error; +bool RcaSymbolParser::functionNameLetter(char c) const { + return symbolLetter(c) || c == '.'; } -Error NumberParser::scanNumberEnd(StrScanner &scan, Radix radix, char suffix) { - auto p = scan; - if (radix == RADIX_2 && suffix == 'B') { - // Check whether Intel binary or C-style binary, '010b' vs '0b10' - if (p.expect('0') && p.iexpect('B') && isbinary(*p)) - return NOT_AN_EXPECTED; - p = scan; - } - if (isValidDigit(*p, radix)) { - if (radix == RADIX_16 && !isValidDigit(*p, RADIX_10)) - return NOT_AN_EXPECTED; - p.trimStart([radix](char c) { return isValidDigit(c, radix); }); - if (suffix == 0) { - if (!isalnum(*p)) { - scan = p; - return OK; - } - } else if (p.iexpect(suffix)) { - scan = p; - return OK; - } - } - return NOT_AN_EXPECTED; +bool RcaSymbolParser::instructionLetter(char c) const { + return SymbolParser::instructionLetter(c) || c == '='; } -Radix ZilogNumberParser::hasPrefix(StrScanner &scan) const { - if (scan.iexpectText_P(PSTR_PERCENT_8)) - return RADIX_8; - if (scan.iexpectText_P(PSTR_PERCENT_2)) - return RADIX_2; - if (scan.expect('%') && isxdigit(*scan)) - return RADIX_16; - return RADIX_NONE; +bool FairchildSymbolParser::locationSymbol(StrScanner &scan) const { + return SymbolParser::locationSymbol(scan, '*') || SymbolParser::locationSymbol(scan, '$') || + SymbolParser::locationSymbol(scan, '.'); } -Error ZilogNumberParser::parseNumber(StrScanner &scan, Value &val, Radix defaultRadix) const { - auto p = scan; - const auto radix = hasPrefix(p); - if (radix == RADIX_NONE) - return IntelNumberParser::singleton().parseNumber(scan, val, defaultRadix); +bool MostekSymbolParser::instructionLetter(char c) const { + return SymbolParser::instructionLetter(c) || c == '.' || c == '=' || c == '*' || c == ':'; +} - const auto error = val.read(p, radix); - if (error != NOT_AN_EXPECTED) - scan = p; - return error; +bool Ins80xxSymbolParser::locationSymbol(StrScanner &scan) const { + return SymbolParser::locationSymbol(scan, '.') || SymbolParser::locationSymbol(scan, '$'); +} + +bool Ins80xxSymbolParser::instructionLetter(char c) const { + return PrefixSymbolParser::instructionLetter(c) || c == '=' || c == '.'; +} + +bool Mc68000SymbolParser::instructionLetter(char c) const { + return PrefixSymbolParser::instructionLetter(c) || c == '.'; +} + +bool Ns32000SymbolParser::locationSymbol(StrScanner &scan) const { + return SymbolParser::locationSymbol(scan, '.') || SymbolParser::locationSymbol(scan, '*'); +} + +bool Ns32000SymbolParser::instructionLetter(char c) const { + return SimpleSymbolParser::instructionLetter(c) || c == '.'; +} + +bool Pdp8SymbolParser::locationSymbol(StrScanner &scan) const { + return SymbolParser::locationSymbol(scan, '.') || SymbolParser::locationSymbol(scan, '$'); +} + +bool Pdp8SymbolParser::instructionLetter(char c) const { + return SymbolParser::symbolLetter(c) || c == '*' || c == '='; +} + +bool Pdp8SymbolParser::instructionTerminator(char c) const { + return c == '*' || c == '='; +} + +bool Tms32010SymbolParser::instructionLetter(char c) const { + return SimpleSymbolParser::instructionLetter(c) || c == '.'; } Error LetterParser::parseLetter(StrScanner &scan, char &letter) const { @@ -260,19 +363,19 @@ char CStyleLetterParser::readLetter(StrScanner &scan, ErrorAt &error, char delim uint32_t n = 0; while (isxdigit(*p)) { n *= 16; - n += tonumbert(*p++); + n += to_digit(*p++); } scan = p; if (n > UINT8_MAX) error.setErrorIf(OVERFLOW_RANGE); return n; } - if (isoctal(*p)) { + if (is_octal(*p)) { // 1~3 octal digits. uint32_t n = 0; - for (auto i = 0; isoctal(*p) && i < 3; i++) { + for (auto i = 0; is_octal(*p) && i < 3; i++) { n *= 8; - n += tonumbert(*p++); + n += to_digit(*p++); } scan = p; if (n > UINT8_MAX) @@ -329,7 +432,7 @@ char ZilogLetterParser::readLetter(StrScanner &scan, ErrorAt &error, char delim) if (c == '%') { // Percent escape sequence if (isxdigit(p[0]) && isxdigit(p[1])) { - c = tonumbert(p[0]) * 16 + tonumbert(p[1]); + c = to_digit(p[0]) * 16 + to_digit(p[1]); p += 2; } else { c = *p++; @@ -362,6 +465,106 @@ char ZilogLetterParser::readLetter(StrScanner &scan, ErrorAt &error, char delim) return c; } +Error FairchildLetterParser::parseLetter(StrScanner &scan, char &letter) const { + auto p = scan; + if (p.iexpect('C')) { // C'C' + const auto error = LetterParser::parseLetter(p, letter); + if (error == OK) + scan = p; + return error; + } + if (p.expect('#')) { // #C + if ((letter = *p) == 0) + return NOT_AN_EXPECTED; + scan = ++p; + return OK; + } + if (p.expect('\'')) { // 'c' or 'c + ErrorAt error; + letter = readLetter(p, error, '\''); + if (error.isOK()) { + p.expect('\''); // closing quote is optional + scan = p; + return OK; + } + return error.getError(); + } + return NOT_AN_EXPECTED; +} + +bool FairchildLetterParser::stringPrefix(StrScanner &scan) const { + scan.iexpect('C'); // optional + return true; +} + +char MostekLetterParser::stringDelimiter(StrScanner &scan) const { + const auto c = scan.expect('\''); + return c ? c : scan.expect('"'); +} + +char Ns32000LetterParser::readLetter(StrScanner &scan, ErrorAt &error, char delim) const { + auto c = *scan++; + if (c == '\\' && *scan) { + c = *scan++; + } else if (c == delim) { + error.setErrorIf(ILLEGAL_CONSTANT); + } + return c; +} + +Error Pdp8LetterParser::parseLetter(StrScanner &scan, char &letter) const { + if (*scan == '\'') + return LetterParser::parseLetter(scan, letter); + auto p = scan; + if (p.expect('"')) { + ErrorAt error; + letter = readLetter(p, error, 0); + if (error.isOK()) { + scan = p; + return OK; + } + return ILLEGAL_CONSTANT; + } + return NOT_AN_EXPECTED; +} + +char Pdp8LetterParser::readLetter(StrScanner &scan, ErrorAt &error, char delim) const { + UNUSED(delim); + const auto c = *scan; + if (c == 0 || (c >= 0x60 && c < 0x7F)) { + error.setErrorIf(ILLEGAL_CONSTANT); // no lowercase letter + return 0; + } + ++scan; + return c + 0x80; // convert to DEC 8-Bit form. +} + +bool SemicolonCommentParser::endOfLine(StrScanner &scan) const { + return *scan.skipSpaces() == 0 || *scan == ';'; +} + +bool SharpCommentParser::endOfLine(StrScanner &scan) const { + return SemicolonCommentParser::singleton().endOfLine(scan) || *scan == '#'; +} + +bool StarCommentParser::commentLine(StrScanner &scan) const { + return *scan == '*' || *scan == ';'; +} + +bool StarCommentParser::endOfLine(StrScanner &scan) const { + const auto end = (*scan == 0 || *scan == ' '); + scan.skipSpaces(); + return end || SemicolonCommentParser::singleton().endOfLine(scan); +} + +bool RcaCommentParser::commentLine(StrScanner &scan) const { + return scan.iexpectText_P(PSTR("..")) || endOfLine(scan); +} + +bool Pdp8CommentParser::endOfLine(StrScanner &scan) const { + return *scan == 0 || *scan == '/' || *scan == ';'; +}; + } // namespace libasm // Local Variables: diff --git a/src/parsers.h b/src/parsers.h index 06956f36..6ef3f88d 100644 --- a/src/parsers.h +++ b/src/parsers.h @@ -18,29 +18,11 @@ #define __LIBASM_PARSERS_H__ #include "comment_parser.h" +#include "function_table.h" #include "letter_parser.h" #include "number_parser.h" #include "symbol_parser.h" -#include "error_reporter.h" -#include "operators.h" -#include "str_scanner.h" -#include "value.h" - -namespace libasm { - -/** - * Pre-defined function table. - */ -struct FunctionTable { - /** - * Look up |name| and returns a Functor pointer for a function, otherwise return nullptr. - */ - virtual const Functor *lookupFunction(const StrScanner &) const { return nullptr; } -}; - -} // namespace libasm - #endif // Local Variables: diff --git a/src/symbol_parser.h b/src/symbol_parser.h index 33f5efcf..6486cbaf 100644 --- a/src/symbol_parser.h +++ b/src/symbol_parser.h @@ -28,9 +28,7 @@ namespace libasm { */ struct SymbolParser { /** Default symbol is '[:alpha:][:alnum:]*' */ - virtual bool symbolLetter(char c, bool headOfSymbol = false) const { - return isalpha(c) || (!headOfSymbol && isdigit(c)) || c == '_'; - } + virtual bool symbolLetter(char c, bool headOfSymbol = false) const; /** Default location symbol is '$' */ virtual bool locationSymbol(StrScanner &scan) const { return locationSymbol(scan, '$'); } @@ -48,14 +46,7 @@ struct SymbolParser { virtual bool functionNameLetter(char c) const { return symbolLetter(c); } protected: - bool locationSymbol(StrScanner &scan, char location) const { - auto p = scan; - if (p.expect(location) && !symbolLetter(*p)) { - scan = p; - return true; - } - return false; - } + bool locationSymbol(StrScanner &scan, char location) const; }; /** @@ -63,9 +54,8 @@ struct SymbolParser { */ struct SimpleSymbolParser : SymbolParser { SimpleSymbolParser(const /*PROGMEM*/ char *extra_P) : _extra_P(extra_P) {} - bool symbolLetter(char c, bool headOfSymbol = false) const override { - return SymbolParser::symbolLetter(c, headOfSymbol) || (c && strchr_P(_extra_P, c)); - } + + bool symbolLetter(char c, bool headOfSymbol = false) const override; private: const /*PROGMEMD*/ char *const _extra_P; @@ -77,23 +67,44 @@ struct SimpleSymbolParser : SymbolParser { struct PrefixSymbolParser : SymbolParser { PrefixSymbolParser(const /*PROGMEM*/ char *prefix_P, const /*PROGMEM*/ char *extra_P = nullptr) : _prefix_P(prefix_P), _extra_P(extra_P) {} - bool symbolLetter(char c, bool headOfSymbol = false) const override { - if (SymbolParser::symbolLetter(c, headOfSymbol)) - return true; - if (headOfSymbol && _prefix_P) - return c && strchr_P(_prefix_P, c); - if (_extra_P) - return c && strchr_P(_extra_P, c); - return false; - } + + bool symbolLetter(char c, bool headOfSymbol = false) const override; private: const /*PROGMEMD*/ char *const _prefix_P; const /*PROGMEMD*/ char *const _extra_P; }; -struct UnderQuestionSymbolParser final : PrefixSymbolParser, Singleton { - UnderQuestionSymbolParser() : PrefixSymbolParser(nullptr, text::common::PSTR_UNDER_QUESTION) {} +struct IntelSymbolParser final : PrefixSymbolParser, Singleton { + IntelSymbolParser() : PrefixSymbolParser(nullptr, text::common::PSTR_UNDER_QUESTION) {} +}; + +struct RcaSymbolParser final : SymbolParser, Singleton { + /** Pre-defined function name may have '.' */ + bool functionNameLetter(char c) const override; + /** Symbol is definde by "=". */ + bool instructionLetter(char c) const override; + bool instructionTerminator(char c) const override { return c == '='; } +}; + +struct FairchildSymbolParser final : SymbolParser, Singleton { + /** Accepts location symbol '*', '$', '.' */ + bool locationSymbol(StrScanner &scan) const override; +}; + +struct PanasonicSymbolParser final : SymbolParser, Singleton { + bool locationSymbol(StrScanner &scan) const override { + return SymbolParser::locationSymbol(scan, '*'); + } +}; + +struct MostekSymbolParser final : SimpleSymbolParser, Singleton { + MostekSymbolParser() : SimpleSymbolParser(text::common::PSTR_UNDER) {} + bool locationSymbol(StrScanner &scan) const override { + return SymbolParser::locationSymbol(scan, '*'); + } + bool instructionLetter(char c) const override; + bool instructionTerminator(char c) const override { return c == '='; } }; struct Mc68xxSymbolParser final : PrefixSymbolParser, Singleton { @@ -106,13 +117,44 @@ struct Mc68xxSymbolParser final : PrefixSymbolParser, Singleton { Ins80xxSymbolParser() : PrefixSymbolParser(text::common::PSTR_DOLLAR) {} + bool locationSymbol(StrScanner &scan) const override; + bool instructionLetter(char c) const override; + bool instructionTerminator(char c) const override { return c == '='; } +}; + +struct Mc68000SymbolParser final : PrefixSymbolParser, Singleton { + Mc68000SymbolParser() + : PrefixSymbolParser(text::common::PSTR_DOT, text::common::PSTR_UNDER_DOT_DOLLAR) {} bool locationSymbol(StrScanner &scan) const override { - return SymbolParser::locationSymbol(scan, '.') || SymbolParser::locationSymbol(scan, '$'); - } - bool instructionLetter(char c) const override { - return PrefixSymbolParser::instructionLetter(c) || c == '=' || c == '.'; + return SymbolParser::locationSymbol(scan, '*'); } - bool instructionTerminator(char c) const override { return c == '='; } + bool instructionLetter(char c) const override; +}; + +struct Ns32000SymbolParser final : SimpleSymbolParser, Singleton { + Ns32000SymbolParser() : SimpleSymbolParser(text::common::PSTR_UNDER_DOT) {} + bool locationSymbol(StrScanner &scan) const override; + bool instructionLetter(char c) const override; +}; + +struct Pdp8SymbolParser final : SymbolParser, Singleton { + bool locationSymbol(StrScanner &scan) const override; + bool labelDelimitor(StrScanner &scan) const override { return scan.expect(','); } + bool instructionLetter(char c) const override; + bool instructionTerminator(char c) const override; +}; + +struct Tms32010SymbolParser final : SimpleSymbolParser, Singleton { + Tms32010SymbolParser() : SimpleSymbolParser(text::common::PSTR_UNDER_DOLLAR) {} + bool instructionLetter(char c) const override; +}; + +struct Z8SymbolParser final : SimpleSymbolParser, Singleton { + Z8SymbolParser() : SimpleSymbolParser(text::common::PSTR_UNDER_DOT_DOLLAR_QUESTION) {} +}; + +struct Z8000SymbolParser final : PrefixSymbolParser, Singleton { + Z8000SymbolParser() : PrefixSymbolParser(nullptr, text::common::PSTR_UNDER) {} }; } // namespace libasm diff --git a/src/value_parser.cpp b/src/value_parser.cpp index 355b9ca1..d348b7aa 100644 --- a/src/value_parser.cpp +++ b/src/value_parser.cpp @@ -64,6 +64,10 @@ const NumberParser &ValueParser::IntelPlugins::number() const { return IntelNumberParser::singleton(); } +const SymbolParser &ValueParser::IntelPlugins::symbol() const { + return IntelSymbolParser::singleton(); +} + const OperatorParser &ValueParser::IntelPlugins::operators() const { return IntelOperatorParser::singleton(); } @@ -90,88 +94,19 @@ const LetterParser &ValueParser::MotorolaPlugins::letter() const { } const OperatorParser &ValueParser::MotorolaPlugins::operators() const { - return Mc68xxOperatorParser::singleton(); + return MotorolaOperatorParser::singleton(); } -namespace fairchild { -/** - * Fairchild style numbers are the same as IBM plus '$hh' for hexadecimal. - */ -struct FairchildNumberParser final : NumberParser, Singleton { - Error parseNumber(StrScanner &scan, Value &val, Radix defaultRadix) const override { - auto p = scan; - if (*p == '$' && isxdigit(p[1])) { - const auto error = val.read(++p, RADIX_16); - if (error != NOT_AN_EXPECTED) - scan = p; - return error; - } - return _ibm.parseNumber(scan, val, defaultRadix); - } - -private: - IbmNumberParser _ibm{'H', 'B', 'O', 'D'}; -}; - -struct FairchildSymbolParser final : SymbolParser, Singleton { - bool locationSymbol(StrScanner &scan) const override { - return SymbolParser::locationSymbol(scan, '*') || SymbolParser::locationSymbol(scan, '$') || - SymbolParser::locationSymbol(scan, '.'); - } -}; - -struct FairchildLetterParser final : LetterParser, Singleton { - /** Fairchild style letter is [cC]'[:print:]', #[:print:], '[:print:]'? */ - Error parseLetter(StrScanner &scan, char &letter) const override { - auto p = scan; - if (p.iexpect('C')) { // C'C' - const auto error = LetterParser::parseLetter(p, letter); - if (error == OK) - scan = p; - return error; - } - if (p.expect('#')) { // #C - if ((letter = *p) == 0) - return NOT_AN_EXPECTED; - scan = ++p; - return OK; - } - if (p.expect('\'')) { // 'c' or 'c - ErrorAt error; - letter = readLetter(p, error, '\''); - if (error.isOK()) { - p.expect('\''); // closing quote is optional - scan = p; - return OK; - } - return error.getError(); - } - return NOT_AN_EXPECTED; - } - - /** Fairchild style string constant is C'str'. */ - bool stringPrefix(StrScanner &scan) const override { - scan.iexpect('C'); // optional - return true; - } -}; +const NumberParser &ValueParser::ZilogPlugins::number() const { + return ZilogNumberParser::singleton(); +} -} // namespace fairchild +const LetterParser &ValueParser::ZilogPlugins::letter() const { + return ZilogLetterParser::singleton(); +} -const ValueParser::Plugins &ValueParser::Plugins::fairchild() { - static const struct final : ValueParser::Plugins { - const NumberParser &number() const override { - return fairchild::FairchildNumberParser::singleton(); - } - const SymbolParser &symbol() const override { - return fairchild::FairchildSymbolParser::singleton(); - } - const CommentParser &comment() const override { return StarCommentParser::singleton(); } - const LetterParser &letter() const override { - return fairchild::FairchildLetterParser::singleton(); - } - } PLUGINS{}; - return PLUGINS; +const OperatorParser &ValueParser::ZilogPlugins::operators() const { + return ZilogOperatorParser::singleton(); } struct OperatorStack : Stack { diff --git a/src/value_parser.h b/src/value_parser.h index 0a56b198..e45909b0 100644 --- a/src/value_parser.h +++ b/src/value_parser.h @@ -18,7 +18,11 @@ #define __LIBASM_VALUE_PARSER_H__ #include -#include "parsers.h" +#include "comment_parser.h" +#include "function_table.h" +#include "letter_parser.h" +#include "number_parser.h" +#include "symbol_parser.h" #include "symbol_table.h" namespace libasm { @@ -47,12 +51,14 @@ struct ValueParser { static const Plugins &defaultPlugins(); static const Plugins &intel(); static const Plugins &motorola(); - static const Plugins &fairchild(); }; + struct IntelPlugins : Plugins { const NumberParser &number() const override; + const SymbolParser &symbol() const override; const OperatorParser &operators() const override; }; + struct MotorolaPlugins : Plugins { const NumberParser &number() const override; const CommentParser &comment() const override; @@ -61,6 +67,12 @@ struct ValueParser { const OperatorParser &operators() const override; }; + struct ZilogPlugins : Plugins { + const NumberParser &number() const override; + const LetterParser &letter() const override; + const OperatorParser &operators() const override; + }; + ValueParser(const Plugins &plugins = Plugins::defaultPlugins()) : _number(plugins.number()), _comment(plugins.comment()), diff --git a/test/test_asm_scn2650.cpp b/test/test_asm_scn2650.cpp index 535cd591..65857f43 100644 --- a/test/test_asm_scn2650.cpp +++ b/test/test_asm_scn2650.cpp @@ -47,8 +47,8 @@ static void test_load_store() { TEST("LODZ,R2", 0x02); TEST("LODZ,R3", 0x03); TEST("LODI,R0 H'56'", 0x04, 0x56); - TEST("LODI,R1 H'789A'", 0x06, 0x78); + TEST("LODI,R1 H'4567'*2", 0x06, 0x8A); TEST("LODI,R3 H'89'", 0x07, 0x89); TEST("LODI,R3 255", 0x07, 0xFF); TEST("LODI,R3 -128", 0x07, 0x80); diff --git a/test/test_expr_fairchild.cpp b/test/test_expr_fairchild.cpp index 688b1e59..ca24ab4f 100644 --- a/test/test_expr_fairchild.cpp +++ b/test/test_expr_fairchild.cpp @@ -19,7 +19,14 @@ using namespace libasm; using namespace libasm::test; -const ValueParser parser{ValueParser::Plugins::fairchild()}; +const struct final : ValueParser::Plugins { + const NumberParser &number() const override { return FairchildNumberParser::singleton(); } + const SymbolParser &symbol() const override { return FairchildSymbolParser::singleton(); } + const CommentParser &comment() const override { return StarCommentParser::singleton(); } + const LetterParser &letter() const override { return FairchildLetterParser::singleton(); } +} PLUGINS{}; + +const ValueParser parser{PLUGINS}; const ValueFormatter formatter{ValueFormatter::Plugins::fairchild()}; diff --git a/test/test_expr_zilog.cpp b/test/test_expr_zilog.cpp index cb62cc37..fc32f57f 100644 --- a/test/test_expr_zilog.cpp +++ b/test/test_expr_zilog.cpp @@ -21,12 +21,8 @@ using namespace libasm; using namespace libasm::test; -const struct final : ValueParser::Plugins { - const NumberParser &number() const override { return ZilogNumberParser::singleton(); } - const LetterParser &letter() const override { return ZilogLetterParser::singleton(); } - const OperatorParser &operators() const override { return ZilogOperatorParser::singleton(); } -} plugins{}; -const ValueParser parser{plugins}; +const ValueParser::ZilogPlugins PLUGINS{}; +const ValueParser parser{PLUGINS}; const ValueFormatter formatter{ValueFormatter::Plugins::zilog()};