-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtokengenerator.cpp
More file actions
133 lines (124 loc) · 4.06 KB
/
tokengenerator.cpp
File metadata and controls
133 lines (124 loc) · 4.06 KB
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include "tokengenerator.h"
#include "utils.h"
#include <string>
#include <iostream>
#include <vector>
using namespace std;
void printtokengenerator(const vector<Token> &RPNTokens,
VarTable &vartabel, string &out, int report)
{
if (!report) return;
cout << "\n******************** tokenList ********************\nout=\t" << out << endl;
cout << "opcode : ";
for (const Token &element : RPNTokens)
// std::cout << "\t" << element.value << " ";
cout << "\t" << ppOC[static_cast<int>(element.opcode)] << " ";
cout << endl;
cout << "opcode: ";
for (const Token &element : RPNTokens)
cout << "\t" << static_cast<int>(element.opcode) << " "; // todo convert to string
cout << endl;
cout << "arity : ";
for (const Token &element : RPNTokens)
cout << "\t" << element.arity << " ";
cout << endl;
cout << "preced: ";
for (const Token &element : RPNTokens)
cout << "\t" << element.precedence << " ";
cout << endl;
cout << "value : ";
for (const Token &element : RPNTokens)
cout << "\t" << element.value << " ";
cout << endl;
}
bool findKeyword(const map<string, Token> &keys,
const string &s,
pair<string, Token> &result)
{
// ordered Map stores "==" always after "=", "==" would never be found. so we loop through the map in reverse
for (auto entry = keys.rbegin(); entry != keys.rend(); ++entry)
{
const string &key = entry->first;
if (s.compare(0, key.size(), key) == 0)
{
result = {entry->first, entry->second};
return true;
}
}
return false;
}
void storeValueOrIndex(string param,
Token &token,
VarTable &vartabel)
{
if (isNumeric(param))
{
token.value = stof(param);
token.opcode = OC::NUM;
}
else
{
token.value = vartabel.getIndex(param);
token.opcode = OC::VAR;
}
}
vector<Token> makeTokenList(string textIn,
const map<std::string, Token> &keywords,
VarTable &vartabel,
int report) // provisional, for debug and reporting
{
string out = ""; // only for reporting
int cursor = 0;
string operand = "";
pair<string, Token> keyPairFound;
int moveCursor;
vector<Token> tokens;
Token token;
// start with a nil token. that way we can check the token before the first one without crash
tokens.push_back({OC::NIL, 0, 0, 0});
while (cursor < textIn.size())
{
if (textIn[cursor] == ' ')
{
cursor++;
continue;
}
if (findKeyword(keywords, textIn.substr(cursor), keyPairFound))
{
// now deal with the operand finished building
if (operand.size() > 0)
{ // operand is a num or var
storeValueOrIndex(operand, token, vartabel);
// if num store it in token, if var reserve an index for it in var array
tokens.push_back(token);
out += "\t{" + operand + "}";
}
operand = "";
token = keyPairFound.second;
tokens.push_back(token);
out += "\t|" + keyPairFound.first + "|";
moveCursor = keyPairFound.first.size();
}
else
{
// operand is a digit or variable because the text at cursor does not start with a keyword
operand += textIn[cursor]; // collect coming chars in operand
moveCursor = 1;
token.arity = 0;
token.precedence = 0; // opcode NUM or VAR follows later
}
cursor += moveCursor;
}
if (operand.size() > 0)
{ // operand is a num or var
storeValueOrIndex(operand, token, vartabel);
tokens.push_back(token);
out += "\t{" + operand + "} ";
}
tokens.push_back({OC::NIL, 0, 0, 0});
out += "\t{";
out += "ETX";
out += "} ";
printtokengenerator(tokens, vartabel, out, report);
return tokens;
}