You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

JSParser.cpp 147KB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229
  1. #include "JSParser.h"
  2. #include "BrowserJS.h"
  3. #include "../../../tools/StringUtils.h"
  4. #include <iostream>
  5. #include <fstream>
  6. #include <algorithm>
  7. extern std::ofstream assignfile;
  8. extern std::ofstream execfile;
  9. std::string typeOfStorage(js_internal_storage *storage) {
  10. if (!storage) {
  11. std::cout << "null passed into typeOfStorage\n";
  12. return "Corrupt";
  13. }
  14. js_string *string = dynamic_cast<js_string*>(storage);
  15. if (string) return "string";
  16. js_number *number = dynamic_cast<js_number*>(storage);
  17. if (number) return "number";
  18. js_bool *jbool = dynamic_cast<js_bool*>(storage);
  19. if (jbool) return "bool";
  20. js_function *func = dynamic_cast<js_function*>(storage);
  21. if (func) return "func";
  22. js_array *arr = dynamic_cast<js_array*>(storage);
  23. if (arr) return "array";
  24. js_object *obj = dynamic_cast<js_object*>(storage);
  25. if (obj) return "object";
  26. js_reference *ref = dynamic_cast<js_reference*>(storage);
  27. if (ref) return "reference";
  28. js_forward *fwd = dynamic_cast<js_forward*>(storage);
  29. if (fwd) return "forward";
  30. return "unknown";
  31. }
  32. bool isStrInt(std::string s) {
  33. return (s.find_first_not_of( "0123456789" ) == std::string::npos);
  34. }
  35. bool isStrRational(std::string s) {
  36. return (s.find_first_not_of( "0123456789." ) == std::string::npos);
  37. }
  38. bool jsIsFalse(js_internal_storage *generic) {
  39. std::string type = typeOfStorage(generic);
  40. if (type == "string") {
  41. js_string *string = dynamic_cast<js_string*>(generic);
  42. return string->value == "" || string->value == "0";
  43. } else
  44. if (type == "number") {
  45. js_number *jnum = dynamic_cast<js_number*>(generic);
  46. return !jnum->value;
  47. } else
  48. if (type == "bool") {
  49. js_bool *jb = dynamic_cast<js_bool*>(generic);
  50. return !jb->value;
  51. } else if (type == "func") {
  52. return false; // func are always true
  53. } else
  54. //if (type == "unknown") {
  55. // why is this needed?
  56. //return true;
  57. //} else
  58. if (type == "Corrupt") {
  59. return true;
  60. } else {
  61. std::cout << "unknown type [" << type << "]\n";
  62. }
  63. return false;
  64. }
  65. js_internal_storage *jsLocateKey(const js_function *scope, const std::string key) {
  66. // do we have it?
  67. auto locate = scope->locals.value.find(key);
  68. if (locate == scope->locals.value.end()) {
  69. // we do have a parent?
  70. if (scope->parentScope) {
  71. return jsLocateKey(scope->parentScope, key);
  72. }
  73. // no parent
  74. return nullptr;
  75. }
  76. // we have it
  77. return locate->second;
  78. }
  79. std::string jsLocatePtrKey(const js_function *scope, js_internal_storage *val) {
  80. // do we have it?
  81. std::string sourceKey = "";
  82. for(auto it2 : scope->locals.value) {
  83. std::cout << "ptr[" << val << "]==[" << it2.second << "] root[" << scope << "]\n";
  84. if (it2.second == val) {
  85. return it2.first;
  86. break;
  87. }
  88. }
  89. // we do have a parent?
  90. if (scope->parentScope) {
  91. return jsLocatePtrKey(scope->parentScope, val);
  92. }
  93. // no parent
  94. return "";
  95. }
  96. void jsDisplayScope(const js_function *scope, size_t level) {
  97. std::cout << "There are " << scope->locals.value.size() << " elements at this level " << level << "\n";
  98. for(auto it : scope->locals.value) {
  99. std::string type = typeOfStorage(it.second);
  100. if (type == "string") {
  101. js_string *string = dynamic_cast<js_string*>(it.second);
  102. std::cout << "[" << level << "]" << "[" << it.first << "] stringValue[" << string->value << "] address[" << it.second << "]\n";
  103. } else {
  104. std::cout << "[" << level << "]" << "[" << it.first << "] type[" << type << "] address[" << it.second << "]\n";
  105. }
  106. }
  107. if (scope->parentScope) {
  108. level++;
  109. jsDisplayScope(scope->parentScope, level);
  110. }
  111. }
  112. // if a function don't pass a starting or ending {}
  113. std::vector<std::string> jsGetTokens(const std::string &source, const size_t start) {
  114. std::vector<std::string> tokens;
  115. //std::cout << "jsGetTokens start [" << source.substr(start) << "]\n";
  116. // tokenize it
  117. size_t cursor;
  118. unsigned char state = 0;
  119. size_t last = start?start - 1 : 0;
  120. size_t quoteStart = 0;
  121. size_t scopeLevel = 0;
  122. size_t jsonStart = 0;
  123. size_t jsonLevel = 0;
  124. size_t parenLevel = 0;
  125. size_t parenStart = 0;
  126. size_t functionStart = 0;
  127. for (cursor = start; cursor < source.length(); cursor++) {
  128. //std::cout << "jsGetTokens step [" << cursor << "] char[" << source[cursor] << "] state[" << std::to_string(state) << "] scopeLevel[" << scopeLevel << "]\n";
  129. if (state == 0) {
  130. if (source[cursor] == '{') {
  131. state = 1; // JSON
  132. jsonStart = cursor;
  133. jsonLevel++;
  134. //std::cout << "Entering JSON: " << cursor << std::endl;
  135. } else if (source[cursor] == '(') {
  136. state = 8; // in a function call or prototype
  137. parenStart = cursor;
  138. parenLevel++;
  139. } else if (source[cursor] == '\'') { // quotes just for allowing [;{}\n] in quotes
  140. quoteStart = cursor;
  141. state = 4;
  142. } else if (source[cursor] == '"') {
  143. quoteStart = cursor;
  144. state = 5;
  145. } else if (source[cursor] == '/' && source.length() > cursor + 1 && source[cursor + 1] == '/') {
  146. // single line comment
  147. state = 2;
  148. } else if (source[cursor] == '/' && source.length() > cursor + 1 && source[cursor + 1] == '*') {
  149. // Multiline comment
  150. state = 3;
  151. } else if (source[cursor] == '/') {
  152. // regex
  153. if (source.length() > cursor + 1) {
  154. size_t endex = locateRegexEnd(source, cursor + 1); // +1 because it can't start on /
  155. cursor = endex; // put here after regex
  156. // state = 9;
  157. } else {
  158. std::cout << "jsGetTokens - warning - no characters left in state 0\n";
  159. }
  160. } else if (source[cursor] == 'v' && source.length() > cursor + 3 && source[cursor + 1] == 'a'
  161. && source[cursor + 2] == 'r' && source[cursor + 3] == ' ') {
  162. // var
  163. state = 7;
  164. } else if (source[cursor] == 'f' && source.length() > cursor + 8 && source[cursor + 1] == 'u'
  165. && source[cursor + 2] == 'n' && source[cursor + 3] == 'c' && source[cursor + 4] == 't'
  166. && source[cursor + 5] == 'i' && source[cursor + 6] == 'o' && source[cursor + 7] == 'n') {
  167. //std::cout << "Entering function: " << cursor << std::endl;
  168. state = 6;
  169. functionStart = cursor;
  170. } else if (source[cursor] == 'r' && source.length() > cursor + 5 && source[cursor + 1] == 'e'
  171. && source[cursor + 2] == 't' && source[cursor + 3] == 'u' && source[cursor + 4] == 'r'
  172. && source[cursor + 5] == 'n') {
  173. // return state, have to ignore , until ; or new line
  174. state = 9;
  175. }
  176. } else if (state == 1) {
  177. // inside a scope (JSON)
  178. if (source[cursor] == '{') {
  179. jsonLevel++;
  180. } else if (source[cursor] == '}') {
  181. jsonLevel--;
  182. if (!jsonLevel) {
  183. //std::cout << "Exiting JSON: " << source.substr(jsonStart, cursor - jsonStart) << "\n" << std::endl;
  184. state = 0; // exit JSON
  185. }
  186. }
  187. } else if (state == 8) {
  188. // inside a paren (function)
  189. //std::cout << "looking at [" << source[cursor] << "]@" << cursor << std::endl;
  190. if (source[cursor] == '(') {
  191. parenLevel++;
  192. } else if (source[cursor] == ')') {
  193. parenLevel--;
  194. if (!parenLevel) {
  195. //std::cout << "Exiting Paren: " << source.substr(parenStart, cursor - parenStart) << "\n" << std::endl;
  196. state = 0; // exit JSON
  197. }
  198. }
  199. } else if (state == 2) {
  200. // inside a single line comment
  201. if (source[cursor] == '\n') {
  202. last = cursor;
  203. state = 0;
  204. }
  205. } else if (state == 3) {
  206. // inside a multiline comment
  207. if (source[cursor] == '*' && source.length() > cursor + 1 && source[cursor + 1] == '/') {
  208. // end multiline comment
  209. last = cursor;
  210. state = 0;
  211. }
  212. } else if (state == 4) {
  213. // inside single quote
  214. if (source[cursor] == '\'') {
  215. if (source[cursor - 1] != '\\') {
  216. //std::string quote = source.substr(quoteStart + 1, cursor - quoteStart - 1);
  217. //std::cout << "single quote: " << quote << std::endl;
  218. state = 0;
  219. }
  220. }
  221. } else if (state == 5) {
  222. // inside double quote
  223. if (source[cursor] == '"') {
  224. if (source[cursor - 1] != '\\') {
  225. //std::string quote = source.substr(quoteStart + 1, cursor - quoteStart - 1);
  226. //std::cout << "double quote: " << quote << std::endl;
  227. state = 0;
  228. }
  229. }
  230. } else if (state == 7) {
  231. }
  232. //
  233. if (source[cursor] == '{') {
  234. scopeLevel++;
  235. }
  236. bool endIt = false;
  237. if (source[cursor] == '}') {
  238. scopeLevel--;
  239. if (state == 6 && !scopeLevel) {
  240. //std::cout << "Exiting function: " << source.substr(functionStart, cursor - functionStart) << "\n" << std::endl;
  241. state = 0;
  242. endIt = true;
  243. }
  244. }
  245. // state 0 or 7, ignore states 1-6
  246. if ((state == 0 || state == 7 || state == 9) && !scopeLevel) {
  247. // , if state (not 7) or (not 9)
  248. if (source[cursor] == '\n' || source[cursor] == ';' || endIt || (source[cursor] == ',' && state == 0)) {
  249. // FIXME: ; in for loops
  250. std::string token = source.substr(last ? last + 1 : last, last ? (cursor - last - 1) : cursor );
  251. if (source[cursor] == '}') {
  252. token += '}';
  253. }
  254. // scopeLevel[" << scopeLevel << "]"
  255. std::cout << "got token [" << token << "] ending[" << source[cursor] << "] endIt[" << endIt << "]" << std::endl;
  256. if (token.length()<3) {
  257. //std::cout << "token too short [" << token << "]" << std::endl;
  258. } else {
  259. tokens.push_back(token);
  260. }
  261. last = cursor;
  262. // state 7 or 9
  263. if (state != 0) { // allow var constructs to end normally and take us out of var construct
  264. state = 0; // reset state
  265. }
  266. }
  267. }
  268. }
  269. std::string token = source.substr(last ? last + 1 : last, last ? (cursor - last - 1) : cursor );
  270. //&& !token.length() // all look like complete valid tokens
  271. // state 9 (return), perfect ok to run to the end
  272. if (!state || state == 9) {
  273. if (token.length()) {
  274. // we can't just be discarding stuff
  275. tokens.push_back(token);
  276. }
  277. return tokens;
  278. }
  279. std::cout << "jsGetTokens - out of characters in state " << std::to_string(state) << " token[" << token << "]" << std::endl;
  280. std::cout << "got token [" << token << "] ending[" << source[cursor] << "]" << std::endl;
  281. if (token.length()<3) {
  282. std::cout << "token too short [" << token << "]" << std::endl;
  283. } else {
  284. tokens.push_back(token);
  285. }
  286. return tokens;
  287. }
  288. js_internal_storage *jsFunctionCall(std::string funcName, js_function *func, std::string paramsStr, js_function &scope) {
  289. if (isConstruct(funcName)) {
  290. return executeConstruct(funcName, paramsStr, scope);
  291. } else {
  292. if (func == nullptr) {
  293. std::cout << "HALT passed null into jsFunctionCall" << std::endl;
  294. return nullptr;
  295. }
  296. // what about the params?
  297. if (paramsStr != "") {
  298. // FIXME: need to parse them ...
  299. std::vector<std::string> opens, closes;
  300. opens.push_back("{");
  301. opens.push_back("'");
  302. opens.push_back("\"");
  303. closes.push_back("}");
  304. closes.push_back("'");
  305. closes.push_back("\"");
  306. auto params = parseSepButNotBetween(paramsStr, ",", opens, closes);
  307. // get the prototype, so we know where to assign this variables into the scope
  308. //std::cout << "parameters supported [" << func->parameters.size() << "]" << std::endl;
  309. uint16_t i = 0;
  310. for(auto it = func->parameters.begin(); it != func->parameters.end(); ++it) {
  311. std::string value = "";
  312. if (i < params.size()) {
  313. value = params[i];
  314. }
  315. js_internal_storage *storeVal = doExpression(scope, value);
  316. std::cout << "Assigning prototype[" << *it << "] = [" << value << "]" << std::endl;
  317. scope.locals.value[*it] = storeVal;
  318. assignfile << *it << "=" << value << "\n";
  319. i++;
  320. }
  321. // well it's implemented, just not sure how well
  322. //std::cout << "HALT/writeme! jsFunctionCall has params[" << paramsStr << "]!" << std::endl;
  323. }
  324. return jsParseTokens(func->tokens, &scope);
  325. }
  326. }
  327. // this should evaluate an expression and return it's return value
  328. int doExpressionLevel = 0;
  329. js_internal_storage *doExpression(js_function &rootScope, std::string token) {
  330. std::vector<std::string> expression_parts;
  331. size_t cursor;
  332. size_t last = 0;
  333. size_t quoteStart = 0;
  334. size_t parenStart = 0;
  335. size_t parenLevel = 0;
  336. size_t trinaryLevel = 0;
  337. unsigned char state = 0;
  338. std::cout << "doExpression start[" << token << "]\n";
  339. // parse expression
  340. for (cursor = 0; cursor < token.length(); cursor++) {
  341. std::cout << "doExpression parse phase state[" << std::to_string(state) << "] char[" << token[cursor] << "]\n";
  342. if (state == 0) {
  343. // ||
  344. // &&
  345. // <, >, <=, >=, ==, ===, !=, !==
  346. // +, -
  347. // *, /, %, !
  348. // ?, >>, <<
  349. if (token[cursor] == 'f' && token.length() > cursor + 7 && token[cursor + 1] == 'u'
  350. && token[cursor + 2] == 'n' && token[cursor + 3] == 'c' && token[cursor + 4] == 't'
  351. && token[cursor + 5] == 'i' && token[cursor + 6] == 'o' && token[cursor + 7] == 'n') {
  352. state = 3;
  353. }
  354. if (token[cursor] == '\'') {
  355. quoteStart = cursor;
  356. state = 4;
  357. } else
  358. if (token[cursor] == '"') {
  359. quoteStart = cursor;
  360. state = 5;
  361. } else
  362. if (token[cursor] == '(') {
  363. parenStart = cursor;
  364. parenLevel++;
  365. state = 8;
  366. if (last != cursor) {
  367. // could be a func call or func def (w/ or w/o call)
  368. expression_parts.push_back(token.substr(last, cursor - last));
  369. }
  370. last = cursor + 1;
  371. expression_parts.push_back("(");
  372. } else
  373. if (token[cursor] == '{') {
  374. parenStart = cursor;
  375. parenLevel++;
  376. state = 1;
  377. //std::cout << "last " << last << " cursor " << cursor << std::endl;
  378. if (last != cursor) {
  379. expression_parts.push_back(token.substr(last, cursor - last - 1));
  380. }
  381. last = cursor + 1;
  382. expression_parts.push_back("{");
  383. }
  384. // single =
  385. if (token[cursor] == '=' && token.length() > cursor + 1 && token[cursor + 1] != '=') {
  386. //state = 1;
  387. //std::cout << "starting = at " << cursor << " last: " << last << std::endl;
  388. expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1;
  389. expression_parts.push_back("=");
  390. }
  391. // hack for JSON parsing
  392. if (token[cursor] == ':') {
  393. expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1;
  394. expression_parts.push_back("=");
  395. state = 2;
  396. }
  397. // ||
  398. if (token[cursor] == '|' && token.length() > cursor + 1 && token[cursor + 1] == '|') {
  399. expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 2;
  400. expression_parts.push_back("||");
  401. }
  402. if (token[cursor] == '&' && token.length() > cursor + 1 && token[cursor + 1] == '&') {
  403. expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 2;
  404. expression_parts.push_back("&&");
  405. }
  406. if (token[cursor] == '>' && token.length() > cursor + 1 && token[cursor + 1] != '=' && token[cursor + 1] != '>') {
  407. expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1;
  408. expression_parts.push_back(">");
  409. }
  410. if (token[cursor] == '<' && token.length() > cursor + 1 && token[cursor + 1] != '=' && token[cursor + 1] != '<') {
  411. expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1;
  412. expression_parts.push_back("<");
  413. }
  414. if (token[cursor] == '<' && token.length() > cursor + 1 && token[cursor + 1] == '&') {
  415. expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 2;
  416. expression_parts.push_back("<=");
  417. }
  418. if (token[cursor] == '>' && token.length() > cursor + 1 && token[cursor + 1] == '&') {
  419. expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 2;
  420. expression_parts.push_back(">=");
  421. }
  422. if (token[cursor] == '=' && token.length() > cursor + 2 && token[cursor + 1] == '=' && token[cursor + 2] != '=') {
  423. expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 2;
  424. expression_parts.push_back("==");
  425. }
  426. if (token[cursor] == '=' && token.length() > cursor + 2 && token[cursor + 1] == '=' && token[cursor + 2] == '=') {
  427. expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 3;
  428. expression_parts.push_back("===");
  429. }
  430. if (token[cursor] == '!' && token.length() > cursor + 2 && token[cursor + 1] == '=' && token[cursor + 2] != '=') {
  431. expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 2;
  432. expression_parts.push_back("!=");
  433. }
  434. if (token[cursor] == '!' && token.length() > cursor + 2 && token[cursor + 1] == '=' && token[cursor + 2] == '=') {
  435. expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 3;
  436. expression_parts.push_back("!==");
  437. }
  438. // +
  439. if (token[cursor] == '+') {
  440. expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1;
  441. expression_parts.push_back("+");
  442. } else
  443. if (token[cursor] == '-') {
  444. expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1;
  445. expression_parts.push_back("-");
  446. } else
  447. if (token[cursor] == '*') {
  448. expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1;
  449. expression_parts.push_back("*");
  450. } else
  451. if (token[cursor] == '/') {
  452. expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1;
  453. expression_parts.push_back("/");
  454. } else
  455. if (token[cursor] == '%') {
  456. expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1;
  457. expression_parts.push_back("%");
  458. } else
  459. if (token[cursor] == '!') {
  460. expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1;
  461. expression_parts.push_back("!");
  462. } else
  463. if (token[cursor] == '?') {
  464. expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1;
  465. expression_parts.push_back("?");
  466. trinaryLevel++;
  467. state = 9;
  468. }
  469. } else if (state == 1) {
  470. if (token[cursor] == '{') {
  471. parenLevel++;
  472. } else
  473. if (token[cursor] == '}') {
  474. parenLevel--;
  475. if (!parenLevel) {
  476. expression_parts.push_back(token.substr(last, cursor - last));
  477. last = cursor + 1;
  478. expression_parts.push_back("}");
  479. state = 0;
  480. }
  481. }
  482. } else if (state == 2) { // json state (can be moved)
  483. if (token[cursor] == ',') {
  484. expression_parts.push_back(token.substr(last, cursor - last));
  485. last = cursor + 1;
  486. state = 0;
  487. }
  488. } else if (state == 3) { // function start (can be moved)
  489. if (token[cursor] == '{') {
  490. // lets put the function prototype
  491. expression_parts.push_back(token.substr(last, cursor - last));
  492. last = cursor + 1;
  493. parenLevel++;
  494. state = 6; // move to the function body
  495. }
  496. } else if (state == 4) {
  497. if (token[cursor] == '\'') {
  498. if (token[cursor - 1] != '\\') {
  499. //std::string quote = token.substr(quoteStart + 1, cursor - quoteStart - 1);
  500. //expression_parts.push_back(quote);
  501. //std::cout << "single quote: " << quote << std::endl;
  502. state = 0;
  503. }
  504. }
  505. } else if (state == 5) {
  506. if (token[cursor] == '"') {
  507. if (token[cursor - 1] != '\\') {
  508. //std::string quote = token.substr(quoteStart + 1, cursor - quoteStart - 1);
  509. //expression_parts.push_back(quote);
  510. //std::cout << "double quote: " << quote << std::endl;
  511. state = 0;
  512. }
  513. }
  514. } else if (state == 6) {
  515. if (token[cursor] == '{') {
  516. parenLevel++;
  517. } else
  518. if (token[cursor] == '}') {
  519. parenLevel--;
  520. if (!parenLevel) {
  521. expression_parts.push_back(token.substr(last, cursor - last));
  522. last = cursor + 1;
  523. expression_parts.push_back("}"); // end function
  524. state = 0;
  525. }
  526. }
  527. } else if (state == 8) {
  528. if (token[cursor] == '(') {
  529. parenLevel++;
  530. } else
  531. if (token[cursor] == ')') {
  532. parenLevel--;
  533. if (!parenLevel) {
  534. expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1;
  535. expression_parts.push_back(")");
  536. state = 0;
  537. }
  538. }
  539. } else if (state == 9) {
  540. if (token[cursor] == '?') {
  541. trinaryLevel++;
  542. } else
  543. if (token[cursor] == ':') {
  544. trinaryLevel--;
  545. if (!trinaryLevel) {
  546. expression_parts.push_back(token.substr(last, cursor - last)); last = cursor + 1;
  547. expression_parts.push_back(":");
  548. state = 0;
  549. }
  550. }
  551. }
  552. }
  553. // flush last part
  554. std::cout << "doExpression end state[" << std::to_string(state) << "] cursor[" << cursor << "] last[" << last << "]\n";
  555. if (cursor != last) {
  556. std::cout << "pushing last part\n";
  557. expression_parts.push_back(token.substr(last, cursor - last));
  558. }
  559. // execute expression
  560. std::cout << "doExpression has [" << expression_parts.size() << "]parts\n";
  561. js_internal_storage *stack = nullptr;
  562. state = 0;
  563. std::string callFuncName = "";
  564. js_function *callFunc = nullptr;
  565. std::string params = "";
  566. //js_function *func = nullptr;
  567. size_t i = 0;
  568. for(auto it : expression_parts) {
  569. std::string trimmedToken = trim(it);
  570. i++;
  571. if (trimmedToken == "") continue;
  572. std::cout << "doExpression part[" << (i - 1) << "][" << it << "] state[" << std::to_string(state) << "]\n";
  573. if (state == 0) {
  574. // &&
  575. if (trimmedToken == "&&") {
  576. // if stack is false abort
  577. std::cout << "typeOf stack is [" << typeOfStorage(stack) << "]\n";
  578. std::string type = typeOfStorage(stack);
  579. if (jsIsFalse(stack)) {
  580. std::cout << "&& stack isFalse\n";
  581. }
  582. if (type=="string") {
  583. js_string *string = dynamic_cast<js_string*>(stack);
  584. std::cout << "stack points to [" << stack << "] value[" << string->value << "]\n";
  585. if (string!=nullptr) {
  586. if (string->value == "" || string->value == "0") {
  587. std::cout << "I believe this value to be false [" << string->value << "]\n";
  588. return nullptr;
  589. } else {
  590. std::cout << "I believe this value to be not false [" << string->value << "]\n";
  591. }
  592. } else {
  593. std::cout << "couldnt convert string\n";
  594. }
  595. } else if (type == "number") {
  596. js_number *jnum = dynamic_cast<js_number*>(stack);
  597. std::cout << "stack points to [" << stack << "] value[" << jnum->value << "]\n";
  598. if (jnum!=nullptr) {
  599. if (!jnum->value) {
  600. std::cout << "I believe this value to be false [" << jnum->value << "]\n";
  601. return nullptr;
  602. } else {
  603. std::cout << "I believe this value to be not false [" << jnum->value << "]\n";
  604. }
  605. } else {
  606. std::cout << "couldnt convert string\n";
  607. }
  608. } else {
  609. std::cout << "doExpression, I don't know how to process this type - WRITE ME\n";
  610. }
  611. continue;
  612. }
  613. // ||
  614. if (trimmedToken == "||") {
  615. std::cout << "typeOf stack is [" << typeOfStorage(stack) << "]\n";
  616. std::string type = typeOfStorage(stack);
  617. if (jsIsFalse(stack)) {
  618. // stack is false, we have to execute next expression
  619. continue;
  620. }
  621. // if stack is true, we don't need to evaulate the rest
  622. std::cout << "No need to execute the rest of this expression\n";
  623. }
  624. if (trimmedToken == "!") {
  625. state = 4;
  626. continue;
  627. }
  628. if (trimmedToken == "{") {
  629. // parseJSON
  630. state = 5;
  631. continue;
  632. }
  633. std::string first8 = trimmedToken.substr(0, 8);
  634. if (first8 == "function") {
  635. std::string prototype = trimmedToken.substr(9, trimmedToken.length() - 10);
  636. std::cout << "extracted[" << prototype << "]\n";
  637. js_function *jsfunc = new js_function;
  638. jsfunc->parameters = split(prototype, ',');
  639. stack = jsfunc;
  640. continue;
  641. }
  642. // handle assignemnt to stack
  643. if (trimmedToken == "=") {
  644. state = 6;
  645. continue;
  646. }
  647. /*
  648. if (trimmedToken[0] == '[') {
  649. // like [0] potentially longer?
  650. size_t n = std::count(trimmedToken.begin(), trimmedToken.end(), ']');
  651. if (n != 1) {
  652. std::cout << "we dont support multiple deindexes, write me\n";
  653. }
  654. // deindex
  655. js_array *arr = dynamic_cast<js_array *>(stack);
  656. if (!arr) {
  657. std::cout << "we only deindex arrarys [" << typeOfStorage(stack) << "], write me\n";
  658. } else {
  659. }
  660. // don't try and deference (object.value)
  661. continue;
  662. }
  663. */
  664. // function name
  665. // (
  666. if (trimmedToken == "(") {
  667. // function call
  668. std::cout << "func call param start\n";
  669. state = 2;
  670. continue;
  671. }
  672. // function params
  673. // )
  674. if (trimmedToken == ")") {
  675. std::cout << "func call param end\n";
  676. state = 3;
  677. continue;
  678. }
  679. if (trimmedToken == "}") {
  680. // {return document.getElementById(e)}
  681. /*
  682. doExpression has [3]parts
  683. doExpression part[{] state[0]
  684. doExpression part[return document.getElementById(e)] state[5]
  685. */
  686. // ?
  687. continue;
  688. }
  689. // variable
  690. // object.property or object[property] or [0]
  691. // well first lets parse the key out
  692. // then resolve the key
  693. // then resolve the value
  694. bool deref = dereferenceHasBase(trimmedToken, &rootScope);
  695. if (deref) {
  696. // if trimmedToken is [0] it needs the stack...
  697. js_internal_storage *dereferenceTest = dereferenceObject(trimmedToken, &rootScope);
  698. if (dereferenceTest) {
  699. if (typeOfStorage(dereferenceTest)=="func") {
  700. // it could be a call...
  701. callFuncName = it;
  702. callFunc = dynamic_cast<js_function *>(dereferenceTest);
  703. if (!callFunc) {
  704. std::cout << "Couldnt cast deference to func\n";
  705. }
  706. state = 1;
  707. } else {
  708. stack = dereferenceTest;
  709. }
  710. continue;
  711. }
  712. }
  713. // it's a string constant
  714. if ((trimmedToken[0] == '"' && trimmedToken[trimmedToken.length() - 1] == '"') ||
  715. (trimmedToken[0] == '\'' && trimmedToken[trimmedToken.length() - 1] == '\'')) {
  716. js_string *jstring = new js_string;
  717. jstring->value = trimmedToken.substr(1, -1);
  718. stack = jstring;
  719. continue;
  720. }
  721. if (trimmedToken == "true") {
  722. js_bool *jbool = new js_bool;
  723. jbool->value = true;
  724. stack = jbool;
  725. continue;
  726. } else if (trimmedToken == "null") {
  727. // FIXME: is null a type?
  728. js_bool *jbool = new js_bool;
  729. jbool->value = false;
  730. stack = jbool;
  731. continue;
  732. } else if (trimmedToken == "false") {
  733. js_bool *jbool = new js_bool;
  734. jbool->value = false;
  735. stack = jbool;
  736. continue;
  737. }
  738. // number constant
  739. bool allDigits = isStrRational(trimmedToken);
  740. /*
  741. bool allDigits = true;
  742. for(auto it2 : trimmedToken) {
  743. if (it2 >= '0' && it2 <= '9') {
  744. } else {
  745. if (it2 != '.') {
  746. allDigits = false;
  747. }
  748. }
  749. }
  750. */
  751. if (allDigits) {
  752. js_number *jnum = new js_number;
  753. // FIXME: float double support
  754. jnum->value = std::stoi(trimmedToken);
  755. std::cout << "allDigits value[" << trimmedToken << "] => jnum[" << jnum->value << "]\n";
  756. stack = jnum;
  757. continue;
  758. }
  759. js_internal_storage **isVar = getObjectKeyPointer(it, &rootScope);
  760. if (isVar != nullptr) {
  761. std::cout << "isVar [" << isVar << "]\n";
  762. std::cout << "stack could be [" << *isVar << "] type[" << typeOfStorage(stack) << "]\n";
  763. if (typeOfStorage(stack)=="func") {
  764. callFuncName = trimmedToken;
  765. callFunc = dynamic_cast<js_function *>(stack);
  766. state = 1;
  767. // (
  768. // 1
  769. // )
  770. } else {
  771. stack = *isVar; // set stack to point to this variable
  772. }
  773. /*
  774. if (typeOfStorage(stack)=="string") {
  775. js_string *string = dynamic_cast<js_string*>(stack);
  776. std::cout << "string stack value[" << string->value << "]\n";
  777. }
  778. */
  779. } else {
  780. js_internal_storage *scopeTest = jsLocateKey(&rootScope, it);
  781. if (scopeTest) {
  782. std::cout << "locatedKey stack[" << scopeTest << "] stackFalse[" << jsIsFalse(scopeTest) << "]\n";
  783. stack = scopeTest;
  784. } else {
  785. if (!deref) {
  786. // well if it's prefixed with var, then we're creating var
  787. size_t hasVarPos = trimmedToken.find("var ");
  788. if (hasVarPos != std::string::npos) {
  789. std::string remainingExpr = trimmedToken.substr(hasVarPos + 4);
  790. std::cout << "variable name [" << remainingExpr << "] it[" << it << "]" << std::endl;
  791. // we're just initialling a blank variable
  792. js_internal_storage **storage = getObjectKeyPointer(remainingExpr, &rootScope);
  793. if (storage != nullptr) {
  794. // actually already exists, so stomp it
  795. *storage = new js_internal_storage; // FIXME;
  796. } else {
  797. // new variable
  798. rootScope.locals.value[remainingExpr] = new js_internal_storage;
  799. }
  800. stack = rootScope.locals.value[remainingExpr];
  801. /*
  802. rootScope.locals.value[remainingExpr] = new js_internal_storage;
  803. js_internal_storage *exprRes = doExpression(rootScope, remainingExpr);
  804. std::cout << "Expression tyoe[" << typeOfStorage(exprRes) << "]" << std::endl;
  805. if (typeOfStorage(exprRes) == "null")
  806. {
  807. stack = new js_internal_storage;
  808. } else {
  809. stack = exprRes;
  810. }
  811. */
  812. std::cout << "Done with creating new variable" << std::endl;
  813. continue;
  814. }
  815. jsDisplayScope(&rootScope, 0);
  816. std::cout << "is Not a Var\n";
  817. } else {
  818. // is an non-existant key
  819. }
  820. }
  821. }
  822. } else if (state == 1) { // call function?
  823. // in func call, double check the (
  824. if (it == "(") {
  825. state = 2;
  826. } else {
  827. std::cout << "doExpression1 - func call did not have (\n";
  828. std::cout << "doExpression1 - stack is [" << stack << "] will now have to set it to [" << callFunc << "]\n";
  829. stack = callFunc;
  830. state = 0;
  831. }
  832. } else if (state == 2) { // start function call?
  833. params = it;
  834. state = 3;
  835. } else if (state == 3) { // finish function call
  836. // in func call, double check the )
  837. if (it == ")") {
  838. /*
  839. js_function *jfunc = dynamic_cast<js_function*>(stack);
  840. if (!jfunc) {
  841. std::cout << "Could cast [" << stack << "] to func\n";
  842. continue;
  843. }
  844. */
  845. if (!callFunc) {
  846. std::cout << "HALT callFunc is null!\n";
  847. continue;
  848. }
  849. std::cout << "doExpression3 - calling [" << callFuncName << "](" << params << ") at [" << callFunc << "] with [" << callFunc->tokens.size() << "]tokens\n";
  850. stack = jsFunctionCall(callFuncName, callFunc, params, rootScope);
  851. state = 0;
  852. } else {
  853. std::cout << "doExpression3 - func call did not have (\n";
  854. std::cout << "doExpression3 - stack is [" << stack << "] will now have to set it to [" << callFunc << "]\n";
  855. stack = callFunc;
  856. state = 0;
  857. }
  858. } else if (state == 4) { // NOT operator
  859. js_internal_storage *expRes = doExpression(rootScope, it);
  860. // invert expRes;
  861. js_bool *jb = new js_bool;
  862. jb->value = !jsIsFalse(expRes);
  863. stack = jb;
  864. state = 0;
  865. } else if (state == 5) { // JSON
  866. /*
  867. js_function *objectScope = new js_function;
  868. js_object *newObject = new js_object;
  869. //doAssignment(*objectScope, it);
  870. parseJSON(*objectScope, it);
  871. // translate the scope into js_object
  872. //std::cout << "JSON object output" << std::endl;
  873. for(auto it2 : objectScope->locals.value) {
  874. //std::cout << "[" << it2.first << "=" << it2.second << "]" << std::endl;
  875. newObject->value[it2.first] = it2.second;
  876. }
  877. //std::cout << "JSON object done" << std::endl;
  878. stack = newObject;
  879. */
  880. stack = jsGetObject(rootScope, it);
  881. std::cout << "doExpression getObject got [" << stack << "]\n";
  882. state = 0;
  883. } else if (state == 6) { // stack =
  884. std::cout << "State 6 = got [" << it << "]\n";
  885. params += it;
  886. } else {
  887. std::cout << "doExpression unknown state[" << std::to_string(state) << "]\n";
  888. }
  889. }
  890. // FIXME: any remainder?
  891. if (state == 1) {
  892. // x = func ref that's never called
  893. std::cout << "doExpressionEND1 - func call did not have (\n";
  894. std::cout << "doExpressionEND1 - stack is [" << stack << "] will now have to set it to [" << callFunc << "]\n";
  895. stack = callFunc;
  896. state = 0;
  897. } else
  898. if (state == 6) {
  899. std::cout << "Finishing state 6 [" << params << "]\n";
  900. std::cout << "Store result in [" << typeOfStorage(stack) << "]\n";
  901. auto resStack = doExpression(rootScope, params);
  902. // store resStack where ever stack is pointing
  903. params = "";
  904. state = 0;
  905. }
  906. if (state != 0) {
  907. std::cout << "doExpression final state[" << std::to_string(state) << "]\n";
  908. }
  909. return stack;
  910. }
  911. size_t findClosing(std::string token, size_t start, char open, char close) {
  912. std::cout << "\nfindClosing start[" << token.substr(start) << "]\n";
  913. size_t parenLevel = 0;
  914. for (size_t cursor = start; cursor < token.length(); cursor++) {
  915. std::cout << "findClosing scanning[" << token[cursor] << "] at[" << cursor << "/" << token.length() << "] parenLevel[" << parenLevel << "]\n";
  916. if (token[cursor] == open) {
  917. parenLevel++;
  918. } else
  919. if (token[cursor] == close) {
  920. parenLevel--;
  921. if (!parenLevel) {
  922. return cursor;
  923. }
  924. }
  925. }
  926. std::cout << "findClosing - HALT didnt find closing element[" << close << "]\n";
  927. return token.length();
  928. }
  929. // start is right after the "function" 8
  930. size_t locateFunctionNameEnd(std::string source, size_t start) {
  931. std::cout << "\nlocateFunctionNameEnd start[" << source.substr(start) << "]\n";
  932. for (size_t cursor = start; cursor < source.length(); cursor++) {
  933. if (source[cursor] == '(') {
  934. return cursor;
  935. }
  936. }
  937. std::cout << "locateFunctionNameEnd - HALT didnt find start paren for function\n";
  938. return source.length();
  939. }
  940. // start is right after the "function name(" 8
  941. size_t locateFunctionParamsEnd(std::string source, size_t start) {
  942. std::cout << "\nlocateFunctionParamsEnd start[" << source.substr(start) << "]\n";
  943. for (size_t cursor = start; cursor < source.length(); cursor++) {
  944. if (source[cursor] == '{') {
  945. return cursor;
  946. }
  947. }
  948. std::cout << "locateFunctionParamsEnd - HALT didnt find start brace for function\n";
  949. return source.length();
  950. }
  951. size_t locateSingleQuoteEnd(const std::string source, const size_t start) {
  952. for (size_t cursor = start; cursor < source.length(); cursor++) {
  953. if (source[cursor] == '\'') {
  954. if (source[cursor - 1] != '\\') {
  955. return cursor;
  956. }
  957. }
  958. }
  959. return start;
  960. }
  961. size_t locateDoubleQuoteEnd(const std::string source, const size_t start) {
  962. for (size_t cursor = start; cursor < source.length(); cursor++) {
  963. if (source[cursor] == '"') {
  964. if (source[cursor - 1] != '\\') {
  965. return cursor;
  966. }
  967. }
  968. }
  969. return start;
  970. }
  971. // well a regex is like a variable, can only be right side
  972. // where a divide is between two variables
  973. // can't start on the /
  974. // also could be division
  975. // end on the / or the last modifier (/x/g)
  976. size_t locateRegexEnd(const std::string source, const size_t start) {
  977. size_t adj = 0;
  978. if (source[start]=='/') {
  979. std::cout << "WARNING starting locateRegexEnd on /\n";
  980. adj = 1;
  981. }
  982. std::cout << "locateRegexEnd start [" << source.substr(start) << "]\n";
  983. unsigned char state = 0;
  984. for (size_t cursor = start + adj; cursor < source.length(); cursor++) {
  985. std::cout << "locateRegexEnd step [" << cursor << "/" << source.length() << "] char[" << source[cursor] << "] state[" << std::to_string(state) << "]\n";
  986. switch(state) {
  987. case 0:
  988. if (source[cursor] == '/') {
  989. if (source[cursor - 1] != '\\') {
  990. state = 1;
  991. }
  992. }
  993. // we need to search until the end of the string for any potential closing element
  994. break;
  995. case 1:
  996. // ,;\n
  997. switch(source[cursor]) {
  998. case '.': // regex obj
  999. return cursor - 1;
  1000. case ',':
  1001. return cursor - 1;
  1002. break;
  1003. case ';':
  1004. return cursor - 1;
  1005. break;
  1006. case '\n':
  1007. return cursor - 1;
  1008. break;
  1009. case ')':
  1010. return cursor - 1;
  1011. break;
  1012. case '}':
  1013. return cursor - 1;
  1014. break;
  1015. }
  1016. break;
  1017. }
  1018. }
  1019. // could be division
  1020. std::cout << "locateRegexEnd division?\n";
  1021. // division confirmation
  1022. state = 0;
  1023. for (size_t cursor = start + adj; cursor < source.length(); cursor++) {
  1024. std::cout << "locateRegexEnd divisionStep [" << cursor << "/" << source.length() << "] char[" << source[cursor] << "] state[" << std::to_string(state) << "]\n";
  1025. switch(state) {
  1026. case 0:
  1027. if (source[cursor] == '/') {
  1028. if (source[cursor - 1] != '\\') {
  1029. state = 1;
  1030. }
  1031. }
  1032. switch(source[cursor]) {
  1033. case ',':
  1034. return start;
  1035. break;
  1036. case ';':
  1037. return start;
  1038. break;
  1039. case '\n':
  1040. return start;
  1041. break;
  1042. // .)} ?
  1043. }
  1044. break;
  1045. case 1:
  1046. // ,;\n
  1047. switch(source[cursor]) {
  1048. case '.': // regex obj
  1049. return cursor;
  1050. break;
  1051. case ',':
  1052. return cursor;
  1053. break;
  1054. case ';':
  1055. return cursor;
  1056. break;
  1057. case '\n':
  1058. return cursor;
  1059. break;
  1060. case ')':
  1061. return cursor - 1;
  1062. break;
  1063. case '}':
  1064. return cursor - 1;
  1065. break;
  1066. }
  1067. break;
  1068. }
  1069. }
  1070. // what the hell is this...
  1071. return start;
  1072. }
  1073. int getNextExpressionLevel = 0;
  1074. // we return the terminator if ,;\n or )}
  1075. // if the expression is a function definition, then we return the () as part of it
  1076. // when returning a function block, it needs to end on the }
  1077. size_t getNextExpression(const std::string source, const size_t start) {
  1078. getNextExpressionLevel++;
  1079. std::cout << "\n" << std::string(getNextExpressionLevel * 2, ' ') << "getNextExpression(" << getNextExpressionLevel << ") start[" << source.substr(start) << "]\n";
  1080. unsigned char state = 0;
  1081. size_t parenLevel = 0;
  1082. size_t stateStart = 0;
  1083. for (size_t cursor = start; cursor < source.length(); cursor++) {
  1084. //std::cout << std::string(getNextExpressionLevel * 2, ' ') << "getNextExpression(" << getNextExpressionLevel << ") scanning[" << source[cursor] << "] at[" << cursor << "/" << source.length() << "] state[" << std::to_string(state) << "] parenLevel[" << parenLevel << "]\n";
  1085. switch(state) {
  1086. case 0:
  1087. // start function call
  1088. if (source[cursor]=='(') {
  1089. parenLevel++;
  1090. stateStart = cursor;
  1091. state = 1;
  1092. } else
  1093. if (source[cursor]=='\'') {
  1094. state = 4;
  1095. } else
  1096. if (source[cursor]=='"') {
  1097. state = 5;
  1098. }
  1099. // detect function definition and recurse
  1100. if (source[cursor] == 'f' && source.length() > cursor + 7 && source[cursor + 1] == 'u'
  1101. && source[cursor + 2] == 'n' && source[cursor + 3] == 'c' && source[cursor + 4] == 't'
  1102. && source[cursor + 5] == 'i' && source[cursor + 6] == 'o' && source[cursor + 7] == 'n') {
  1103. size_t last = cursor;
  1104. // parse name
  1105. last = locateFunctionNameEnd(source, cursor);
  1106. // parse params
  1107. last = locateFunctionParamsEnd(source, last);
  1108. // you need to find first brace
  1109. // call parseFunctionBody
  1110. last = parseFunctionBody(source, last);
  1111. std::cout << std::string(getNextExpressionLevel * 2, ' ') << "getNextExpression(" << getNextExpressionLevel << ") parseFunctionBody last[" << source[last] << "] just extracted[" << source.substr(cursor, last - cursor + 1) << "]\n";
  1112. cursor = last + 1; // artificially inflact the end because we're going to strip it
  1113. }
  1114. // detect for
  1115. // and end expression after }
  1116. // start regex
  1117. if (source[cursor]=='/' && source.length() > cursor + 1 && source[cursor + 1] != '/') {
  1118. // is this a regex or division?
  1119. size_t next = locateRegexEnd(source, cursor + 1);
  1120. if (next != start) {
  1121. // was a regex
  1122. cursor = next;
  1123. } // else was division element
  1124. }
  1125. // start scope
  1126. if (source[cursor]=='{') {
  1127. parenLevel++;
  1128. state = 2;
  1129. }
  1130. // minification technique (or list of variables, still an end of an expression tho)
  1131. if (source[cursor]==',') {
  1132. getNextExpressionLevel--;
  1133. return cursor;
  1134. }
  1135. // normal expression ender
  1136. if (source[cursor]==';') {
  1137. getNextExpressionLevel--;
  1138. return cursor;
  1139. }
  1140. // modern experession ender
  1141. if (source[cursor]=='\n') {
  1142. getNextExpressionLevel--;
  1143. return cursor;
  1144. }
  1145. // this is the last expression in a function
  1146. if (source[cursor]=='}') {
  1147. getNextExpressionLevel--;
  1148. // -1 doesn't work if the previous call in this block was from parseFunctionBody
  1149. // but we need -1 when found a stray }
  1150. return cursor - 1; // need to include the end }
  1151. }
  1152. // this is the last element in a list
  1153. if (source[cursor]==')') {
  1154. getNextExpressionLevel--;
  1155. return cursor;
  1156. }
  1157. /// maybe && and || should be expression terminators too
  1158. break;
  1159. case 1: // inside a function call, (
  1160. // make sure function isn't in a quote
  1161. if (source[cursor]=='\'') {
  1162. cursor = locateSingleQuoteEnd(source, cursor + 1);
  1163. } else
  1164. if (source[cursor]=='"') {
  1165. cursor = locateDoubleQuoteEnd(source, cursor + 1);
  1166. }
  1167. // we can't do this because
  1168. // getNextExpression(1) start[!!e.tailSize&&(t=$.cls("replyContainer"),!(a=t[t.length-e.tailSize])||(a=$.cls("dateTime",a)[0],n=(0|e.lastUpdated/1e3)-+a.getAttribute("data-utc"),i=0|(Date.now()-e.lastUpdated)/1e3,n>i))}]
  1169. // after e.lastUpdated
  1170. // getNextExpression(1) scanning[/] at[192/267] state[1] parenLevel[3]
  1171. // locateRegexEnd start [1e3)-+a.getAttribute("data-utc"),i=0|(Date.now()-e.lastUpdated)/1e3,n>i))}]
  1172. // we're just not smart enough to tell if we're division or regex (left/right or middle)
  1173. // if we're right after the starting (, then we know we're a regex in all cases.
  1174. if (stateStart + 1 == cursor) {
  1175. // start regex
  1176. if (source[cursor]=='/') {
  1177. // is this a regex or division?
  1178. size_t next = locateRegexEnd(source, cursor + 1);
  1179. if (next != start) {
  1180. // was a regex
  1181. cursor = next;
  1182. } // else was division element
  1183. }
  1184. }
  1185. // (function() {})
  1186. // detect function definition and recurse
  1187. if (source[cursor] == 'f' && source.length() > cursor + 7 && source[cursor + 1] == 'u'
  1188. && source[cursor + 2] == 'n' && source[cursor + 3] == 'c' && source[cursor + 4] == 't'
  1189. && source[cursor + 5] == 'i' && source[cursor + 6] == 'o' && source[cursor + 7] == 'n') {
  1190. // parse name
  1191. cursor = locateFunctionNameEnd(source, cursor);
  1192. // parse params
  1193. cursor = locateFunctionParamsEnd(source, cursor);
  1194. // you need to find first brace
  1195. // call parseFunctionBody
  1196. cursor = parseFunctionBody(source, cursor);
  1197. std::cout << std::string(getNextExpressionLevel * 2, ' ') << "getNextExpression - after parseFunctionBody now at " << cursor << "/" << source.length() << " char[" << source[cursor] << "] prev[" << source[cursor - 1] << "]\n";
  1198. }
  1199. // find end of function call
  1200. if (source[cursor] == '(') {
  1201. parenLevel++;
  1202. } else
  1203. if (source[cursor] == ')') {
  1204. parenLevel--;
  1205. if (!parenLevel) {
  1206. // while nothing can happen after a function call
  1207. // we need to process the terminating ,; or \n
  1208. state = 0;
  1209. }
  1210. }
  1211. break;
  1212. case 2:
  1213. // find end of scope
  1214. if (source[cursor] == '{') {
  1215. parenLevel++;
  1216. } else
  1217. if (source[cursor] == '}') {
  1218. parenLevel--;
  1219. if (!parenLevel) {
  1220. state = 0;
  1221. }
  1222. }
  1223. break;
  1224. case 4:
  1225. if (source[cursor] == '\'') {
  1226. if (source[cursor - 1] != '\\') {
  1227. //quoteEnd = cursor - 1;
  1228. state = 0;
  1229. }
  1230. }
  1231. break;
  1232. case 5:
  1233. if (source[cursor] == '"') {
  1234. if (source[cursor - 1] != '\\') {
  1235. //quoteEnd = cursor - 1;
  1236. state = 0;
  1237. }
  1238. }
  1239. break;
  1240. }
  1241. }
  1242. std::cout << std::string(getNextExpressionLevel * 2, ' ') << "getNextExpression[" << source.substr(start) << "] - WARNING didnt find another expression\n";
  1243. return source.length();
  1244. }
  1245. // also finishing character would be good to return
  1246. // we just need to find the start and ends, we don't need to parse contents
  1247. // we'll parse contents on execution
  1248. // sometimes the token starts at function()
  1249. // othertimes inside function
  1250. // we're supposed to be parsing a function definition
  1251. // ok we should only parse function bodies after the parameters
  1252. // so no () unless after
  1253. // so do we start at { or right before? well we don't need to...
  1254. // start should be after {?
  1255. // we should return a character that points to }
  1256. size_t parseFunctionBodyLevel = 0;
  1257. size_t parseFunctionBody(std::string source, size_t start) {
  1258. parseFunctionBodyLevel++;
  1259. std::cout << "\nparseFunctionBody(" << parseFunctionBodyLevel << ") start[" << source.substr(start) << "] next8[" << source.substr(start, 8) << "]\n";
  1260. size_t state = 0;
  1261. size_t parenLevel = 0;
  1262. //size_t last = start ? start - 1 : 0;
  1263. for (size_t cursor = start; cursor < source.length(); cursor++) {
  1264. std::cout << "parseFunctionBody(" << parseFunctionBodyLevel << ") scanning[" << source[cursor] << "] at[" << cursor << "/" << source.length() << "] state[" << std::to_string(state) << "]\n";
  1265. switch(state) {
  1266. case 0: // look for function body start
  1267. if (source[cursor] == '{') {
  1268. std::cout << "detected{ at" << " cursor " << cursor << std::endl;
  1269. // there really shouldn't be anything between ) and {
  1270. parenLevel++;
  1271. //last = cursor + 1;
  1272. state = 1;
  1273. //cursor = findClosing(source, cursor, '{', '}');
  1274. // FIXME: take function string and send it to a tokenizer
  1275. // save tokens to func.tokens
  1276. //expression_parts.push_back("{");
  1277. //return cursor;
  1278. }
  1279. break;
  1280. case 1:
  1281. // we're not done with outer function, but we are with the inner
  1282. /*
  1283. if (source[cursor] == '}') {
  1284. parenLevel--;
  1285. if (!parenLevel) {
  1286. std::cout << "parseFunctionBody(" << parseFunctionBodyLevel << ") PRE final} [" << source.substr(start, cursor + 1 - start) << "]\n";
  1287. parseFunctionBodyLevel--;
  1288. return cursor; // return a character ending on } according to spec
  1289. }
  1290. }
  1291. */
  1292. // what we can enter that has {
  1293. // well a function
  1294. // so we need to step expression by expression tbh
  1295. size_t next = getNextExpression(source, cursor);
  1296. std::cout << "parseFunctionBody(" << parseFunctionBodyLevel << ") - state1 start[" << cursor << "] next[" << next << "]\n";
  1297. if (next < cursor) next = cursor; // advanced at least 1 char
  1298. std::string exp = source.substr(cursor, next + 1 - cursor);
  1299. exp = trim(exp);
  1300. std::cout << "parseFunctionBody(" << parseFunctionBodyLevel << ") - NextExpression [" << exp << "]\n";
  1301. // we're basically looking for a next expression of {
  1302. /*
  1303. if (exp.length() == 0) {
  1304. return cursor;
  1305. }
  1306. */
  1307. if (exp.length() == 1) {
  1308. if (exp == "{") {
  1309. parenLevel++;
  1310. } else
  1311. if (exp == "}") {
  1312. parenLevel--;
  1313. if (!parenLevel) {
  1314. // this doesn't mean the function is over
  1315. // how it can it not, we have equal amounts of level
  1316. // well the levels aren't at the character level
  1317. std::cout << "parseFunctionBody(" << parseFunctionBodyLevel << ") final} [" << source.substr(start, next + 1 - start) << "]\n";
  1318. parseFunctionBodyLevel--;
  1319. return next; // return a character ending on } according to spec
  1320. }
  1321. }
  1322. }
  1323. // FIXME: kind of an ugly hack
  1324. // can't just be () because the expression could just be a call itself
  1325. // needs to be }()
  1326. if (exp.length() > 2) {
  1327. std::string last3 = exp.substr(exp.length() - 3, 3);
  1328. std::cout << "last3[" << last3 << "]\n";
  1329. if (last3 == "}()") {
  1330. // function declartion & call
  1331. std::cout << "parseFunctionBody(" << parseFunctionBodyLevel << ") final}() [" << source.substr(start, cursor + 1 - start) << "]\n";
  1332. parseFunctionBodyLevel--;
  1333. return cursor;
  1334. }
  1335. }
  1336. cursor = next;
  1337. std::cout << "parseFunctionBody1(" << parseFunctionBodyLevel << ") now at " << cursor << "/" << source.length() << " char[" << source[cursor] << "]\n";
  1338. if (cursor == source.length() - 1) {
  1339. // we just ended on
  1340. if (source[cursor]=='}') {
  1341. parseFunctionBodyLevel--;
  1342. return cursor;
  1343. }
  1344. }
  1345. /*
  1346. if (source[cursor] == '{') {
  1347. parenLevel++;
  1348. } else
  1349. if (source[cursor] == '}') {
  1350. parenLevel--;
  1351. if (!parenLevel) {
  1352. return cursor;
  1353. }
  1354. }
  1355. */
  1356. break;
  1357. }
  1358. }
  1359. parseFunctionBodyLevel--;
  1360. std::cout << "parseFunctionBody(" << parseFunctionBodyLevel << ") - HALT didnt find closing element for function\n";
  1361. return source.length();
  1362. /*
  1363. //jsGetTokens will tokenize the entire body of the function
  1364. // and return it as one token
  1365. std::vector<std::string> tokens = jsGetTokens(source, start + 1); // +1 to skip {
  1366. std::cout << "\nparseFunctionBody - jsGetTokens got " << tokens.size() << " tokens\n";
  1367. for(auto it: tokens) {
  1368. std::cout << "[" << it << "]" "\n";
  1369. }
  1370. std::string funcBody = tokens[0];
  1371. return start + funcBody.length();
  1372. */
  1373. }
  1374. // don't include the start { or ending }
  1375. // prototype doesn't include ()
  1376. js_function *makeFunctionFromString(const std::string body, const std::string prototype, js_function *parent) {
  1377. std::cout << "makeFunctionFromString [" << prototype << "][" << body << "]\n";
  1378. js_function *func = new js_function;
  1379. func->tokens = jsGetTokens(body, 0);
  1380. // FIXME: needs to be smarter
  1381. func->parameters = split(prototype, ',');
  1382. //for(auto it = func->parameters.begin(); it != func->)
  1383. if (!func->tokens.size()) {
  1384. std::cout << "empty function?\n";
  1385. }
  1386. func->parentScope = parent;
  1387. return func;
  1388. }
  1389. js_array *jsGetArray(js_function &rootScope, std::string token) {
  1390. js_function *objectScope = new js_function;
  1391. js_array *jsArr = new js_array;
  1392. parseJSON(*objectScope, token);
  1393. for(auto it2 : objectScope->locals.value) {
  1394. jsArr->value.push_back(it2.second);
  1395. }
  1396. return jsArr;
  1397. }
  1398. void parseArray(js_function &rootScope, std::string token) {
  1399. std::vector<std::string> json_keys;
  1400. std::vector<std::string> json_values;
  1401. size_t cursor;
  1402. size_t last = 0;
  1403. size_t quoteStart = 0;
  1404. size_t quoteEnd = 0;
  1405. size_t parenStart = 0;
  1406. size_t parenLevel = 0;
  1407. unsigned char state = 0;
  1408. for (cursor = 0; cursor < token.length(); cursor++) {
  1409. // we should only look for [:'"]
  1410. if (state == 0) {
  1411. switch(token[cursor]) {
  1412. // { or [ could be expression parsed I think...
  1413. case '\'':
  1414. quoteStart = cursor;
  1415. state = 4;
  1416. break;
  1417. case '"':
  1418. quoteStart = cursor;
  1419. state = 5;
  1420. break;
  1421. case ',':
  1422. std::string key = "";
  1423. if (quoteStart) {
  1424. // constant
  1425. key = token.substr(quoteStart + 1, quoteEnd - quoteStart); // skip the quotes
  1426. } else {
  1427. // variable
  1428. key = token.substr(last, cursor - last);
  1429. }
  1430. key = trim(key);
  1431. std::cout << "element[" << key << "] quoted: " << quoteStart << std::endl;
  1432. json_keys.push_back(key);
  1433. last = cursor + 1;
  1434. state = 2;
  1435. quoteStart = 0;
  1436. quoteEnd = 0;
  1437. break;
  1438. }
  1439. } else if (state == 2) { // get value state
  1440. // now we haven't to make sure we don't enter {, } or function
  1441. // ', " are ok, but have to turn off parsing until we encounter the next
  1442. // a-zA-Z$ for variables assignment
  1443. switch(state) {
  1444. case 0:
  1445. switch(token[cursor]) {
  1446. case '{':
  1447. parenStart = cursor;
  1448. parenLevel++;
  1449. state = 1;
  1450. break;
  1451. case '[':
  1452. parenStart = cursor;
  1453. parenLevel++;
  1454. state = 2;
  1455. break;
  1456. case '\'':
  1457. quoteStart = cursor;
  1458. state = 4;
  1459. break;
  1460. case '"':
  1461. quoteStart = cursor;
  1462. state = 5;
  1463. break;
  1464. case ',':
  1465. std::string value = "";
  1466. if (quoteStart) {
  1467. value = token.substr(quoteStart + 1, quoteEnd - quoteStart); // skip the quotes
  1468. } else {
  1469. value = token.substr(last, cursor - last);
  1470. value = trim(value);
  1471. }
  1472. std::cout << "value[" << value << "] quoted" << quoteStart << std::endl;
  1473. // JSON objects will already be assigned and empty
  1474. if (value != "") {
  1475. json_values.push_back(value);
  1476. js_string *newString = new js_string();
  1477. newString->value = value;
  1478. rootScope.locals.value[json_keys.back()] = newString;
  1479. }
  1480. last = cursor + 1;
  1481. state = 0;
  1482. quoteStart = 0;
  1483. quoteEnd = 0;
  1484. break;
  1485. }
  1486. break;
  1487. case 1:
  1488. switch(token[cursor]) {
  1489. case '{':
  1490. parenLevel++;
  1491. break;
  1492. case '}':
  1493. parenLevel--;
  1494. if (!parenLevel) {
  1495. std::string JSON = token.substr(parenStart + 1, cursor - parenStart);
  1496. std::cout << "PA Need to deJSON [" << JSON << "]" << std::endl;
  1497. /*
  1498. // well we can get a scope back
  1499. js_function *objectScope = new js_function;
  1500. parseJSON(*objectScope, JSON);
  1501. js_object *newObject = new js_object;
  1502. */
  1503. js_object *newObject = jsGetObject(rootScope, JSON);
  1504. rootScope.locals.value[json_keys.back()] = newObject;
  1505. last = cursor + 1;
  1506. state = 0;
  1507. }
  1508. break;
  1509. }
  1510. break;
  1511. case 2:
  1512. switch(token[cursor]) {
  1513. case '[':
  1514. parenLevel++;
  1515. break;
  1516. case ']':
  1517. parenLevel--;
  1518. if (!parenLevel) {
  1519. std::string arrStr = token.substr(parenStart + 1, cursor - parenStart);
  1520. std::cout << "Need to deArray [" << arrStr << "]" << std::endl;
  1521. // well we can get a scope back
  1522. js_function *objectScope = new js_function;
  1523. parseArray(*objectScope, arrStr);
  1524. js_object *newObject = new js_object;
  1525. rootScope.locals.value[json_keys.back()] = newObject;
  1526. last = cursor + 1;
  1527. state = 0;
  1528. }
  1529. break;
  1530. }
  1531. break;
  1532. case 4:
  1533. if (token[cursor] == '\'') {
  1534. if (token[cursor - 1] != '\\') {
  1535. quoteEnd = cursor - 1;
  1536. state = 0;
  1537. }
  1538. }
  1539. break;
  1540. case 5:
  1541. if (token[cursor] == '"') {
  1542. if (token[cursor - 1] != '\\') {
  1543. quoteEnd = cursor - 1;
  1544. state = 0;
  1545. }
  1546. }
  1547. break;
  1548. }
  1549. } else if (state == 4) {
  1550. if (token[cursor] == '\'') {
  1551. if (token[cursor - 1] != '\\') {
  1552. quoteEnd = cursor - 1;
  1553. state = 0;
  1554. }
  1555. }
  1556. } else if (state == 5) {
  1557. if (token[cursor] == '"') {
  1558. if (token[cursor - 1] != '\\') {
  1559. quoteEnd = cursor - 1;
  1560. state = 0;
  1561. }
  1562. }
  1563. }
  1564. }
  1565. }
  1566. js_object *jsGetObject(js_function &rootScope, std::string token) {
  1567. js_function *objectScope = new js_function;
  1568. js_object *jsonObj = new js_object;
  1569. parseJSON(*objectScope, token);
  1570. for(auto it2 : objectScope->locals.value) {
  1571. jsonObj->value[it2.first] = it2.second;
  1572. }
  1573. return jsonObj;
  1574. }
  1575. // we still need rootScope to read any vars from
  1576. // FIXME: take js_object and start
  1577. void parseJSON(js_function &rootScope, std::string token) {
  1578. std::vector<std::string> json_keys;
  1579. std::vector<std::string> json_values;
  1580. size_t cursor;
  1581. size_t last = 0;
  1582. size_t quoteStart = 0;
  1583. size_t quoteEnd = 0;
  1584. size_t parenStart = 0;
  1585. size_t parenLevel = 0;
  1586. unsigned char keyState = 0;
  1587. unsigned char valueState = 0;
  1588. std::cout << "parseJSON start[" << token << "]\n";
  1589. for (cursor = 0; cursor < token.length(); cursor++) {
  1590. std::cout << "parseJSON step cursor[" << cursor << "/" << token.length() << "] char[" << token[cursor] << "] keyState[" << std::to_string(keyState) << "] valueState[" << std::to_string(valueState) << "]\n";
  1591. if (keyState == 0) {
  1592. valueState = 0; // reset value state
  1593. switch(token[cursor]) {
  1594. case '\'':
  1595. quoteStart = cursor;
  1596. keyState = 4;
  1597. break;
  1598. case '"':
  1599. quoteStart = cursor;
  1600. keyState = 5;
  1601. break;
  1602. case ':':
  1603. std::string key = "";
  1604. if (quoteStart) {
  1605. key = token.substr(quoteStart + 1, quoteEnd - quoteStart); // skip the quotes
  1606. } else {
  1607. key = token.substr(last, cursor - last);
  1608. }
  1609. key = trim(key);
  1610. std::cout << "parsingJSON - key[" << key << "] quoted: " << quoteStart << std::endl;
  1611. if (key == "prettyPrint") {
  1612. std::cout << "Found your shit, now step it\n";
  1613. }
  1614. json_keys.push_back(key);
  1615. last = cursor + 1;
  1616. keyState = 2;
  1617. quoteStart = 0;
  1618. quoteEnd = 0;
  1619. break;
  1620. }
  1621. } else if (keyState == 2) { // get value state
  1622. // now we haven't to make sure we don't enter {, } or function
  1623. // ', " are ok, but have to turn off parsing until we encounter the next
  1624. // a-zA-Z$ for variables assignment
  1625. // we should only look for [:'"]
  1626. //std::cout << "parseJSON ks2 looking at [" << token[cursor] << "] vs[" << std::to_string(valueState) << "]\n";
  1627. switch(valueState) {
  1628. case 0:
  1629. switch(token[cursor]) {
  1630. case 'f':
  1631. if (cursor + 7 < token.length()) {
  1632. std::string next8 = token.substr(cursor, 8);
  1633. //std::cout << "parsingJSON - isFunction [" << next8 << "]" << std::endl;
  1634. if (next8 == "function") {
  1635. cursor = locateFunctionNameEnd(token, cursor);
  1636. last = locateFunctionParamsEnd(token, cursor);
  1637. std::string prototype = token.substr(cursor + 1, last - cursor - 1);
  1638. cursor = last;
  1639. // you need to find first brace
  1640. last = parseFunctionBody(token, cursor);
  1641. if (token[last]!='}') {
  1642. // should end on }
  1643. // but should it be last + 1? definitely not
  1644. std::cout << "parsingJSON - parseFunctionBody broke spec, ending on [" << token[last] << "]\n";
  1645. }
  1646. //std::cout << "parseJSON last[" << token[last] << "]\n";
  1647. // + 1 to skip initial { and not + 1 because } and -1 because of that starting + 1
  1648. std::string funcContents = token.substr(cursor + 1, last - cursor - 1);
  1649. std::cout << "parsingJSON - function " << json_keys.back() << "[" << prototype << "] [" << funcContents << "]" << std::endl;
  1650. std::cout << "parsingJSON - current char [" << token[last] << "]\n";
  1651. cursor = last; // continue after } (for loop will advance this)
  1652. // we have this key now but we'll wait for the , to do it's thing
  1653. //valueState = 6;
  1654. json_values.push_back(funcContents);
  1655. // [" << funcContents << "]
  1656. assignfile << "JSON." << json_keys.back() << "=" << "_NTRFUNC0[" << funcContents.length() << "]" << "\n";
  1657. rootScope.locals.value[json_keys.back()] = makeFunctionFromString(funcContents, prototype, &rootScope);
  1658. valueState = 6;
  1659. //keyState = 0;
  1660. //valueState = 0;
  1661. }
  1662. }
  1663. break;
  1664. case '{':
  1665. parenStart = cursor;
  1666. parenLevel++;
  1667. valueState = 1;
  1668. break;
  1669. case '[':
  1670. parenStart = cursor;
  1671. parenLevel++;
  1672. valueState = 2;
  1673. break;
  1674. case '\'':
  1675. quoteStart = cursor;
  1676. valueState = 4;
  1677. break;
  1678. case '"':
  1679. quoteStart = cursor;
  1680. valueState = 5;
  1681. break;
  1682. case ',':
  1683. std::string value = "";
  1684. if (quoteStart) {
  1685. value = token.substr(quoteStart + 1, quoteEnd - quoteStart); // skip the quotes
  1686. } else {
  1687. value = token.substr(last, cursor - last);
  1688. value = trim(value);
  1689. }
  1690. //std::cout << "parsingJSON - value[" << value << "] quoted" << quoteStart << std::endl;
  1691. // JSON objects will already be assigned and empty
  1692. if (value != "") {
  1693. json_values.push_back(value);
  1694. js_string *newString = new js_string();
  1695. newString->value = value;
  1696. assignfile << "JSON." << json_keys.back() << "=_NTRSTRING(,):'" << value << "'\n";
  1697. rootScope.locals.value[json_keys.back()] = newString;
  1698. } else {
  1699. if (quoteStart) {
  1700. // likely ""
  1701. json_values.push_back("");
  1702. js_string *newString = new js_string();
  1703. newString->value = "";
  1704. assignfile << "JSON." << json_keys.back() << "=_NTRSTRING(,):'" << value << "'\n";
  1705. rootScope.locals.value[json_keys.back()] = newString;
  1706. }
  1707. }
  1708. last = cursor + 1;
  1709. std::cout << "remainder last now points to[" << token[last] << "] should not be comma\n";
  1710. keyState = 0;
  1711. valueState = 0;
  1712. quoteStart = 0;
  1713. quoteEnd = 0;
  1714. break;
  1715. }
  1716. break;
  1717. case 1:
  1718. switch(token[cursor]) {
  1719. case '{':
  1720. parenLevel++;
  1721. break;
  1722. case '}':
  1723. parenLevel--;
  1724. if (!parenLevel) {
  1725. std::string JSON = token.substr(parenStart + 1, cursor - parenStart);
  1726. //std::cout << "parsingJSON - PJ Need to deJSON [" << JSON << "]" << std::endl;
  1727. // well we can get a scope back
  1728. /*
  1729. js_function *objectScope = new js_function;
  1730. parseJSON(*objectScope, JSON);
  1731. js_object *newObject = new js_object;
  1732. */
  1733. js_object *newObject = jsGetObject(rootScope, JSON);
  1734. assignfile << "JSON." << json_keys.back() << "=" << "_NTRJSON" << "\n";
  1735. rootScope.locals.value[json_keys.back()] = newObject;
  1736. last = cursor + 1;
  1737. valueState = 0;
  1738. // let keyState 2 finish it out
  1739. }
  1740. break;
  1741. }
  1742. break;
  1743. case 2:
  1744. switch(token[cursor]) {
  1745. case '[':
  1746. parenLevel++;
  1747. break;
  1748. case ']':
  1749. parenLevel--;
  1750. if (!parenLevel) {
  1751. std::string arrayStr = token.substr(parenStart + 1, cursor - parenStart);
  1752. //std::cout << "parsingJSON - Need to deArray [" << arrayStr << "]" << std::endl;
  1753. // well we can get a scope back
  1754. js_function *arrayScope = new js_function;
  1755. parseArray(*arrayScope, arrayStr);
  1756. js_array *newArray = new js_array;
  1757. assignfile << "JSON." << json_keys.back() << "=" << "_NTRARRAY" << "\n";
  1758. rootScope.locals.value[json_keys.back()] = newArray;
  1759. last = cursor + 1;
  1760. valueState = 0;
  1761. keyState = 0;
  1762. }
  1763. break;
  1764. }
  1765. break;
  1766. case 4:
  1767. if (token[cursor] == '\'') {
  1768. if (token[cursor - 1] != '\\') {
  1769. quoteEnd = cursor - 1;
  1770. valueState = 0;
  1771. }
  1772. }
  1773. break;
  1774. case 5:
  1775. if (token[cursor] == '"') {
  1776. if (token[cursor - 1] != '\\') {
  1777. quoteEnd = cursor - 1;
  1778. valueState = 0;
  1779. }
  1780. }
  1781. break;
  1782. case 6: // function push back
  1783. std::cout << "parseJSON state6 char[" << token[cursor] << "]\n";
  1784. if (token[cursor] == ',') {
  1785. /*
  1786. std::string value = "";
  1787. if (quoteStart) {
  1788. value = token.substr(quoteStart + 1, quoteEnd - quoteStart); // skip the quotes
  1789. } else {
  1790. value = token.substr(last, cursor - last);
  1791. value = trim(value);
  1792. }
  1793. std::cout << "parsingJSON - value[" << value << "] quoted" << quoteStart << std::endl;
  1794. if (value != "") {
  1795. json_values.push_back(value);
  1796. assignfile << "JSON." << json_keys.back() << "=" << "_NTRFUNC6" << "\n";
  1797. rootScope.data[json_keys.back()] = func;
  1798. }
  1799. */
  1800. last = cursor + 1; // set to after the current character (next char after ,)
  1801. keyState = 0;
  1802. valueState = 0;
  1803. quoteStart = 0;
  1804. quoteEnd = 0;
  1805. } else if (token[cursor] == '}') {
  1806. // it's the end of the JSON
  1807. keyState = 0;
  1808. }
  1809. break;
  1810. }
  1811. } else if (keyState == 4) {
  1812. if (token[cursor] == '\'') {
  1813. if (token[cursor - 1] != '\\') {
  1814. quoteEnd = cursor - 1;
  1815. keyState = 0;
  1816. }
  1817. }
  1818. } else if (keyState == 5) {
  1819. if (token[cursor] == '"') {
  1820. if (token[cursor - 1] != '\\') {
  1821. quoteEnd = cursor - 1;
  1822. keyState = 0;
  1823. }
  1824. }
  1825. }
  1826. }
  1827. std::cout << "done parsingJSON keyState[" << std::to_string(keyState) << "] valueState[" << std::to_string(valueState) << "]\n";
  1828. // we can end safely if after a function, likely just the } left over
  1829. if (keyState == 2 && valueState != 6) {
  1830. std::string value = "";
  1831. if (quoteStart) {
  1832. value = token.substr(quoteStart + 1, quoteEnd - quoteStart); // skip the quotes
  1833. } else {
  1834. value = token.substr(last, cursor - last);
  1835. value = trim(value);
  1836. }
  1837. //std::cout << "parsingJSON - value[" << value << "] quoted" << quoteStart << std::endl;
  1838. // JSON objects will already be assigned and empty
  1839. if (value != "") {
  1840. json_values.push_back(value);
  1841. js_string *newString = new js_string();
  1842. newString->value = value;
  1843. assignfile << "JSON." << json_keys.back() << "=_NTRSTRING(END):'" << value << "'\n";
  1844. rootScope.locals.value[json_keys.back()] = newString;
  1845. }
  1846. }
  1847. std::cout << "exiting parseJSON with: \n";
  1848. jsDisplayScope(&rootScope, 0);
  1849. }
  1850. // return value is if there was any error (false for error, true for no error)
  1851. // actually assignments are expressions
  1852. int doAssignmentLevel = 0;
  1853. bool doAssignment(js_function &rootScope, std::string token) {
  1854. doAssignmentLevel++;
  1855. // FIXME: make sure = isn't in quotes or JSON?
  1856. // FIXME: double or triple equal differentiation
  1857. //std::cout << "looking at [" << token << "]" << std::endl;
  1858. // document.documentElement.classList?($.hasClass=function(e,t){return e.classList.contains(t)},$.addClass=function(e,t){e.classList.add(t)},$.removeClass=function(e,t){e.classList.remove(t)}):($.hasClass=function(e,t){return-1!=(" "+e.className+" ").indexOf(" "+t+" ")},$.addClass=function(e,t){e.className=""===e.className?t:e.className+" "+t},$.removeClass=function(e,t){e.className=(" "+e.className+" ").replace(" "+t+" ","")})
  1859. std::vector<std::string> expression_parts;
  1860. size_t cursor;
  1861. size_t last = 0;
  1862. size_t quoteStart = 0;
  1863. size_t parenStart = 0;
  1864. size_t parenLevel = 0;
  1865. size_t trinaryLevel = 0;
  1866. unsigned char state = 0;
  1867. for (cursor = 0; cursor < token.length(); cursor++) {
  1868. std::cout << std::string(doAssignmentLevel * 2, ' ') << "doAssignment(" << doAssignmentLevel << ") step [" << cursor << "/" << token.length() << "] char[" << token[cursor] << "] state[" << std::to_string(state) << "] parenLevel[" << parenLevel << "]\n";
  1869. if (state == 0) {
  1870. // =
  1871. // ||
  1872. // &&
  1873. // <, >, <=, >=, ==, ===, !=, !==
  1874. // +, -
  1875. // *, /, %
  1876. // ?, >>, <<
  1877. if (token[cursor] == 'f' && token.length() > cursor + 7 && token[cursor + 1] == 'u'
  1878. && token[cursor + 2] == 'n' && token[cursor + 3] == 'c' && token[cursor + 4] == 't'
  1879. && token[cursor + 5] == 'i' && token[cursor + 6] == 'o' && token[cursor + 7] == 'n') {
  1880. state = 3;
  1881. }
  1882. // if? yea we have to, otherwise it's scope becomes a JSON decode
  1883. // but that's not exactly a problem
  1884. // else?
  1885. if (token[cursor] == '\'') {
  1886. quoteStart = cursor;
  1887. state = 4;
  1888. } else
  1889. if (token[cursor] == '"') {
  1890. quoteStart = c