2 changed files with 157 additions and 0 deletions
@ -0,0 +1,142 @@
@@ -0,0 +1,142 @@
|
||||
#include "JSParser.h" |
||||
#include <vector> |
||||
#include <map> |
||||
#include <iostream> |
||||
|
||||
class js_scope { |
||||
public: |
||||
js_scope *parent; |
||||
js_scope() { |
||||
parent = nullptr; |
||||
} |
||||
std::map<std::string, std::string> variables; |
||||
}; |
||||
|
||||
std::shared_ptr<JavaScript> JSParser::parse(const std::string &source) const { |
||||
std::shared_ptr<JavaScript> ret = std::make_shared<JavaScript>(); |
||||
std::shared_ptr<js_scope> global = std::make_shared<js_scope>(); |
||||
std::cout << "source: " << source << "\n" << std::endl; |
||||
// tokenize it
|
||||
unsigned int cursor; |
||||
int state = 0; |
||||
int last = 0; |
||||
int quoteStart = 0; |
||||
int scopeLevel = 0; |
||||
int jsonStart = 0; |
||||
int jsonLevel = 0; |
||||
int functionStart = 0; |
||||
// each token is one statement
|
||||
std::vector<std::string> tokens; |
||||
for (cursor = 0; cursor < source.length(); cursor++) { |
||||
if (state == 0) { |
||||
if (source[cursor] == '{') { |
||||
state = 1; // JSON
|
||||
jsonStart = cursor; |
||||
jsonLevel++; |
||||
//std::cout << "Entering JSON: " << cursor << std::endl;
|
||||
} else if (source[cursor] == '\'') { // quotes just for allowing [;{}\n] in quotes
|
||||
quoteStart = cursor; |
||||
state = 4; |
||||
} else if (source[cursor] == '"') { |
||||
quoteStart = cursor; |
||||
state = 5; |
||||
} else if (source[cursor] == '/' && source.length() > cursor + 1 && source[cursor + 1] == '/') { |
||||
// single line comment
|
||||
state = 2; |
||||
} else if (source[cursor] == '/' && source.length() > cursor + 1 && source[cursor + 1] == '*') { |
||||
// Multiline comment
|
||||
state = 3; |
||||
} else if (source[cursor] == 'v' && source.length() > cursor + 3 && source[cursor + 1] == 'a' |
||||
&& source[cursor + 2] == 'r' && source[cursor + 3] == ' ') { |
||||
// var
|
||||
state = 7; |
||||
} else if (source[cursor] == 'f' && source.length() > cursor + 8 && source[cursor + 1] == 'u' |
||||
&& source[cursor + 2] == 'n' && source[cursor + 3] == 'c' && source[cursor + 4] == 't' |
||||
&& source[cursor + 5] == 'i' && source[cursor + 6] == 'o' && source[cursor + 7] == 'n') { |
||||
//std::cout << "Entering function: " << cursor << std::endl;
|
||||
state = 6; |
||||
functionStart = cursor; |
||||
} |
||||
} else if (state == 1) { |
||||
// inside a scope (JSON)
|
||||
if (source[cursor] == '{') { |
||||
jsonLevel++; |
||||
} else |
||||
if (source[cursor] == '}') { |
||||
jsonLevel--; |
||||
if (!jsonLevel) { |
||||
std::cout << "Exiting JSON: " << source.substr(jsonStart, cursor - jsonStart) << std::endl; |
||||
state = 0; // exit JSON
|
||||
} |
||||
} |
||||
} else if (state == 2) { |
||||
// inside a single line comment
|
||||
if (source[cursor] == '\n') { |
||||
state = 0; |
||||
} |
||||
} else if (state == 3) { |
||||
// inside a multiline comment
|
||||
if (source[cursor] == '*' && source.length() > cursor + 1 && source[cursor + 1] == '/') { |
||||
// end multiline comment
|
||||
state = 0; |
||||
} |
||||
} else if (state == 4) { |
||||
// inside single quote
|
||||
if (source[cursor] == '\'') { |
||||
if (source[cursor - 1] != '\\') { |
||||
//std::string quote = source.substr(quoteStart + 1, cursor - quoteStart - 1);
|
||||
//std::cout << "single quote: " << quote << std::endl;
|
||||
state = 0; |
||||
} |
||||
} |
||||
} else if (state == 5) { |
||||
// inside double quote
|
||||
if (source[cursor] == '"') { |
||||
if (source[cursor - 1] != '\\') { |
||||
//std::string quote = source.substr(quoteStart + 1, cursor - quoteStart - 1);
|
||||
//std::cout << "double quote: " << quote << std::endl;
|
||||
state = 0; |
||||
} |
||||
} |
||||
} else if (state == 7) { |
||||
} |
||||
|
||||
//
|
||||
if (source[cursor] == '{') { |
||||
scopeLevel++; |
||||
} |
||||
bool endIt = false; |
||||
if (source[cursor] == '}') { |
||||
scopeLevel--; |
||||
if (state == 6 && !scopeLevel) { |
||||
std::cout << "Exiting function: " << source.substr(functionStart, cursor - functionStart) << std::endl; |
||||
state = 0; |
||||
endIt = true; |
||||
} |
||||
} |
||||
|
||||
// state 0 or 7, ignore states 1-6
|
||||
if ((state == 0 || state == 7) && !scopeLevel) { |
||||
if (source[cursor] == '\n' || source[cursor] == ';' || endIt) { |
||||
// FIXME: ; in for loops
|
||||
std::string token = source.substr(last ? last + 1 : last, last ? (cursor - last - 1) : cursor ); |
||||
if (source[cursor] == '}') { |
||||
token += '}'; |
||||
} |
||||
// scopeLevel[" << scopeLevel << "]"
|
||||
std::cout << "got token [" << token << "] ending[" << source[cursor] << "] endIt[" << endIt << "]" << std::endl; |
||||
tokens.push_back(token); |
||||
last = cursor; |
||||
|
||||
if (state == 7) { // allow var constructs to end normally and take us out of var construct
|
||||
state = 0; // reset state
|
||||
} |
||||
} |
||||
} |
||||
} |
||||
std::cout << "out of characters in state " << state << std::endl; |
||||
std::string token = source.substr(last ? last + 1 : last, last ? (cursor - last - 1) : cursor ); |
||||
tokens.push_back(token); |
||||
std::cout << "got token [" << token << "] ending[" << source[cursor] << "]" << std::endl; |
||||
return ret; |
||||
} |
Loading…
Reference in new issue