mirror of
https://github.com/ksherlock/merlin-utils.git
synced 2025-01-02 05:29:45 +00:00
defer operand parsing to eval. also adds symbol table lookup.
This commit is contained in:
parent
3c6be110b1
commit
e7e77f4b5c
160
link.cpp
160
link.cpp
@ -63,6 +63,44 @@ namespace {
|
||||
std::vector<omf::segment> segments;
|
||||
std::vector<std::vector<pending_reloc>> relocations;
|
||||
|
||||
std::unordered_map<std::string, uint32_t> file_types = {
|
||||
|
||||
{ "NON", 0x00 },
|
||||
{ "BAD", 0x01 },
|
||||
{ "BIN", 0x06 },
|
||||
{ "TXT", 0x04 },
|
||||
{ "DIR", 0x0f },
|
||||
{ "ADB", 0x19 },
|
||||
{ "AWP", 0x1a },
|
||||
{ "ASP", 0x1b },
|
||||
{ "GSB", 0xab },
|
||||
{ "TDF", 0xac },
|
||||
{ "BDF", 0xad },
|
||||
{ "SRC", 0xb0 },
|
||||
{ "OBJ", 0xb1 },
|
||||
{ "LIB", 0xb2 },
|
||||
{ "S16", 0xb3 },
|
||||
{ "RTL", 0xb4 },
|
||||
{ "EXE", 0xb5 },
|
||||
{ "PIF", 0xb6 },
|
||||
{ "TIF", 0xb7 },
|
||||
{ "NDA", 0xb8 },
|
||||
{ "CDA", 0xb9 },
|
||||
{ "TOL", 0xba },
|
||||
{ "DRV", 0xbb },
|
||||
{ "DOC", 0xbf },
|
||||
{ "PNT", 0xc0 },
|
||||
{ "PIC", 0xc1 },
|
||||
{ "FON", 0xcb },
|
||||
{ "PAS", 0xef },
|
||||
{ "CMD", 0xf0 },
|
||||
{ "LNK", 0xf8 },
|
||||
{ "BAS", 0xfc },
|
||||
{ "VAR", 0xfd },
|
||||
{ "REL", 0xfe },
|
||||
{ "SYS", 0xff },
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -120,6 +158,8 @@ namespace {
|
||||
unsigned kind = 0x0000;
|
||||
unsigned sav = 0;
|
||||
bool end = false;
|
||||
bool fas = false;
|
||||
int ovr = OVR_OFF;
|
||||
|
||||
size_t pos_offset = 0;
|
||||
size_t len_offset = 0;
|
||||
@ -545,16 +585,24 @@ static bool op_after_end(opcode_t op) {
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t eval(operand_t op) {
|
||||
if (std::holds_alternative<uint32_t>(op)) return std::get<uint32_t>(op);
|
||||
std::string &name = std::get<std::string>(op);
|
||||
auto iter = local_symbol_table.find(name);
|
||||
if (iter == local_symbol_table.end()) throw std::runtime_error("Bad symbol");
|
||||
return iter->second;
|
||||
|
||||
extern uint32_t number_operand(const char *cursor, int flags = OP_REQUIRED);
|
||||
extern uint32_t number_operand(const char *cursor, const std::unordered_map<std::string, uint32_t> &, int flags = OP_REQUIRED);
|
||||
extern int ovr_operand(const char *cursor);
|
||||
extern std::string label_operand(const char *cursor, int flags = OP_REQUIRED);
|
||||
extern std::string string_operand(const char *cursor, int flags = OP_REQUIRED);
|
||||
extern std::string path_operand(const char *cursor, int flags = OP_REQUIRED);
|
||||
|
||||
extern void no_operand(const char *cursor);
|
||||
|
||||
static std::string basename(const std::string &str) {
|
||||
|
||||
auto ix = str.find_last_of("/:");
|
||||
if (ix == str.npos) return str;
|
||||
return str.substr(0, ix);
|
||||
}
|
||||
|
||||
|
||||
void evaluate(label_t label, opcode_t opcode, operand_t operand) {
|
||||
void evaluate(label_t label, opcode_t opcode, const char *cursor) {
|
||||
|
||||
// todo - should move operand parsing to here.
|
||||
|
||||
@ -562,8 +610,11 @@ void evaluate(label_t label, opcode_t opcode, operand_t operand) {
|
||||
case OP_DO:
|
||||
if (active_bits & 0x80000000) throw std::runtime_error("too much do do");
|
||||
active_bits <<= 1;
|
||||
active_bits |= eval(operand) ? 1 : 0;
|
||||
if (active) {
|
||||
uint32_t value = number_operand(cursor, local_symbol_table);
|
||||
active_bits |= value ? 1 : 0;
|
||||
active = (active_bits & (active_bits + 1)) == 0;
|
||||
}
|
||||
return;
|
||||
break;
|
||||
|
||||
@ -623,22 +674,20 @@ void evaluate(label_t label, opcode_t opcode, operand_t operand) {
|
||||
|
||||
|
||||
case OP_TYP:
|
||||
// todo - should evaluate with file type dictionary.
|
||||
ftype = eval(operand);
|
||||
ftype = number_operand(cursor, file_types, OP_REQUIRED | OP_INSENSITIVE);
|
||||
break;
|
||||
case OP_ADR:
|
||||
atype = eval(operand);
|
||||
atype = number_operand(cursor, local_symbol_table);
|
||||
break;
|
||||
|
||||
case OP_KND:
|
||||
kind = eval(operand);
|
||||
kind = number_operand(cursor, local_symbol_table);
|
||||
break;
|
||||
|
||||
case OP_LKV: {
|
||||
/* specify linker version */
|
||||
/* 0 = binary, 1 = Linker.GS, 2 = Linker.XL, 3 = convert to OMF object file */
|
||||
|
||||
uint32_t value = eval(operand);
|
||||
uint32_t value = number_operand(cursor, local_symbol_table);
|
||||
switch (value) {
|
||||
case 0: throw std::runtime_error("binary linker not supported");
|
||||
case 3: throw std::runtime_error("object file linker not supported");
|
||||
@ -654,7 +703,7 @@ void evaluate(label_t label, opcode_t opcode, operand_t operand) {
|
||||
|
||||
case OP_VER: {
|
||||
/* OMF version, 1 or 2 */
|
||||
uint32_t value = eval(operand);
|
||||
uint32_t value = number_operand(cursor, local_symbol_table);
|
||||
|
||||
if (value != 2)
|
||||
throw std::runtime_error("bad OMF version");
|
||||
@ -662,29 +711,40 @@ void evaluate(label_t label, opcode_t opcode, operand_t operand) {
|
||||
break;
|
||||
}
|
||||
|
||||
case OP_LNK:
|
||||
case OP_LNK: {
|
||||
if (end) throw std::runtime_error("link after end");
|
||||
//link_unit(std::get<std::string>(operand));
|
||||
|
||||
std::string path = path_operand(cursor);
|
||||
process_unit(path);
|
||||
break;
|
||||
}
|
||||
|
||||
case OP_SAV:
|
||||
case OP_SAV: {
|
||||
if (end) throw std::runtime_error("save after end");
|
||||
if (save_file.empty()) save_file = std::get<std::string>(operand);
|
||||
|
||||
/* if linker version 1, save to disk */
|
||||
/* if linker version 2, finish the current segment */
|
||||
if (lkv == 1) {
|
||||
std::string path = path_operand(cursor);
|
||||
|
||||
/* use 1st SAV as the path */
|
||||
if (save_file.empty()) save_file = path;
|
||||
|
||||
/*
|
||||
lkv 0 = binary linker (unsupported)
|
||||
lkv 1 = 1 segment GS linker
|
||||
lkv 2 = multi-segment GS linker
|
||||
lkv 3 = convert REL to OMF object file (unsupported)
|
||||
*/
|
||||
|
||||
if (lkv == 1 || lkv == 2 || lkv == 3) {
|
||||
auto &seg = segments.back();
|
||||
seg.segname = std::get<std::string>(operand);
|
||||
std::string base = basename(path);
|
||||
seg.segname = std::move(base);
|
||||
seg.kind = kind;
|
||||
}
|
||||
if (lkv == 1) {
|
||||
finish();
|
||||
end = true;
|
||||
}
|
||||
if (lkv == 2) {
|
||||
auto &seg = segments.back();
|
||||
seg.segname = std::get<std::string>(operand);
|
||||
seg.kind = kind;
|
||||
|
||||
/* add a new segment */
|
||||
segments.emplace_back();
|
||||
relocations.emplace_back();
|
||||
@ -692,9 +752,9 @@ void evaluate(label_t label, opcode_t opcode, operand_t operand) {
|
||||
}
|
||||
++sav;
|
||||
break;
|
||||
}
|
||||
|
||||
case OP_KBD: {
|
||||
std::string prompt;
|
||||
char buffer[256];
|
||||
|
||||
if (!isatty(STDIN_FILENO)) return;
|
||||
@ -703,8 +763,7 @@ void evaluate(label_t label, opcode_t opcode, operand_t operand) {
|
||||
if (local_symbol_table.find(label) != local_symbol_table.end())
|
||||
return;
|
||||
|
||||
if (std::holds_alternative<std::string>(operand))
|
||||
prompt = std::get<std::string>(operand);
|
||||
std::string prompt = string_operand(cursor, OP_OPTIONAL);
|
||||
|
||||
if (prompt.empty()) prompt = "Give value for " + label;
|
||||
prompt += ": ";
|
||||
@ -713,12 +772,11 @@ void evaluate(label_t label, opcode_t opcode, operand_t operand) {
|
||||
|
||||
char *cp = fgets(buffer, sizeof(buffer), stdin);
|
||||
|
||||
if (!cp) return;
|
||||
if (!cp) throw std::runtime_error("Bad input");
|
||||
|
||||
operand_t number_operand(const char *YYCURSOR, bool required);
|
||||
operand_t op = number_operand(cp, true);
|
||||
uint32_t value = number_operand(cp, local_symbol_table, true);
|
||||
|
||||
define(label, eval(op), LBL_KBD);
|
||||
define(label, value, LBL_KBD);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -726,10 +784,10 @@ void evaluate(label_t label, opcode_t opcode, operand_t operand) {
|
||||
// POS label << sets label = current segment offset
|
||||
// POS << resets pos byte counter.
|
||||
|
||||
if (std::holds_alternative<std::monostate>(operand)) {
|
||||
std::string label = label_operand(cursor, OP_OPTIONAL);
|
||||
if (label.empty()) {
|
||||
pos_offset = segments.back().data.size();
|
||||
} else {
|
||||
std::string label = std::get<std::string>(operand);
|
||||
uint32_t value = segments.back().data.size() - pos_offset;
|
||||
|
||||
define(label, value, LBL_POS);
|
||||
@ -739,30 +797,44 @@ void evaluate(label_t label, opcode_t opcode, operand_t operand) {
|
||||
case OP_LEN: {
|
||||
// LEN label
|
||||
// sets label = length of most recent file linked
|
||||
std::string label = std::get<std::string>(operand);
|
||||
|
||||
std::string label = label_operand(cursor);
|
||||
uint32_t value = len_offset;
|
||||
define(label, value, LBL_LEN);
|
||||
break;
|
||||
}
|
||||
|
||||
case OP_EQ:
|
||||
define(label, eval(operand), LBL_EQ);
|
||||
define(label, number_operand(cursor, local_symbol_table), LBL_EQ);
|
||||
break;
|
||||
case OP_EQU:
|
||||
define(label, eval(operand), LBL_EQU);
|
||||
define(label, number_operand(cursor, local_symbol_table), LBL_EQU);
|
||||
break;
|
||||
case OP_GEQ:
|
||||
define(label, eval(operand), LBL_GEQ);
|
||||
define(label, number_operand(cursor, local_symbol_table), LBL_GEQ);
|
||||
break;
|
||||
|
||||
case OP_FAS:
|
||||
/* fast linker, only 1 file allowed */
|
||||
fas = true;
|
||||
break;
|
||||
case OP_OVR:
|
||||
case OP_PUT:
|
||||
case OP_IF:
|
||||
ovr = ovr_operand(cursor);
|
||||
break;
|
||||
|
||||
case OP_ASM:
|
||||
case OP_PUT: {
|
||||
std::string path = path_operand(cursor);
|
||||
break;
|
||||
}
|
||||
case OP_IF: {
|
||||
std::string path = path_operand(cursor);
|
||||
break;
|
||||
}
|
||||
|
||||
case OP_ASM: {
|
||||
std::string path = path_operand(cursor);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error("opcode not yet supported");
|
||||
}
|
||||
|
8
script.h
8
script.h
@ -3,10 +3,8 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
typedef std::string label_t;
|
||||
typedef std::variant<std::monostate, uint32_t, std::string> operand_t;
|
||||
|
||||
enum opcode_t {
|
||||
|
||||
@ -23,4 +21,10 @@ enum {
|
||||
OVR_OFF = 0
|
||||
};
|
||||
|
||||
enum {
|
||||
OP_OPTIONAL = 0,
|
||||
OP_REQUIRED = 1,
|
||||
OP_INSENSITIVE = 2
|
||||
};
|
||||
|
||||
#endif
|
||||
|
237
script.re2c
237
script.re2c
@ -11,7 +11,6 @@
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <stdexcept>
|
||||
#include <variant>
|
||||
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
@ -51,45 +50,6 @@ namespace {
|
||||
{ "=", OP_EQ }
|
||||
};
|
||||
|
||||
|
||||
std::unordered_map<std::string, int> types = {
|
||||
|
||||
{ "NON", 0x00 },
|
||||
{ "BAD", 0x01 },
|
||||
{ "BIN", 0x06 },
|
||||
{ "TXT", 0x04 },
|
||||
{ "DIR", 0x0f },
|
||||
{ "ADB", 0x19 },
|
||||
{ "AWP", 0x1a },
|
||||
{ "ASP", 0x1b },
|
||||
{ "GSB", 0xab },
|
||||
{ "TDF", 0xac },
|
||||
{ "BDF", 0xad },
|
||||
{ "SRC", 0xb0 },
|
||||
{ "OBJ", 0xb1 },
|
||||
{ "LIB", 0xb2 },
|
||||
{ "S16", 0xb3 },
|
||||
{ "RTL", 0xb4 },
|
||||
{ "EXE", 0xb5 },
|
||||
{ "PIF", 0xb6 },
|
||||
{ "TIF", 0xb7 },
|
||||
{ "NDA", 0xb8 },
|
||||
{ "CDA", 0xb9 },
|
||||
{ "TOL", 0xba },
|
||||
{ "DRV", 0xbb },
|
||||
{ "DOC", 0xbf },
|
||||
{ "PNT", 0xc0 },
|
||||
{ "PIC", 0xc1 },
|
||||
{ "FON", 0xcb },
|
||||
{ "PAS", 0xef },
|
||||
{ "CMD", 0xf0 },
|
||||
{ "LNK", 0xf8 },
|
||||
{ "BAS", 0xfc },
|
||||
{ "VAR", 0xfd },
|
||||
{ "REL", 0xfe },
|
||||
{ "SYS", 0xff },
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -138,7 +98,7 @@ exit:
|
||||
throw std::invalid_argument("bad operand");
|
||||
}
|
||||
|
||||
static std::string x_label_operand(const char *YYCURSOR) {
|
||||
static std::string x_label_operand(const char *YYCURSOR, bool insensitive) {
|
||||
const char *iter = YYCURSOR;
|
||||
// const char *YYMARKER = nullptr;
|
||||
std::string rv;
|
||||
@ -147,6 +107,8 @@ static std::string x_label_operand(const char *YYCURSOR) {
|
||||
|
||||
ident {
|
||||
rv = std::string(iter, YYCURSOR);
|
||||
if (insensitive)
|
||||
for (char &c : rv) rv = std::toupper(c);
|
||||
goto exit;
|
||||
}
|
||||
*/
|
||||
@ -177,64 +139,33 @@ exit:
|
||||
throw std::invalid_argument("bad operand");
|
||||
}
|
||||
|
||||
uint32_t number_operand(const char *YYCURSOR, const std::unordered_map<std::string, uint32_t> &map, int flags) {
|
||||
|
||||
|
||||
/* not static - called from link.cpp */
|
||||
operand_t number_operand(const char *YYCURSOR, bool required = true) {
|
||||
|
||||
const char *iter = YYCURSOR;
|
||||
const char *cp = YYCURSOR;
|
||||
// const char *YYMARKER = nullptr;
|
||||
/*!re2c
|
||||
* { throw std::invalid_argument("bad operand"); }
|
||||
[;*] | eof {
|
||||
if (!required) return 0;
|
||||
if (flags & OP_REQUIRED)
|
||||
throw std::invalid_argument("missing operand");
|
||||
return 0;
|
||||
}
|
||||
|
||||
number_prefix {
|
||||
return x_number_operand(iter);
|
||||
return x_number_operand(cp);
|
||||
}
|
||||
|
||||
ident_prefix { return x_label_operand(iter); }
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
static uint32_t type_operand(const char *YYCURSOR, bool required = true) {
|
||||
|
||||
const char *iter = YYCURSOR;
|
||||
const char *YYMARKER = nullptr;
|
||||
uint32_t rv = 0;
|
||||
/*!re2c
|
||||
* { throw std::invalid_argument("bad operand"); }
|
||||
|
||||
[;*] | eof {
|
||||
if (!required) return rv;
|
||||
throw std::invalid_argument("missing operand");
|
||||
}
|
||||
number_prefix { return x_number_operand(iter); }
|
||||
|
||||
[A-Za-z][A-Za-z0-9]{2} {
|
||||
std::string s(iter, YYCURSOR);
|
||||
for(char &c : s) c = std::toupper(c);
|
||||
auto iter = types.find(s);
|
||||
if (iter == types.end()) {
|
||||
throw std::invalid_argument("bad operand");
|
||||
}
|
||||
rv = iter->second;
|
||||
goto exit;
|
||||
ident_prefix {
|
||||
std::string s = x_label_operand(cp, flags & OP_INSENSITIVE);
|
||||
auto iter = map.find(s);
|
||||
if (iter == map.end()) throw std::runtime_error("Bad symbol");
|
||||
return iter->second;
|
||||
}
|
||||
*/
|
||||
exit:
|
||||
char c = *YYCURSOR;
|
||||
if (isspace(c) || c == 0) return rv;
|
||||
|
||||
throw std::invalid_argument("bad operand");
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int ovr_operand(const char *YYCURSOR) {
|
||||
int ovr_operand(const char *YYCURSOR) {
|
||||
int rv = 0;
|
||||
const char *YYMARKER = nullptr;
|
||||
|
||||
@ -257,49 +188,44 @@ static int ovr_operand(const char *YYCURSOR) {
|
||||
throw std::invalid_argument("bad operand");
|
||||
}
|
||||
|
||||
static std::string label_operand(const char *YYCURSOR, bool required = true) {
|
||||
std::string rv;
|
||||
const char *iter = YYCURSOR;
|
||||
std::string label_operand(const char *YYCURSOR, int flags) {
|
||||
const char *cp = YYCURSOR;
|
||||
// const char *YYMARKER = nullptr;
|
||||
/*!re2c
|
||||
* { throw std::invalid_argument("bad operand"); }
|
||||
[;*] | eof {
|
||||
if (!required) return rv;
|
||||
if (flags & OP_REQUIRED)
|
||||
throw std::invalid_argument("missing operand");
|
||||
return std::string();
|
||||
}
|
||||
ident {
|
||||
rv = std::string(iter, YYCURSOR);
|
||||
goto exit;
|
||||
ident_prefix {
|
||||
return x_label_operand(cp, flags & OP_INSENSITIVE);
|
||||
}
|
||||
*/
|
||||
|
||||
exit:
|
||||
char c = *YYCURSOR;
|
||||
if (isspace(c) || c == 0) return rv;
|
||||
|
||||
throw std::invalid_argument("bad operand");
|
||||
}
|
||||
|
||||
|
||||
static std::string path_operand(const char *YYCURSOR, bool required = true) {
|
||||
std::string path_operand(const char *YYCURSOR, int flags) {
|
||||
std::string rv;
|
||||
const char *iter = YYCURSOR;
|
||||
// const char *YYMARKER = nullptr;
|
||||
/*!re2c
|
||||
* { throw std::invalid_argument("bad operand"); }
|
||||
|
||||
[;*] | eof {
|
||||
if (!required) return rv;
|
||||
if (flags & OP_REQUIRED)
|
||||
throw std::invalid_argument("missing operand");
|
||||
return rv;
|
||||
}
|
||||
string_prefix {
|
||||
return x_string_operand(iter);
|
||||
}
|
||||
|
||||
// don't allow leading quotes, eof, or comment chars
|
||||
[^;*\x00'"][^ \t]* {
|
||||
. [^ \t]* {
|
||||
rv = std::string(iter, YYCURSOR);
|
||||
goto exit;
|
||||
}
|
||||
['] [^']* ['] | ["] [^"]* ["] {
|
||||
rv = std::string(iter+1, YYCURSOR-1);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
@ -310,8 +236,27 @@ exit:
|
||||
throw std::invalid_argument("bad operand");
|
||||
}
|
||||
|
||||
std::string string_operand(const char *YYCURSOR, int flags) {
|
||||
const char *cp = YYCURSOR;
|
||||
// const char *YYMARKER = nullptr;
|
||||
/*!re2c
|
||||
* { throw std::invalid_argument("bad operand"); }
|
||||
|
||||
static void no_operand(const char *YYCURSOR) {
|
||||
[;*] | eof {
|
||||
if (flags & OP_REQUIRED)
|
||||
throw std::invalid_argument("missing operand");
|
||||
return std::string();
|
||||
}
|
||||
string_prefix {
|
||||
return x_string_operand(cp);
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
void no_operand(const char *YYCURSOR) {
|
||||
/*!re2c
|
||||
* { throw std::invalid_argument("bad operand"); }
|
||||
[;*] | eof { return; }
|
||||
@ -319,35 +264,10 @@ static void no_operand(const char *YYCURSOR) {
|
||||
}
|
||||
|
||||
|
||||
static std::string string_operand(const char *YYCURSOR, bool required = true) {
|
||||
|
||||
std::string rv;
|
||||
const char *iter = YYCURSOR;
|
||||
// const char *YYMARKER = nullptr;
|
||||
/*!re2c
|
||||
* { throw std::invalid_argument("bad operand"); }
|
||||
[;*] | eof {
|
||||
if (!required) return rv;
|
||||
throw std::invalid_argument("missing operand");
|
||||
}
|
||||
['] [^']* ['] | ["] [^"]* ["] {
|
||||
rv = std::string(iter+1, YYCURSOR-1);
|
||||
goto exit;
|
||||
}
|
||||
*/
|
||||
exit:
|
||||
char c = *YYCURSOR;
|
||||
if (isspace(c) || c == 0) return rv;
|
||||
throw std::invalid_argument("bad operand");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void parse_line(const char *YYCURSOR) {
|
||||
|
||||
label_t label;
|
||||
opcode_t opcode = OP_NONE;
|
||||
operand_t operand;
|
||||
|
||||
const char *iter = YYCURSOR;
|
||||
const char *YYMARKER = nullptr;
|
||||
@ -398,64 +318,9 @@ operand:
|
||||
while (isspace(*YYCURSOR)) ++YYCURSOR;
|
||||
iter = YYCURSOR;
|
||||
|
||||
void evaluate(label_t label, opcode_t opcode, const char *);
|
||||
|
||||
switch(opcode) {
|
||||
case OP_LNK:
|
||||
case OP_PUT:
|
||||
case OP_ASM:
|
||||
case OP_SAV:
|
||||
case OP_LIB:
|
||||
case OP_IF:
|
||||
case OP_PFX:
|
||||
case OP_IMP:
|
||||
case OP_RES:
|
||||
case OP_FIL:
|
||||
operand = path_operand(YYCURSOR);
|
||||
break;
|
||||
case OP_ORG:
|
||||
case OP_ADR:
|
||||
case OP_DS:
|
||||
case OP_KND:
|
||||
case OP_VER:
|
||||
case OP_ALI:
|
||||
case OP_LKV:
|
||||
case OP_DO:
|
||||
case OP_EQU:
|
||||
case OP_EQ:
|
||||
case OP_GEQ:
|
||||
operand = number_operand(YYCURSOR);
|
||||
break;
|
||||
case OP_TYP:
|
||||
operand = type_operand(YYCURSOR);
|
||||
break;
|
||||
case OP_OVR:
|
||||
operand = ovr_operand(YYCURSOR);
|
||||
break;
|
||||
case OP_POS:
|
||||
case OP_LEN: {
|
||||
std::string tmp = label_operand(YYCURSOR, false);
|
||||
if (!tmp.empty()) operand = std::move(tmp);
|
||||
break;
|
||||
}
|
||||
case OP_KBD: {
|
||||
std::string tmp = string_operand(YYCURSOR, false);
|
||||
if (!tmp.empty()) operand = std::move(tmp);
|
||||
break;
|
||||
}
|
||||
|
||||
case OP_CMD:
|
||||
operand = std::string(YYCURSOR);
|
||||
break;
|
||||
|
||||
default:
|
||||
no_operand(YYCURSOR);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
void evaluate(label_t label, opcode_t opcode, operand_t operand);
|
||||
|
||||
evaluate(label, opcode, operand);
|
||||
evaluate(label, opcode, YYCURSOR);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user