diff options
| author | Syndamia <kamen@syndamia.com> | 2022-11-29 19:02:10 +0200 |
|---|---|---|
| committer | Syndamia <kamen@syndamia.com> | 2022-11-29 19:02:10 +0200 |
| commit | 83c7854b3f6e60d6e3c430b9c3dd59b3773c4ef2 (patch) | |
| tree | 08511019dfa78f49c9ecddde864186a7fa81cf5f /src/PolishNotationParser.cpp | |
| parent | 6f5fe499c2ba09057f3462edaeccfee5cc6f25a4 (diff) | |
| download | arzu-interpreter-83c7854b3f6e60d6e3c430b9c3dd59b3773c4ef2.tar arzu-interpreter-83c7854b3f6e60d6e3c430b9c3dd59b3773c4ef2.tar.gz arzu-interpreter-83c7854b3f6e60d6e3c430b9c3dd59b3773c4ef2.zip | |
Added a somewhat working version of the parser
Diffstat (limited to 'src/PolishNotationParser.cpp')
| -rw-r--r-- | src/PolishNotationParser.cpp | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/src/PolishNotationParser.cpp b/src/PolishNotationParser.cpp new file mode 100644 index 0000000..f99f404 --- /dev/null +++ b/src/PolishNotationParser.cpp @@ -0,0 +1,145 @@ +#include "PolishNotationParser.h" +#include "MemoryData.h" + +#include <iostream> + +Instruction::Instruction(const char* str, unsigned argc, void (*exec)(Memory&)) : name(str), argc(argc), exec(exec) {} + +Atom::Atom(bool (*isAtomChar)(char), MemoryData* (*absorb)(ifstream&)) : isAtomChar(isAtomChar), absorb(absorb) {} + +void PNParser::addInstr(Instruction i) { + this->instr.push_back(i); +} + +void PNParser::addAtom(Atom a) { + this->atoms.push_back(a); +} + +bool isSpacing(char ch) { + return ch == ' ' || ch == '\t' || ch == EOF; +} + +void skipSpacing(ifstream& inFile) { + while(isSpacing(inFile.peek())) + inFile.get(); +} + +void PNParser::evaluateFunction(Memory& mem, Function* func, ifstream& inFile) { + if (func->scopeEnd < 0) { + instr[func->scopeStart].exec(mem); + delete func; + return; + } + + for (auto i = func->argumentNames.rbegin(); i != func->argumentNames.rend(); ++i) { + mem.vars.push_back(new Name(*i)); + mem.vars.push_back(mem.work.top()); + mem.work.pop(); + } + mem.scopeVars.push(func->argumentNames.size()); + + this->parseScope(inFile, mem, func->scopeStart, func->scopeEnd); +} + +void PNParser::pushToWork(Memory& mem, MemoryData* data, ifstream& inFile) { + if (data->get_type() == MemoryData::TFunc) { + Function* func = static_cast<Function*>(data); + mem.work.push(data); + mem.work.push(new Int(func->argumentNames.size())); + return; + } + + // We keep the amount of required arguments and the function + // on the top of the stack at all times + Int* argc = static_cast<Int*>(mem.work.top()); + mem.work.pop(); + Function* func = static_cast<Function*>(mem.work.top()); + mem.work.pop(); + + mem.work.push(data); + argc->value--; + + while (argc->value == 0) { + delete argc; + evaluateFunction(mem, func, inFile); + + if (mem.work.size() == 1) return; + + data = mem.work.top(); + mem.work.pop(); + argc = static_cast<Int*>(mem.work.top()); + mem.work.pop(); + func = static_cast<Function*>(mem.work.top()); + mem.work.pop(); + + mem.work.push(data); + argc->value--; + } + + mem.work.push(func); + mem.work.push(argc); +} + +void PNParser::parseScope(ifstream& inFile, Memory& mem, int start, int end) { + mem.scopeVars.push(0); + bool absorbed = false; + while (start < inFile.tellg() && inFile.tellg() < end && inFile.peek() != EOF) { + skipSpacing(inFile); + + /* If value is an atom */ + + for (Atom& a : this->atoms) { + if (a.isAtomChar(inFile.peek())) { + pushToWork(mem, a.absorb(inFile), inFile); + absorbed = true; + break; + } + } + + if (absorbed) { absorbed = false; continue; } + + /* If value is a built-in function */ + + string name; + while (!isSpacing(inFile.peek())) + name.push_back(inFile.get()); + + for (int i = instr.size() - 1; i >= 0; i--) { + if (instr[i].name == name) { + list<string> temp; + temp.resize(instr[i].argc); + pushToWork(mem, new Function(temp, i, -1), inFile); + absorbed = true; + break; + } + } + + if (absorbed) { absorbed = false; continue; } + + /* If value is a variable */ + + Name* cname; + for (auto i = ++mem.vars.rbegin(); i != mem.vars.rend(); ++(++i)) { + cname = static_cast<Name*>(*i); + if (cname->value == name) { + MemoryData* value = new MemoryData(*static_cast<MemoryData*>(*(--i))); + pushToWork(mem, value, inFile); + break; + } + } + } + cout << mem.vars.size(); + // cout << static_cast<Int*>(mem.work.top())->value << endl; + + for (int i = mem.scopeVars.top(); i > 0; i--) { + delete mem.vars.back(); + mem.vars.pop_back(); + delete mem.vars.back(); + mem.vars.pop_back(); + } + mem.scopeVars.pop(); +} + +void PNParser::parse(ifstream& inFile, Memory& mem) { + parseScope(inFile, mem, -1, 100000); // global scope +} |
