From 79bd205eb768fcece6af5118f91ae0f364417b2d Mon Sep 17 00:00:00 2001 From: Odilitime Date: Thu, 1 Feb 2018 04:23:07 -0800 Subject: [PATCH] doFunctionCall() actually return return value, doExpression() handle ) only once / if func value hang around to see if it's called first before changing stack, parseJSON wait for , before reseting keyState, doAssignment() check to see if func is called before setting stack, JavaScript::parse() disable debug --- src/parsers/scripting/javascript/JSParser.cpp | 170 ++++++++++++++++++++++---- 1 file changed, 147 insertions(+), 23 deletions(-) diff --git a/src/parsers/scripting/javascript/JSParser.cpp b/src/parsers/scripting/javascript/JSParser.cpp index 9bda930..b2c4cbf 100644 --- a/src/parsers/scripting/javascript/JSParser.cpp +++ b/src/parsers/scripting/javascript/JSParser.cpp @@ -285,8 +285,7 @@ js_internal_storage *doFunctionCall(js_function *func, std::string params, js_fu std::cout << "passed null into doFunctionCall\n"; return nullptr; } - jsParseTokens(func->tokens, &scope); - return nullptr; + return jsParseTokens(func->tokens, &scope); } // this should evaluate an expression and return it's return value @@ -303,6 +302,7 @@ js_internal_storage *doExpression(js_function &rootScope, std::string token) { std::cout << "doExpression start[" << token << "]\n"; // parse expression for (cursor = 0; cursor < token.length(); cursor++) { + std::cout << "doExpression parse phase state[" << std::to_string(state) << "] char[" << token[cursor] << "]\n"; if (state == 0) { // || // && @@ -497,7 +497,7 @@ js_internal_storage *doExpression(js_function &rootScope, std::string token) { if (token[cursor] == ')') { parenLevel--; if (!parenLevel) { - expression_parts.push_back(token.substr(last, cursor - last)); last = cursor; + expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1; expression_parts.push_back(")"); state = 0; } @@ -526,13 +526,16 @@ js_internal_storage *doExpression(js_function &rootScope, std::string token) { std::cout << "doExpression has [" << expression_parts.size() << "]parts\n"; js_internal_storage *stack = nullptr; state = 0; - std::string callFunc = ""; + std::string callFuncName = ""; + js_function *callFunc = nullptr; std::string params = ""; //js_function *func = nullptr; + size_t i = 0; for(auto it : expression_parts) { std::string trimmedToken = trim(it); + i++; if (trimmedToken == "") continue; - std::cout << "doExpression part[" << it << "] state[" << std::to_string(state) << "]\n"; + std::cout << "doExpression part[" << (i - 1) << "][" << it << "] state[" << std::to_string(state) << "]\n"; if (state == 0) { // && if (trimmedToken == "&&") { @@ -594,6 +597,7 @@ js_internal_storage *doExpression(js_function &rootScope, std::string token) { if (trimmedToken == "(") { // function call std::cout << "func call param start\n"; + state = 2; continue; } @@ -620,11 +624,16 @@ js_internal_storage *doExpression(js_function &rootScope, std::string token) { // object.property js_internal_storage *dereferenceTest = dereferenceObject(trimmedToken, &rootScope); if (dereferenceTest) { - stack = dereferenceTest; - if (typeOfStorage(stack)=="func") { + if (typeOfStorage(dereferenceTest)=="func") { // it could be a call... - callFunc = it; + callFuncName = it; + callFunc = dynamic_cast(dereferenceTest); + if (!callFunc) { + std::cout << "Couldnt cast deference to func\n"; + } state = 1; + } else { + stack = dereferenceTest; } continue; } @@ -677,14 +686,16 @@ js_internal_storage *doExpression(js_function &rootScope, std::string token) { js_internal_storage **isVar = getObjectKeyPointer(it, &rootScope); if (isVar != nullptr) { std::cout << "isVar [" << isVar << "]\n"; - stack = *isVar; // set stack to point to this variable - std::cout << "stack is [" << stack << "] type[" << typeOfStorage(stack) << "]\n"; + std::cout << "stack could be [" << *isVar << "] type[" << typeOfStorage(stack) << "]\n"; if (typeOfStorage(stack)=="func") { - callFunc = it; + callFuncName = it; + callFunc = dynamic_cast(dereferenceTest); state = 1; // ( // 1 // ) + } else { + stack = *isVar; // set stack to point to this variable } /* if (typeOfStorage(stack)=="string") { @@ -706,7 +717,9 @@ js_internal_storage *doExpression(js_function &rootScope, std::string token) { if (it == "(") { state = 2; } else { - std::cout << "func call did not have (\n"; + std::cout << "doExpression1 - func call did not have (\n"; + std::cout << "doExpression1 - stack is [" << stack << "] will now have to set it to [" << callFunc << "]\n"; + stack = callFunc; state = 0; } } else if (state == 2) { @@ -715,16 +728,24 @@ js_internal_storage *doExpression(js_function &rootScope, std::string token) { } else if (state == 3) { // in func call, double check the ) if (it == ")") { + /* js_function *jfunc = dynamic_cast(stack); if (!jfunc) { std::cout << "Could cast [" << stack << "] to func\n"; continue; } - std::cout << "calling [" << callFunc << "](" << params << ") at [" << jfunc << "] with [" << jfunc->tokens.size() << "]tokens\n"; - stack = doFunctionCall(jfunc, params, rootScope); + */ + if (!callFunc) { + std::cout << "HALT callFunc is null!\n"; + continue; + } + std::cout << "doExpression3 - calling [" << callFuncName << "](" << params << ") at [" << callFunc << "] with [" << callFunc->tokens.size() << "]tokens\n"; + stack = doFunctionCall(callFunc, params, rootScope); state = 0; } else { - std::cout << "func call did not have (\n"; + std::cout << "doExpression3 - func call did not have (\n"; + std::cout << "doExpression3 - stack is [" << stack << "] will now have to set it to [" << callFunc << "]\n"; + stack = callFunc; state = 0; } } else if (state == 4) { @@ -754,6 +775,16 @@ js_internal_storage *doExpression(js_function &rootScope, std::string token) { } } // FIXME: any remainder? + if (state == 1) { + // x = func ref that's never called + std::cout << "doExpressionEND1 - func call did not have (\n"; + std::cout << "doExpressionEND1 - stack is [" << stack << "] will now have to set it to [" << callFunc << "]\n"; + stack = callFunc; + state = 0; + } + if (state != 0) { + std::cout << "doExpression final state[" << std::to_string(state) << "]\n"; + } return stack; } @@ -1552,6 +1583,7 @@ void parseJSON(js_function &rootScope, std::string token) { } } last = cursor + 1; + std::cout << "remainder last now points to[" << token[last] << "] should not be comma\n"; keyState = 0; valueState = 0; quoteStart = 0; @@ -1577,7 +1609,7 @@ void parseJSON(js_function &rootScope, std::string token) { rootScope.locals.value[json_keys.back()] = newObject; last = cursor + 1; valueState = 0; - keyState = 0; + // let keyState 2 finish it out } break; } @@ -2028,10 +2060,12 @@ bool doAssignment(js_function &rootScope, std::string token) { } bool negate = false; js_function *func = nullptr; + js_function *callFunc = nullptr; std::string prototype = ""; + std::string params = ""; for(auto it : expression_parts) { // probably should trim these - std::cout << std::string(doAssignmentLevel * 2, ' ') << "expression(" << doAssignmentLevel << ") token[" << it << "]" << std::to_string(state) << std::endl; + std::cout << std::string(doAssignmentLevel * 2, ' ') << "doAssignment expression(" << doAssignmentLevel << ") token[" << it << "]" << std::to_string(state) << std::endl; // default: put token in left, get op (usually =) and then get right side if (state==0) { negate = false; @@ -2067,16 +2101,32 @@ bool doAssignment(js_function &rootScope, std::string token) { } } else if (state == 1) { if (it == "") continue; // skip empties, don't fire the assignment too early + if (it == " ") continue; // skip empties, don't fire the assignment too early + if (it == "!") continue; // valid expression + if (it == "}") continue; // valid part of an expression (why are we getting this, should have a starting { and be in state 2) + // so these next 2 execute a function that's on the stack + // state 0: elem = + // state 1: funcName,(,proto,),; + if (it == "(") continue; // valid part of an expression + if (it == ")") continue; // valid part of an expression + if (it == "&&") continue; // valid part of an expression if (it == "{") { state = 2; } else { - std::string tLeft = trim(left); - if (tLeft[0]=='"' && tLeft[tLeft.length() - 1]=='"') { - //std::cout << "dequoting[" << tLeft << "]" << std::endl; - tLeft=tLeft.substr(1, tLeft.length() - 2); - } + js_internal_storage *storage = doExpression(rootScope, it); if (storage) { + js_function *funcTest = dynamic_cast(storage); + if (funcTest) { + callFunc = funcTest; + state = 9; + continue; + } + std::string tLeft = trim(left); + if (tLeft[0]=='"' && tLeft[tLeft.length() - 1]=='"') { + //std::cout << "dequoting[" << tLeft << "]" << std::endl; + tLeft=tLeft.substr(1, tLeft.length() - 2); + } bool alreadySet = false; size_t dotPos = tLeft.find('.'); @@ -2212,6 +2262,79 @@ bool doAssignment(js_function &rootScope, std::string token) { // call params std::cout << std::string(doAssignmentLevel * 2, ' ') << "HALT need to parse these params[" << it << "]\n"; } + } else if (state == 9) { // are we a function call with return value, or assigning a function reference + js_internal_storage *storage = nullptr; + // we'll need a way to get tLeft back to set it + if (it == "(") { + // it's a function call + // set state = 10 until we get all prototype + state = 10; + //storage = jsParseTokens(callFunc->tokens, callFunc); + } else { + // it's a function reference + storage = callFunc; + state = 0; // assuming end of this expression + } + if (storage) { + std::string tLeft = trim(left); + if (tLeft[0]=='"' && tLeft[tLeft.length() - 1]=='"') { + //std::cout << "dequoting[" << tLeft << "]" << std::endl; + tLeft=tLeft.substr(1, tLeft.length() - 2); + } + bool alreadySet = false; + + size_t dotPos = tLeft.find('.'); + if (dotPos != std::string::npos) { + js_internal_storage **key = getObjectKeyPointer(tLeft, &rootScope); + if (key != nullptr) { + alreadySet = true; + *key = storage; + } + } + if (!alreadySet) { + std::cout << "doAssignment final assign[" << tLeft << "] of type[" << typeOfStorage(storage) << "] scope[" << &rootScope << "]\n"; + rootScope.locals.value[tLeft] = storage; + jsDisplayScope(&rootScope, 0); + left = ""; // reset left + assignfile << tLeft << "=" << it << "\n"; + } + } + } else if (state == 10) { // in function call params + if (it == ")") { + // use doFunctionCall + js_internal_storage *storage = nullptr; + std::cout << "calling function [" << callFunc << "](" << params << ")\n"; + storage = doFunctionCall(callFunc, params, rootScope); + std::cout << "function retval[" << storage << "] type[" << typeOfStorage(storage) << "]\n"; + if (storage) { + std::string tLeft = trim(left); + if (tLeft[0]=='"' && tLeft[tLeft.length() - 1]=='"') { + //std::cout << "dequoting[" << tLeft << "]" << std::endl; + tLeft=tLeft.substr(1, tLeft.length() - 2); + } + bool alreadySet = false; + + size_t dotPos = tLeft.find('.'); + if (dotPos != std::string::npos) { + js_internal_storage **key = getObjectKeyPointer(tLeft, &rootScope); + if (key != nullptr) { + alreadySet = true; + *key = storage; + } + } + if (!alreadySet) { + std::cout << "doAssignment final assign[" << tLeft << "] of type[" << typeOfStorage(storage) << "] scope[" << &rootScope << "]\n"; + rootScope.locals.value[tLeft] = storage; + jsDisplayScope(&rootScope, 0); + left = ""; // reset left + assignfile << tLeft << "=" << it << "\n"; + } + } + state = 0; + } else { + // collect params + params = it; + } } // { starts JSON capture (should be exactly one block before the } token) // you create a scope for that variable and recurse @@ -2322,6 +2445,7 @@ js_internal_storage **getObjectKeyPointer(const std::string input, const js_func js_internal_storage *dereferenceObject(const std::string input, const js_function *scope) { // FIXME: too simple, catches quoted strings with . in them + // FIXME: make sure we're not inside quotes size_t dotPos = input.find('.'); if (dotPos != std::string::npos) { std::string baseObj = input.substr(0, dotPos); @@ -2595,7 +2719,7 @@ js_internal_storage *jsParseTokens(const std::vector &tokens, js_fu void JavaScript::parse(const std::string source) { // tokenize source - std::cout << "JavaScript::parse source[" << source << "]\n\n"; + //std::cout << "JavaScript::parse source[" << source << "]\n\n"; this->tokens = jsGetTokens(source, 0); jsParseTokens(this->tokens, &this->rootScope); }