2019-01-18 15:55:51 +01:00
|
|
|
#include "toker.hpp"
|
2019-01-18 17:04:57 +01:00
|
|
|
#include <cctype>
|
2019-01-18 15:55:51 +01:00
|
|
|
#include "ex.hpp"
|
2019-01-19 18:28:07 +01:00
|
|
|
|
|
|
|
|
#include <stdutil.hpp>
|
2014-01-31 08:23:00 +13:00
|
|
|
|
|
|
|
|
int Toker::chars_toked;
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
static std::map<std::string, int> alphaTokes, lowerTokes;
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
static void makeKeywords()
|
|
|
|
|
{
|
2014-01-31 08:23:00 +13:00
|
|
|
static bool made;
|
2019-01-18 17:04:57 +01:00
|
|
|
if (made)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
alphaTokes["Dim"] = DIM;
|
|
|
|
|
alphaTokes["Goto"] = GOTO;
|
|
|
|
|
alphaTokes["Gosub"] = GOSUB;
|
|
|
|
|
alphaTokes["Return"] = RETURN;
|
|
|
|
|
alphaTokes["Exit"] = EXIT;
|
|
|
|
|
alphaTokes["If"] = IF;
|
|
|
|
|
alphaTokes["Then"] = THEN;
|
|
|
|
|
alphaTokes["Else"] = ELSE;
|
|
|
|
|
alphaTokes["EndIf"] = ENDIF;
|
|
|
|
|
alphaTokes["End If"] = ENDIF;
|
|
|
|
|
alphaTokes["ElseIf"] = ELSEIF;
|
|
|
|
|
alphaTokes["Else If"] = ELSEIF;
|
|
|
|
|
alphaTokes["While"] = WHILE;
|
|
|
|
|
alphaTokes["Wend"] = WEND;
|
|
|
|
|
alphaTokes["For"] = FOR;
|
|
|
|
|
alphaTokes["To"] = TO;
|
|
|
|
|
alphaTokes["Step"] = STEP;
|
|
|
|
|
alphaTokes["Next"] = NEXT;
|
|
|
|
|
alphaTokes["Function"] = FUNCTION;
|
|
|
|
|
alphaTokes["End Function"] = ENDFUNCTION;
|
|
|
|
|
alphaTokes["Type"] = TYPE;
|
|
|
|
|
alphaTokes["End Type"] = ENDTYPE;
|
|
|
|
|
alphaTokes["Each"] = EACH;
|
|
|
|
|
alphaTokes["Local"] = LOCAL;
|
|
|
|
|
alphaTokes["Global"] = GLOBAL;
|
|
|
|
|
alphaTokes["Field"] = FIELD;
|
|
|
|
|
alphaTokes["Const"] = BBCONST;
|
|
|
|
|
alphaTokes["Select"] = SELECT;
|
|
|
|
|
alphaTokes["Case"] = CASE;
|
|
|
|
|
alphaTokes["Default"] = DEFAULT;
|
|
|
|
|
alphaTokes["End Select"] = ENDSELECT;
|
|
|
|
|
alphaTokes["Repeat"] = REPEAT;
|
|
|
|
|
alphaTokes["Until"] = UNTIL;
|
|
|
|
|
alphaTokes["Forever"] = FOREVER;
|
|
|
|
|
alphaTokes["Data"] = DATA;
|
|
|
|
|
alphaTokes["Read"] = READ;
|
|
|
|
|
alphaTokes["Restore"] = RESTORE;
|
|
|
|
|
alphaTokes["Abs"] = ABS;
|
|
|
|
|
alphaTokes["Sgn"] = SGN;
|
|
|
|
|
alphaTokes["Mod"] = MOD;
|
|
|
|
|
alphaTokes["Pi"] = PI;
|
|
|
|
|
alphaTokes["True"] = BBTRUE;
|
|
|
|
|
alphaTokes["False"] = BBFALSE;
|
|
|
|
|
alphaTokes["Int"] = BBINT;
|
|
|
|
|
alphaTokes["Float"] = BBFLOAT;
|
|
|
|
|
alphaTokes["Str"] = BBSTR;
|
|
|
|
|
alphaTokes["Include"] = INCLUDE;
|
|
|
|
|
|
|
|
|
|
alphaTokes["New"] = BBNEW;
|
|
|
|
|
alphaTokes["Delete"] = BBDELETE;
|
|
|
|
|
alphaTokes["First"] = FIRST;
|
|
|
|
|
alphaTokes["Last"] = LAST;
|
|
|
|
|
alphaTokes["Insert"] = INSERT;
|
|
|
|
|
alphaTokes["Before"] = BEFORE;
|
|
|
|
|
alphaTokes["After"] = AFTER;
|
|
|
|
|
alphaTokes["Null"] = BBNULL;
|
|
|
|
|
alphaTokes["Object"] = OBJECT;
|
|
|
|
|
alphaTokes["Handle"] = BBHANDLE;
|
|
|
|
|
|
|
|
|
|
alphaTokes["And"] = AND;
|
|
|
|
|
alphaTokes["Or"] = OR;
|
|
|
|
|
alphaTokes["Xor"] = XOR;
|
|
|
|
|
alphaTokes["Not"] = NOT;
|
|
|
|
|
alphaTokes["Shl"] = SHL;
|
|
|
|
|
alphaTokes["Shr"] = SHR;
|
|
|
|
|
alphaTokes["Sar"] = SAR;
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
std::map<std::string, int>::const_iterator it;
|
2019-01-18 17:04:57 +01:00
|
|
|
for (it = alphaTokes.begin(); it != alphaTokes.end(); ++it) {
|
|
|
|
|
lowerTokes[tolower(it->first)] = it->second;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2019-01-18 17:04:57 +01:00
|
|
|
made = true;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
Toker::Toker(std::istream& in) : in(in), curr_row(-1)
|
2019-01-18 17:04:57 +01:00
|
|
|
{
|
2014-01-31 08:23:00 +13:00
|
|
|
makeKeywords();
|
|
|
|
|
nextline();
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
std::map<std::string, int>& Toker::getKeywords()
|
2019-01-18 17:04:57 +01:00
|
|
|
{
|
2014-01-31 08:23:00 +13:00
|
|
|
makeKeywords();
|
|
|
|
|
return alphaTokes;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
int Toker::pos()
|
|
|
|
|
{
|
|
|
|
|
return ((curr_row) << 16) | (tokes[curr_toke].from);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
int Toker::curr()
|
|
|
|
|
{
|
2014-01-31 08:23:00 +13:00
|
|
|
return tokes[curr_toke].n;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
std::string Toker::text()
|
2019-01-18 17:04:57 +01:00
|
|
|
{
|
|
|
|
|
int from = tokes[curr_toke].from, to = tokes[curr_toke].to;
|
|
|
|
|
return line.substr(from, to - from);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
int Toker::lookAhead(int n)
|
|
|
|
|
{
|
|
|
|
|
return tokes[curr_toke + n].n;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
void Toker::nextline()
|
|
|
|
|
{
|
2014-01-31 08:23:00 +13:00
|
|
|
++curr_row;
|
2019-01-18 17:04:57 +01:00
|
|
|
curr_toke = 0;
|
2014-01-31 08:23:00 +13:00
|
|
|
tokes.clear();
|
2019-01-18 17:04:57 +01:00
|
|
|
if (in.eof()) {
|
|
|
|
|
line.resize(1);
|
|
|
|
|
line[0] = EOF;
|
|
|
|
|
tokes.push_back(Toke(EOF, 0, 1));
|
2014-01-31 08:23:00 +13:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
getline(in, line);
|
|
|
|
|
line += '\n';
|
|
|
|
|
chars_toked += line.size();
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
for (int k = 0; k < line.size();) {
|
|
|
|
|
int c = line[k], from = k;
|
|
|
|
|
if (c == '\n') {
|
|
|
|
|
tokes.push_back(Toke(c, from, ++k));
|
2014-01-31 08:23:00 +13:00
|
|
|
continue;
|
|
|
|
|
}
|
2019-01-18 17:04:57 +01:00
|
|
|
if (isspace(c)) {
|
|
|
|
|
++k;
|
2014-01-31 08:23:00 +13:00
|
|
|
continue;
|
|
|
|
|
}
|
2019-01-18 17:04:57 +01:00
|
|
|
if (c == ';') {
|
|
|
|
|
for (++k; line[k] != '\n'; ++k) {
|
|
|
|
|
}
|
2014-01-31 08:23:00 +13:00
|
|
|
continue;
|
|
|
|
|
}
|
2019-01-18 17:04:57 +01:00
|
|
|
if (c == '.' && isdigit(line[k + 1])) {
|
|
|
|
|
for (k += 2; isdigit(line[k]); ++k) {
|
|
|
|
|
}
|
|
|
|
|
tokes.push_back(Toke(FLOATCONST, from, k));
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (isdigit(c)) {
|
|
|
|
|
for (++k; isdigit(line[k]); ++k) {
|
|
|
|
|
}
|
|
|
|
|
if (line[k] == '.') {
|
|
|
|
|
for (++k; isdigit(line[k]); ++k) {
|
|
|
|
|
}
|
|
|
|
|
tokes.push_back(Toke(FLOATCONST, from, k));
|
2014-01-31 08:23:00 +13:00
|
|
|
continue;
|
|
|
|
|
}
|
2019-01-18 17:04:57 +01:00
|
|
|
tokes.push_back(Toke(INTCONST, from, k));
|
2014-01-31 08:23:00 +13:00
|
|
|
continue;
|
|
|
|
|
}
|
2019-01-18 17:04:57 +01:00
|
|
|
if (c == '%' && (line[k + 1] == '0' || line[k + 1] == '1')) {
|
|
|
|
|
for (k += 2; line[k] == '0' || line[k] == '1'; ++k) {
|
|
|
|
|
}
|
|
|
|
|
tokes.push_back(Toke(BINCONST, from, k));
|
2014-01-31 08:23:00 +13:00
|
|
|
continue;
|
|
|
|
|
}
|
2019-01-18 17:04:57 +01:00
|
|
|
if (c == '$' && isxdigit(line[k + 1])) {
|
|
|
|
|
for (k += 2; isxdigit(line[k]); ++k) {
|
|
|
|
|
}
|
|
|
|
|
tokes.push_back(Toke(HEXCONST, from, k));
|
2014-01-31 08:23:00 +13:00
|
|
|
continue;
|
|
|
|
|
}
|
2019-01-18 17:04:57 +01:00
|
|
|
if (isalpha(c)) {
|
|
|
|
|
for (++k; isalnum(line[k]) || line[k] == '_'; ++k) {
|
|
|
|
|
}
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
std::string ident = tolower(line.substr(from, k - from));
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
if (line[k] == ' ' && isalpha(line[k + 1])) {
|
|
|
|
|
int t = k;
|
|
|
|
|
for (t += 2; isalnum(line[t]) || line[t] == '_'; ++t) {
|
|
|
|
|
}
|
2019-01-19 18:28:07 +01:00
|
|
|
std::string s = tolower(line.substr(from, t - from));
|
2019-01-18 17:04:57 +01:00
|
|
|
if (lowerTokes.find(s) != lowerTokes.end()) {
|
|
|
|
|
k = t;
|
|
|
|
|
ident = s;
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-19 18:28:07 +01:00
|
|
|
std::map<std::string, int>::iterator it = lowerTokes.find(ident);
|
2014-01-31 08:23:00 +13:00
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
if (it == lowerTokes.end()) {
|
|
|
|
|
for (int n = from; n < k; ++n)
|
|
|
|
|
line[n] = tolower(line[n]);
|
|
|
|
|
tokes.push_back(Toke(IDENT, from, k));
|
2014-01-31 08:23:00 +13:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
tokes.push_back(Toke(it->second, from, k));
|
2014-01-31 08:23:00 +13:00
|
|
|
continue;
|
|
|
|
|
}
|
2019-01-18 17:04:57 +01:00
|
|
|
if (c == '\"') {
|
|
|
|
|
for (++k; line[k] != '\"' && line[k] != '\n'; ++k) {
|
|
|
|
|
}
|
|
|
|
|
if (line[k] == '\"')
|
|
|
|
|
++k;
|
|
|
|
|
tokes.push_back(Toke(STRINGCONST, from, k));
|
2014-01-31 08:23:00 +13:00
|
|
|
continue;
|
|
|
|
|
}
|
2019-01-18 17:04:57 +01:00
|
|
|
int n = line[k + 1];
|
|
|
|
|
if ((c == '<' && n == '>') || (c == '>' && n == '<')) {
|
|
|
|
|
tokes.push_back(Toke(NE, from, k += 2));
|
2014-01-31 08:23:00 +13:00
|
|
|
continue;
|
|
|
|
|
}
|
2019-01-18 17:04:57 +01:00
|
|
|
if ((c == '<' && n == '=') || (c == '=' && n == '<')) {
|
|
|
|
|
tokes.push_back(Toke(LE, from, k += 2));
|
2014-01-31 08:23:00 +13:00
|
|
|
continue;
|
|
|
|
|
}
|
2019-01-18 17:04:57 +01:00
|
|
|
if ((c == '>' && n == '=') || (c == '=' && n == '>')) {
|
|
|
|
|
tokes.push_back(Toke(GE, from, k += 2));
|
2014-01-31 08:23:00 +13:00
|
|
|
continue;
|
|
|
|
|
}
|
2019-01-18 17:04:57 +01:00
|
|
|
tokes.push_back(Toke(c, from, ++k));
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
2019-01-18 17:04:57 +01:00
|
|
|
if (!tokes.size())
|
|
|
|
|
exit(0);
|
2014-01-31 08:23:00 +13:00
|
|
|
}
|
|
|
|
|
|
2019-01-18 17:04:57 +01:00
|
|
|
int Toker::next()
|
|
|
|
|
{
|
|
|
|
|
if (++curr_toke == tokes.size())
|
|
|
|
|
nextline();
|
2014-01-31 08:23:00 +13:00
|
|
|
return curr();
|
|
|
|
|
}
|