parser: add dma and mvi parsers
This commit is contained in:
parent
22625c7c90
commit
b97abc776c
61
ast.cpp
61
ast.cpp
@ -15,7 +15,7 @@ void ast_printer_t::visit(const binary_t * binary) const
|
|||||||
|
|
||||||
void ast_printer_t::visit(const grouping_t * grouping) const
|
void ast_printer_t::visit(const grouping_t * grouping) const
|
||||||
{
|
{
|
||||||
parenthesize(std::string_view("<grouping>"), grouping->expr);
|
parenthesize("grouping", grouping->expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ast_printer_t::visit(const literal_t * literal) const
|
void ast_printer_t::visit(const literal_t * literal) const
|
||||||
@ -37,18 +37,25 @@ void ast_printer_t::parenthesize(const std::string_view s1, const std::string_vi
|
|||||||
os << ')';
|
os << ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ast_printer_t::parenthesize(const std::string_view s1, const std::string_view s2, const std::string_view s3, const expr_t * a) const
|
||||||
|
{
|
||||||
|
os << '(' << s1 << ' ' << s2 << ' ' << s3 << ' ';
|
||||||
|
a->accept(this);
|
||||||
|
os << ')';
|
||||||
|
}
|
||||||
|
|
||||||
void ast_printer_t::parenthesize(const std::string_view s1, const expr_t * a, const std::string_view s2) const
|
void ast_printer_t::parenthesize(const std::string_view s1, const expr_t * a, const std::string_view s2) const
|
||||||
{
|
{
|
||||||
os << '(' << s1 << ' ';
|
os << '(' << s1 << ' ';
|
||||||
a->accept(this);
|
a->accept(this);
|
||||||
os << s2 << ')';
|
os << ' ' << s2 << ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
void ast_printer_t::parenthesize(const std::string_view s1, const expr_t * a, const std::string_view s2, const std::string_view s3) const
|
void ast_printer_t::parenthesize(const std::string_view s1, const expr_t * a, const std::string_view s2, const std::string_view s3) const
|
||||||
{
|
{
|
||||||
os << '(' << s1 << ' ';
|
os << '(' << s1 << ' ';
|
||||||
a->accept(this);
|
a->accept(this);
|
||||||
os << s2 << ' ' << s3 << ')';
|
os << ' ' << s2 << ' ' << s3 << ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
void ast_printer_t::parenthesize(const std::string_view s) const
|
void ast_printer_t::parenthesize(const std::string_view s) const
|
||||||
@ -66,6 +73,11 @@ void ast_printer_t::parenthesize(const std::string_view s1, const std::string_vi
|
|||||||
os << '(' << s1 << ' ' << s2 << ' ' << s3 << ')';
|
os << '(' << s1 << ' ' << s2 << ' ' << s3 << ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ast_printer_t::parenthesize(const std::string_view s1, const std::string_view s2, const std::string_view s3, const std::string_view s4) const
|
||||||
|
{
|
||||||
|
os << '(' << s1 << ' ' << s2 << ' ' << s3 << ' ' << s4 << ')';
|
||||||
|
}
|
||||||
|
|
||||||
void ast_printer_t::parenthesize(const std::string_view s, const expr_t * a, const expr_t * b) const
|
void ast_printer_t::parenthesize(const std::string_view s, const expr_t * a, const expr_t * b) const
|
||||||
{
|
{
|
||||||
os << '(' << s << ' ';
|
os << '(' << s << ' ';
|
||||||
@ -139,6 +151,7 @@ void ast_printer_t::visit(const op::control_word_t * control_word) const
|
|||||||
os << "(control_word ";
|
os << "(control_word ";
|
||||||
for (const auto& op : control_word->ops) {
|
for (const auto& op : control_word->ops) {
|
||||||
reinterpret_cast<const stmt_t *>(op)->accept(this);
|
reinterpret_cast<const stmt_t *>(op)->accept(this);
|
||||||
|
os << ' ';
|
||||||
}
|
}
|
||||||
os << ')';
|
os << ')';
|
||||||
}
|
}
|
||||||
@ -162,32 +175,36 @@ static std::string dma_hold_add(bool hold, dma::add_mode_t add)
|
|||||||
+ dma::add_mode_string[static_cast<int>(add)];
|
+ dma::add_mode_string[static_cast<int>(add)];
|
||||||
}
|
}
|
||||||
|
|
||||||
void ast_printer_t::visit(const dma::ingress_imm_t * ingress_imm) const
|
void ast_printer_t::visit(const dma::src_d0_imm_t * src_d0_imm) const
|
||||||
{
|
{
|
||||||
parenthesize(dma_hold_add(ingress_imm->hold, ingress_imm->add),
|
parenthesize(dma_hold_add(src_d0_imm->hold, src_d0_imm->add),
|
||||||
dma::ingress_string[static_cast<int>(ingress_imm->ingress)],
|
dma::src_string[static_cast<int>(src_d0_imm->src)],
|
||||||
ingress_imm->imm.expr);
|
"d0",
|
||||||
|
src_d0_imm->imm.expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ast_printer_t::visit(const dma::egress_imm_t * egress_imm) const
|
void ast_printer_t::visit(const dma::d0_dst_imm_t * d0_dst_imm) const
|
||||||
{
|
{
|
||||||
parenthesize(dma_hold_add(egress_imm->hold, egress_imm->add),
|
parenthesize(dma_hold_add(d0_dst_imm->hold, d0_dst_imm->add),
|
||||||
dma::egress_string[static_cast<int>(egress_imm->egress)],
|
"d0",
|
||||||
egress_imm->imm.expr);
|
dma::dst_string[static_cast<int>(d0_dst_imm->dst)],
|
||||||
|
d0_dst_imm->imm.expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ast_printer_t::visit(const dma::ingress_ram_t * ingress_ram) const
|
void ast_printer_t::visit(const dma::src_d0_ram_t * src_d0_ram) const
|
||||||
{
|
{
|
||||||
parenthesize(dma_hold_add(ingress_ram->hold, ingress_ram->add),
|
parenthesize(dma_hold_add(src_d0_ram->hold, src_d0_ram->add),
|
||||||
dma::ingress_string[static_cast<int>(ingress_ram->ingress)],
|
dma::src_string[static_cast<int>(src_d0_ram->src)],
|
||||||
dma::length_ram_string[static_cast<int>(ingress_ram->ram)]);
|
"d0",
|
||||||
|
dma::length_ram_string[static_cast<int>(src_d0_ram->ram)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ast_printer_t::visit(const dma::egress_ram_t * egress_ram) const
|
void ast_printer_t::visit(const dma::d0_dst_ram_t * d0_dst_ram) const
|
||||||
{
|
{
|
||||||
parenthesize(dma_hold_add(egress_ram->hold, egress_ram->add),
|
parenthesize(dma_hold_add(d0_dst_ram->hold, d0_dst_ram->add),
|
||||||
dma::egress_string[static_cast<int>(egress_ram->egress)],
|
"d0",
|
||||||
dma::length_ram_string[static_cast<int>(egress_ram->ram)]);
|
dma::dst_string[static_cast<int>(d0_dst_ram->dst)],
|
||||||
|
dma::length_ram_string[static_cast<int>(d0_dst_ram->ram)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ast_printer_t::visit(const jump::jmp_t * jmp) const
|
void ast_printer_t::visit(const jump::jmp_t * jmp) const
|
||||||
@ -226,4 +243,10 @@ void ast_printer_t::visit(const end::endi_t * endi) const
|
|||||||
parenthesize("endi");
|
parenthesize("endi");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ast_printer_t::visit(const nop::nop_t * nop) const
|
||||||
|
{
|
||||||
|
(void)nop;
|
||||||
|
parenthesize("nop");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
14
ast.hpp
14
ast.hpp
@ -37,10 +37,10 @@ struct ast_printer_t : visitor_t<void>
|
|||||||
void visit(const load::mvi_t * mvi) const;
|
void visit(const load::mvi_t * mvi) const;
|
||||||
void visit(const load::mvi_cond_t * mvi_cond) const;
|
void visit(const load::mvi_cond_t * mvi_cond) const;
|
||||||
|
|
||||||
void visit(const dma::ingress_imm_t * ingress_imm) const;
|
void visit(const dma::src_d0_imm_t * src_d0_imm) const;
|
||||||
void visit(const dma::egress_imm_t * egress_imm) const;
|
void visit(const dma::d0_dst_imm_t * d0_dst_imm) const;
|
||||||
void visit(const dma::ingress_ram_t * ingress_ram) const;
|
void visit(const dma::src_d0_ram_t * src_d0_ram) const;
|
||||||
void visit(const dma::egress_ram_t * egress_ram) const;
|
void visit(const dma::d0_dst_ram_t * d0_dst_ram) const;
|
||||||
|
|
||||||
void visit(const jump::jmp_t * jmp) const;
|
void visit(const jump::jmp_t * jmp) const;
|
||||||
void visit(const jump::jmp_cond_t * jmp_cond) const;
|
void visit(const jump::jmp_cond_t * jmp_cond) const;
|
||||||
@ -51,15 +51,19 @@ struct ast_printer_t : visitor_t<void>
|
|||||||
void visit(const end::end_t * end) const;
|
void visit(const end::end_t * end) const;
|
||||||
void visit(const end::endi_t * endi) const;
|
void visit(const end::endi_t * endi) const;
|
||||||
|
|
||||||
|
void visit(const nop::nop_t * nop) const;
|
||||||
|
|
||||||
|
|
||||||
void parenthesize(const std::string_view s, const expr_t * a) const;
|
void parenthesize(const std::string_view s, const expr_t * a) const;
|
||||||
void parenthesize(const std::string_view s1, const std::string_view s2, const expr_t * a) const;
|
void parenthesize(const std::string_view s1, const std::string_view s2, const expr_t * a) const;
|
||||||
|
void parenthesize(const std::string_view s1, const std::string_view s2, const std::string_view s3, const expr_t * a) const;
|
||||||
void parenthesize(const std::string_view s1, const expr_t * a, const std::string_view s2) const;
|
void parenthesize(const std::string_view s1, const expr_t * a, const std::string_view s2) const;
|
||||||
void parenthesize(const std::string_view s1, const expr_t * a, const std::string_view s2, const std::string_view s3) const;
|
void parenthesize(const std::string_view s1, const expr_t * a, const std::string_view s2, const std::string_view s3) const;
|
||||||
void parenthesize(const std::string_view s, const expr_t * a, const expr_t * b) const;
|
void parenthesize(const std::string_view s, const expr_t * a, const expr_t * b) const;
|
||||||
void parenthesize(const std::string_view s) const;
|
void parenthesize(const std::string_view s) const;
|
||||||
void parenthesize(const std::string_view s1, const std::string_view s2) const;
|
void parenthesize(const std::string_view s1, const std::string_view s2) const;
|
||||||
void parenthesize(const std::string_view s1, const std::string_view s2, const std::string_view s3) const;
|
void parenthesize(const std::string_view s1, const std::string_view s2, const std::string_view s3) const;
|
||||||
|
void parenthesize(const std::string_view s1, const std::string_view s2, const std::string_view s3, const std::string_view s4) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -115,6 +115,7 @@ reg_keywords = [
|
|||||||
"ct1",
|
"ct1",
|
||||||
"ct2",
|
"ct2",
|
||||||
"ct3",
|
"ct3",
|
||||||
|
"pc",
|
||||||
]
|
]
|
||||||
|
|
||||||
cond_keywords = [
|
cond_keywords = [
|
||||||
@ -134,9 +135,13 @@ move_immediate_keywords = [
|
|||||||
"mvi",
|
"mvi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
_dma_add = [0, 1, 2, 4, 8, 16, 32, 64]
|
||||||
|
|
||||||
dma_keywords = [
|
dma_keywords = [
|
||||||
"dma",
|
"dma",
|
||||||
"dmah",
|
"dmah",
|
||||||
|
*(f"dma{i}" for i in _dma_add),
|
||||||
|
*(f"dmah{i}" for i in _dma_add),
|
||||||
"d0",
|
"d0",
|
||||||
"prg",
|
"prg",
|
||||||
]
|
]
|
||||||
@ -185,6 +190,6 @@ elif sys.argv[1] == 'enum_inc':
|
|||||||
print(f"_{k},")
|
print(f"_{k},")
|
||||||
elif sys.argv[1] == 'case_inc':
|
elif sys.argv[1] == 'case_inc':
|
||||||
for k in keywords:
|
for k in keywords:
|
||||||
print(f'case _{k.ljust(4, " ")} : return os << "{k.upper()}";')
|
print(f'case _{k.ljust(7, " ")} : return os << "{k.upper()}";')
|
||||||
else:
|
else:
|
||||||
assert False, sys.argv
|
assert False, sys.argv
|
||||||
|
@ -14,7 +14,23 @@ case _ct2 : return os << "CT2";
|
|||||||
case _ct3 : return os << "CT3";
|
case _ct3 : return os << "CT3";
|
||||||
case _d0 : return os << "D0";
|
case _d0 : return os << "D0";
|
||||||
case _dma : return os << "DMA";
|
case _dma : return os << "DMA";
|
||||||
|
case _dma0 : return os << "DMA0";
|
||||||
|
case _dma1 : return os << "DMA1";
|
||||||
|
case _dma16 : return os << "DMA16";
|
||||||
|
case _dma2 : return os << "DMA2";
|
||||||
|
case _dma32 : return os << "DMA32";
|
||||||
|
case _dma4 : return os << "DMA4";
|
||||||
|
case _dma64 : return os << "DMA64";
|
||||||
|
case _dma8 : return os << "DMA8";
|
||||||
case _dmah : return os << "DMAH";
|
case _dmah : return os << "DMAH";
|
||||||
|
case _dmah0 : return os << "DMAH0";
|
||||||
|
case _dmah1 : return os << "DMAH1";
|
||||||
|
case _dmah16 : return os << "DMAH16";
|
||||||
|
case _dmah2 : return os << "DMAH2";
|
||||||
|
case _dmah32 : return os << "DMAH32";
|
||||||
|
case _dmah4 : return os << "DMAH4";
|
||||||
|
case _dmah64 : return os << "DMAH64";
|
||||||
|
case _dmah8 : return os << "DMAH8";
|
||||||
case _end : return os << "END";
|
case _end : return os << "END";
|
||||||
case _endi : return os << "ENDI";
|
case _endi : return os << "ENDI";
|
||||||
case _equ : return os << "EQU";
|
case _equ : return os << "EQU";
|
||||||
@ -41,6 +57,7 @@ case _nzs : return os << "NZS";
|
|||||||
case _or : return os << "OR";
|
case _or : return os << "OR";
|
||||||
case _org : return os << "ORG";
|
case _org : return os << "ORG";
|
||||||
case _p : return os << "P";
|
case _p : return os << "P";
|
||||||
|
case _pc : return os << "PC";
|
||||||
case _pl : return os << "PL";
|
case _pl : return os << "PL";
|
||||||
case _prg : return os << "PRG";
|
case _prg : return os << "PRG";
|
||||||
case _ra0 : return os << "RA0";
|
case _ra0 : return os << "RA0";
|
||||||
|
@ -14,7 +14,23 @@ _ct2,
|
|||||||
_ct3,
|
_ct3,
|
||||||
_d0,
|
_d0,
|
||||||
_dma,
|
_dma,
|
||||||
|
_dma0,
|
||||||
|
_dma1,
|
||||||
|
_dma16,
|
||||||
|
_dma2,
|
||||||
|
_dma32,
|
||||||
|
_dma4,
|
||||||
|
_dma64,
|
||||||
|
_dma8,
|
||||||
_dmah,
|
_dmah,
|
||||||
|
_dmah0,
|
||||||
|
_dmah1,
|
||||||
|
_dmah16,
|
||||||
|
_dmah2,
|
||||||
|
_dmah32,
|
||||||
|
_dmah4,
|
||||||
|
_dmah64,
|
||||||
|
_dmah8,
|
||||||
_end,
|
_end,
|
||||||
_endi,
|
_endi,
|
||||||
_equ,
|
_equ,
|
||||||
@ -41,6 +57,7 @@ _nzs,
|
|||||||
_or,
|
_or,
|
||||||
_org,
|
_org,
|
||||||
_p,
|
_p,
|
||||||
|
_pc,
|
||||||
_pl,
|
_pl,
|
||||||
_prg,
|
_prg,
|
||||||
_ra0,
|
_ra0,
|
||||||
|
88
keyword.hpp
88
keyword.hpp
@ -137,9 +137,93 @@ find(const std::string_view s)
|
|||||||
if (ix == s.length()) return { token_t::type_t::_dma };
|
if (ix == s.length()) return { token_t::type_t::_dma };
|
||||||
else {
|
else {
|
||||||
switch (s[ix++]) {
|
switch (s[ix++]) {
|
||||||
|
case '0':
|
||||||
|
if (ix == s.length()) return { token_t::type_t::_dma0 };
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
if (ix == s.length()) return { token_t::type_t::_dma1 };
|
||||||
|
else {
|
||||||
|
switch (s[ix++]) {
|
||||||
|
case '6':
|
||||||
|
if (ix == s.length()) return { token_t::type_t::_dma16 };
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
if (ix == s.length()) return { token_t::type_t::_dma2 };
|
||||||
|
break;
|
||||||
|
case '3':
|
||||||
|
if (ix < s.length()) {
|
||||||
|
switch (s[ix++]) {
|
||||||
|
case '2':
|
||||||
|
if (ix == s.length()) return { token_t::type_t::_dma32 };
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '4':
|
||||||
|
if (ix == s.length()) return { token_t::type_t::_dma4 };
|
||||||
|
break;
|
||||||
|
case '6':
|
||||||
|
if (ix < s.length()) {
|
||||||
|
switch (s[ix++]) {
|
||||||
|
case '4':
|
||||||
|
if (ix == s.length()) return { token_t::type_t::_dma64 };
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '8':
|
||||||
|
if (ix == s.length()) return { token_t::type_t::_dma8 };
|
||||||
|
break;
|
||||||
case 'H': [[fallthrough]];
|
case 'H': [[fallthrough]];
|
||||||
case 'h':
|
case 'h':
|
||||||
if (ix == s.length()) return { token_t::type_t::_dmah };
|
if (ix == s.length()) return { token_t::type_t::_dmah };
|
||||||
|
else {
|
||||||
|
switch (s[ix++]) {
|
||||||
|
case '0':
|
||||||
|
if (ix == s.length()) return { token_t::type_t::_dmah0 };
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
if (ix == s.length()) return { token_t::type_t::_dmah1 };
|
||||||
|
else {
|
||||||
|
switch (s[ix++]) {
|
||||||
|
case '6':
|
||||||
|
if (ix == s.length()) return { token_t::type_t::_dmah16 };
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
if (ix == s.length()) return { token_t::type_t::_dmah2 };
|
||||||
|
break;
|
||||||
|
case '3':
|
||||||
|
if (ix < s.length()) {
|
||||||
|
switch (s[ix++]) {
|
||||||
|
case '2':
|
||||||
|
if (ix == s.length()) return { token_t::type_t::_dmah32 };
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '4':
|
||||||
|
if (ix == s.length()) return { token_t::type_t::_dmah4 };
|
||||||
|
break;
|
||||||
|
case '6':
|
||||||
|
if (ix < s.length()) {
|
||||||
|
switch (s[ix++]) {
|
||||||
|
case '4':
|
||||||
|
if (ix == s.length()) return { token_t::type_t::_dmah64 };
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '8':
|
||||||
|
if (ix == s.length()) return { token_t::type_t::_dmah8 };
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -377,6 +461,10 @@ find(const std::string_view s)
|
|||||||
if (ix == s.length()) return { token_t::type_t::_p };
|
if (ix == s.length()) return { token_t::type_t::_p };
|
||||||
else {
|
else {
|
||||||
switch (s[ix++]) {
|
switch (s[ix++]) {
|
||||||
|
case 'C': [[fallthrough]];
|
||||||
|
case 'c':
|
||||||
|
if (ix == s.length()) return { token_t::type_t::_pc };
|
||||||
|
break;
|
||||||
case 'L': [[fallthrough]];
|
case 'L': [[fallthrough]];
|
||||||
case 'l':
|
case 'l':
|
||||||
if (ix == s.length()) return { token_t::type_t::_pl };
|
if (ix == s.length()) return { token_t::type_t::_pl };
|
||||||
|
7
main.cpp
7
main.cpp
@ -1,6 +1,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include "lexer.hpp"
|
#include "lexer.hpp"
|
||||||
#include "token.hpp"
|
#include "token.hpp"
|
||||||
@ -21,9 +22,11 @@ static void run(std::string source)
|
|||||||
lexer_t lexer(buf);
|
lexer_t lexer(buf);
|
||||||
std::vector<token_t> tokens = lexer.lex_tokens();
|
std::vector<token_t> tokens = lexer.lex_tokens();
|
||||||
parser_t parser(tokens);
|
parser_t parser(tokens);
|
||||||
expr_t * expr = parser.expression();
|
std::optional<stmt_t *> stmt_o = parser.instruction();
|
||||||
|
if (stmt_o) {
|
||||||
dsp::ast_printer_t p(std::cout);
|
dsp::ast_printer_t p(std::cout);
|
||||||
expr->accept(&p);
|
(*stmt_o)->accept(&p);
|
||||||
|
}
|
||||||
std::cout << std::endl << std::flush;
|
std::cout << std::endl << std::flush;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
251
parser.cpp
251
parser.cpp
@ -34,17 +34,17 @@ parse_error_t parser_t::error(const token_t& token, const std::string message)
|
|||||||
return parse_error_t(message);
|
return parse_error_t(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
token_t& parser_t::previous()
|
const token_t& parser_t::previous()
|
||||||
{
|
{
|
||||||
return tokens[current_ix-1];
|
return tokens[current_ix-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
token_t& parser_t::peek()
|
const token_t& parser_t::peek()
|
||||||
{
|
{
|
||||||
return tokens[current_ix];
|
return tokens[current_ix];
|
||||||
}
|
}
|
||||||
|
|
||||||
token_t& parser_t::advance()
|
const token_t& parser_t::advance()
|
||||||
{
|
{
|
||||||
if (!at_end_p()) current_ix++;
|
if (!at_end_p()) current_ix++;
|
||||||
return previous();
|
return previous();
|
||||||
@ -275,10 +275,9 @@ std::optional<op::op_t *> parser_t::xyd1_bus()
|
|||||||
else
|
else
|
||||||
throw error(peek(), "expected x-bus, y-bus, or d-bus destination operand");
|
throw error(peek(), "expected x-bus, y-bus, or d-bus destination operand");
|
||||||
} else {
|
} else {
|
||||||
expr_t * expr = expression();
|
simm_t<8> imm = simm_t<8>(expression());
|
||||||
simm_t<8> simm = simm_t<8>(expr);
|
|
||||||
if (auto dest_o = d1_dest())
|
if (auto dest_o = d1_dest())
|
||||||
return {new op::mov_imm_d1_t(simm, *dest_o)};
|
return {new op::mov_imm_d1_t(imm, *dest_o)};
|
||||||
else
|
else
|
||||||
throw error(peek(), "expected d1 destination operand");
|
throw error(peek(), "expected d1 destination operand");
|
||||||
}
|
}
|
||||||
@ -305,16 +304,240 @@ std::optional<stmt_t *> parser_t::op()
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
load::dest_t parser_t::load_dest()
|
||||||
|
{
|
||||||
|
using namespace dsp::load;
|
||||||
|
|
||||||
|
if (match(_mc0)) return dest_t::mc0;
|
||||||
|
else if (match(_mc1)) return dest_t::mc1;
|
||||||
|
else if (match(_mc2)) return dest_t::mc2;
|
||||||
|
else if (match(_mc3)) return dest_t::mc3;
|
||||||
|
else if (match(_rx)) return dest_t::rx;
|
||||||
|
else if (match(_pl)) return dest_t::pl;
|
||||||
|
else if (match(_ra0)) return dest_t::ra0;
|
||||||
|
else if (match(_wa0)) return dest_t::wa0;
|
||||||
|
else if (match(_lop)) return dest_t::lop;
|
||||||
|
else if (match(_pc)) return dest_t::pc;
|
||||||
|
else
|
||||||
|
throw error(peek(), "expected mvi destination");
|
||||||
|
}
|
||||||
|
|
||||||
|
load::cond_t parser_t::load_cond()
|
||||||
|
{
|
||||||
|
using namespace dsp::load;
|
||||||
|
|
||||||
|
switch (advance().type) {
|
||||||
|
case _z: return cond_t::z;
|
||||||
|
case _nz: return cond_t::nz;
|
||||||
|
case _s: return cond_t::s;
|
||||||
|
case _ns: return cond_t::ns;
|
||||||
|
case _c: return cond_t::c;
|
||||||
|
case _nc: return cond_t::nc;
|
||||||
|
case _t0: return cond_t::t0;
|
||||||
|
case _nt0: return cond_t::nt0;
|
||||||
|
case _zs: return cond_t::zs;
|
||||||
|
case _nzs: return cond_t::nzs;
|
||||||
|
default:
|
||||||
|
throw error(previous(), "expected mvi condition after ','");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<stmt_t *> parser_t::load()
|
||||||
|
{
|
||||||
|
if (match(_mvi)) {
|
||||||
|
expr_t * expr = expression();
|
||||||
|
consume(comma, "expected `,`");
|
||||||
|
load::dest_t dest = parser_t::load_dest();
|
||||||
|
if (match(comma)) {
|
||||||
|
load::cond_t cond = load_cond();
|
||||||
|
uimm_t<19> imm = uimm_t<19>(expr);
|
||||||
|
return {new load::mvi_cond_t(imm, dest, cond)};
|
||||||
|
} else {
|
||||||
|
uimm_t<25> imm = uimm_t<25>(expr);
|
||||||
|
return {new load::mvi_t(imm, dest)};
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool dma_p(const token_t& token)
|
||||||
|
{
|
||||||
|
switch (token.type) {
|
||||||
|
case _dmah: [[fallthrough]];
|
||||||
|
case _dmah0: [[fallthrough]];
|
||||||
|
case _dmah1: [[fallthrough]];
|
||||||
|
case _dmah2: [[fallthrough]];
|
||||||
|
case _dmah4: [[fallthrough]];
|
||||||
|
case _dmah8: [[fallthrough]];
|
||||||
|
case _dmah16: [[fallthrough]];
|
||||||
|
case _dmah32: [[fallthrough]];
|
||||||
|
case _dmah64: [[fallthrough]];
|
||||||
|
case _dma: [[fallthrough]];
|
||||||
|
case _dma0: [[fallthrough]];
|
||||||
|
case _dma1: [[fallthrough]];
|
||||||
|
case _dma2: [[fallthrough]];
|
||||||
|
case _dma4: [[fallthrough]];
|
||||||
|
case _dma8: [[fallthrough]];
|
||||||
|
case _dma16: [[fallthrough]];
|
||||||
|
case _dma32: [[fallthrough]];
|
||||||
|
case _dma64: return true;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool dma_hold_p(const token_t& token)
|
||||||
|
{
|
||||||
|
switch (token.type) {
|
||||||
|
case _dmah: [[fallthrough]];
|
||||||
|
case _dmah0: [[fallthrough]];
|
||||||
|
case _dmah1: [[fallthrough]];
|
||||||
|
case _dmah2: [[fallthrough]];
|
||||||
|
case _dmah4: [[fallthrough]];
|
||||||
|
case _dmah8: [[fallthrough]];
|
||||||
|
case _dmah16: [[fallthrough]];
|
||||||
|
case _dmah32: [[fallthrough]];
|
||||||
|
case _dmah64: return true;
|
||||||
|
case _dma: [[fallthrough]];
|
||||||
|
case _dma0: [[fallthrough]];
|
||||||
|
case _dma1: [[fallthrough]];
|
||||||
|
case _dma2: [[fallthrough]];
|
||||||
|
case _dma4: [[fallthrough]];
|
||||||
|
case _dma8: [[fallthrough]];
|
||||||
|
case _dma16: [[fallthrough]];
|
||||||
|
case _dma32: [[fallthrough]];
|
||||||
|
case _dma64: return false;
|
||||||
|
default: assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static dma::add_mode_t dma_add(const token_t& token)
|
||||||
|
{
|
||||||
|
using namespace dsp::dma;
|
||||||
|
|
||||||
|
switch (token.type) {
|
||||||
|
case _dma: [[fallthrough]];
|
||||||
|
case _dmah: return add_mode_t::_1;
|
||||||
|
case _dma0: [[fallthrough]];
|
||||||
|
case _dmah0: return add_mode_t::_0;
|
||||||
|
case _dma1: [[fallthrough]];
|
||||||
|
case _dmah1: return add_mode_t::_1;
|
||||||
|
case _dma2: [[fallthrough]];
|
||||||
|
case _dmah2: return add_mode_t::_2;
|
||||||
|
case _dma4: [[fallthrough]];
|
||||||
|
case _dmah4: return add_mode_t::_4;
|
||||||
|
case _dma8: [[fallthrough]];
|
||||||
|
case _dmah8: return add_mode_t::_8;
|
||||||
|
case _dma16: [[fallthrough]];
|
||||||
|
case _dmah16: return add_mode_t::_16;
|
||||||
|
case _dma32: [[fallthrough]];
|
||||||
|
case _dmah32: return add_mode_t::_32;
|
||||||
|
case _dma64: [[fallthrough]];
|
||||||
|
case _dmah64: return add_mode_t::_64;
|
||||||
|
default: assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dma::src_t parser_t::dma_src()
|
||||||
|
{
|
||||||
|
switch (advance().type) {
|
||||||
|
case _m0: return dma::src_t::m0;
|
||||||
|
case _m1: return dma::src_t::m1;
|
||||||
|
case _m2: return dma::src_t::m2;
|
||||||
|
case _m3: return dma::src_t::m3;
|
||||||
|
default:
|
||||||
|
throw error(previous(), "expected dma source operand");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dma::dst_t parser_t::dma_dst()
|
||||||
|
{
|
||||||
|
switch (advance().type) {
|
||||||
|
case _m0: return dma::dst_t::m0;
|
||||||
|
case _m1: return dma::dst_t::m1;
|
||||||
|
case _m2: return dma::dst_t::m2;
|
||||||
|
case _m3: return dma::dst_t::m3;
|
||||||
|
case _prg: return dma::dst_t::prg;
|
||||||
|
default:
|
||||||
|
throw error(previous(), "expected dma destination operand");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<dma::length_ram_t> parser_t::dma_length_ram()
|
||||||
|
{
|
||||||
|
using namespace dsp::dma;
|
||||||
|
|
||||||
|
if (match(_m0)) return length_ram_t::m0;
|
||||||
|
else if (match(_m1)) return length_ram_t::m1;
|
||||||
|
else if (match(_m2)) return length_ram_t::m2;
|
||||||
|
else if (match(_m3)) return length_ram_t::m3;
|
||||||
|
else if (match(_mc0)) return length_ram_t::mc0;
|
||||||
|
else if (match(_mc1)) return length_ram_t::mc1;
|
||||||
|
else if (match(_mc2)) return length_ram_t::mc2;
|
||||||
|
else if (match(_mc3)) return length_ram_t::mc3;
|
||||||
|
else return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<stmt_t *> parser_t::dma()
|
||||||
|
{
|
||||||
|
if (dma_p(peek())) {
|
||||||
|
const token_t& token = advance();
|
||||||
|
bool hold = dma_hold_p(token);
|
||||||
|
dma::add_mode_t add = dma_add(token);
|
||||||
|
if (match(_d0)) {
|
||||||
|
consume(comma, "expected `,`");
|
||||||
|
dma::dst_t dst = dma_dst();
|
||||||
|
consume(comma, "expected `,`");
|
||||||
|
if (auto length_ram_o = dma_length_ram()) {
|
||||||
|
return {new dma::d0_dst_ram_t(hold, add, dst, *length_ram_o)};
|
||||||
|
} else {
|
||||||
|
uimm_t<8> imm = uimm_t<8>(expression());
|
||||||
|
return {new dma::d0_dst_imm_t(hold, add, dst, imm)};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dma::src_t src = dma_src();
|
||||||
|
consume(comma, "expected `,`");
|
||||||
|
consume(_d0, "expected `d0`");
|
||||||
|
consume(comma, "expected `,`");
|
||||||
|
if (auto length_ram_o = dma_length_ram()) {
|
||||||
|
return {new dma::src_d0_ram_t(hold, add, src, *length_ram_o)};
|
||||||
|
} else {
|
||||||
|
uimm_t<8> imm = uimm_t<8>(expression());
|
||||||
|
return {new dma::src_d0_imm_t(hold, add, src, imm)};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<stmt_t *> parser_t::jump()
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<stmt_t *> parser_t::loop()
|
||||||
|
{
|
||||||
|
if (match(_btm)) return {new loop::btm_t()};
|
||||||
|
else if (match(_lps)) return {new loop::lps_t()};
|
||||||
|
else return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<stmt_t *> parser_t::end()
|
||||||
|
{
|
||||||
|
if (match(_end)) return {new end::end_t()};
|
||||||
|
else if (match(_endi)) return {new end::endi_t()};
|
||||||
|
else return {};
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<stmt_t *> parser_t::instruction()
|
std::optional<stmt_t *> parser_t::instruction()
|
||||||
{
|
{
|
||||||
// "nop"
|
if (match(_nop)) return {new nop::nop_t()};
|
||||||
// op
|
else if (auto op_o = op()) return op_o;
|
||||||
// load
|
else if (auto load_o = load()) return load_o;
|
||||||
// dma
|
else if (auto dma_o = dma()) return dma_o;
|
||||||
// jump
|
else if (auto jump_o = jump()) return jump_o;
|
||||||
// loop
|
else if (auto loop_o = loop()) return loop_o;
|
||||||
// end
|
else if (auto end_o = end()) return end_o;
|
||||||
return {};
|
else return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<stmt_t *> parser_t::instruction_statement()
|
std::optional<stmt_t *> parser_t::instruction_statement()
|
||||||
|
16
parser.hpp
16
parser.hpp
@ -29,9 +29,9 @@ struct parser_t
|
|||||||
|
|
||||||
bool at_end_p();
|
bool at_end_p();
|
||||||
|
|
||||||
token_t& previous();
|
const token_t& previous();
|
||||||
token_t& peek();
|
const token_t& peek();
|
||||||
token_t& advance();
|
const token_t& advance();
|
||||||
bool check(enum token_t::type_t token_type);
|
bool check(enum token_t::type_t token_type);
|
||||||
bool match(enum token_t::type_t token_type);
|
bool match(enum token_t::type_t token_type);
|
||||||
template <typename... Targs>
|
template <typename... Targs>
|
||||||
@ -52,6 +52,16 @@ struct parser_t
|
|||||||
std::optional<op::d1_dest_t> d1_dest();
|
std::optional<op::d1_dest_t> d1_dest();
|
||||||
std::optional<op::op_t *> xyd1_bus();
|
std::optional<op::op_t *> xyd1_bus();
|
||||||
std::optional<stmt_t *> op();
|
std::optional<stmt_t *> op();
|
||||||
|
load::dest_t load_dest();
|
||||||
|
load::cond_t load_cond();
|
||||||
|
std::optional<stmt_t *> load();
|
||||||
|
dma::src_t dma_src();
|
||||||
|
dma::dst_t dma_dst();
|
||||||
|
std::optional<dma::length_ram_t> dma_length_ram();
|
||||||
|
std::optional<stmt_t *> dma();
|
||||||
|
std::optional<stmt_t *> jump();
|
||||||
|
std::optional<stmt_t *> loop();
|
||||||
|
std::optional<stmt_t *> end();
|
||||||
std::optional<stmt_t *> instruction();
|
std::optional<stmt_t *> instruction();
|
||||||
std::optional<stmt_t *> instruction_statement();
|
std::optional<stmt_t *> instruction_statement();
|
||||||
stmt_t * statement();
|
stmt_t * statement();
|
||||||
|
45
stmt.hpp
45
stmt.hpp
@ -157,47 +157,48 @@ struct mvi_cond_t : stmt_accept_t<mvi_cond_t>
|
|||||||
|
|
||||||
namespace dma {
|
namespace dma {
|
||||||
|
|
||||||
struct ingress_imm_t : stmt_accept_t<ingress_imm_t>
|
struct src_d0_imm_t : stmt_accept_t<src_d0_imm_t>
|
||||||
{
|
{
|
||||||
ingress_imm_t(bool hold, add_mode_t add, ingress_t ingress, simm_t<8> imm)
|
src_d0_imm_t(bool hold, add_mode_t add, src_t src, uimm_t<8> imm)
|
||||||
: hold(hold), add(add), ingress(ingress), imm(imm) {}
|
: hold(hold), add(add), src(src), imm(imm) {}
|
||||||
|
|
||||||
const bool hold;
|
const bool hold;
|
||||||
const add_mode_t add;
|
const add_mode_t add;
|
||||||
const ingress_t ingress;
|
const src_t src;
|
||||||
const simm_t<8> imm;
|
const uimm_t<8> imm;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct egress_imm_t : stmt_accept_t<egress_imm_t>
|
struct d0_dst_imm_t : stmt_accept_t<d0_dst_imm_t>
|
||||||
{
|
{
|
||||||
egress_imm_t(bool hold, add_mode_t add, egress_t egress, simm_t<8> imm)
|
d0_dst_imm_t(bool hold, add_mode_t add, dst_t dst, uimm_t<8> imm)
|
||||||
: hold(hold), add(add), egress(egress), imm(imm) {}
|
: hold(hold), add(add), dst(dst), imm(imm) {}
|
||||||
|
|
||||||
const bool hold;
|
const bool hold;
|
||||||
const add_mode_t add;
|
const add_mode_t add;
|
||||||
const egress_t egress;
|
const dst_t dst;
|
||||||
const simm_t<8> imm;
|
const uimm_t<8> imm;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ingress_ram_t : stmt_accept_t<ingress_ram_t>
|
struct src_d0_ram_t : stmt_accept_t<src_d0_ram_t>
|
||||||
{
|
{
|
||||||
ingress_ram_t(bool hold, add_mode_t add, ingress_t ingress, length_ram_t ram)
|
// from src to d0
|
||||||
: hold(hold), add(add), ingress(ingress), ram(ram) {}
|
src_d0_ram_t(bool hold, add_mode_t add, src_t src, length_ram_t ram)
|
||||||
|
: hold(hold), add(add), src(src), ram(ram) {}
|
||||||
|
|
||||||
const bool hold;
|
const bool hold;
|
||||||
const add_mode_t add;
|
const add_mode_t add;
|
||||||
const ingress_t ingress;
|
const src_t src;
|
||||||
const length_ram_t ram;
|
const length_ram_t ram;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct egress_ram_t : stmt_accept_t<egress_ram_t>
|
struct d0_dst_ram_t : stmt_accept_t<d0_dst_ram_t>
|
||||||
{
|
{
|
||||||
egress_ram_t(bool hold, add_mode_t add, egress_t egress, length_ram_t ram)
|
d0_dst_ram_t(bool hold, add_mode_t add, dst_t dst, length_ram_t ram)
|
||||||
: hold(hold), add(add), egress(egress), ram(ram) {}
|
: hold(hold), add(add), dst(dst), ram(ram) {}
|
||||||
|
|
||||||
const bool hold;
|
const bool hold;
|
||||||
const add_mode_t add;
|
const add_mode_t add;
|
||||||
const egress_t egress;
|
const dst_t dst;
|
||||||
const length_ram_t ram;
|
const length_ram_t ram;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -249,6 +250,14 @@ struct endi_t : stmt_accept_t<endi_t>
|
|||||||
|
|
||||||
} // end
|
} // end
|
||||||
|
|
||||||
|
namespace nop {
|
||||||
|
|
||||||
|
struct nop_t : stmt_accept_t<nop_t>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
struct assign_t : stmt_accept_t<assign_t>
|
struct assign_t : stmt_accept_t<assign_t>
|
||||||
{
|
{
|
||||||
|
@ -70,11 +70,11 @@ enum struct add_mode_t {
|
|||||||
_64,
|
_64,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum struct ingress_t {
|
enum struct src_t {
|
||||||
m0, m1, m2, m3
|
m0, m1, m2, m3
|
||||||
};
|
};
|
||||||
|
|
||||||
enum struct egress_t {
|
enum struct dst_t {
|
||||||
m0, m1, m2, m3,
|
m0, m1, m2, m3,
|
||||||
prg,
|
prg,
|
||||||
};
|
};
|
||||||
|
@ -106,19 +106,19 @@ const std::string add_mode_string[] = {
|
|||||||
[i(add_mode_t::_64)] = "64",
|
[i(add_mode_t::_64)] = "64",
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::string ingress_string[] = {
|
const std::string src_string[] = {
|
||||||
[i(ingress_t::m0)] = "m0",
|
[i(src_t::m0)] = "m0",
|
||||||
[i(ingress_t::m1)] = "m1",
|
[i(src_t::m1)] = "m1",
|
||||||
[i(ingress_t::m2)] = "m2",
|
[i(src_t::m2)] = "m2",
|
||||||
[i(ingress_t::m3)] = "m3"
|
[i(src_t::m3)] = "m3"
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::string egress_string[] = {
|
const std::string dst_string[] = {
|
||||||
[i(egress_t::m0 )] = "m0",
|
[i(dst_t::m0 )] = "m0",
|
||||||
[i(egress_t::m1 )] = "m1",
|
[i(dst_t::m1 )] = "m1",
|
||||||
[i(egress_t::m2 )] = "m2",
|
[i(dst_t::m2 )] = "m2",
|
||||||
[i(egress_t::m3 )] = "m3",
|
[i(dst_t::m3 )] = "m3",
|
||||||
[i(egress_t::prg)] = "prg",
|
[i(dst_t::prg)] = "prg",
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::string length_ram_string[] = {
|
const std::string length_ram_string[] = {
|
||||||
|
@ -24,8 +24,8 @@ namespace dma {
|
|||||||
|
|
||||||
extern const std::string hold_mode_string[];
|
extern const std::string hold_mode_string[];
|
||||||
extern const std::string add_mode_string[];
|
extern const std::string add_mode_string[];
|
||||||
extern const std::string ingress_string[];
|
extern const std::string src_string[];
|
||||||
extern const std::string egress_string[];
|
extern const std::string dst_string[];
|
||||||
extern const std::string length_ram_string[];
|
extern const std::string length_ram_string[];
|
||||||
|
|
||||||
} // dma
|
} // dma
|
||||||
|
@ -31,10 +31,10 @@ struct mvi_cond_t;
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace dma {
|
namespace dma {
|
||||||
struct ingress_imm_t;
|
struct src_d0_imm_t;
|
||||||
struct egress_imm_t;
|
struct d0_dst_imm_t;
|
||||||
struct ingress_ram_t;
|
struct src_d0_ram_t;
|
||||||
struct egress_ram_t;
|
struct d0_dst_ram_t;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace jump {
|
namespace jump {
|
||||||
@ -52,5 +52,8 @@ struct end_t;
|
|||||||
struct endi_t;
|
struct endi_t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace nop {
|
||||||
|
struct nop_t;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -28,10 +28,10 @@ struct visitor_t
|
|||||||
virtual T visit(const load::mvi_t * mvi) const = 0;
|
virtual T visit(const load::mvi_t * mvi) const = 0;
|
||||||
virtual T visit(const load::mvi_cond_t * mvi_cond) const = 0;
|
virtual T visit(const load::mvi_cond_t * mvi_cond) const = 0;
|
||||||
|
|
||||||
virtual T visit(const dma::ingress_imm_t * ingress_imm) const = 0;
|
virtual T visit(const dma::src_d0_imm_t * src_d0_imm) const = 0;
|
||||||
virtual T visit(const dma::egress_imm_t * egress_imm) const = 0;
|
virtual T visit(const dma::d0_dst_imm_t * d0_dst_imm) const = 0;
|
||||||
virtual T visit(const dma::ingress_ram_t * ingress_ram) const = 0;
|
virtual T visit(const dma::src_d0_ram_t * src_d0_ram) const = 0;
|
||||||
virtual T visit(const dma::egress_ram_t * egress_ram) const = 0;
|
virtual T visit(const dma::d0_dst_ram_t * d0_dst_ram) const = 0;
|
||||||
|
|
||||||
virtual T visit(const jump::jmp_t * jmp) const = 0;
|
virtual T visit(const jump::jmp_t * jmp) const = 0;
|
||||||
virtual T visit(const jump::jmp_cond_t * jmp_cond) const = 0;
|
virtual T visit(const jump::jmp_cond_t * jmp_cond) const = 0;
|
||||||
@ -42,6 +42,7 @@ struct visitor_t
|
|||||||
virtual T visit(const end::end_t * end) const = 0;
|
virtual T visit(const end::end_t * end) const = 0;
|
||||||
virtual T visit(const end::endi_t * endi) const = 0;
|
virtual T visit(const end::endi_t * endi) const = 0;
|
||||||
|
|
||||||
|
virtual T visit(const nop::nop_t * nop) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user