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_tms7000.cpp b/src/asm_tms7000.cpp index 2fb1cce4..0e855262 100644 --- a/src/asm_tms7000.cpp +++ b/src/asm_tms7000.cpp @@ -44,11 +44,7 @@ PROGMEM constexpr Pseudos PSEUDO_TABLE{ARRAY_RANGE(PSEUDOS)}; } // namespace const ValueParser::Plugins &AsmTms7000::defaultPlugins() { - static const struct final : ValueParser::Plugins { - const NumberParser &number() const override { return TexasNumberParser::singleton(); } - const CommentParser &comment() const override { return StarCommentParser::singleton(); } - } PLUGINS{}; - return PLUGINS; + return ValueParser::Plugins::texas(); } AsmTms7000::AsmTms7000(const ValueParser::Plugins &plugins) diff --git a/src/asm_tms9900.cpp b/src/asm_tms9900.cpp index 5ae24f7a..7bfd6c34 100644 --- a/src/asm_tms9900.cpp +++ b/src/asm_tms9900.cpp @@ -43,11 +43,7 @@ PROGMEM constexpr Pseudos PSEUDO_TABLE{ARRAY_RANGE(PSEUDOS)}; } // namespace const ValueParser::Plugins &AsmTms9900::defaultPlugins() { - static const struct final : ValueParser::Plugins { - const NumberParser &number() const override { return TexasNumberParser::singleton(); } - const CommentParser &comment() const override { return StarCommentParser::singleton(); } - } PLUGINS{}; - return PLUGINS; + return ValueParser::Plugins::texas(); } AsmTms9900::AsmTms9900(const ValueParser::Plugins &plugins) 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/dis_f3850.cpp b/src/dis_f3850.cpp index d5343d4f..52ddc06a 100644 --- a/src/dis_f3850.cpp +++ b/src/dis_f3850.cpp @@ -27,13 +27,7 @@ using namespace reg; using namespace text::common; const ValueFormatter::Plugins& DisF3850::defaultPlugins() { - static const struct fianl : ValueFormatter::Plugins { - const HexFormatter& hex() const override { return _hex; } - char locationSymbol() const override { return '$'; } - const /*PROGMEM*/ char* lineComment_P() const override { return PSTR_STAR; } - const SurroundHexFormatter _hex{PSTR_H_DASH, '\''}; - } PLUGINS{}; - return PLUGINS; + return ValueFormatter::Plugins::fairchild(); } DisF3850::DisF3850(const ValueFormatter::Plugins& plugins) : Disassembler(plugins), Config(TABLE) { diff --git a/src/dis_ns32000.cpp b/src/dis_ns32000.cpp index 7d282ed0..711fc3db 100644 --- a/src/dis_ns32000.cpp +++ b/src/dis_ns32000.cpp @@ -35,9 +35,9 @@ const char OPT_DESC_EXTERNAL_PAREN[] PROGMEM = "disp2(disp(ext)) as external add const ValueFormatter::Plugins &DisNs32000::defaultPlugins() { static const struct final : ValueFormatter::Plugins { - const HexFormatter &hex() const override { return _hex; } + const HexFormatter &hex() const override { return NationalHexFormatter::singleton(); } + char locationSymbol() const override { return '.'; } const /*PROGMEM*/ char *lineComment_P() const override { return PSTR_SHARP; } - const PrefixStrHexFormatter _hex{PSTR_X_DASH}; } PLUGINS{}; return PLUGINS; } diff --git a/src/formatters.cpp b/src/formatters.cpp index b09035fa..bacd7179 100644 --- a/src/formatters.cpp +++ b/src/formatters.cpp @@ -1,3 +1,4 @@ +#include /* * Copyright 2023 Tadashi G. Takaoka * diff --git a/src/formatters.h b/src/formatters.h index a902f596..1e4231a7 100644 --- a/src/formatters.h +++ b/src/formatters.h @@ -18,15 +18,15 @@ #define _FORMATTERS_H__ #include - #include "str_buffer.h" +#include "text_common.h" namespace libasm { /** * Decimal number formatter */ -struct DecFormatter : Singleton { +struct DecFormatter { /** Format unsigned |val| as decimal. */ virtual StrBuffer &format(StrBuffer &out, uint32_t val) const; @@ -40,7 +40,7 @@ struct DecFormatter : Singleton { /** * Binary number formatter */ -struct BinFormatter : Singleton { +struct BinFormatter { /** Format unsigned |val| as |bits| bit binary. */ virtual StrBuffer &format(StrBuffer &out, uint32_t val, uint8_t bits) const; @@ -54,7 +54,7 @@ struct BinFormatter : Singleton { /** * Octal number formatter */ -struct OctFormatter : Singleton { +struct OctFormatter { /** Format unsigned |val| as |bits| bit hexadecimal. */ virtual StrBuffer &format(StrBuffer &out, uint32_t val, uint8_t bits) const; @@ -68,7 +68,7 @@ struct OctFormatter : Singleton { /** * Hexadecimal number formatter */ -struct HexFormatter : Singleton { +struct HexFormatter { /** Format unsigned |val| as |bits| bit hexadecimal. */ virtual StrBuffer &format(StrBuffer &out, uint32_t val, uint8_t bits) const; @@ -86,8 +86,8 @@ template struct PrefixFormatter {}; template -struct PrefixFormatter : FORMATTER { - PrefixFormatter(const char prefix) : FORMATTER(), _prefix(prefix) {} +struct PrefixFormatter : FORMATTER { + PrefixFormatter(char prefix) : FORMATTER(), _prefix(prefix) {} StrBuffer &format(StrBuffer &out, uint32_t val, uint8_t bits) const override final { return FORMATTER::format(out.letter(_prefix), val, bits); @@ -116,8 +116,8 @@ template struct SuffixFormatter {}; template -struct SuffixFormatter : FORMATTER { - SuffixFormatter(const char suffix) : FORMATTER(), _suffix(suffix) {} +struct SuffixFormatter : FORMATTER { + SuffixFormatter(char suffix) : FORMATTER(), _suffix(suffix) {} StrBuffer &format(StrBuffer &out, uint32_t val, uint8_t bits) const override { return FORMATTER::format(out, val, bits).letter(_suffix); @@ -134,8 +134,8 @@ template struct SurroundFormatter {}; template -struct SurroundFormatter : FORMATTER { - SurroundFormatter(const /*PROGMEM*/ char *const prefix_P, const char suffix) +struct SurroundFormatter : FORMATTER { + SurroundFormatter(const /*PROGMEM*/ char *const prefix_P, char suffix) : FORMATTER(), _prefix_P(prefix_P), _suffix(suffix) {} StrBuffer &format(StrBuffer &out, uint32_t val, uint8_t bits) const override final { @@ -150,33 +150,33 @@ struct SurroundFormatter : /** * Binary number is prefixed with |prefix|. */ -struct PrefixBinFormatter final : PrefixFormatter { +struct PrefixBinFormatter : PrefixFormatter { PrefixBinFormatter(const char prefix) : PrefixFormatter(prefix) {} }; -struct PrefixStrBinFormatter final : PrefixFormatter { +struct PrefixStrBinFormatter : PrefixFormatter { PrefixStrBinFormatter(const /*PROGMEM*/ char *const prefix_P) : PrefixFormatter(prefix_P) {} }; /** * Octal number is prefixed with |prefix|. */ -struct PrefixOctFormatter final : PrefixFormatter { +struct PrefixOctFormatter : PrefixFormatter { PrefixOctFormatter(const char prefix) : PrefixFormatter(prefix) {} }; -struct PrefixStrOctFormatter final : PrefixFormatter { +struct PrefixStrOctFormatter : PrefixFormatter { PrefixStrOctFormatter(const /*PROGMEM*/ char *prefix_P) : PrefixFormatter(prefix_P) {} }; /** * Hexadecimal number is prefixed with |prefix|. */ -struct PrefixHexFormatter final : PrefixFormatter { +struct PrefixHexFormatter : PrefixFormatter { PrefixHexFormatter(const char prefix) : PrefixFormatter(prefix) {} }; -struct PrefixStrHexFormatter final : PrefixFormatter { +struct PrefixStrHexFormatter : PrefixFormatter { PrefixStrHexFormatter(const /*PROGMEM*/ char *prefix_P) : PrefixFormatter(prefix_P) {} }; @@ -184,14 +184,14 @@ struct PrefixStrHexFormatter final : PrefixFormatter { +struct SuffixBinFormatter : SuffixFormatter { SuffixBinFormatter(const char suffix) : SuffixFormatter(suffix) {} }; /** * Octal number is suffixed with |suffix|. */ -struct SuffixOctFormatter final : SuffixFormatter { +struct SuffixOctFormatter : SuffixFormatter { SuffixOctFormatter(const char suffix) : SuffixFormatter(suffix) {} }; @@ -199,7 +199,7 @@ struct SuffixOctFormatter final : SuffixFormatter { * Hexadecimal number is suffixed with |suffix|. It is also prefixed with '0' when it starts with * non-digit letter. */ -struct SuffixHexFormatter final : SuffixFormatter { +struct SuffixHexFormatter : SuffixFormatter { SuffixHexFormatter(const char suffix) : SuffixFormatter(suffix) {} StrBuffer &format(StrBuffer &out, uint32_t val, uint8_t bits) const override; @@ -208,7 +208,7 @@ struct SuffixHexFormatter final : SuffixFormatter { /** * Binary number is surrounded by |prefix| and |suffix|. */ -struct SurroundBinFormatter final : SurroundFormatter { +struct SurroundBinFormatter : SurroundFormatter { SurroundBinFormatter(const /*PROGMEM*/ char *const prefix_P, const char suffix) : SurroundFormatter(prefix_P, suffix) {} }; @@ -216,7 +216,7 @@ struct SurroundBinFormatter final : SurroundFormatter { +struct SurroundOctFormatter : SurroundFormatter { SurroundOctFormatter(const /*PROGMEM*/ char *const prefix_P, char suffix) : SurroundFormatter(prefix_P, suffix) {} }; @@ -224,7 +224,7 @@ struct SurroundOctFormatter final : SurroundFormatter { +struct SurroundHexFormatter : SurroundFormatter { SurroundHexFormatter(const /*PROGMEM*/ char *const prefix_P, char suffix) : SurroundFormatter(prefix_P, suffix) {} }; @@ -232,9 +232,8 @@ struct SurroundHexFormatter final : SurroundFormatter { - CStyleBinFormatter() : PrefixFormatter(PSTR("0b")) {} - +struct CStyleBinFormatter : PrefixStrBinFormatter, Singleton { + CStyleBinFormatter() : PrefixStrBinFormatter(PSTR("0b")) {} StrBuffer &format(StrBuffer &out, uint32_t val, uint8_t bits) const override { return BinFormatter::format(out.rtext_P(_prefix_P), val, bits); } @@ -243,21 +242,88 @@ struct CStyleBinFormatter final : PrefixFormatter { - CStyleOctFormatter() : PrefixFormatter('0') {} +struct CStyleOctFormatter final : PrefixOctFormatter, Singleton { + CStyleOctFormatter() : PrefixOctFormatter('0') {} }; /** * C-Style hexadecimal number is "0xFF" */ -struct CStyleHexFormatter final : PrefixFormatter { - CStyleHexFormatter() : PrefixFormatter(PSTR("0x")) {} - +struct CStyleHexFormatter final : PrefixStrHexFormatter, Singleton { + CStyleHexFormatter() : PrefixStrHexFormatter(PSTR("0x")) {} StrBuffer &format(StrBuffer &out, uint32_t val, uint8_t bits) const override { return HexFormatter::format(out.rtext_P(_prefix_P), val, bits); } }; +struct IntelBinFormatter final : SuffixBinFormatter, Singleton { + IntelBinFormatter() : SuffixBinFormatter('B') {} +}; + +struct IntelOctFormatter final : SuffixOctFormatter, Singleton { + IntelOctFormatter() : SuffixOctFormatter('Q') {} +}; + +struct IntelHexFormatter final : SuffixHexFormatter, Singleton { + IntelHexFormatter() : SuffixHexFormatter('H') {} +}; + +struct MotorolaBinFormatter final : PrefixBinFormatter, Singleton { + MotorolaBinFormatter() : PrefixBinFormatter('%') {} +}; + +struct MotorolaOctFormatter final : PrefixOctFormatter, Singleton { + MotorolaOctFormatter() : PrefixOctFormatter('@') {} +}; + +struct MotorolaHexFormatter final : PrefixHexFormatter, Singleton { + MotorolaHexFormatter() : PrefixHexFormatter('$') {} +}; + +struct FairchildBinFormatter final : SurroundBinFormatter, Singleton { + FairchildBinFormatter() : SurroundBinFormatter(text::common::PSTR_B_DASH, '\'') {} +}; + +struct FairchildOctFormatter final : SurroundOctFormatter, Singleton { + FairchildOctFormatter() : SurroundOctFormatter(text::common::PSTR_O_DASH, '\'') {} +}; + +struct FairchildHexFormatter final : SurroundHexFormatter, Singleton { + FairchildHexFormatter() : SurroundHexFormatter(text::common::PSTR_H_DASH, '\'') {} +}; + +struct NationalBinFormatter final : PrefixStrBinFormatter, Singleton { + NationalBinFormatter() : PrefixStrBinFormatter(text::common::PSTR_B_DASH) {} +}; + +struct NationalOctFormatter final : PrefixStrOctFormatter, Singleton { + NationalOctFormatter() : PrefixStrOctFormatter(text::common::PSTR_O_DASH) {} +}; + +struct NationalHexFormatter final : PrefixStrHexFormatter, Singleton { + NationalHexFormatter() : PrefixStrHexFormatter(text::common::PSTR_X_DASH) {} +}; + +struct TexasBinFormatter final : PrefixBinFormatter, Singleton { + TexasBinFormatter() : PrefixBinFormatter('?') {} +}; + +struct TexasHexFormatter final : PrefixHexFormatter, Singleton { + TexasHexFormatter() : PrefixHexFormatter('>') {} +}; + +struct ZilogBinFormatter final : PrefixStrBinFormatter, Singleton { + ZilogBinFormatter() : PrefixStrBinFormatter(text::common::PSTR_PERCENT_2) {} +}; + +struct ZilogOctFormatter final : PrefixStrOctFormatter, Singleton { + ZilogOctFormatter() : PrefixStrOctFormatter(text::common::PSTR_PERCENT_8) {} +}; + +struct ZilogHexFormatter final : PrefixHexFormatter, Singleton { + ZilogHexFormatter() : PrefixHexFormatter('%') {} +}; + } // namespace libasm #endif 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..c40080ad 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); } @@ -112,9 +117,9 @@ static Error subtract(ValueStack &stack, ParserContext &) { return OK; } -static Error logical_shift_left_32bit(ValueStack &stack, ParserContext &) { +static Error logical_shift_left(ValueStack &stack, ParserContext &) { const auto rhs = stack.pop().getUnsigned(); - const auto lhs = stack.pop().getUnsigned() & UINT32_MAX; + const auto lhs = stack.pop().getUnsigned(); const auto value = (rhs < 32) ? (lhs << rhs) : 0; stack.pushUnsigned(value & UINT32_MAX); return OK; @@ -221,8 +226,8 @@ const Operator Operator::OP_DIV( 5, L, 2, divide); const Operator Operator::OP_MOD( 5, L, 2, modulo); const Operator Operator::OP_ADD( 6, L, 2, add); const Operator Operator::OP_SUB( 6, L, 2, subtract); -const Operator Operator::OP_SHIFT_LEFT( 7, L, 2, logical_shift_left_32bit); -const Operator Operator::OP_SHIFT_RIGHT( 7, L, 2, arithmetic_shift_right); +const Operator Operator::OP_SHIFT_LEFT( 7, L, 2, logical_shift_left); +const Operator Operator::OP_SHIFT_RIGHT(7, L, 2, arithmetic_shift_right); const Operator Operator::OP_LOGICAL_LT( 9, N, 2, less_than); const Operator Operator::OP_LOGICAL_LE( 9, N, 2, less_than_or_equal); const Operator Operator::OP_LOGICAL_GE( 9, N, 2, greater_than_or_equal); @@ -321,7 +326,7 @@ static Error exponential(ValueStack &stack, ParserContext &) { static Error rotate_left_16bit(ValueStack &stack, ParserContext &) { const auto rhs = stack.pop().getUnsigned() % 16; - const auto lhs = stack.pop().getUnsigned() & UINT16_MAX; + const uint16_t lhs = stack.pop().getUnsigned(); const auto v = (lhs << rhs) | (lhs >> (16 - rhs)); stack.pushUnsigned(v & UINT16_MAX); return OK; @@ -329,7 +334,7 @@ static Error rotate_left_16bit(ValueStack &stack, ParserContext &) { static Error rotate_right_16bit(ValueStack &stack, ParserContext &) { const auto rhs = stack.pop().getUnsigned() % 16; - const auto lhs = stack.pop().getUnsigned() & UINT16_MAX; + const uint16_t lhs = stack.pop().getUnsigned(); const auto v = (lhs >> rhs) | (lhs << (16 - rhs)); stack.pushUnsigned(v & UINT16_MAX); return OK; @@ -337,7 +342,7 @@ static Error rotate_right_16bit(ValueStack &stack, ParserContext &) { static Error logical_shift_left_16bit(ValueStack &stack, ParserContext &) { const auto rhs = stack.pop().getUnsigned(); - const auto lhs = stack.pop().getUnsigned() & UINT16_MAX; + const uint16_t lhs = stack.pop().getUnsigned(); const auto value = (rhs < 16) ? (lhs << rhs) : 0; stack.pushUnsigned(value & UINT16_MAX); return OK; @@ -345,44 +350,44 @@ static Error logical_shift_left_16bit(ValueStack &stack, ParserContext &) { static Error logical_shift_right_16bit(ValueStack &stack, ParserContext &) { const auto rhs = stack.pop().getUnsigned(); - const auto lhs = stack.pop().getUnsigned() & UINT16_MAX; + const uint16_t lhs = stack.pop().getUnsigned(); const auto value = (rhs < 16) ? (lhs >> rhs) : 0; stack.pushUnsigned(value & UINT16_MAX); return OK; } // 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,124 @@ 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 *TexasOperatorParser::readPrefix( + StrScanner &scan, ValueStack &stack, ParserContext &context) const { + if (scan.expect('#')) + return &Operator::OP_BITWISE_NOT; + return CStyleOperatorParser::singleton().readPrefix(scan, stack, context); +} + +const Operator *TexasOperatorParser::readInfix( + StrScanner &scan, ValueStack &stack, ParserContext &context) const { + if (scan.iexpectText_P(PSTR("++"))) { + return &Operator::OP_BITWISE_OR; + } else if (scan.iexpectText_P(PSTR("&&"))) { + return &Operator::OP_BITWISE_XOR; + } else if (scan.iexpectText_P(PSTR("//"))) { + return &MOTOROLA_SHIFT_RIGHT; + } else if (scan.expect('=')) { + return &Operator::OP_LOGICAL_EQ; + } else if (scan.iexpectText_P(PSTR("#="))) { + return &Operator::OP_LOGICAL_NE; + } + return CStyleOperatorParser::singleton().readInfix(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..524d0c05 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,11 +144,20 @@ 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 { +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 TexasOperatorParser final : OperatorParser, Singleton { const Operator *readPrefix(StrScanner &, ValueStack &, ParserContext &) const override; const Operator *readInfix(StrScanner &, ValueStack &, ParserContext &) const override; }; @@ -159,6 +167,11 @@ struct ZilogOperatorParser 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..5d6b13bc 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,44 +67,96 @@ 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 Mc68xxSymbolParser final : PrefixSymbolParser, Singleton { - Mc68xxSymbolParser() +struct MotorolaSymbolParser final : PrefixSymbolParser, Singleton { + MotorolaSymbolParser() : PrefixSymbolParser(text::common::PSTR_DOT, text::common::PSTR_UNDER_DOT_DOLLAR) {} bool locationSymbol(StrScanner &scan) const override { return SymbolParser::locationSymbol(scan, '*'); } }; -struct Ins80xxSymbolParser final : PrefixSymbolParser, Singleton { - Ins80xxSymbolParser() : PrefixSymbolParser(text::common::PSTR_DOLLAR) {} +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, '.') || SymbolParser::locationSymbol(scan, '$'); + return SymbolParser::locationSymbol(scan, '*'); } - bool instructionLetter(char c) const override { - return PrefixSymbolParser::instructionLetter(c) || c == '=' || c == '.'; +}; + +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 Ins80xxSymbolParser 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, '*'); + } + 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 #endif diff --git a/src/text_common.cpp b/src/text_common.cpp index 6cd9b2bf..8149933c 100644 --- a/src/text_common.cpp +++ b/src/text_common.cpp @@ -534,6 +534,7 @@ constexpr char TEXT_TEXT[] PROGMEM = "text"; constexpr char PSTR_AT[] PROGMEM = "@"; constexpr char PSTR_DOLLAR[] PROGMEM = "$"; constexpr char PSTR_DOT[] PROGMEM = "."; +constexpr char PSTR_SEMI[] PROGMEM = ";"; constexpr char PSTR_SHARP[] PROGMEM = "#"; constexpr char PSTR_STAR[] PROGMEM = "*"; constexpr char PSTR_UNDER[] PROGMEM = "_"; diff --git a/src/text_common.h b/src/text_common.h index 14c47bfe..446a5ab4 100644 --- a/src/text_common.h +++ b/src/text_common.h @@ -537,6 +537,7 @@ extern const char TEXT_TEXT[] PROGMEM; extern const char PSTR_AT[] PROGMEM; // "*" extern const char PSTR_DOLLAR[] PROGMEM; // "$" extern const char PSTR_DOT[] PROGMEM; // "." +extern const char PSTR_SEMI[] PROGMEM; // ";" extern const char PSTR_SHARP[] PROGMEM; // "#" extern const char PSTR_STAR[] PROGMEM; // "*" extern const char PSTR_UNDER[] PROGMEM; // "_" diff --git a/src/value_formatter.cpp b/src/value_formatter.cpp index 50c2616d..a4c309ba 100644 --- a/src/value_formatter.cpp +++ b/src/value_formatter.cpp @@ -15,121 +15,108 @@ */ #include "value_formatter.h" - #include - #include "text_common.h" namespace libasm { +using namespace text::common; + const DecFormatter &ValueFormatter::Plugins::dec() const { - return DecFormatter::singleton(); + static const DecFormatter FORMATTER{}; + return FORMATTER; } const BinFormatter &ValueFormatter::Plugins::bin() const { - return BinFormatter::singleton(); + static const BinFormatter FORMATTER{}; + return FORMATTER; } const OctFormatter &ValueFormatter::Plugins::oct() const { - return OctFormatter::singleton(); + static const OctFormatter FORMATTER{}; + return FORMATTER; } const HexFormatter &ValueFormatter::Plugins::hex() const { - return HexFormatter::singleton(); + static const HexFormatter FORMATTER{}; + return FORMATTER; } char ValueFormatter::Plugins::locationSymbol() const { - return '.'; + return '$'; } const /*PROGMEM*/ char *ValueFormatter::Plugins::lineComment_P() const { - return PSTR(";"); + return PSTR_SEMI; } -const ValueFormatter::Plugins &ValueFormatter::Plugins::cstyle() { - static const struct fianl : Plugins { - const BinFormatter &bin() const override { return _bin; } - const OctFormatter &oct() const override { return _oct; } - const HexFormatter &hex() const override { return _hex; } - const CStyleBinFormatter _bin{}; - const CStyleOctFormatter _oct{}; - const CStyleHexFormatter _hex{}; - } PLUGINS{}; +const ValueFormatter::Plugins &ValueFormatter::Plugins::singleton() { + static const Plugins PLUGINS{}; return PLUGINS; } -const ValueFormatter::Plugins &ValueFormatter::Plugins::fairchild() { +const ValueFormatter::Plugins &ValueFormatter::Plugins::cstyle() { static const struct fianl : Plugins { - const BinFormatter &bin() const override { return _bin; } - const OctFormatter &oct() const override { return _oct; } - const HexFormatter &hex() const override { return _hex; } - char locationSymbol() const override { return '*'; } - const SurroundBinFormatter _bin{text::common::PSTR_B_DASH, '\''}; - const SurroundOctFormatter _oct{text::common::PSTR_O_DASH, '\''}; - const SurroundHexFormatter _hex{text::common::PSTR_H_DASH, '\''}; + const BinFormatter &bin() const override { return CStyleBinFormatter::singleton(); } + const OctFormatter &oct() const override { return CStyleOctFormatter::singleton(); } + const HexFormatter &hex() const override { return CStyleHexFormatter::singleton(); } } PLUGINS{}; return PLUGINS; } const ValueFormatter::Plugins &ValueFormatter::Plugins::intel() { static const struct fianl : Plugins { - const BinFormatter &bin() const override { return _bin; } - const OctFormatter &oct() const override { return _oct; } - const HexFormatter &hex() const override { return _hex; } - char locationSymbol() const override { return '$'; } - const SuffixBinFormatter _bin{'b'}; - const SuffixOctFormatter _oct{'q'}; - const SuffixHexFormatter _hex{'h'}; + const BinFormatter &bin() const override { return IntelBinFormatter::singleton(); } + const OctFormatter &oct() const override { return IntelOctFormatter::singleton(); } + const HexFormatter &hex() const override { return IntelHexFormatter::singleton(); } } PLUGINS{}; return PLUGINS; } const ValueFormatter::Plugins &ValueFormatter::Plugins::motorola() { static const struct fianl : Plugins { - const BinFormatter &bin() const override { return _bin; } - const OctFormatter &oct() const override { return _oct; } - const HexFormatter &hex() const override { return _hex; } + const BinFormatter &bin() const override { return MotorolaBinFormatter::singleton(); } + const OctFormatter &oct() const override { return MotorolaOctFormatter::singleton(); } + const HexFormatter &hex() const override { return MotorolaHexFormatter::singleton(); } char locationSymbol() const override { return '*'; } - const /*PROGMEM*/ char *lineComment_P() const override { return text::common::PSTR_STAR; } - const PrefixBinFormatter _bin{'%'}; - const PrefixStrOctFormatter _oct{text::common::PSTR_AT}; - const PrefixHexFormatter _hex{'$'}; + const /*PROGMEM*/ char *lineComment_P() const override { return PSTR_STAR; } + } PLUGINS{}; + return PLUGINS; +} + +const ValueFormatter::Plugins &ValueFormatter::Plugins::fairchild() { + static const struct fianl : Plugins { + const BinFormatter &bin() const override { return FairchildBinFormatter::singleton(); } + const OctFormatter &oct() const override { return FairchildOctFormatter::singleton(); } + const HexFormatter &hex() const override { return FairchildHexFormatter::singleton(); } + const /*PROGMEM*/ char *lineComment_P() const override { return PSTR_STAR; } } PLUGINS{}; return PLUGINS; } const ValueFormatter::Plugins &ValueFormatter::Plugins::national() { static const struct fianl : Plugins { - const BinFormatter &bin() const override { return _bin; } - const OctFormatter &oct() const override { return _oct; } - const HexFormatter &hex() const override { return _hex; } - char locationSymbol() const override { return '$'; } - const PrefixStrBinFormatter _bin{text::common::PSTR_B_DASH}; - const PrefixStrOctFormatter _oct{text::common::PSTR_O_DASH}; - const PrefixStrHexFormatter _hex{text::common::PSTR_X_DASH}; + const BinFormatter &bin() const override { return NationalBinFormatter::singleton(); } + const OctFormatter &oct() const override { return NationalOctFormatter::singleton(); } + const HexFormatter &hex() const override { return NationalHexFormatter::singleton(); } } PLUGINS{}; return PLUGINS; } const ValueFormatter::Plugins &ValueFormatter::Plugins::texas() { static const struct fianl : Plugins { - const HexFormatter &hex() const override { return _hex; } - char locationSymbol() const override { return '$'; } - const /*PROGMEM*/ char *lineComment_P() const override { return text::common::PSTR_STAR; } - const PrefixHexFormatter _hex{'>'}; + const BinFormatter &bin() const override { return TexasBinFormatter::singleton(); } + const HexFormatter &hex() const override { return TexasHexFormatter::singleton(); } + const /*PROGMEM*/ char *lineComment_P() const override { return PSTR_STAR; } } PLUGINS{}; return PLUGINS; } const ValueFormatter::Plugins &ValueFormatter::Plugins::zilog() { static const struct fianl : Plugins { - const BinFormatter &bin() const override { return _bin; } - const OctFormatter &oct() const override { return _oct; } - const HexFormatter &hex() const override { return _hex; } - char locationSymbol() const override { return '$'; } - const PrefixStrBinFormatter _bin{text::common::PSTR_PERCENT_2}; - const PrefixStrOctFormatter _oct{text::common::PSTR_PERCENT_8}; - const PrefixHexFormatter _hex{'%'}; + const BinFormatter &bin() const override { return ZilogBinFormatter::singleton(); } + const OctFormatter &oct() const override { return ZilogOctFormatter::singleton(); } + const HexFormatter &hex() const override { return ZilogHexFormatter::singleton(); } } PLUGINS{}; return PLUGINS; } diff --git a/src/value_formatter.h b/src/value_formatter.h index ced345c7..adcc5f5e 100644 --- a/src/value_formatter.h +++ b/src/value_formatter.h @@ -25,7 +25,7 @@ namespace libasm { struct ValueFormatter final { - struct Plugins : Singleton { + struct Plugins { virtual const DecFormatter &dec() const; virtual const BinFormatter &bin() const; virtual const OctFormatter &oct() const; @@ -33,6 +33,7 @@ struct ValueFormatter final { virtual char locationSymbol() const; virtual const /*PROGMEM*/ char *lineComment_P() const; + static const Plugins &singleton(); static const Plugins &cstyle(); static const Plugins &fairchild(); static const Plugins &intel(); diff --git a/src/value_parser.cpp b/src/value_parser.cpp index 355b9ca1..4485896d 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(); } @@ -82,7 +86,7 @@ const CommentParser &ValueParser::MotorolaPlugins::comment() const { } const SymbolParser &ValueParser::MotorolaPlugins::symbol() const { - return Mc68xxSymbolParser::singleton(); + return MotorolaSymbolParser::singleton(); } const LetterParser &ValueParser::MotorolaPlugins::letter() const { @@ -90,88 +94,36 @@ 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); - } +const NumberParser &ValueParser::TexasPlugins::number() const { + return TexasNumberParser::singleton(); +} -private: - IbmNumberParser _ibm{'H', 'B', 'O', 'D'}; -}; +const CommentParser &ValueParser::TexasPlugins::comment() const { + return StarCommentParser::singleton(); +} -struct FairchildSymbolParser final : SymbolParser, Singleton { - bool locationSymbol(StrScanner &scan) const override { - return SymbolParser::locationSymbol(scan, '*') || SymbolParser::locationSymbol(scan, '$') || - SymbolParser::locationSymbol(scan, '.'); - } -}; +const OperatorParser &ValueParser::TexasPlugins::operators() const { + return TexasOperatorParser::singleton(); +} -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; - } +const ValueParser::Plugins &ValueParser::Plugins::texas() { + static const TexasPlugins PLUGINS; + return PLUGINS; +} - /** 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..8724710d 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 { @@ -46,13 +50,16 @@ struct ValueParser { static const Plugins &defaultPlugins(); static const Plugins &intel(); + static const Plugins &texas(); 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 +68,18 @@ struct ValueParser { const OperatorParser &operators() const override; }; + struct TexasPlugins : Plugins { + const NumberParser &number() const override; + const CommentParser &comment() const override; + 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_asm_tms7000.cpp b/test/test_asm_tms7000.cpp index eb992e12..742d08c7 100644 --- a/test/test_asm_tms7000.cpp +++ b/test/test_asm_tms7000.cpp @@ -172,7 +172,7 @@ void test_register() { TEST("AND A, R69", 0x43, 0x00, 0x45); TEST("AND B, R69", 0x43, 0x01, 0x45); TEST("AND R68, R69", 0x43, 0x44, 0x45); - TEST("AND %>24, A", 0x23, 0x24); + TEST("AND %#>24, A", 0x23, 0xDB); TEST("AND %>54, B", 0x53, 0x54); TEST("AND %>74, R117", 0x73, 0x74, 0x75); diff --git a/test/test_asm_tms9900.cpp b/test/test_asm_tms9900.cpp index 1e30e1cc..cc5c3d01 100644 --- a/test/test_asm_tms9900.cpp +++ b/test/test_asm_tms9900.cpp @@ -118,11 +118,15 @@ static void test_reg() { } static void test_reg_imm() { - TEST("LI R0,>0000", 0x0200, 0x0000); - TEST("AI R1,+1", 0x0221, 0x0001); - TEST("ANDI R8,>00FF", 0x0248, 0x00FF); - TEST("ORI R14,~>FF", 0x026E, 0xFF00); - TEST("CI R15,-1", 0x028F, 0xFFFF); + TEST("LI R0, >0000", 0x0200, 0x0000); + TEST("AI R1, +1", 0x0221, 0x0001); + TEST("ANDI R8, >00FF", 0x0248, 0x00FF); + TEST("ORI R14, #>00FF", 0x026E, 0xFF00); + TEST("ORI R14, >1200++>0034", 0x026E, 0x1234); + TEST("ORI R14, >1234&>0FF0", 0x026E, 0x0230); + TEST("ORI R14, >00FF&&>0FF0", 0x026E, 0x0F0F); + TEST("CI R15, -1", 0x028F, 0xFFFF); + TEST("CI R15, -1//8", 0x028F, 0x00FF); symtab.intern(0x1234, "sym1234"); 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()};