keyword: add more keywords
This also concedes that a lexer that returns std::vector is probably the simplest API for the parser, but I will still continue to consider alternatives.
This commit is contained in:
parent
c59a221c54
commit
e48bd182dc
1
Makefile
1
Makefile
@ -7,6 +7,7 @@ CXX = $(TARGET)clang++
|
||||
SRC = main.cpp
|
||||
SRC += lexer.cpp
|
||||
SRC += ast.cpp
|
||||
SRC += parser.cpp
|
||||
OBJ = $(patsubst %.cpp,%.o,$(SRC))
|
||||
DEP = $(patsubst %.cpp,%.d,$(SRC))
|
||||
|
||||
|
2
ast.cpp
2
ast.cpp
@ -4,7 +4,7 @@ namespace dsp {
|
||||
|
||||
void ast_printer_t::visit(const unary_t * unary) const
|
||||
{
|
||||
parenthesize((unary->oper).lexeme, unary->expr);
|
||||
parenthesize((unary->oper).lexeme, unary->right);
|
||||
}
|
||||
|
||||
void ast_printer_t::visit(const binary_t * binary) const
|
||||
|
@ -1,3 +1,5 @@
|
||||
import sys
|
||||
|
||||
def build_radix_tree(ops: list[str]) -> dict:
|
||||
root = dict()
|
||||
for op in ops:
|
||||
@ -62,38 +64,123 @@ def print_keyword_func(root):
|
||||
p()
|
||||
p("}")
|
||||
|
||||
from pprint import pprint
|
||||
d = build_radix_tree([
|
||||
"alh",
|
||||
"all",
|
||||
"alu",
|
||||
"m0", "m1", "m2", "m3",
|
||||
"mc0", "mc1", "mc2", "mc3",
|
||||
"mul",
|
||||
"nop",
|
||||
"and",
|
||||
"or",
|
||||
"xor",
|
||||
"add",
|
||||
"sub",
|
||||
|
||||
alu_keywords = [
|
||||
"ad2",
|
||||
"sr",
|
||||
"rr",
|
||||
"sl",
|
||||
"add",
|
||||
"and",
|
||||
"nop",
|
||||
"or",
|
||||
"rl",
|
||||
"rl8",
|
||||
"rr",
|
||||
"sl",
|
||||
"sr",
|
||||
"sub",
|
||||
"xor",
|
||||
]
|
||||
|
||||
x_bus_keywords = [
|
||||
"mov", # Mn, MCn
|
||||
"x",
|
||||
"p",
|
||||
"mul",
|
||||
]
|
||||
|
||||
mn = ["m0", "m1", "m2", "m3"]
|
||||
mcn = ["mc0", "mc1", "mc2", "mc3"]
|
||||
|
||||
y_bus_keywords = [
|
||||
"mov", # Mn, MCn
|
||||
"clr",
|
||||
"mov",
|
||||
"y",
|
||||
"a",
|
||||
"alu",
|
||||
]
|
||||
|
||||
d1_bus_keywords = [
|
||||
"mov", # MCn
|
||||
"alh",
|
||||
"all",
|
||||
]
|
||||
|
||||
reg_keywords = [
|
||||
"rx",
|
||||
"pl",
|
||||
"ra0",
|
||||
"wa0",
|
||||
"lop",
|
||||
"top",
|
||||
]
|
||||
|
||||
cond_keywords = [
|
||||
"z",
|
||||
"nz",
|
||||
"s",
|
||||
"ns",
|
||||
"c",
|
||||
"nc",
|
||||
"t0",
|
||||
"nt0",
|
||||
"zs",
|
||||
"nzs",
|
||||
]
|
||||
|
||||
move_immediate_keywords = [
|
||||
"mvi",
|
||||
]
|
||||
|
||||
dma_keywords = [
|
||||
"dma",
|
||||
"dmah",
|
||||
"d0",
|
||||
"prg",
|
||||
]
|
||||
|
||||
jmp_keywords = [
|
||||
"jmp",
|
||||
]
|
||||
|
||||
loop_keywords = [
|
||||
"btm",
|
||||
"lps",
|
||||
]
|
||||
|
||||
halt_keywords = [
|
||||
"end",
|
||||
"endi",
|
||||
]
|
||||
|
||||
directive_keywords = [
|
||||
"equ",
|
||||
"org",
|
||||
"ends",
|
||||
])
|
||||
print_keyword_func(d)
|
||||
]
|
||||
|
||||
keywords = sorted(set([
|
||||
*alu_keywords,
|
||||
*x_bus_keywords,
|
||||
*mn,
|
||||
*mcn,
|
||||
*y_bus_keywords,
|
||||
*d1_bus_keywords,
|
||||
*reg_keywords,
|
||||
*cond_keywords,
|
||||
*move_immediate_keywords,
|
||||
*dma_keywords,
|
||||
*jmp_keywords,
|
||||
*loop_keywords,
|
||||
*halt_keywords,
|
||||
*directive_keywords,
|
||||
]))
|
||||
|
||||
if sys.argv[1] == 'hpp':
|
||||
d = build_radix_tree(keywords)
|
||||
print_keyword_func(d)
|
||||
elif sys.argv[1] == 'enum_inc':
|
||||
for k in keywords:
|
||||
print(f"_{k},")
|
||||
elif sys.argv[1] == 'case_inc':
|
||||
for k in keywords:
|
||||
print(f'case _{k.ljust(4, " ")} : return os << "{k.upper()}";')
|
||||
else:
|
||||
assert False, sys.argv
|
||||
|
58
keyword.case_inc
Normal file
58
keyword.case_inc
Normal file
@ -0,0 +1,58 @@
|
||||
case _a : return os << "A";
|
||||
case _ad2 : return os << "AD2";
|
||||
case _add : return os << "ADD";
|
||||
case _alh : return os << "ALH";
|
||||
case _all : return os << "ALL";
|
||||
case _alu : return os << "ALU";
|
||||
case _and : return os << "AND";
|
||||
case _btm : return os << "BTM";
|
||||
case _c : return os << "C";
|
||||
case _clr : return os << "CLR";
|
||||
case _d0 : return os << "D0";
|
||||
case _dma : return os << "DMA";
|
||||
case _dmah : return os << "DMAH";
|
||||
case _end : return os << "END";
|
||||
case _endi : return os << "ENDI";
|
||||
case _equ : return os << "EQU";
|
||||
case _jmp : return os << "JMP";
|
||||
case _lop : return os << "LOP";
|
||||
case _lps : return os << "LPS";
|
||||
case _m0 : return os << "M0";
|
||||
case _m1 : return os << "M1";
|
||||
case _m2 : return os << "M2";
|
||||
case _m3 : return os << "M3";
|
||||
case _mc0 : return os << "MC0";
|
||||
case _mc1 : return os << "MC1";
|
||||
case _mc2 : return os << "MC2";
|
||||
case _mc3 : return os << "MC3";
|
||||
case _mov : return os << "MOV";
|
||||
case _mul : return os << "MUL";
|
||||
case _mvi : return os << "MVI";
|
||||
case _nc : return os << "NC";
|
||||
case _nop : return os << "NOP";
|
||||
case _ns : return os << "NS";
|
||||
case _nt0 : return os << "NT0";
|
||||
case _nz : return os << "NZ";
|
||||
case _nzs : return os << "NZS";
|
||||
case _or : return os << "OR";
|
||||
case _org : return os << "ORG";
|
||||
case _p : return os << "P";
|
||||
case _pl : return os << "PL";
|
||||
case _prg : return os << "PRG";
|
||||
case _ra0 : return os << "RA0";
|
||||
case _rl : return os << "RL";
|
||||
case _rl8 : return os << "RL8";
|
||||
case _rr : return os << "RR";
|
||||
case _rx : return os << "RX";
|
||||
case _s : return os << "S";
|
||||
case _sl : return os << "SL";
|
||||
case _sr : return os << "SR";
|
||||
case _sub : return os << "SUB";
|
||||
case _t0 : return os << "T0";
|
||||
case _top : return os << "TOP";
|
||||
case _wa0 : return os << "WA0";
|
||||
case _x : return os << "X";
|
||||
case _xor : return os << "XOR";
|
||||
case _y : return os << "Y";
|
||||
case _z : return os << "Z";
|
||||
case _zs : return os << "ZS";
|
58
keyword.enum_inc
Normal file
58
keyword.enum_inc
Normal file
@ -0,0 +1,58 @@
|
||||
_a,
|
||||
_ad2,
|
||||
_add,
|
||||
_alh,
|
||||
_all,
|
||||
_alu,
|
||||
_and,
|
||||
_btm,
|
||||
_c,
|
||||
_clr,
|
||||
_d0,
|
||||
_dma,
|
||||
_dmah,
|
||||
_end,
|
||||
_endi,
|
||||
_equ,
|
||||
_jmp,
|
||||
_lop,
|
||||
_lps,
|
||||
_m0,
|
||||
_m1,
|
||||
_m2,
|
||||
_m3,
|
||||
_mc0,
|
||||
_mc1,
|
||||
_mc2,
|
||||
_mc3,
|
||||
_mov,
|
||||
_mul,
|
||||
_mvi,
|
||||
_nc,
|
||||
_nop,
|
||||
_ns,
|
||||
_nt0,
|
||||
_nz,
|
||||
_nzs,
|
||||
_or,
|
||||
_org,
|
||||
_p,
|
||||
_pl,
|
||||
_prg,
|
||||
_ra0,
|
||||
_rl,
|
||||
_rl8,
|
||||
_rr,
|
||||
_rx,
|
||||
_s,
|
||||
_sl,
|
||||
_sr,
|
||||
_sub,
|
||||
_t0,
|
||||
_top,
|
||||
_wa0,
|
||||
_x,
|
||||
_xor,
|
||||
_y,
|
||||
_z,
|
||||
_zs,
|
533
keyword.hpp
533
keyword.hpp
@ -15,8 +15,23 @@ find(const std::string_view s)
|
||||
switch (s[ix++]) {
|
||||
case 'A': [[fallthrough]];
|
||||
case 'a':
|
||||
if (ix < s.length()) {
|
||||
if (ix == s.length()) return { token_t::type_t::_a };
|
||||
else {
|
||||
switch (s[ix++]) {
|
||||
case 'D': [[fallthrough]];
|
||||
case 'd':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case '2':
|
||||
if (ix == s.length()) return { token_t::type_t::_ad2 };
|
||||
break;
|
||||
case 'D': [[fallthrough]];
|
||||
case 'd':
|
||||
if (ix == s.length()) return { token_t::type_t::_add };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'L': [[fallthrough]];
|
||||
case 'l':
|
||||
if (ix < s.length()) {
|
||||
@ -47,16 +62,152 @@ find(const std::string_view s)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'D': [[fallthrough]];
|
||||
case 'd':
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'B': [[fallthrough]];
|
||||
case 'b':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'T': [[fallthrough]];
|
||||
case 't':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'M': [[fallthrough]];
|
||||
case 'm':
|
||||
if (ix == s.length()) return { token_t::type_t::_btm };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'C': [[fallthrough]];
|
||||
case 'c':
|
||||
if (ix == s.length()) return { token_t::type_t::_c };
|
||||
else {
|
||||
switch (s[ix++]) {
|
||||
case 'L': [[fallthrough]];
|
||||
case 'l':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'R': [[fallthrough]];
|
||||
case 'r':
|
||||
if (ix == s.length()) return { token_t::type_t::_clr };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'D': [[fallthrough]];
|
||||
case 'd':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case '0':
|
||||
if (ix == s.length()) return { token_t::type_t::_d0 };
|
||||
break;
|
||||
case 'M': [[fallthrough]];
|
||||
case 'm':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'A': [[fallthrough]];
|
||||
case 'a':
|
||||
if (ix == s.length()) return { token_t::type_t::_dma };
|
||||
else {
|
||||
switch (s[ix++]) {
|
||||
case 'H': [[fallthrough]];
|
||||
case 'h':
|
||||
if (ix == s.length()) return { token_t::type_t::_dmah };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'E': [[fallthrough]];
|
||||
case 'e':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'N': [[fallthrough]];
|
||||
case 'n':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'D': [[fallthrough]];
|
||||
case 'd':
|
||||
if (ix == s.length()) return { token_t::type_t::_add };
|
||||
if (ix == s.length()) return { token_t::type_t::_end };
|
||||
else {
|
||||
switch (s[ix++]) {
|
||||
case 'I': [[fallthrough]];
|
||||
case 'i':
|
||||
if (ix == s.length()) return { token_t::type_t::_endi };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '2':
|
||||
if (ix == s.length()) return { token_t::type_t::_ad2 };
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'Q': [[fallthrough]];
|
||||
case 'q':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'U': [[fallthrough]];
|
||||
case 'u':
|
||||
if (ix == s.length()) return { token_t::type_t::_equ };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'J': [[fallthrough]];
|
||||
case 'j':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'M': [[fallthrough]];
|
||||
case 'm':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'P': [[fallthrough]];
|
||||
case 'p':
|
||||
if (ix == s.length()) return { token_t::type_t::_jmp };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'L': [[fallthrough]];
|
||||
case 'l':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'O': [[fallthrough]];
|
||||
case 'o':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'P': [[fallthrough]];
|
||||
case 'p':
|
||||
if (ix == s.length()) return { token_t::type_t::_lop };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'P': [[fallthrough]];
|
||||
case 'p':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'S': [[fallthrough]];
|
||||
case 's':
|
||||
if (ix == s.length()) return { token_t::type_t::_lps };
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -99,17 +250,6 @@ find(const std::string_view s)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'U': [[fallthrough]];
|
||||
case 'u':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'L': [[fallthrough]];
|
||||
case 'l':
|
||||
if (ix == s.length()) return { token_t::type_t::_mul };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'O': [[fallthrough]];
|
||||
case 'o':
|
||||
if (ix < s.length()) {
|
||||
@ -121,6 +261,17 @@ find(const std::string_view s)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'U': [[fallthrough]];
|
||||
case 'u':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'L': [[fallthrough]];
|
||||
case 'l':
|
||||
if (ix == s.length()) return { token_t::type_t::_mul };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'V': [[fallthrough]];
|
||||
case 'v':
|
||||
if (ix < s.length()) {
|
||||
@ -139,6 +290,10 @@ find(const std::string_view s)
|
||||
case 'n':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'C': [[fallthrough]];
|
||||
case 'c':
|
||||
if (ix == s.length()) return { token_t::type_t::_nc };
|
||||
break;
|
||||
case 'O': [[fallthrough]];
|
||||
case 'o':
|
||||
if (ix < s.length()) {
|
||||
@ -150,6 +305,32 @@ find(const std::string_view s)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'S': [[fallthrough]];
|
||||
case 's':
|
||||
if (ix == s.length()) return { token_t::type_t::_ns };
|
||||
break;
|
||||
case 'T': [[fallthrough]];
|
||||
case 't':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case '0':
|
||||
if (ix == s.length()) return { token_t::type_t::_nt0 };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'Z': [[fallthrough]];
|
||||
case 'z':
|
||||
if (ix == s.length()) return { token_t::type_t::_nz };
|
||||
else {
|
||||
switch (s[ix++]) {
|
||||
case 'S': [[fallthrough]];
|
||||
case 's':
|
||||
if (ix == s.length()) return { token_t::type_t::_nzs };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -172,9 +353,134 @@ find(const std::string_view s)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'P': [[fallthrough]];
|
||||
case 'p':
|
||||
if (ix == s.length()) return { token_t::type_t::_p };
|
||||
else {
|
||||
switch (s[ix++]) {
|
||||
case 'L': [[fallthrough]];
|
||||
case 'l':
|
||||
if (ix == s.length()) return { token_t::type_t::_pl };
|
||||
break;
|
||||
case 'R': [[fallthrough]];
|
||||
case 'r':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'G': [[fallthrough]];
|
||||
case 'g':
|
||||
if (ix == s.length()) return { token_t::type_t::_prg };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'R': [[fallthrough]];
|
||||
case 'r':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'A': [[fallthrough]];
|
||||
case 'a':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case '0':
|
||||
if (ix == s.length()) return { token_t::type_t::_ra0 };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'L': [[fallthrough]];
|
||||
case 'l':
|
||||
if (ix == s.length()) return { token_t::type_t::_rl };
|
||||
else {
|
||||
switch (s[ix++]) {
|
||||
case '8':
|
||||
if (ix == s.length()) return { token_t::type_t::_rl8 };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'R': [[fallthrough]];
|
||||
case 'r':
|
||||
if (ix == s.length()) return { token_t::type_t::_rr };
|
||||
break;
|
||||
case 'X': [[fallthrough]];
|
||||
case 'x':
|
||||
if (ix == s.length()) return { token_t::type_t::_rx };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'S': [[fallthrough]];
|
||||
case 's':
|
||||
if (ix == s.length()) return { token_t::type_t::_s };
|
||||
else {
|
||||
switch (s[ix++]) {
|
||||
case 'L': [[fallthrough]];
|
||||
case 'l':
|
||||
if (ix == s.length()) return { token_t::type_t::_sl };
|
||||
break;
|
||||
case 'R': [[fallthrough]];
|
||||
case 'r':
|
||||
if (ix == s.length()) return { token_t::type_t::_sr };
|
||||
break;
|
||||
case 'U': [[fallthrough]];
|
||||
case 'u':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'B': [[fallthrough]];
|
||||
case 'b':
|
||||
if (ix == s.length()) return { token_t::type_t::_sub };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'T': [[fallthrough]];
|
||||
case 't':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case '0':
|
||||
if (ix == s.length()) return { token_t::type_t::_t0 };
|
||||
break;
|
||||
case 'O': [[fallthrough]];
|
||||
case 'o':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'P': [[fallthrough]];
|
||||
case 'p':
|
||||
if (ix == s.length()) return { token_t::type_t::_top };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'W': [[fallthrough]];
|
||||
case 'w':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'A': [[fallthrough]];
|
||||
case 'a':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case '0':
|
||||
if (ix == s.length()) return { token_t::type_t::_wa0 };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'X': [[fallthrough]];
|
||||
case 'x':
|
||||
if (ix < s.length()) {
|
||||
if (ix == s.length()) return { token_t::type_t::_x };
|
||||
else {
|
||||
switch (s[ix++]) {
|
||||
case 'O': [[fallthrough]];
|
||||
case 'o':
|
||||
@ -190,189 +496,18 @@ find(const std::string_view s)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'S': [[fallthrough]];
|
||||
case 's':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'U': [[fallthrough]];
|
||||
case 'u':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'B': [[fallthrough]];
|
||||
case 'b':
|
||||
if (ix == s.length()) return { token_t::type_t::_sub };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'R': [[fallthrough]];
|
||||
case 'r':
|
||||
if (ix == s.length()) return { token_t::type_t::_sr };
|
||||
break;
|
||||
case 'L': [[fallthrough]];
|
||||
case 'l':
|
||||
if (ix == s.length()) return { token_t::type_t::_sl };
|
||||
break;
|
||||
}
|
||||
}
|
||||
case 'Y': [[fallthrough]];
|
||||
case 'y':
|
||||
if (ix == s.length()) return { token_t::type_t::_y };
|
||||
break;
|
||||
case 'R': [[fallthrough]];
|
||||
case 'r':
|
||||
if (ix < s.length()) {
|
||||
case 'Z': [[fallthrough]];
|
||||
case 'z':
|
||||
if (ix == s.length()) return { token_t::type_t::_z };
|
||||
else {
|
||||
switch (s[ix++]) {
|
||||
case 'R': [[fallthrough]];
|
||||
case 'r':
|
||||
if (ix == s.length()) return { token_t::type_t::_rr };
|
||||
break;
|
||||
case 'L': [[fallthrough]];
|
||||
case 'l':
|
||||
if (ix == s.length()) return { token_t::type_t::_rl };
|
||||
else {
|
||||
switch (s[ix++]) {
|
||||
case '8':
|
||||
if (ix == s.length()) return { token_t::type_t::_rl8 };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'C': [[fallthrough]];
|
||||
case 'c':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'L': [[fallthrough]];
|
||||
case 'l':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'R': [[fallthrough]];
|
||||
case 'r':
|
||||
if (ix == s.length()) return { token_t::type_t::_clr };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'D': [[fallthrough]];
|
||||
case 'd':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'M': [[fallthrough]];
|
||||
case 'm':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'A': [[fallthrough]];
|
||||
case 'a':
|
||||
if (ix == s.length()) return { token_t::type_t::_dma };
|
||||
else {
|
||||
switch (s[ix++]) {
|
||||
case 'H': [[fallthrough]];
|
||||
case 'h':
|
||||
if (ix == s.length()) return { token_t::type_t::_dmah };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'J': [[fallthrough]];
|
||||
case 'j':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'M': [[fallthrough]];
|
||||
case 'm':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'P': [[fallthrough]];
|
||||
case 'p':
|
||||
if (ix == s.length()) return { token_t::type_t::_jmp };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'B': [[fallthrough]];
|
||||
case 'b':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'T': [[fallthrough]];
|
||||
case 't':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'M': [[fallthrough]];
|
||||
case 'm':
|
||||
if (ix == s.length()) return { token_t::type_t::_btm };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'L': [[fallthrough]];
|
||||
case 'l':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'P': [[fallthrough]];
|
||||
case 'p':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'S': [[fallthrough]];
|
||||
case 's':
|
||||
if (ix == s.length()) return { token_t::type_t::_lps };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'E': [[fallthrough]];
|
||||
case 'e':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'N': [[fallthrough]];
|
||||
case 'n':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'D': [[fallthrough]];
|
||||
case 'd':
|
||||
if (ix == s.length()) return { token_t::type_t::_end };
|
||||
else {
|
||||
switch (s[ix++]) {
|
||||
case 'I': [[fallthrough]];
|
||||
case 'i':
|
||||
if (ix == s.length()) return { token_t::type_t::_endi };
|
||||
break;
|
||||
case 'S': [[fallthrough]];
|
||||
case 's':
|
||||
if (ix == s.length()) return { token_t::type_t::_ends };
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'Q': [[fallthrough]];
|
||||
case 'q':
|
||||
if (ix < s.length()) {
|
||||
switch (s[ix++]) {
|
||||
case 'U': [[fallthrough]];
|
||||
case 'u':
|
||||
if (ix == s.length()) return { token_t::type_t::_equ };
|
||||
break;
|
||||
}
|
||||
}
|
||||
case 'S': [[fallthrough]];
|
||||
case 's':
|
||||
if (ix == s.length()) return { token_t::type_t::_zs };
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
15
lexer.cpp
15
lexer.cpp
@ -139,7 +139,7 @@ token_t lexer_t::_identifier()
|
||||
else return {pos, token_t::identifier, lexeme()};
|
||||
}
|
||||
|
||||
std::optional<token_t> lexer_t::scan_token()
|
||||
std::optional<token_t> lexer_t::lex_token()
|
||||
{
|
||||
using enum token_t::type_t;
|
||||
|
||||
@ -215,4 +215,17 @@ std::optional<token_t> lexer_t::scan_token()
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
std::vector<token_t> lexer_t::lex_tokens()
|
||||
{
|
||||
std::vector<token_t> tokens;
|
||||
|
||||
while (true) {
|
||||
std::optional<token_t> token_o = lex_token();
|
||||
if (!token_o) continue;
|
||||
tokens.push_back(*token_o);
|
||||
if (token_o->type == token_t::eof) break;
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <string_view>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include "token.hpp"
|
||||
|
||||
@ -19,7 +20,8 @@ struct lexer_t {
|
||||
: source(source), start_ix(0), current_ix(0), pos{ .line = 1, .col = 0 }
|
||||
{ }
|
||||
|
||||
std::optional<token_t> scan_token();
|
||||
std::optional<token_t> lex_token();
|
||||
std::vector<token_t> lex_tokens();
|
||||
|
||||
private:
|
||||
bool at_end_p();
|
||||
|
35
lexer_iterator.cpp
Normal file
35
lexer_iterator.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
#include "lexer.hpp"
|
||||
#include "token.hpp"
|
||||
|
||||
namespace dsp {
|
||||
|
||||
struct lexer_iterator_t
|
||||
{
|
||||
token_t previous_token;
|
||||
token_t current_token;
|
||||
lexer_t& lexer;
|
||||
|
||||
lexer_iterator_t(lexer_t& lexer)
|
||||
: lexer(lexer), previous_token(lexer.scan_token()), current_token(previous_token)
|
||||
{
|
||||
}
|
||||
|
||||
token_t& advance()
|
||||
{
|
||||
previous_token = current_token;
|
||||
current_token = lexer.scan_token();
|
||||
return previous_token;
|
||||
}
|
||||
|
||||
token_t& peek()
|
||||
{
|
||||
return current_token;
|
||||
}
|
||||
|
||||
token_t& previous()
|
||||
{
|
||||
return previous_token;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
28
main.cpp
28
main.cpp
@ -5,6 +5,7 @@
|
||||
#include "lexer.hpp"
|
||||
#include "token.hpp"
|
||||
#include "ast.hpp"
|
||||
#include "parser.hpp"
|
||||
|
||||
namespace dsp {
|
||||
|
||||
@ -12,28 +13,18 @@ bool had_error = false;
|
||||
|
||||
}
|
||||
|
||||
static void print()
|
||||
{
|
||||
dsp::literal_t l(56);
|
||||
std::string_view s("-");
|
||||
dsp::token_t t({0, 0}, dsp::token_t::minus, s);
|
||||
dsp::unary_t a(t, &l);
|
||||
dsp::ast_printer_t p(std::cout);
|
||||
p.visit(&a);
|
||||
}
|
||||
|
||||
static void run(std::string source)
|
||||
{
|
||||
using namespace dsp;
|
||||
|
||||
std::string_view buf {source};
|
||||
lexer_t lexer {buf};
|
||||
while (std::optional<token_t> token_o = lexer.scan_token()) {
|
||||
std::cout << *token_o << std::endl;
|
||||
if (token_o->type == token_t::type_t::eof) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::string_view buf(source);
|
||||
lexer_t lexer(buf);
|
||||
std::vector<token_t> tokens = lexer.lex_tokens();
|
||||
parser_t parser(tokens);
|
||||
expr_t * expr = parser.expression();
|
||||
dsp::ast_printer_t p(std::cout);
|
||||
expr->accept(&p);
|
||||
std::cout << std::endl << std::flush;
|
||||
}
|
||||
|
||||
static void run_prompt()
|
||||
@ -67,7 +58,6 @@ static int run_file(char const * const filename)
|
||||
|
||||
int main(const int argc, char const * const argv[])
|
||||
{
|
||||
print();
|
||||
switch (argc) {
|
||||
case 1: run_prompt(); return dsp::had_error;
|
||||
case 2: return run_file(argv[1]);
|
||||
|
83
token.hpp
83
token.hpp
@ -45,47 +45,12 @@ struct token_t {
|
||||
string,
|
||||
number,
|
||||
|
||||
// keywords
|
||||
_alh,
|
||||
_all,
|
||||
_alu,
|
||||
_m0,
|
||||
_m1,
|
||||
_m2,
|
||||
_m3,
|
||||
_mc0,
|
||||
_mc1,
|
||||
_mc2,
|
||||
_mc3,
|
||||
_mul,
|
||||
_nop,
|
||||
_and,
|
||||
_or,
|
||||
_xor,
|
||||
_add,
|
||||
_sub,
|
||||
_ad2,
|
||||
_sr,
|
||||
_rr,
|
||||
_sl,
|
||||
_rl,
|
||||
_rl8,
|
||||
_clr,
|
||||
_mov,
|
||||
_mvi,
|
||||
_dma,
|
||||
_dmah,
|
||||
_jmp,
|
||||
_btm,
|
||||
_lps,
|
||||
_end,
|
||||
_endi,
|
||||
_equ,
|
||||
_org,
|
||||
_ends,
|
||||
|
||||
// ends
|
||||
eof,
|
||||
eol,
|
||||
|
||||
// keywords
|
||||
#include "keyword.enum_inc"
|
||||
};
|
||||
|
||||
using literal_t = std::variant<std::monostate, num_type>;
|
||||
@ -133,44 +98,8 @@ struct token_t {
|
||||
case string : return os << "STRING";
|
||||
case number : return os << "NUMBER";
|
||||
|
||||
// keywords
|
||||
case _alh : return os << "ALH";
|
||||
case _all : return os << "ALL";
|
||||
case _alu : return os << "ALU";
|
||||
case _m0 : return os << "M0";
|
||||
case _m1 : return os << "M1";
|
||||
case _m2 : return os << "M2";
|
||||
case _m3 : return os << "M3";
|
||||
case _mc0 : return os << "MC0";
|
||||
case _mc1 : return os << "MC1";
|
||||
case _mc2 : return os << "MC2";
|
||||
case _mc3 : return os << "MC3";
|
||||
case _mul : return os << "MUL";
|
||||
case _nop : return os << "NOP";
|
||||
case _and : return os << "AND";
|
||||
case _or : return os << "OR";
|
||||
case _xor : return os << "XOR";
|
||||
case _add : return os << "ADD";
|
||||
case _sub : return os << "SUB";
|
||||
case _ad2 : return os << "AD2";
|
||||
case _sr : return os << "SR";
|
||||
case _rr : return os << "RR";
|
||||
case _sl : return os << "SL";
|
||||
case _rl : return os << "RL";
|
||||
case _rl8 : return os << "RL8";
|
||||
case _clr : return os << "CLR";
|
||||
case _mov : return os << "MOV";
|
||||
case _mvi : return os << "MVI";
|
||||
case _dma : return os << "DMA";
|
||||
case _dmah : return os << "DMAH";
|
||||
case _jmp : return os << "JMP";
|
||||
case _btm : return os << "BTM";
|
||||
case _lps : return os << "LPS";
|
||||
case _end : return os << "END";
|
||||
case _endi : return os << "ENDI";
|
||||
case _equ : return os << "EQU";
|
||||
case _org : return os << "ORG";
|
||||
case _ends : return os << "ENDS";
|
||||
// keywords
|
||||
#include "keyword.case_inc"
|
||||
|
||||
case eof : return os << "EOF";
|
||||
case eol : return os << "EOL";
|
||||
|
Loading…
x
Reference in New Issue
Block a user