secd parser

This commit is contained in:
2023-12-23 19:21:05 +01:00
parent 43c41282f3
commit a9050fc9b9
2 changed files with 72 additions and 7 deletions

View File

@@ -43,6 +43,34 @@ void Parser::compileBody(const std::function<void(Cell *)> &sink) {
int64_t loc = std::stoi(_tokenizer.getNext());
if (_tokenizer.getNext() != ")") throw std::invalid_argument("Expected )");
sink(_vm.makeCell<ConsCell>(_vm.makeCell<IntCell>(frame), _vm.makeCell<IntCell>(loc)));
} else if (token == "SEL") {
std::stack<Cell *> outt;
compileBody([&outt](Cell *cmd) { outt.emplace(cmd); });
std::stack<Cell *> outf;
compileBody([&outf](Cell *cmd) { outf.emplace(cmd); });
if (outt.empty()) throw std::invalid_argument("Function body empty");
if (outf.empty()) throw std::invalid_argument("Function body empty");
ConsCell *ttop = _vm.makeCell<ConsCell>(outt.top());
outt.pop();
while (!outt.empty()) {
_vm.push(ttop, outt.top());
outt.pop();
}
ConsCell *ftop = _vm.makeCell<ConsCell>(outf.top());
outf.pop();
while (!outf.empty()) {
_vm.push(ftop, outf.top());
outf.pop();
}
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::SEL));
sink(ttop);
sink(ftop);
} else if (token == "JOIN") {
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::JOIN));
} else if (token == "LDF") {
std::stack<Cell *> out;
@@ -59,22 +87,31 @@ void Parser::compileBody(const std::function<void(Cell *)> &sink) {
}
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::LDF));
sink(fntop);
} else if (token == "CONS") {
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::CONS));
} else if (token == "AP") {
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::AP));
} else if (token == "ADD") {
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::ADD));
} else if (token == "RET") {
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::RET));
} else if (token == "DUM") {
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::DUM));
} else if (token == "RAP") {
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::RAP));
} else if (token == "STOP") {
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::STOP));
} else if (token == "ADD") {
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::ADD));
} else if (token == "SUB") {
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::SUB));
} else if (token == "READCHAR") {
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::READCHAR));
} else if (token == "PUTCHAR") {
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::PUTCHAR));
} else if (token == "PUTNUM") {
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::PUTNUM));
} else if (token == "STOP") {
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::STOP));
} else if (token == "CONS") {
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::CONS));
} else {
if (token != ")")throw std::invalid_argument("Unknown token " + token);
if (token != ")")
throw std::invalid_argument("Unknown token " + token);
}
}
}

View File

@@ -16,6 +16,20 @@ TEST(VMWithParserTest, BasicHello) {
EXPECT_EQ(ssout.str(), "h");
}
TEST(VMWithParserTest, BasicBranch) {
std::stringstream ssin;
std::stringstream ssout;
{
VM vm(ssin, ssout);
Parser parser(vm);
parser.loadSecd(
"( LDC 1 SEL ( LDC 10 PUTNUM JOIN ) ( LDC 20 PUTNUM JOIN ) LDC 0 SEL ( LDC 30 PUTNUM JOIN ) ( LDC 40 PUTNUM JOIN ) STOP )");
vm.run();
}
ssout.flush();
EXPECT_EQ(ssout.str(), "1040");
}
TEST(VMWithParserTest, BasicFunction) {
std::stringstream ssin;
std::stringstream ssout;
@@ -27,4 +41,18 @@ TEST(VMWithParserTest, BasicFunction) {
}
ssout.flush();
EXPECT_EQ(ssout.str(), "3");
}
TEST(VMWithParserTest, RecFunction) {
std::stringstream ssin;
std::stringstream ssout;
{
VM vm(ssin, ssout);
Parser parser(vm);
parser.loadSecd(
"( DUM NIL LDF ( LD ( 1 . 1 ) SEL ( LD ( 1 . 1 ) LDC -1 ADD SEL ( NIL LD ( 1 . 1 ) LDC -1 ADD CONS LD ( 2 . 1 ) AP NIL LD ( 1 . 1 ) LDC -2 ADD CONS LD ( 2 . 1 ) AP ADD JOIN ) ( LDC 1 JOIN ) JOIN ) ( LDC 0 JOIN ) RET ) CONS LDF ( NIL LDC 20 CONS LD ( 1 . 1 ) AP RET ) RAP PUTNUM STOP )");
vm.run();
}
ssout.flush();
EXPECT_EQ(ssout.str(), "6765");
}