summaryrefslogtreecommitdiff
path: root/src/ArzuParser.cpp
blob: 0556a27e9655f20a43e48643ad691c1e6e664750 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include "ArzuParser.h"
#include "PolishNotationParser.h"
#include "Memory.h"

bool isDigit(char ch) {
	return '0' <= ch && ch <= '9';
}

bool isName(char ch) {
	return ch == '$';
}

bool isSeparator(char ch) {
	return ch == ' ' || ch == '\t' || ch == '\n' || ch == EOF;
}

void _arzuIntOp(char op, Memory& mem) {
	Int* right = static_cast<Int*>(mem.work.top());
	mem.work.pop();
	Int* left = static_cast<Int*>(mem.work.top());
	switch (op) {
		case '+': left->value += right->value; break;
		case '-': left->value -= right->value; break;
		case '*': left->value *= right->value; break;
		case '/': left->value /= right->value; break;
		 default: throw "Bad op";
	}
	delete right;
}
void arzu_sum(Memory& mem) {
	_arzuIntOp('+', mem);
}
void arzu_sub(Memory& mem) {
	_arzuIntOp('-', mem);
}
void arzu_mult(Memory& mem) {
	_arzuIntOp('*', mem);
}
void arzu_div(Memory& mem) {
	_arzuIntOp('/', mem);
}

void arzu_devar(Memory& mem) {
	MemoryData* val = mem.work.top();
	mem.work.pop();
	Name* name = static_cast<Name*>(mem.work.top());
	mem.work.pop();

	mem.vars.push_back(name);
	mem.vars.push_back(val);
	mem.scopeVars.top()++;
}


MemoryData* arzu_Int_absorb(ifstream& inFile) {
	Int* num = new Int(0);
	while (!isSeparator(inFile.peek())) {
		num->value = (num->value * 10) + (inFile.peek() - '0');
		inFile.get();
	}
	return num;
}

MemoryData* arzu_Name_absorb(ifstream& inFile) {
	Name* name = new Name();
	while (isDigit(inFile.peek()) || ('0' <= inFile.peek() && inFile.peek() <= 'z'))
		name->value.push_back(inFile.get());
	return name;
}

ArzuParser::ArzuParser() : PNParser() {
	this->addInstr(Instruction("+", 2, arzu_sum));
	this->addInstr(Instruction("-", 2, arzu_sub));
	this->addInstr(Instruction("*", 2, arzu_mult));
	this->addInstr(Instruction("/", 2, arzu_div));
	this->addInstr(Instruction("devar", 2, arzu_devar));

	this->addAtom(Atom(isDigit, arzu_Int_absorb));
	this->addAtom(Atom(isName, arzu_Name_absorb));
}