Files
BlitzNext/compiler/toker.cpp
T

247 lines
5.7 KiB
C++
Raw Normal View History

2014-01-31 08:23:00 +13:00
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-18 17:04:57 +01:00
#include "std.hpp"
2014-01-31 08:23:00 +13:00
int Toker::chars_toked;
2019-01-18 17:04:57 +01:00
static map<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;
map<string, int>::const_iterator it;
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-18 17:04:57 +01:00
Toker::Toker(istream& in) : in(in), curr_row(-1)
{
2014-01-31 08:23:00 +13:00
makeKeywords();
nextline();
}
2019-01-18 17:04:57 +01:00
map<string, int>& Toker::getKeywords()
{
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-18 17:04:57 +01:00
string Toker::text()
{
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-18 17:04:57 +01:00
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) {
}
string s = tolower(line.substr(from, t - from));
if (lowerTokes.find(s) != lowerTokes.end()) {
k = t;
ident = s;
2014-01-31 08:23:00 +13:00
}
}
2019-01-18 17:04:57 +01:00
map<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();
}