|
|
|
@ -158,6 +158,684 @@ std::vector<std::string> JSParser::getTokens(const std::string &source) const {
@@ -158,6 +158,684 @@ std::vector<std::string> JSParser::getTokens(const std::string &source) const {
|
|
|
|
|
return tokens; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void doExpression(js_scope &rootScope, std::string token) { |
|
|
|
|
std::vector<std::string> expression_parts; |
|
|
|
|
size_t cursor; |
|
|
|
|
size_t last = 0; |
|
|
|
|
size_t quoteStart = 0; |
|
|
|
|
size_t parenStart = 0; |
|
|
|
|
size_t parenLevel = 0; |
|
|
|
|
size_t trinaryLevel = 0; |
|
|
|
|
unsigned char state = 0; |
|
|
|
|
for (cursor = 0; cursor < token.length(); cursor++) { |
|
|
|
|
if (state == 0) { |
|
|
|
|
// ||
|
|
|
|
|
// &&
|
|
|
|
|
// <, >, <=, >=, ==, ===, !=, !==
|
|
|
|
|
// +, -
|
|
|
|
|
// *, /, %
|
|
|
|
|
// ?, >>, <<
|
|
|
|
|
if (token[cursor] == 'f' && token.length() > cursor + 7 && token[cursor + 1] == 'u' |
|
|
|
|
&& token[cursor + 2] == 'n' && token[cursor + 3] == 'c' && token[cursor + 4] == 't' |
|
|
|
|
&& token[cursor + 5] == 'i' && token[cursor + 6] == 'o' && token[cursor + 7] == 'n') { |
|
|
|
|
state = 3; |
|
|
|
|
} |
|
|
|
|
if (token[cursor] == '\'') { |
|
|
|
|
quoteStart = cursor; |
|
|
|
|
state = 4; |
|
|
|
|
} else |
|
|
|
|
if (token[cursor] == '"') { |
|
|
|
|
quoteStart = cursor; |
|
|
|
|
state = 5; |
|
|
|
|
} else |
|
|
|
|
if (token[cursor] == '(') { |
|
|
|
|
parenStart = cursor; |
|
|
|
|
parenLevel++; |
|
|
|
|
state = 8; |
|
|
|
|
if (last != cursor) { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last - 1)); |
|
|
|
|
} |
|
|
|
|
last = cursor + 1; |
|
|
|
|
expression_parts.push_back("("); |
|
|
|
|
} else |
|
|
|
|
if (token[cursor] == '{') { |
|
|
|
|
parenStart = cursor; |
|
|
|
|
parenLevel++; |
|
|
|
|
state = 1; |
|
|
|
|
//std::cout << "last " << last << " cursor " << cursor << std::endl;
|
|
|
|
|
if (last != cursor) { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last - 1)); |
|
|
|
|
} |
|
|
|
|
last = cursor + 1; |
|
|
|
|
expression_parts.push_back("{"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// single =
|
|
|
|
|
if (token[cursor] == '=' && token.length() > cursor + 1 && token[cursor + 1] != '=') { |
|
|
|
|
//state = 1;
|
|
|
|
|
//std::cout << "starting = at " << cursor << " last: " << last << std::endl;
|
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back("="); |
|
|
|
|
} |
|
|
|
|
// hack for JSON parsing
|
|
|
|
|
if (token[cursor] == ':') { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back("="); |
|
|
|
|
state = 2; |
|
|
|
|
} |
|
|
|
|
// ||
|
|
|
|
|
if (token[cursor] == '|' && token.length() > cursor + 1 && token[cursor + 1] == '|') { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back("||"); |
|
|
|
|
} |
|
|
|
|
if (token[cursor] == '&' && token.length() > cursor + 1 && token[cursor + 1] == '&') { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back("&&"); |
|
|
|
|
} |
|
|
|
|
if (token[cursor] == '>' && token.length() > cursor + 1 && token[cursor + 1] != '=' && token[cursor + 1] != '>') { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back(">"); |
|
|
|
|
} |
|
|
|
|
if (token[cursor] == '<' && token.length() > cursor + 1 && token[cursor + 1] != '=' && token[cursor + 1] != '<') { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back("<"); |
|
|
|
|
} |
|
|
|
|
if (token[cursor] == '<' && token.length() > cursor + 1 && token[cursor + 1] == '&') { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back("<="); |
|
|
|
|
} |
|
|
|
|
if (token[cursor] == '>' && token.length() > cursor + 1 && token[cursor + 1] == '&') { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back(">="); |
|
|
|
|
} |
|
|
|
|
if (token[cursor] == '=' && token.length() > cursor + 2 && token[cursor + 1] == '=' && token[cursor + 2] != '=') { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back("=="); |
|
|
|
|
} |
|
|
|
|
if (token[cursor] == '=' && token.length() > cursor + 2 && token[cursor + 1] == '=' && token[cursor + 2] == '=') { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back("==="); |
|
|
|
|
} |
|
|
|
|
if (token[cursor] == '!' && token.length() > cursor + 2 && token[cursor + 1] == '=' && token[cursor + 2] != '=') { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back("!="); |
|
|
|
|
} |
|
|
|
|
if (token[cursor] == '!' && token.length() > cursor + 2 && token[cursor + 1] == '=' && token[cursor + 2] == '=') { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back("!=="); |
|
|
|
|
} |
|
|
|
|
// +
|
|
|
|
|
if (token[cursor] == '+') { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back("+"); |
|
|
|
|
} else |
|
|
|
|
if (token[cursor] == '-') { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back("+"); |
|
|
|
|
} else |
|
|
|
|
if (token[cursor] == '*') { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back("*"); |
|
|
|
|
} else |
|
|
|
|
if (token[cursor] == '/') { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back("/"); |
|
|
|
|
} else |
|
|
|
|
if (token[cursor] == '%') { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back("%"); |
|
|
|
|
} else |
|
|
|
|
if (token[cursor] == '?') { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back("?"); |
|
|
|
|
trinaryLevel++; |
|
|
|
|
state = 9; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} else if (state == 1) { |
|
|
|
|
if (token[cursor] == '{') { |
|
|
|
|
parenLevel++; |
|
|
|
|
} else |
|
|
|
|
if (token[cursor] == '}') { |
|
|
|
|
parenLevel--; |
|
|
|
|
if (!parenLevel) { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); |
|
|
|
|
last = cursor + 1; |
|
|
|
|
expression_parts.push_back("}"); |
|
|
|
|
state = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else if (state == 2) { // json state (can be moved)
|
|
|
|
|
if (token[cursor] == ',') { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); |
|
|
|
|
last = cursor + 1; |
|
|
|
|
state = 0; |
|
|
|
|
} |
|
|
|
|
} else if (state == 3) { // function start (can be moved)
|
|
|
|
|
if (token[cursor] == '{') { |
|
|
|
|
// lets put the function prototype
|
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); |
|
|
|
|
last = cursor + 1; |
|
|
|
|
parenLevel++; |
|
|
|
|
state = 6; // move to the function body
|
|
|
|
|
} |
|
|
|
|
} else if (state == 4) { |
|
|
|
|
if (token[cursor] == '\'') { |
|
|
|
|
if (token[cursor - 1] != '\\') { |
|
|
|
|
//std::string quote = token.substr(quoteStart + 1, cursor - quoteStart - 1);
|
|
|
|
|
//expression_parts.push_back(quote);
|
|
|
|
|
//std::cout << "single quote: " << quote << std::endl;
|
|
|
|
|
state = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else if (state == 5) { |
|
|
|
|
if (token[cursor] == '"') { |
|
|
|
|
if (token[cursor - 1] != '\\') { |
|
|
|
|
//std::string quote = token.substr(quoteStart + 1, cursor - quoteStart - 1);
|
|
|
|
|
//expression_parts.push_back(quote);
|
|
|
|
|
//std::cout << "double quote: " << quote << std::endl;
|
|
|
|
|
state = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else if (state == 6) { |
|
|
|
|
if (token[cursor] == '{') { |
|
|
|
|
parenLevel++; |
|
|
|
|
} else |
|
|
|
|
if (token[cursor] == '}') { |
|
|
|
|
parenLevel--; |
|
|
|
|
if (!parenLevel) { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); |
|
|
|
|
last = cursor + 1; |
|
|
|
|
expression_parts.push_back("}"); // end function
|
|
|
|
|
state = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else if (state == 8) { |
|
|
|
|
if (token[cursor] == '(') { |
|
|
|
|
parenLevel++; |
|
|
|
|
} else |
|
|
|
|
if (token[cursor] == ')') { |
|
|
|
|
parenLevel--; |
|
|
|
|
if (!parenLevel) { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor; |
|
|
|
|
expression_parts.push_back(")"); |
|
|
|
|
state = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else if (state == 9) { |
|
|
|
|
if (token[cursor] == '?') { |
|
|
|
|
trinaryLevel++; |
|
|
|
|
} else |
|
|
|
|
if (token[cursor] == ':') { |
|
|
|
|
trinaryLevel--; |
|
|
|
|
if (!trinaryLevel) { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back(":"); |
|
|
|
|
state = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void parseArray(js_scope &rootScope, std::string token) { |
|
|
|
|
std::vector<std::string> json_keys; |
|
|
|
|
std::vector<std::string> json_values; |
|
|
|
|
size_t cursor; |
|
|
|
|
size_t last = 0; |
|
|
|
|
size_t quoteStart = 0; |
|
|
|
|
size_t quoteEnd = 0; |
|
|
|
|
size_t parenStart = 0; |
|
|
|
|
size_t parenLevel = 0; |
|
|
|
|
unsigned char state = 0; |
|
|
|
|
for (cursor = 0; cursor < token.length(); cursor++) { |
|
|
|
|
// we should only look for [:'"]
|
|
|
|
|
if (state == 0) { |
|
|
|
|
switch(token[cursor]) { |
|
|
|
|
// { or [ could be expression parsed I think...
|
|
|
|
|
case '\'': |
|
|
|
|
quoteStart = cursor; |
|
|
|
|
state = 4; |
|
|
|
|
break; |
|
|
|
|
case '"': |
|
|
|
|
quoteStart = cursor; |
|
|
|
|
state = 5; |
|
|
|
|
break; |
|
|
|
|
case ',': |
|
|
|
|
std::string key = ""; |
|
|
|
|
if (quoteStart) { |
|
|
|
|
// constant
|
|
|
|
|
key = token.substr(quoteStart + 1, quoteEnd - quoteStart); // skip the quotes
|
|
|
|
|
} else { |
|
|
|
|
// variable
|
|
|
|
|
key = token.substr(last, cursor - last); |
|
|
|
|
} |
|
|
|
|
key = trim(key); |
|
|
|
|
std::cout << "element[" << key << "] quoted: " << quoteStart << std::endl; |
|
|
|
|
json_keys.push_back(key); |
|
|
|
|
last = cursor + 1; |
|
|
|
|
state = 2; |
|
|
|
|
quoteStart = 0; |
|
|
|
|
quoteEnd = 0; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} else if (state == 2) { // get value state
|
|
|
|
|
// now we haven't to make sure we don't enter {, } or function
|
|
|
|
|
// ', " are ok, but have to turn off parsing until we encounter the next
|
|
|
|
|
// a-zA-Z$ for variables assignment
|
|
|
|
|
switch(state) { |
|
|
|
|
case 0: |
|
|
|
|
switch(token[cursor]) { |
|
|
|
|
case '{': |
|
|
|
|
parenStart = cursor; |
|
|
|
|
parenLevel++; |
|
|
|
|
state = 1; |
|
|
|
|
break; |
|
|
|
|
case '[': |
|
|
|
|
parenStart = cursor; |
|
|
|
|
parenLevel++; |
|
|
|
|
state = 2; |
|
|
|
|
break; |
|
|
|
|
case '\'': |
|
|
|
|
quoteStart = cursor; |
|
|
|
|
state = 4; |
|
|
|
|
break; |
|
|
|
|
case '"': |
|
|
|
|
quoteStart = cursor; |
|
|
|
|
state = 5; |
|
|
|
|
break; |
|
|
|
|
case ',': |
|
|
|
|
std::string value = ""; |
|
|
|
|
if (quoteStart) { |
|
|
|
|
value = token.substr(quoteStart + 1, quoteEnd - quoteStart); // skip the quotes
|
|
|
|
|
} else { |
|
|
|
|
value = token.substr(last, cursor - last); |
|
|
|
|
value = trim(value); |
|
|
|
|
} |
|
|
|
|
std::cout << "value[" << value << "] quoted" << quoteStart << std::endl; |
|
|
|
|
// JSON objects will already be assigned and empty
|
|
|
|
|
if (value != "") { |
|
|
|
|
json_values.push_back(value); |
|
|
|
|
js_string *newString = new js_string(); |
|
|
|
|
newString->value = value; |
|
|
|
|
rootScope.data[json_keys.back()] = *newString; |
|
|
|
|
} |
|
|
|
|
last = cursor + 1; |
|
|
|
|
state = 0; |
|
|
|
|
quoteStart = 0; |
|
|
|
|
quoteEnd = 0; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case 1: |
|
|
|
|
switch(token[cursor]) { |
|
|
|
|
case '{': |
|
|
|
|
parenLevel++; |
|
|
|
|
break; |
|
|
|
|
case '}': |
|
|
|
|
parenLevel--; |
|
|
|
|
if (!parenLevel) { |
|
|
|
|
std::string JSON = token.substr(parenStart + 1, cursor - parenStart); |
|
|
|
|
std::cout << "Need to deJSON [" << JSON << "]" << std::endl; |
|
|
|
|
// well we can get a scope back
|
|
|
|
|
js_scope *objectScope = new js_scope; |
|
|
|
|
parseJSON(*objectScope, JSON); |
|
|
|
|
js_object *newObject = new js_object; |
|
|
|
|
rootScope.data[json_keys.back()] = *newObject; |
|
|
|
|
last = cursor + 1; |
|
|
|
|
state = 0; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case 2: |
|
|
|
|
switch(token[cursor]) { |
|
|
|
|
case '[': |
|
|
|
|
parenLevel++; |
|
|
|
|
break; |
|
|
|
|
case ']': |
|
|
|
|
parenLevel--; |
|
|
|
|
if (!parenLevel) { |
|
|
|
|
std::string JSON = token.substr(parenStart + 1, cursor - parenStart); |
|
|
|
|
std::cout << "Need to deArray [" << JSON << "]" << std::endl; |
|
|
|
|
// well we can get a scope back
|
|
|
|
|
js_scope *objectScope = new js_scope; |
|
|
|
|
parseJSON(*objectScope, JSON); |
|
|
|
|
js_object *newObject = new js_object; |
|
|
|
|
rootScope.data[json_keys.back()] = *newObject; |
|
|
|
|
last = cursor + 1; |
|
|
|
|
state = 0; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case 4: |
|
|
|
|
if (token[cursor] == '\'') { |
|
|
|
|
if (token[cursor - 1] != '\\') { |
|
|
|
|
quoteEnd = cursor - 1; |
|
|
|
|
state = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case 5: |
|
|
|
|
if (token[cursor] == '"') { |
|
|
|
|
if (token[cursor - 1] != '\\') { |
|
|
|
|
quoteEnd = cursor - 1; |
|
|
|
|
state = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} else if (state == 4) { |
|
|
|
|
if (token[cursor] == '\'') { |
|
|
|
|
if (token[cursor - 1] != '\\') { |
|
|
|
|
quoteEnd = cursor - 1; |
|
|
|
|
state = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else if (state == 5) { |
|
|
|
|
if (token[cursor] == '"') { |
|
|
|
|
if (token[cursor - 1] != '\\') { |
|
|
|
|
quoteEnd = cursor - 1; |
|
|
|
|
state = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// we handle right value
|
|
|
|
|
// we could be in JSON { key:
|
|
|
|
|
// we could be in variable bob=
|
|
|
|
|
// token: we have a complete expression
|
|
|
|
|
// if right is:
|
|
|
|
|
// - object
|
|
|
|
|
// - array
|
|
|
|
|
// - string
|
|
|
|
|
// - function
|
|
|
|
|
// we could avoid returning, if a pointer to the lvalue is passed in
|
|
|
|
|
js_internal_storage *parseExpression(js_scope &rootScope, std::string token) { |
|
|
|
|
js_internal_storage *returnValue = nullptr; |
|
|
|
|
size_t cursor; |
|
|
|
|
size_t last = 0; |
|
|
|
|
size_t quoteStart = 0; |
|
|
|
|
size_t quoteEnd = 0; |
|
|
|
|
size_t parenStart = 0; |
|
|
|
|
size_t parenLevel = 0; |
|
|
|
|
unsigned char state = 0; |
|
|
|
|
for (cursor = 0; cursor < token.length(); cursor++) { |
|
|
|
|
// now we haven't to make sure we don't enter {, } or function
|
|
|
|
|
// ', " are ok, but have to turn off parsing until we encounter the next
|
|
|
|
|
// a-zA-Z$ for variables assignment
|
|
|
|
|
switch(state) { |
|
|
|
|
case 0: |
|
|
|
|
switch(token[cursor]) { |
|
|
|
|
case '{': |
|
|
|
|
parenStart = cursor; |
|
|
|
|
parenLevel++; |
|
|
|
|
state = 1; |
|
|
|
|
break; |
|
|
|
|
case '[': |
|
|
|
|
parenStart = cursor; |
|
|
|
|
parenLevel++; |
|
|
|
|
state = 2; |
|
|
|
|
break; |
|
|
|
|
case '\'': |
|
|
|
|
quoteStart = cursor; |
|
|
|
|
state = 4; |
|
|
|
|
break; |
|
|
|
|
case '"': |
|
|
|
|
quoteStart = cursor; |
|
|
|
|
state = 5; |
|
|
|
|
break; |
|
|
|
|
case ',': |
|
|
|
|
std::string value = ""; |
|
|
|
|
if (quoteStart) { |
|
|
|
|
value = token.substr(quoteStart + 1, quoteEnd - quoteStart); // skip the quotes
|
|
|
|
|
} else { |
|
|
|
|
value = token.substr(last, cursor - last); |
|
|
|
|
value = trim(value); |
|
|
|
|
} |
|
|
|
|
std::cout << "value[" << value << "] quoted" << quoteStart << std::endl; |
|
|
|
|
// JSON objects will already be assigned and empty
|
|
|
|
|
if (value != "") { |
|
|
|
|
js_string *newString = new js_string(); |
|
|
|
|
newString->value = value; |
|
|
|
|
} |
|
|
|
|
last = cursor + 1; |
|
|
|
|
state = 0; |
|
|
|
|
quoteStart = 0; |
|
|
|
|
quoteEnd = 0; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case 1: |
|
|
|
|
switch(token[cursor]) { |
|
|
|
|
case '{': |
|
|
|
|
parenLevel++; |
|
|
|
|
break; |
|
|
|
|
case '}': |
|
|
|
|
parenLevel--; |
|
|
|
|
if (!parenLevel) { |
|
|
|
|
std::string JSON = token.substr(parenStart + 1, cursor - parenStart); |
|
|
|
|
std::cout << "Need to deJSON [" << JSON << "]" << std::endl; |
|
|
|
|
// well we can get a scope back
|
|
|
|
|
js_scope *objectScope = new js_scope; |
|
|
|
|
parseJSON(*objectScope, JSON); |
|
|
|
|
//js_object *newObject = new js_object;
|
|
|
|
|
//rootScope.data[json_keys.back()] = *newObject;
|
|
|
|
|
last = cursor + 1; |
|
|
|
|
state = 0; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case 2: |
|
|
|
|
switch(token[cursor]) { |
|
|
|
|
case '[': |
|
|
|
|
parenLevel++; |
|
|
|
|
break; |
|
|
|
|
case ']': |
|
|
|
|
parenLevel--; |
|
|
|
|
if (!parenLevel) { |
|
|
|
|
std::string arrayStr = token.substr(parenStart + 1, cursor - parenStart); |
|
|
|
|
std::cout << "Need to deArray [" << arrayStr << "]" << std::endl; |
|
|
|
|
// well we can get a scope back
|
|
|
|
|
js_scope *objectScope = new js_scope; |
|
|
|
|
parseArray(*objectScope, arrayStr); |
|
|
|
|
js_object *newObject = new js_object; |
|
|
|
|
//rootScope.data[json_keys.back()] = *newObject;
|
|
|
|
|
last = cursor + 1; |
|
|
|
|
state = 0; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case 4: |
|
|
|
|
if (token[cursor] == '\'') { |
|
|
|
|
if (token[cursor - 1] != '\\') { |
|
|
|
|
quoteEnd = cursor - 1; |
|
|
|
|
state = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case 5: |
|
|
|
|
if (token[cursor] == '"') { |
|
|
|
|
if (token[cursor - 1] != '\\') { |
|
|
|
|
quoteEnd = cursor - 1; |
|
|
|
|
state = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return returnValue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void parseJSON(js_scope &rootScope, std::string token) { |
|
|
|
|
std::vector<std::string> json_keys; |
|
|
|
|
std::vector<std::string> json_values; |
|
|
|
|
size_t cursor; |
|
|
|
|
size_t last = 0; |
|
|
|
|
size_t quoteStart = 0; |
|
|
|
|
size_t quoteEnd = 0; |
|
|
|
|
size_t parenStart = 0; |
|
|
|
|
size_t parenLevel = 0; |
|
|
|
|
unsigned char keyState = 0; |
|
|
|
|
unsigned char valueState = 0; |
|
|
|
|
for (cursor = 0; cursor < token.length(); cursor++) { |
|
|
|
|
// we should only look for [:'"]
|
|
|
|
|
if (keyState == 0) { |
|
|
|
|
switch(token[cursor]) { |
|
|
|
|
case '\'': |
|
|
|
|
quoteStart = cursor; |
|
|
|
|
keyState = 4; |
|
|
|
|
break; |
|
|
|
|
case '"': |
|
|
|
|
quoteStart = cursor; |
|
|
|
|
keyState = 5; |
|
|
|
|
break; |
|
|
|
|
case ':': |
|
|
|
|
std::string key = ""; |
|
|
|
|
if (quoteStart) { |
|
|
|
|
key = token.substr(quoteStart + 1, quoteEnd - quoteStart); // skip the quotes
|
|
|
|
|
} else { |
|
|
|
|
key = token.substr(last, cursor - last); |
|
|
|
|
} |
|
|
|
|
key = trim(key); |
|
|
|
|
std::cout << "key[" << key << "] quoted: " << quoteStart << std::endl; |
|
|
|
|
json_keys.push_back(key); |
|
|
|
|
last = cursor + 1; |
|
|
|
|
keyState = 2; |
|
|
|
|
quoteStart = 0; |
|
|
|
|
quoteEnd = 0; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} else if (keyState == 2) { // get value state
|
|
|
|
|
// now we haven't to make sure we don't enter {, } or function
|
|
|
|
|
// ', " are ok, but have to turn off parsing until we encounter the next
|
|
|
|
|
// a-zA-Z$ for variables assignment
|
|
|
|
|
switch(valueState) { |
|
|
|
|
case 0: |
|
|
|
|
switch(token[cursor]) { |
|
|
|
|
case '{': |
|
|
|
|
parenStart = cursor; |
|
|
|
|
parenLevel++; |
|
|
|
|
valueState = 1; |
|
|
|
|
break; |
|
|
|
|
case '[': |
|
|
|
|
parenStart = cursor; |
|
|
|
|
parenLevel++; |
|
|
|
|
valueState = 2; |
|
|
|
|
break; |
|
|
|
|
case '\'': |
|
|
|
|
quoteStart = cursor; |
|
|
|
|
valueState = 4; |
|
|
|
|
break; |
|
|
|
|
case '"': |
|
|
|
|
quoteStart = cursor; |
|
|
|
|
valueState = 5; |
|
|
|
|
break; |
|
|
|
|
case ',': |
|
|
|
|
std::string value = ""; |
|
|
|
|
if (quoteStart) { |
|
|
|
|
value = token.substr(quoteStart + 1, quoteEnd - quoteStart); // skip the quotes
|
|
|
|
|
} else { |
|
|
|
|
value = token.substr(last, cursor - last); |
|
|
|
|
value = trim(value); |
|
|
|
|
} |
|
|
|
|
std::cout << "value[" << value << "] quoted" << quoteStart << std::endl; |
|
|
|
|
// JSON objects will already be assigned and empty
|
|
|
|
|
if (value != "") { |
|
|
|
|
json_values.push_back(value); |
|
|
|
|
js_string *newString = new js_string(); |
|
|
|
|
newString->value = value; |
|
|
|
|
rootScope.data[json_keys.back()] = *newString; |
|
|
|
|
} |
|
|
|
|
last = cursor + 1; |
|
|
|
|
keyState = 0; |
|
|
|
|
quoteStart = 0; |
|
|
|
|
quoteEnd = 0; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case 1: |
|
|
|
|
switch(token[cursor]) { |
|
|
|
|
case '{': |
|
|
|
|
parenLevel++; |
|
|
|
|
break; |
|
|
|
|
case '}': |
|
|
|
|
parenLevel--; |
|
|
|
|
if (!parenLevel) { |
|
|
|
|
std::string JSON = token.substr(parenStart + 1, cursor - parenStart); |
|
|
|
|
std::cout << "Need to deJSON [" << JSON << "]" << std::endl; |
|
|
|
|
// well we can get a scope back
|
|
|
|
|
js_scope *objectScope = new js_scope; |
|
|
|
|
parseJSON(*objectScope, JSON); |
|
|
|
|
js_object *newObject = new js_object; |
|
|
|
|
rootScope.data[json_keys.back()] = *newObject; |
|
|
|
|
last = cursor + 1; |
|
|
|
|
valueState = 0; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case 2: |
|
|
|
|
switch(token[cursor]) { |
|
|
|
|
case '[': |
|
|
|
|
parenLevel++; |
|
|
|
|
break; |
|
|
|
|
case ']': |
|
|
|
|
parenLevel--; |
|
|
|
|
if (!parenLevel) { |
|
|
|
|
std::string arrayStr = token.substr(parenStart + 1, cursor - parenStart); |
|
|
|
|
std::cout << "Need to deArray [" << arrayStr << "]" << std::endl; |
|
|
|
|
// well we can get a scope back
|
|
|
|
|
js_scope *objectScope = new js_scope; |
|
|
|
|
parseArray(*objectScope, arrayStr); |
|
|
|
|
js_object *newObject = new js_object; |
|
|
|
|
rootScope.data[json_keys.back()] = *newObject; |
|
|
|
|
last = cursor + 1; |
|
|
|
|
valueState = 0; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case 4: |
|
|
|
|
if (token[cursor] == '\'') { |
|
|
|
|
if (token[cursor - 1] != '\\') { |
|
|
|
|
quoteEnd = cursor - 1; |
|
|
|
|
valueState = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case 5: |
|
|
|
|
if (token[cursor] == '"') { |
|
|
|
|
if (token[cursor - 1] != '\\') { |
|
|
|
|
quoteEnd = cursor - 1; |
|
|
|
|
valueState = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} else if (keyState == 4) { |
|
|
|
|
if (token[cursor] == '\'') { |
|
|
|
|
if (token[cursor - 1] != '\\') { |
|
|
|
|
quoteEnd = cursor - 1; |
|
|
|
|
keyState = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else if (keyState == 5) { |
|
|
|
|
if (token[cursor] == '"') { |
|
|
|
|
if (token[cursor - 1] != '\\') { |
|
|
|
|
quoteEnd = cursor - 1; |
|
|
|
|
keyState = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool doAssignment(js_scope &rootScope, std::string token) { |
|
|
|
|
// FIXME: make sure = isn't in quotes or JSON?
|
|
|
|
|
// FIXME: double or triple equal differentiation
|
|
|
|
@ -181,7 +859,11 @@ bool doAssignment(js_scope &rootScope, std::string token) {
@@ -181,7 +859,11 @@ bool doAssignment(js_scope &rootScope, std::string token) {
|
|
|
|
|
// +, -
|
|
|
|
|
// *, /, %
|
|
|
|
|
// ?, >>, <<
|
|
|
|
|
|
|
|
|
|
if (token[cursor] == 'f' && token.length() > cursor + 7 && token[cursor + 1] == 'u' |
|
|
|
|
&& token[cursor + 2] == 'n' && token[cursor + 3] == 'c' && token[cursor + 4] == 't' |
|
|
|
|
&& token[cursor + 5] == 'i' && token[cursor + 6] == 'o' && token[cursor + 7] == 'n') { |
|
|
|
|
state = 3; |
|
|
|
|
} |
|
|
|
|
if (token[cursor] == '\'') { |
|
|
|
|
quoteStart = cursor; |
|
|
|
|
state = 4; |
|
|
|
@ -219,6 +901,12 @@ bool doAssignment(js_scope &rootScope, std::string token) {
@@ -219,6 +901,12 @@ bool doAssignment(js_scope &rootScope, std::string token) {
|
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back("="); |
|
|
|
|
} |
|
|
|
|
// hack for JSON parsing
|
|
|
|
|
if (token[cursor] == ':') { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back("="); |
|
|
|
|
state = 2; |
|
|
|
|
} |
|
|
|
|
// ||
|
|
|
|
|
if (token[cursor] == '|' && token.length() > cursor + 1 && token[cursor + 1] == '|') { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
@ -236,11 +924,11 @@ bool doAssignment(js_scope &rootScope, std::string token) {
@@ -236,11 +924,11 @@ bool doAssignment(js_scope &rootScope, std::string token) {
|
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back("<"); |
|
|
|
|
} |
|
|
|
|
if (token[cursor] == '<' && token.length() > cursor + 1 && token[cursor + 1] == '&') { |
|
|
|
|
if (token[cursor] == '<' && token.length() > cursor + 1 && token[cursor + 1] == '=') { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back("<="); |
|
|
|
|
} |
|
|
|
|
if (token[cursor] == '>' && token.length() > cursor + 1 && token[cursor + 1] == '&') { |
|
|
|
|
if (token[cursor] == '>' && token.length() > cursor + 1 && token[cursor + 1] == '=') { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; |
|
|
|
|
expression_parts.push_back(">="); |
|
|
|
|
} |
|
|
|
@ -301,6 +989,20 @@ bool doAssignment(js_scope &rootScope, std::string token) {
@@ -301,6 +989,20 @@ bool doAssignment(js_scope &rootScope, std::string token) {
|
|
|
|
|
state = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else if (state == 2) { // json state (can be moved)
|
|
|
|
|
if (token[cursor] == ',') { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); |
|
|
|
|
last = cursor + 1; |
|
|
|
|
state = 0; |
|
|
|
|
} |
|
|
|
|
} else if (state == 3) { // function start (can be moved)
|
|
|
|
|
if (token[cursor] == '{') { |
|
|
|
|
// lets put the function prototype
|
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); |
|
|
|
|
last = cursor + 1; |
|
|
|
|
parenLevel++; |
|
|
|
|
state = 6; // move to the function body
|
|
|
|
|
} |
|
|
|
|
} else if (state == 4) { |
|
|
|
|
if (token[cursor] == '\'') { |
|
|
|
|
if (token[cursor - 1] != '\\') { |
|
|
|
@ -319,6 +1021,19 @@ bool doAssignment(js_scope &rootScope, std::string token) {
@@ -319,6 +1021,19 @@ bool doAssignment(js_scope &rootScope, std::string token) {
|
|
|
|
|
state = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else if (state == 6) { |
|
|
|
|
if (token[cursor] == '{') { |
|
|
|
|
parenLevel++; |
|
|
|
|
} else |
|
|
|
|
if (token[cursor] == '}') { |
|
|
|
|
parenLevel--; |
|
|
|
|
if (!parenLevel) { |
|
|
|
|
expression_parts.push_back(token.substr(last, cursor - last)); |
|
|
|
|
last = cursor + 1; |
|
|
|
|
expression_parts.push_back("}"); // end function
|
|
|
|
|
state = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else if (state == 8) { |
|
|
|
|
if (token[cursor] == '(') { |
|
|
|
|
parenLevel++; |
|
|
|
@ -345,20 +1060,79 @@ bool doAssignment(js_scope &rootScope, std::string token) {
@@ -345,20 +1060,79 @@ bool doAssignment(js_scope &rootScope, std::string token) {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
std::cout << "ending state " << state << std::endl; |
|
|
|
|
//std::cout << "ending state " << state << std::endl;
|
|
|
|
|
if (last != token.length()) { |
|
|
|
|
expression_parts.push_back(token.substr(last, token.length())); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::cout << "expression token[" << token << "]" << std::endl; |
|
|
|
|
std::cout << "expression string[" << token << "]" << std::endl; |
|
|
|
|
std::cout << "expression debug" << std::endl; |
|
|
|
|
std::string lastToken = ""; |
|
|
|
|
state = 0; |
|
|
|
|
std::string left = ""; |
|
|
|
|
if (expression_parts.size() == 1) { |
|
|
|
|
// usually just a variable declaration
|
|
|
|
|
std::string tLeft = trim(expression_parts[0]); |
|
|
|
|
if (tLeft[0]=='"' && tLeft[tLeft.length() - 1]=='"') { |
|
|
|
|
//std::cout << "dequoting[" << tLeft << "]" << std::endl;
|
|
|
|
|
tLeft=tLeft.substr(1, tLeft.length() - 2); |
|
|
|
|
} |
|
|
|
|
std::cout << "Assigning [" << tLeft << "=]" << std::endl; |
|
|
|
|
rootScope.variables[tLeft] = ""; |
|
|
|
|
std::cout << "expression end" << std::endl << std::endl; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
for(auto it : expression_parts) { |
|
|
|
|
// probably should trim these
|
|
|
|
|
std::cout << "[" << it << "]" << std::endl; |
|
|
|
|
std::cout << "expression token[" << it << "]" << std::to_string(state) << std::endl; |
|
|
|
|
// default: put token in left, get op (usually =) and then get right side
|
|
|
|
|
if (state==0) { |
|
|
|
|
if (it == "=") { |
|
|
|
|
left = lastToken; |
|
|
|
|
state = 1; |
|
|
|
|
} |
|
|
|
|
} else if (state == 1) { |
|
|
|
|
if (it == "") continue; // skip empties, don't fire the assignment too early
|
|
|
|
|
// do assignment
|
|
|
|
|
if (it == "{") { |
|
|
|
|
// FIXME: make sure it's not a function definition!
|
|
|
|
|
// could be JSON or a scope
|
|
|
|
|
state = 2; |
|
|
|
|
} else { |
|
|
|
|
// FIXME: figure out what type it is
|
|
|
|
|
//rootScope.data[trim(left)] = it;
|
|
|
|
|
std::string tLeft = trim(left); |
|
|
|
|
std::string value = trim(it); |
|
|
|
|
//std::cout << "left[" << tLeft[0] << "] right[" << tLeft[tLeft.length() - 1] << "]" << std::endl;
|
|
|
|
|
if (tLeft[0]=='"' && tLeft[tLeft.length() - 1]=='"') { |
|
|
|
|
//std::cout << "dequoting[" << tLeft << "]" << std::endl;
|
|
|
|
|
tLeft=tLeft.substr(1, tLeft.length() - 2); |
|
|
|
|
} |
|
|
|
|
rootScope.variables[tLeft] = value; |
|
|
|
|
std::cout << "Assigning [" << tLeft << "=" << value << "]" << std::endl; |
|
|
|
|
state = 0; |
|
|
|
|
} |
|
|
|
|
} else if (state == 2) { |
|
|
|
|
js_scope *objectScope = new js_scope; |
|
|
|
|
//doAssignment(*objectScope, it);
|
|
|
|
|
parseJSON(*objectScope, it); |
|
|
|
|
// translate the scope into js_object
|
|
|
|
|
//std::cout << "JSON object output" << std::endl;
|
|
|
|
|
js_object *newObject = new js_object; |
|
|
|
|
for(auto it2 : objectScope->variables) { |
|
|
|
|
//std::cout << "[" << it2.first << "=" << it2.second << "]" << std::endl;
|
|
|
|
|
//newObject->value[it2.first] = //
|
|
|
|
|
} |
|
|
|
|
//std::cout << "JSON object done" << std::endl;
|
|
|
|
|
rootScope.data[left] = *newObject; |
|
|
|
|
state = 0; |
|
|
|
|
} |
|
|
|
|
// { starts JSON capture (should be exactly one block before the } token)
|
|
|
|
|
// you create a scope for that variable and recurse
|
|
|
|
|
lastToken = it; |
|
|
|
|
} |
|
|
|
|
std::cout << "expression end" << std::endl; |
|
|
|
|
|
|
|
|
|
std::cout << "expression end" << std::endl << std::endl; |
|
|
|
|
/*
|
|
|
|
|
auto hasTripleEqual = token.find("==="); |
|
|
|
|
auto hasDoubleEqual = std::string::npos; |
|
|
|
|
auto hasSingleEqual = std::string::npos; |
|
|
|
@ -391,6 +1165,7 @@ bool doAssignment(js_scope &rootScope, std::string token) {
@@ -391,6 +1165,7 @@ bool doAssignment(js_scope &rootScope, std::string token) {
|
|
|
|
|
// var bob; just make sure the variable exists
|
|
|
|
|
rootScope.variables[token] = ""; |
|
|
|
|
} |
|
|
|
|
*/ |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|