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 = main.cpp
|
||||||
SRC += lexer.cpp
|
SRC += lexer.cpp
|
||||||
SRC += ast.cpp
|
SRC += ast.cpp
|
||||||
|
SRC += parser.cpp
|
||||||
OBJ = $(patsubst %.cpp,%.o,$(SRC))
|
OBJ = $(patsubst %.cpp,%.o,$(SRC))
|
||||||
DEP = $(patsubst %.cpp,%.d,$(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
|
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
|
void ast_printer_t::visit(const binary_t * binary) const
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
def build_radix_tree(ops: list[str]) -> dict:
|
def build_radix_tree(ops: list[str]) -> dict:
|
||||||
root = dict()
|
root = dict()
|
||||||
for op in ops:
|
for op in ops:
|
||||||
@ -62,38 +64,123 @@ def print_keyword_func(root):
|
|||||||
p()
|
p()
|
||||||
p("}")
|
p("}")
|
||||||
|
|
||||||
from pprint import pprint
|
|
||||||
d = build_radix_tree([
|
alu_keywords = [
|
||||||
"alh",
|
|
||||||
"all",
|
|
||||||
"alu",
|
|
||||||
"m0", "m1", "m2", "m3",
|
|
||||||
"mc0", "mc1", "mc2", "mc3",
|
|
||||||
"mul",
|
|
||||||
"nop",
|
|
||||||
"and",
|
|
||||||
"or",
|
|
||||||
"xor",
|
|
||||||
"add",
|
|
||||||
"sub",
|
|
||||||
"ad2",
|
"ad2",
|
||||||
"sr",
|
"add",
|
||||||
"rr",
|
"and",
|
||||||
"sl",
|
"nop",
|
||||||
|
"or",
|
||||||
"rl",
|
"rl",
|
||||||
"rl8",
|
"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",
|
"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",
|
"mvi",
|
||||||
|
]
|
||||||
|
|
||||||
|
dma_keywords = [
|
||||||
"dma",
|
"dma",
|
||||||
"dmah",
|
"dmah",
|
||||||
|
"d0",
|
||||||
|
"prg",
|
||||||
|
]
|
||||||
|
|
||||||
|
jmp_keywords = [
|
||||||
"jmp",
|
"jmp",
|
||||||
|
]
|
||||||
|
|
||||||
|
loop_keywords = [
|
||||||
"btm",
|
"btm",
|
||||||
"lps",
|
"lps",
|
||||||
|
]
|
||||||
|
|
||||||
|
halt_keywords = [
|
||||||
"end",
|
"end",
|
||||||
"endi",
|
"endi",
|
||||||
|
]
|
||||||
|
|
||||||
|
directive_keywords = [
|
||||||
"equ",
|
"equ",
|
||||||
"org",
|
"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
|
||||||
|
2
expr.hpp
2
expr.hpp
@ -1,3 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "token.hpp"
|
#include "token.hpp"
|
||||||
|
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++]) {
|
switch (s[ix++]) {
|
||||||
case 'A': [[fallthrough]];
|
case 'A': [[fallthrough]];
|
||||||
case 'a':
|
case 'a':
|
||||||
if (ix < s.length()) {
|
if (ix == s.length()) return { token_t::type_t::_a };
|
||||||
|
else {
|
||||||
switch (s[ix++]) {
|
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': [[fallthrough]];
|
||||||
case 'l':
|
case 'l':
|
||||||
if (ix < s.length()) {
|
if (ix < s.length()) {
|
||||||
@ -47,16 +62,152 @@ find(const std::string_view s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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()) {
|
if (ix < s.length()) {
|
||||||
switch (s[ix++]) {
|
switch (s[ix++]) {
|
||||||
case 'D': [[fallthrough]];
|
case 'D': [[fallthrough]];
|
||||||
case 'd':
|
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;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,17 +250,6 @@ find(const std::string_view s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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': [[fallthrough]];
|
||||||
case 'o':
|
case 'o':
|
||||||
if (ix < s.length()) {
|
if (ix < s.length()) {
|
||||||
@ -121,6 +261,17 @@ find(const std::string_view s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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': [[fallthrough]];
|
||||||
case 'v':
|
case 'v':
|
||||||
if (ix < s.length()) {
|
if (ix < s.length()) {
|
||||||
@ -139,6 +290,10 @@ find(const std::string_view s)
|
|||||||
case 'n':
|
case 'n':
|
||||||
if (ix < s.length()) {
|
if (ix < s.length()) {
|
||||||
switch (s[ix++]) {
|
switch (s[ix++]) {
|
||||||
|
case 'C': [[fallthrough]];
|
||||||
|
case 'c':
|
||||||
|
if (ix == s.length()) return { token_t::type_t::_nc };
|
||||||
|
break;
|
||||||
case 'O': [[fallthrough]];
|
case 'O': [[fallthrough]];
|
||||||
case 'o':
|
case 'o':
|
||||||
if (ix < s.length()) {
|
if (ix < s.length()) {
|
||||||
@ -150,6 +305,32 @@ find(const std::string_view s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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;
|
break;
|
||||||
@ -172,9 +353,134 @@ find(const std::string_view s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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': [[fallthrough]];
|
||||||
case 'x':
|
case 'x':
|
||||||
if (ix < s.length()) {
|
if (ix == s.length()) return { token_t::type_t::_x };
|
||||||
|
else {
|
||||||
switch (s[ix++]) {
|
switch (s[ix++]) {
|
||||||
case 'O': [[fallthrough]];
|
case 'O': [[fallthrough]];
|
||||||
case 'o':
|
case 'o':
|
||||||
@ -190,189 +496,18 @@ find(const std::string_view s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'S': [[fallthrough]];
|
case 'Y': [[fallthrough]];
|
||||||
case 's':
|
case 'y':
|
||||||
if (ix < s.length()) {
|
if (ix == s.length()) return { token_t::type_t::_y };
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'R': [[fallthrough]];
|
case 'Z': [[fallthrough]];
|
||||||
case 'r':
|
case 'z':
|
||||||
if (ix < s.length()) {
|
if (ix == s.length()) return { token_t::type_t::_z };
|
||||||
|
else {
|
||||||
switch (s[ix++]) {
|
switch (s[ix++]) {
|
||||||
case 'R': [[fallthrough]];
|
case 'S': [[fallthrough]];
|
||||||
case 'r':
|
case 's':
|
||||||
if (ix == s.length()) return { token_t::type_t::_rr };
|
if (ix == s.length()) return { token_t::type_t::_zs };
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
15
lexer.cpp
15
lexer.cpp
@ -139,7 +139,7 @@ token_t lexer_t::_identifier()
|
|||||||
else return {pos, token_t::identifier, lexeme()};
|
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;
|
using enum token_t::type_t;
|
||||||
|
|
||||||
@ -215,4 +215,17 @@ std::optional<token_t> lexer_t::scan_token()
|
|||||||
__builtin_unreachable();
|
__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 <string_view>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "token.hpp"
|
#include "token.hpp"
|
||||||
|
|
||||||
@ -19,7 +20,8 @@ struct lexer_t {
|
|||||||
: source(source), start_ix(0), current_ix(0), pos{ .line = 1, .col = 0 }
|
: 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:
|
private:
|
||||||
bool at_end_p();
|
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 "lexer.hpp"
|
||||||
#include "token.hpp"
|
#include "token.hpp"
|
||||||
#include "ast.hpp"
|
#include "ast.hpp"
|
||||||
|
#include "parser.hpp"
|
||||||
|
|
||||||
namespace dsp {
|
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)
|
static void run(std::string source)
|
||||||
{
|
{
|
||||||
using namespace dsp;
|
using namespace dsp;
|
||||||
|
|
||||||
std::string_view buf {source};
|
std::string_view buf(source);
|
||||||
lexer_t lexer {buf};
|
lexer_t lexer(buf);
|
||||||
while (std::optional<token_t> token_o = lexer.scan_token()) {
|
std::vector<token_t> tokens = lexer.lex_tokens();
|
||||||
std::cout << *token_o << std::endl;
|
parser_t parser(tokens);
|
||||||
if (token_o->type == token_t::type_t::eof) {
|
expr_t * expr = parser.expression();
|
||||||
break;
|
dsp::ast_printer_t p(std::cout);
|
||||||
}
|
expr->accept(&p);
|
||||||
}
|
std::cout << std::endl << std::flush;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void run_prompt()
|
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[])
|
int main(const int argc, char const * const argv[])
|
||||||
{
|
{
|
||||||
print();
|
|
||||||
switch (argc) {
|
switch (argc) {
|
||||||
case 1: run_prompt(); return dsp::had_error;
|
case 1: run_prompt(); return dsp::had_error;
|
||||||
case 2: return run_file(argv[1]);
|
case 2: return run_file(argv[1]);
|
||||||
|
83
token.hpp
83
token.hpp
@ -45,47 +45,12 @@ struct token_t {
|
|||||||
string,
|
string,
|
||||||
number,
|
number,
|
||||||
|
|
||||||
// keywords
|
// ends
|
||||||
_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,
|
|
||||||
|
|
||||||
eof,
|
eof,
|
||||||
eol,
|
eol,
|
||||||
|
|
||||||
|
// keywords
|
||||||
|
#include "keyword.enum_inc"
|
||||||
};
|
};
|
||||||
|
|
||||||
using literal_t = std::variant<std::monostate, num_type>;
|
using literal_t = std::variant<std::monostate, num_type>;
|
||||||
@ -133,44 +98,8 @@ struct token_t {
|
|||||||
case string : return os << "STRING";
|
case string : return os << "STRING";
|
||||||
case number : return os << "NUMBER";
|
case number : return os << "NUMBER";
|
||||||
|
|
||||||
// keywords
|
// keywords
|
||||||
case _alh : return os << "ALH";
|
#include "keyword.case_inc"
|
||||||
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";
|
|
||||||
|
|
||||||
case eof : return os << "EOF";
|
case eof : return os << "EOF";
|
||||||
case eol : return os << "EOL";
|
case eol : return os << "EOL";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user