mirror of
https://github.com/usatiuk/psil.git
synced 2025-10-29 03:07:49 +01:00
secd parser
This commit is contained in:
@@ -43,6 +43,34 @@ void Parser::compileBody(const std::function<void(Cell *)> &sink) {
|
|||||||
int64_t loc = std::stoi(_tokenizer.getNext());
|
int64_t loc = std::stoi(_tokenizer.getNext());
|
||||||
if (_tokenizer.getNext() != ")") throw std::invalid_argument("Expected )");
|
if (_tokenizer.getNext() != ")") throw std::invalid_argument("Expected )");
|
||||||
sink(_vm.makeCell<ConsCell>(_vm.makeCell<IntCell>(frame), _vm.makeCell<IntCell>(loc)));
|
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") {
|
} else if (token == "LDF") {
|
||||||
std::stack<Cell *> out;
|
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(_vm.makeCell<CommandCell>(CommandCell::CommandNum::LDF));
|
||||||
sink(fntop);
|
sink(fntop);
|
||||||
} else if (token == "CONS") {
|
|
||||||
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::CONS));
|
|
||||||
} else if (token == "AP") {
|
} else if (token == "AP") {
|
||||||
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::AP));
|
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::AP));
|
||||||
} else if (token == "ADD") {
|
|
||||||
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::ADD));
|
|
||||||
} else if (token == "RET") {
|
} else if (token == "RET") {
|
||||||
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::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") {
|
} else if (token == "PUTCHAR") {
|
||||||
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::PUTCHAR));
|
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::PUTCHAR));
|
||||||
} else if (token == "PUTNUM") {
|
} else if (token == "PUTNUM") {
|
||||||
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::PUTNUM));
|
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::PUTNUM));
|
||||||
} else if (token == "STOP") {
|
} else if (token == "CONS") {
|
||||||
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::STOP));
|
sink(_vm.makeCell<CommandCell>(CommandCell::CommandNum::CONS));
|
||||||
} else {
|
} else {
|
||||||
if (token != ")")throw std::invalid_argument("Unknown token " + token);
|
if (token != ")")
|
||||||
|
throw std::invalid_argument("Unknown token " + token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,20 @@ TEST(VMWithParserTest, BasicHello) {
|
|||||||
EXPECT_EQ(ssout.str(), "h");
|
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) {
|
TEST(VMWithParserTest, BasicFunction) {
|
||||||
std::stringstream ssin;
|
std::stringstream ssin;
|
||||||
std::stringstream ssout;
|
std::stringstream ssout;
|
||||||
@@ -27,4 +41,18 @@ TEST(VMWithParserTest, BasicFunction) {
|
|||||||
}
|
}
|
||||||
ssout.flush();
|
ssout.flush();
|
||||||
EXPECT_EQ(ssout.str(), "3");
|
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");
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user