TinyJS on mbed. TinyJS is very simple JavaScript engine.

Dependencies:   mbed

TinyJS on mbed

what's this ?

TinyJS is an extremely simple (under than 2000 lines) JavaScript interpreter engine.
I ported on mbed. but it restrict any features.
TinyJS project is https://github.com/gfwilliams/tiny-js

TinyJSは2000行以下で書かれた非常に小さいJavaScriptインタプリタエンジンです。
これをmbedに移植してみました。(ただし、いろいろ制限があります)
本家はこちら。 https://github.com/gfwilliams/tiny-js

how to use

You must use on serial terminal application by mbed serial USB.
baud is 57600bps
USBシリアルとして、ターミナルソフトを接続するとコンソールが表示されます。
ボーレートは57600bpsになってます。

functions

functions for mbed.
mbed用関数

  • mbed.DigitalIn(pinName, mode)
  • mbed.DigitalOut(pinName, val)
  • mbed.AnalogIn(pinName)
  • mbed.AnalogOut(pinName, val)
  • mbed.InterruptIn(pinName, edge, mode, callback)
  • mbed.TimerStart()
  • mbed.TimerStop()
  • mbed.TimerReset()
  • mbed.TimerRead()
  • mbed.Timeout(callback, t)
  • mbed.wait(s)
  • mbed.memfree()

sample JavaScript codes

DigitalOut

mbed.DigitalOut('LED1', 1);
mbed.DigitalOut('LED2', 0);
mbed.DigitalOut('LED3', 1);
mbed.DigitalOut('LED4', 0);

LED1 = On, LED2=Off, LED3=On, ED4=Off
LED1 = 点灯、LED2=消灯、LED3=点灯、LED4=消灯

DigitalIn

print(mbed.DigitalIn('p5', 'PullUp'));

p5 is pull up, read, and print on console.
p5をPullUpして読みプリントする。

AnalogOut

mbed.AnalogOut('p18', 0.8);

p18 is analog output, value is 0.8.
p18を 値0.8でアナログ出力する。

AnalogIn

print(mbed.AnalogIn('p20'));

p20 is read analog voltage, and print on console.
p20をアナログ入力しプリントする。

InterruptIn

var led1 = 0;
mbed.InterruptIn('p5', 'fall', 'PullUp', function() {led1 = !led1; mbed.DigitalOut('LED1', led1);});

Interrupt on p5, and ON/OFF does LED1.
p5で割り込んでLED1をON/OFFする。

Timeout and wait sample code

mbed.Timeout(function() {mbed.DigitalOut('LED1', 1);mbed.wait(3);mbed.DigitalOut('LED1', 0);}, 4);

LED1=on when wait for 4 seconds. and LED1=off for 3 seconds later.
LED1を4秒待って点灯して3秒後に消灯する。

memfree

print(mbed.memfree());

This prints the number of bytes of the remainder memory on mbed where TinyJS is usable.
これはTinyJSが使えるmbed上での残りメモリのバイト数をプリントアウトする。

LED Blinker by Timeout

blinker = function() {var led = 0; mbed.Timeout(function() {led = !led; mbed.DigitalOut('LED1', led);blinker();}, 0.5);};
blinker();

LED Blinker by Timeout.
Timeoutを使ったLチカ。

restrictions

  • There is very little available memory. (Less than 9kbytes on LPC1768)
  • Registration of InterruptIn is 4 limit.
  • The loop to 8,192 times.
  • The built-in functions (general JavaScript functions) that TinyJS prepares for for securing of memory is not included.

more, more, more ....

制限事項

  • 利用できるメモリは非常に少ない。(LPC1768で9kbytes以下)
  • InterruptInで登録できる割り込みは4つまで。4つを超えると1つめから順番に削除される。
  • ループは8192回まで。
  • メモリ確保のためTinyJSが用意している組み込み関数(一般的なJavaScript関数)は含まれない。

他、多数....

sample movies

http://www.youtube.com/watch?v=ARp0DK70JGM
http://www.youtube.com/watch?v=UOZQ4eEC4xA

Committer:
ohneta
Date:
Sat Jan 11 20:19:11 2014 +0000
Revision:
0:aae260bdcdd9
TinyJS for mbed porting.; 1st edition.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ohneta 0:aae260bdcdd9 1 /*
ohneta 0:aae260bdcdd9 2 * TinyJS
ohneta 0:aae260bdcdd9 3 *
ohneta 0:aae260bdcdd9 4 * A single-file Javascript-alike engine
ohneta 0:aae260bdcdd9 5 *
ohneta 0:aae260bdcdd9 6 * Authored By Gordon Williams <gw@pur3.co.uk>
ohneta 0:aae260bdcdd9 7 *
ohneta 0:aae260bdcdd9 8 * Copyright (C) 2009 Pur3 Ltd
ohneta 0:aae260bdcdd9 9 *
ohneta 0:aae260bdcdd9 10 * Permission is hereby granted, free of charge, to any person obtaining a copy of
ohneta 0:aae260bdcdd9 11 * this software and associated documentation files (the "Software"), to deal in
ohneta 0:aae260bdcdd9 12 * the Software without restriction, including without limitation the rights to
ohneta 0:aae260bdcdd9 13 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
ohneta 0:aae260bdcdd9 14 * of the Software, and to permit persons to whom the Software is furnished to do
ohneta 0:aae260bdcdd9 15 * so, subject to the following conditions:
ohneta 0:aae260bdcdd9 16
ohneta 0:aae260bdcdd9 17 * The above copyright notice and this permission notice shall be included in all
ohneta 0:aae260bdcdd9 18 * copies or substantial portions of the Software.
ohneta 0:aae260bdcdd9 19
ohneta 0:aae260bdcdd9 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
ohneta 0:aae260bdcdd9 21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
ohneta 0:aae260bdcdd9 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
ohneta 0:aae260bdcdd9 23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
ohneta 0:aae260bdcdd9 24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
ohneta 0:aae260bdcdd9 25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
ohneta 0:aae260bdcdd9 26 * SOFTWARE.
ohneta 0:aae260bdcdd9 27 */
ohneta 0:aae260bdcdd9 28
ohneta 0:aae260bdcdd9 29 /* Version 0.1 : (gw) First published on Google Code
ohneta 0:aae260bdcdd9 30 Version 0.11 : Making sure the 'root' variable never changes
ohneta 0:aae260bdcdd9 31 'symbol_base' added for the current base of the sybmbol table
ohneta 0:aae260bdcdd9 32 Version 0.12 : Added findChildOrCreate, changed string passing to use references
ohneta 0:aae260bdcdd9 33 Fixed broken string encoding in getJSString()
ohneta 0:aae260bdcdd9 34 Removed getInitCode and added getJSON instead
ohneta 0:aae260bdcdd9 35 Added nil
ohneta 0:aae260bdcdd9 36 Added rough JSON parsing
ohneta 0:aae260bdcdd9 37 Improved example app
ohneta 0:aae260bdcdd9 38 Version 0.13 : Added tokenEnd/tokenLastEnd to lexer to avoid parsing whitespace
ohneta 0:aae260bdcdd9 39 Ability to define functions without names
ohneta 0:aae260bdcdd9 40 Can now do "var mine = function(a,b) { ... };"
ohneta 0:aae260bdcdd9 41 Slightly better 'trace' function
ohneta 0:aae260bdcdd9 42 Added findChildOrCreateByPath function
ohneta 0:aae260bdcdd9 43 Added simple test suite
ohneta 0:aae260bdcdd9 44 Added skipping of blocks when not executing
ohneta 0:aae260bdcdd9 45 Version 0.14 : Added parsing of more number types
ohneta 0:aae260bdcdd9 46 Added parsing of string defined with '
ohneta 0:aae260bdcdd9 47 Changed nil to null as per spec, added 'undefined'
ohneta 0:aae260bdcdd9 48 Now set variables with the correct scope, and treat unknown
ohneta 0:aae260bdcdd9 49 as 'undefined' rather than failing
ohneta 0:aae260bdcdd9 50 Added proper (I hope) handling of null and undefined
ohneta 0:aae260bdcdd9 51 Added === check
ohneta 0:aae260bdcdd9 52 Version 0.15 : Fix for possible memory leaks
ohneta 0:aae260bdcdd9 53 Version 0.16 : Removal of un-needed findRecursive calls
ohneta 0:aae260bdcdd9 54 symbol_base removed and replaced with 'scopes' stack
ohneta 0:aae260bdcdd9 55 Added reference counting a proper tree structure
ohneta 0:aae260bdcdd9 56 (Allowing pass by reference)
ohneta 0:aae260bdcdd9 57 Allowed JSON output to output IDs, not strings
ohneta 0:aae260bdcdd9 58 Added get/set for array indices
ohneta 0:aae260bdcdd9 59 Changed Callbacks to include user data pointer
ohneta 0:aae260bdcdd9 60 Added some support for objects
ohneta 0:aae260bdcdd9 61 Added more Java-esque builtin functions
ohneta 0:aae260bdcdd9 62 Version 0.17 : Now we don't deepCopy the parent object of the class
ohneta 0:aae260bdcdd9 63 Added JSON.stringify and eval()
ohneta 0:aae260bdcdd9 64 Nicer JSON indenting
ohneta 0:aae260bdcdd9 65 Fixed function output in JSON
ohneta 0:aae260bdcdd9 66 Added evaluateComplex
ohneta 0:aae260bdcdd9 67 Fixed some reentrancy issues with evaluate/execute
ohneta 0:aae260bdcdd9 68 Version 0.18 : Fixed some issues with code being executed when it shouldn't
ohneta 0:aae260bdcdd9 69 Version 0.19 : Added array.length
ohneta 0:aae260bdcdd9 70 Changed '__parent' to 'prototype' to bring it more in line with javascript
ohneta 0:aae260bdcdd9 71 Version 0.20 : Added '%' operator
ohneta 0:aae260bdcdd9 72 Version 0.21 : Added array type
ohneta 0:aae260bdcdd9 73 String.length() no more - now String.length
ohneta 0:aae260bdcdd9 74 Added extra constructors to reduce confusion
ohneta 0:aae260bdcdd9 75 Fixed checks against undefined
ohneta 0:aae260bdcdd9 76 Version 0.22 : First part of ardi's changes:
ohneta 0:aae260bdcdd9 77 sprintf -> sprintf_s
ohneta 0:aae260bdcdd9 78 extra tokens parsed
ohneta 0:aae260bdcdd9 79 array memory leak fixed
ohneta 0:aae260bdcdd9 80 Fixed memory leak in evaluateComplex
ohneta 0:aae260bdcdd9 81 Fixed memory leak in FOR loops
ohneta 0:aae260bdcdd9 82 Fixed memory leak for unary minus
ohneta 0:aae260bdcdd9 83 Version 0.23 : Allowed evaluate[Complex] to take in semi-colon separated
ohneta 0:aae260bdcdd9 84 statements and then only return the value from the last one.
ohneta 0:aae260bdcdd9 85 Also checks to make sure *everything* was parsed.
ohneta 0:aae260bdcdd9 86 Ints + doubles are now stored in binary form (faster + more precise)
ohneta 0:aae260bdcdd9 87 Version 0.24 : More useful error for maths ops
ohneta 0:aae260bdcdd9 88 Don't dump everything on a match error.
ohneta 0:aae260bdcdd9 89 Version 0.25 : Better string escaping
ohneta 0:aae260bdcdd9 90 Version 0.26 : Add CScriptVar::equals
ohneta 0:aae260bdcdd9 91 Add built-in array functions
ohneta 0:aae260bdcdd9 92 Version 0.27 : Added OZLB's TinyJS.setVariable (with some tweaks)
ohneta 0:aae260bdcdd9 93 Added OZLB's Maths Functions
ohneta 0:aae260bdcdd9 94 Version 0.28 : Ternary operator
ohneta 0:aae260bdcdd9 95 Rudimentary call stack on error
ohneta 0:aae260bdcdd9 96 Added String Character functions
ohneta 0:aae260bdcdd9 97 Added shift operators
ohneta 0:aae260bdcdd9 98 Version 0.29 : Added new object via functions
ohneta 0:aae260bdcdd9 99 Fixed getString() for double on some platforms
ohneta 0:aae260bdcdd9 100 Version 0.30 : Rlyeh Mario's patch for Math Functions on VC++
ohneta 0:aae260bdcdd9 101 Version 0.31 : Add exec() to TinyJS functions
ohneta 0:aae260bdcdd9 102 Now print quoted JSON that can be read by PHP/Python parsers
ohneta 0:aae260bdcdd9 103 Fixed postfix increment operator
ohneta 0:aae260bdcdd9 104 Version 0.32 : Fixed Math.randInt on 32 bit PCs, where it was broken
ohneta 0:aae260bdcdd9 105 Version 0.33 : Fixed Memory leak + brokenness on === comparison
ohneta 0:aae260bdcdd9 106
ohneta 0:aae260bdcdd9 107 NOTE:
ohneta 0:aae260bdcdd9 108 Constructing an array with an initial length 'Array(5)' doesn't work
ohneta 0:aae260bdcdd9 109 Recursive loops of data such as a.foo = a; fail to be garbage collected
ohneta 0:aae260bdcdd9 110 length variable cannot be set
ohneta 0:aae260bdcdd9 111 The postfix increment operator returns the current value, not the previous as it should.
ohneta 0:aae260bdcdd9 112 There is no prefix increment operator
ohneta 0:aae260bdcdd9 113 Arrays are implemented as a linked list - hence a lookup time is O(n)
ohneta 0:aae260bdcdd9 114
ohneta 0:aae260bdcdd9 115 TODO:
ohneta 0:aae260bdcdd9 116 Utility va-args style function in TinyJS for executing a function directly
ohneta 0:aae260bdcdd9 117 Merge the parsing of expressions/statements so eval("statement") works like we'd expect.
ohneta 0:aae260bdcdd9 118 Move 'shift' implementation into mathsOp
ohneta 0:aae260bdcdd9 119
ohneta 0:aae260bdcdd9 120 */
ohneta 0:aae260bdcdd9 121 /*
ohneta 0:aae260bdcdd9 122 * TinyJS for mbed.
ohneta 0:aae260bdcdd9 123 *
ohneta 0:aae260bdcdd9 124 * Authored by Takehisa Oneta (ohneta@gmail.com)
ohneta 0:aae260bdcdd9 125 * 10th Jan. 2013
ohneta 0:aae260bdcdd9 126 */
ohneta 0:aae260bdcdd9 127
ohneta 0:aae260bdcdd9 128 #include "TinyJS.h"
ohneta 0:aae260bdcdd9 129 #include <assert.h>
ohneta 0:aae260bdcdd9 130
ohneta 0:aae260bdcdd9 131 #define ASSERT(X) assert(X)
ohneta 0:aae260bdcdd9 132 /* Frees the given link IF it isn't owned by anything else */
ohneta 0:aae260bdcdd9 133 #define CLEAN(x) { CScriptVarLink *__v = x; if (__v && !__v->owned) { delete __v; } }
ohneta 0:aae260bdcdd9 134 /* Create a LINK to point to VAR and free the old link.
ohneta 0:aae260bdcdd9 135 * BUT this is more clever - it tries to keep the old link if it's not owned to save allocations */
ohneta 0:aae260bdcdd9 136 #define CREATE_LINK(LINK, VAR) { if (!LINK || LINK->owned) LINK = new CScriptVarLink(VAR); else LINK->replaceWith(VAR); }
ohneta 0:aae260bdcdd9 137
ohneta 0:aae260bdcdd9 138 #include <string>
ohneta 0:aae260bdcdd9 139 #include <string.h>
ohneta 0:aae260bdcdd9 140 #include <sstream>
ohneta 0:aae260bdcdd9 141 #include <cstdlib>
ohneta 0:aae260bdcdd9 142 #include <stdio.h>
ohneta 0:aae260bdcdd9 143
ohneta 0:aae260bdcdd9 144 using namespace std;
ohneta 0:aae260bdcdd9 145
ohneta 0:aae260bdcdd9 146 #ifdef _WIN32
ohneta 0:aae260bdcdd9 147 #ifdef _DEBUG
ohneta 0:aae260bdcdd9 148 #ifndef DBG_NEW
ohneta 0:aae260bdcdd9 149 #define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
ohneta 0:aae260bdcdd9 150 #define new DBG_NEW
ohneta 0:aae260bdcdd9 151 #endif
ohneta 0:aae260bdcdd9 152 #endif
ohneta 0:aae260bdcdd9 153 #endif
ohneta 0:aae260bdcdd9 154
ohneta 0:aae260bdcdd9 155 #ifdef __GNUC__
ohneta 0:aae260bdcdd9 156 #define vsprintf_s vsnprintf
ohneta 0:aae260bdcdd9 157 #define sprintf_s snprintf
ohneta 0:aae260bdcdd9 158 #ifndef MBED
ohneta 0:aae260bdcdd9 159 #define _strdup strdup
ohneta 0:aae260bdcdd9 160 #else
ohneta 0:aae260bdcdd9 161 char *_strdup(const char *str)
ohneta 0:aae260bdcdd9 162 {
ohneta 0:aae260bdcdd9 163 size_t siz;
ohneta 0:aae260bdcdd9 164 char *copy;
ohneta 0:aae260bdcdd9 165
ohneta 0:aae260bdcdd9 166 siz = strlen(str) + 1;
ohneta 0:aae260bdcdd9 167 if ((copy = (char *)malloc(siz)) == NULL)
ohneta 0:aae260bdcdd9 168 return(NULL);
ohneta 0:aae260bdcdd9 169 (void)memcpy(copy, str, siz);
ohneta 0:aae260bdcdd9 170 return(copy);
ohneta 0:aae260bdcdd9 171 }
ohneta 0:aae260bdcdd9 172 #endif
ohneta 0:aae260bdcdd9 173 #endif
ohneta 0:aae260bdcdd9 174
ohneta 0:aae260bdcdd9 175 #ifdef MBED
ohneta 0:aae260bdcdd9 176 extern int mbedErrorFlag;
ohneta 0:aae260bdcdd9 177 extern std::string mbedErrorMessage;
ohneta 0:aae260bdcdd9 178
ohneta 0:aae260bdcdd9 179 #define LMATCH_VOID(c) {mbedErrorFlag = 0;l->match(c);if (mbedErrorFlag != 0) return;}
ohneta 0:aae260bdcdd9 180 #define LMATCH(c) {mbedErrorFlag = 0;l->match(c);if (mbedErrorFlag != 0) return 0;}
ohneta 0:aae260bdcdd9 181 //#define LMATCH_VOID(c) {l->match(c);}
ohneta 0:aae260bdcdd9 182 //#define LMATCH(c) {l->match(c);}
ohneta 0:aae260bdcdd9 183 #endif
ohneta 0:aae260bdcdd9 184
ohneta 0:aae260bdcdd9 185
ohneta 0:aae260bdcdd9 186 // ----------------------------------------------------------------------------------- Memory Debug
ohneta 0:aae260bdcdd9 187
ohneta 0:aae260bdcdd9 188 #if DEBUG_MEMORY
ohneta 0:aae260bdcdd9 189
ohneta 0:aae260bdcdd9 190 vector<CScriptVar*> allocatedVars;
ohneta 0:aae260bdcdd9 191 vector<CScriptVarLink*> allocatedLinks;
ohneta 0:aae260bdcdd9 192
ohneta 0:aae260bdcdd9 193 void mark_allocated(CScriptVar *v) {
ohneta 0:aae260bdcdd9 194 allocatedVars.push_back(v);
ohneta 0:aae260bdcdd9 195 }
ohneta 0:aae260bdcdd9 196
ohneta 0:aae260bdcdd9 197 void mark_deallocated(CScriptVar *v) {
ohneta 0:aae260bdcdd9 198 for (size_t i=0;i<allocatedVars.size();i++) {
ohneta 0:aae260bdcdd9 199 if (allocatedVars[i] == v) {
ohneta 0:aae260bdcdd9 200 allocatedVars.erase(allocatedVars.begin()+i);
ohneta 0:aae260bdcdd9 201 break;
ohneta 0:aae260bdcdd9 202 }
ohneta 0:aae260bdcdd9 203 }
ohneta 0:aae260bdcdd9 204 }
ohneta 0:aae260bdcdd9 205
ohneta 0:aae260bdcdd9 206 void mark_allocated(CScriptVarLink *v) {
ohneta 0:aae260bdcdd9 207 allocatedLinks.push_back(v);
ohneta 0:aae260bdcdd9 208 }
ohneta 0:aae260bdcdd9 209
ohneta 0:aae260bdcdd9 210 void mark_deallocated(CScriptVarLink *v) {
ohneta 0:aae260bdcdd9 211 for (size_t i=0;i<allocatedLinks.size();i++) {
ohneta 0:aae260bdcdd9 212 if (allocatedLinks[i] == v) {
ohneta 0:aae260bdcdd9 213 allocatedLinks.erase(allocatedLinks.begin()+i);
ohneta 0:aae260bdcdd9 214 break;
ohneta 0:aae260bdcdd9 215 }
ohneta 0:aae260bdcdd9 216 }
ohneta 0:aae260bdcdd9 217 }
ohneta 0:aae260bdcdd9 218
ohneta 0:aae260bdcdd9 219 void show_allocated() {
ohneta 0:aae260bdcdd9 220 for (size_t i=0;i<allocatedVars.size();i++) {
ohneta 0:aae260bdcdd9 221 printf("ALLOCATED, %d refs\n", allocatedVars[i]->getRefs());
ohneta 0:aae260bdcdd9 222 allocatedVars[i]->trace(" ");
ohneta 0:aae260bdcdd9 223 }
ohneta 0:aae260bdcdd9 224 for (size_t i=0;i<allocatedLinks.size();i++) {
ohneta 0:aae260bdcdd9 225 printf("ALLOCATED LINK %s, allocated[%d] to \n", allocatedLinks[i]->name.c_str(), allocatedLinks[i]->var->getRefs());
ohneta 0:aae260bdcdd9 226 allocatedLinks[i]->var->trace(" ");
ohneta 0:aae260bdcdd9 227 }
ohneta 0:aae260bdcdd9 228 allocatedVars.clear();
ohneta 0:aae260bdcdd9 229 allocatedLinks.clear();
ohneta 0:aae260bdcdd9 230 }
ohneta 0:aae260bdcdd9 231 #endif
ohneta 0:aae260bdcdd9 232
ohneta 0:aae260bdcdd9 233 // ----------------------------------------------------------------------------------- Utils
ohneta 0:aae260bdcdd9 234 bool isWhitespace(char ch) {
ohneta 0:aae260bdcdd9 235 return (ch==' ') || (ch=='\t') || (ch=='\n') || (ch=='\r');
ohneta 0:aae260bdcdd9 236 }
ohneta 0:aae260bdcdd9 237
ohneta 0:aae260bdcdd9 238 bool isNumeric(char ch) {
ohneta 0:aae260bdcdd9 239 return (ch>='0') && (ch<='9');
ohneta 0:aae260bdcdd9 240 }
ohneta 0:aae260bdcdd9 241 bool isNumber(const string &str) {
ohneta 0:aae260bdcdd9 242 for (size_t i=0;i<str.size();i++)
ohneta 0:aae260bdcdd9 243 if (!isNumeric(str[i])) return false;
ohneta 0:aae260bdcdd9 244 return true;
ohneta 0:aae260bdcdd9 245 }
ohneta 0:aae260bdcdd9 246 bool isHexadecimal(char ch) {
ohneta 0:aae260bdcdd9 247 return ((ch>='0') && (ch<='9')) ||
ohneta 0:aae260bdcdd9 248 ((ch>='a') && (ch<='f')) ||
ohneta 0:aae260bdcdd9 249 ((ch>='A') && (ch<='F'));
ohneta 0:aae260bdcdd9 250 }
ohneta 0:aae260bdcdd9 251 bool isAlpha(char ch) {
ohneta 0:aae260bdcdd9 252 return ((ch>='a') && (ch<='z')) || ((ch>='A') && (ch<='Z')) || ch=='_';
ohneta 0:aae260bdcdd9 253 }
ohneta 0:aae260bdcdd9 254
ohneta 0:aae260bdcdd9 255 bool isIDString(const char *s) {
ohneta 0:aae260bdcdd9 256 if (!isAlpha(*s))
ohneta 0:aae260bdcdd9 257 return false;
ohneta 0:aae260bdcdd9 258 while (*s) {
ohneta 0:aae260bdcdd9 259 if (!(isAlpha(*s) || isNumeric(*s)))
ohneta 0:aae260bdcdd9 260 return false;
ohneta 0:aae260bdcdd9 261 s++;
ohneta 0:aae260bdcdd9 262 }
ohneta 0:aae260bdcdd9 263 return true;
ohneta 0:aae260bdcdd9 264 }
ohneta 0:aae260bdcdd9 265
ohneta 0:aae260bdcdd9 266 void replace(string &str, char textFrom, const char *textTo) {
ohneta 0:aae260bdcdd9 267 int sLen = strlen(textTo);
ohneta 0:aae260bdcdd9 268 size_t p = str.find(textFrom);
ohneta 0:aae260bdcdd9 269 while (p != string::npos) {
ohneta 0:aae260bdcdd9 270 str = str.substr(0, p) + textTo + str.substr(p+1);
ohneta 0:aae260bdcdd9 271 p = str.find(textFrom, p+sLen);
ohneta 0:aae260bdcdd9 272 }
ohneta 0:aae260bdcdd9 273 }
ohneta 0:aae260bdcdd9 274
ohneta 0:aae260bdcdd9 275 /// convert the given string into a quoted string suitable for javascript
ohneta 0:aae260bdcdd9 276 std::string getJSString(const std::string &str) {
ohneta 0:aae260bdcdd9 277 std::string nStr = str;
ohneta 0:aae260bdcdd9 278 for (size_t i=0;i<nStr.size();i++) {
ohneta 0:aae260bdcdd9 279 const char *replaceWith = "";
ohneta 0:aae260bdcdd9 280 bool replace = true;
ohneta 0:aae260bdcdd9 281
ohneta 0:aae260bdcdd9 282 switch (nStr[i]) {
ohneta 0:aae260bdcdd9 283 case '\\': replaceWith = "\\\\"; break;
ohneta 0:aae260bdcdd9 284 case '\n': replaceWith = "\\n"; break;
ohneta 0:aae260bdcdd9 285 case '\r': replaceWith = "\\r"; break;
ohneta 0:aae260bdcdd9 286 case '\a': replaceWith = "\\a"; break;
ohneta 0:aae260bdcdd9 287 case '"': replaceWith = "\\\""; break;
ohneta 0:aae260bdcdd9 288 default: {
ohneta 0:aae260bdcdd9 289 int nCh = ((int)nStr[i]) &0xFF;
ohneta 0:aae260bdcdd9 290 if (nCh<32 || nCh>127) {
ohneta 0:aae260bdcdd9 291 char buffer[5];
ohneta 0:aae260bdcdd9 292 sprintf_s(buffer, 5, "\\x%02X", nCh);
ohneta 0:aae260bdcdd9 293 replaceWith = buffer;
ohneta 0:aae260bdcdd9 294 } else replace=false;
ohneta 0:aae260bdcdd9 295 }
ohneta 0:aae260bdcdd9 296 }
ohneta 0:aae260bdcdd9 297
ohneta 0:aae260bdcdd9 298 if (replace) {
ohneta 0:aae260bdcdd9 299 nStr = nStr.substr(0, i) + replaceWith + nStr.substr(i+1);
ohneta 0:aae260bdcdd9 300 i += strlen(replaceWith)-1;
ohneta 0:aae260bdcdd9 301 }
ohneta 0:aae260bdcdd9 302 }
ohneta 0:aae260bdcdd9 303 return "\"" + nStr + "\"";
ohneta 0:aae260bdcdd9 304 }
ohneta 0:aae260bdcdd9 305
ohneta 0:aae260bdcdd9 306 /** Is the string alphanumeric */
ohneta 0:aae260bdcdd9 307 bool isAlphaNum(const std::string &str) {
ohneta 0:aae260bdcdd9 308 if (str.size()==0) return true;
ohneta 0:aae260bdcdd9 309 if (!isAlpha(str[0])) return false;
ohneta 0:aae260bdcdd9 310 for (size_t i=0;i<str.size();i++)
ohneta 0:aae260bdcdd9 311 if (!(isAlpha(str[i]) || isNumeric(str[i])))
ohneta 0:aae260bdcdd9 312 return false;
ohneta 0:aae260bdcdd9 313 return true;
ohneta 0:aae260bdcdd9 314 }
ohneta 0:aae260bdcdd9 315
ohneta 0:aae260bdcdd9 316 // ----------------------------------------------------------------------------------- CSCRIPTEXCEPTION
ohneta 0:aae260bdcdd9 317
ohneta 0:aae260bdcdd9 318 CScriptException::CScriptException(const string &exceptionText) {
ohneta 0:aae260bdcdd9 319 text = exceptionText;
ohneta 0:aae260bdcdd9 320 }
ohneta 0:aae260bdcdd9 321
ohneta 0:aae260bdcdd9 322 // ----------------------------------------------------------------------------------- CSCRIPTLEX
ohneta 0:aae260bdcdd9 323
ohneta 0:aae260bdcdd9 324 CScriptLex::CScriptLex(const string &input) {
ohneta 0:aae260bdcdd9 325 data = _strdup(input.c_str());
ohneta 0:aae260bdcdd9 326 dataOwned = true;
ohneta 0:aae260bdcdd9 327 dataStart = 0;
ohneta 0:aae260bdcdd9 328 dataEnd = strlen(data);
ohneta 0:aae260bdcdd9 329 reset();
ohneta 0:aae260bdcdd9 330 }
ohneta 0:aae260bdcdd9 331
ohneta 0:aae260bdcdd9 332 CScriptLex::CScriptLex(CScriptLex *owner, int startChar, int endChar) {
ohneta 0:aae260bdcdd9 333 data = owner->data;
ohneta 0:aae260bdcdd9 334 dataOwned = false;
ohneta 0:aae260bdcdd9 335 dataStart = startChar;
ohneta 0:aae260bdcdd9 336 dataEnd = endChar;
ohneta 0:aae260bdcdd9 337 reset();
ohneta 0:aae260bdcdd9 338 }
ohneta 0:aae260bdcdd9 339
ohneta 0:aae260bdcdd9 340 CScriptLex::~CScriptLex(void)
ohneta 0:aae260bdcdd9 341 {
ohneta 0:aae260bdcdd9 342 if (dataOwned)
ohneta 0:aae260bdcdd9 343 free((void*)data);
ohneta 0:aae260bdcdd9 344 }
ohneta 0:aae260bdcdd9 345
ohneta 0:aae260bdcdd9 346 void CScriptLex::reset() {
ohneta 0:aae260bdcdd9 347 dataPos = dataStart;
ohneta 0:aae260bdcdd9 348 tokenStart = 0;
ohneta 0:aae260bdcdd9 349 tokenEnd = 0;
ohneta 0:aae260bdcdd9 350 tokenLastEnd = 0;
ohneta 0:aae260bdcdd9 351 tk = 0;
ohneta 0:aae260bdcdd9 352 tkStr = "";
ohneta 0:aae260bdcdd9 353 getNextCh();
ohneta 0:aae260bdcdd9 354 getNextCh();
ohneta 0:aae260bdcdd9 355 getNextToken();
ohneta 0:aae260bdcdd9 356 }
ohneta 0:aae260bdcdd9 357
ohneta 0:aae260bdcdd9 358 void CScriptLex::match(int expected_tk) {
ohneta 0:aae260bdcdd9 359 if (tk!=expected_tk) {
ohneta 0:aae260bdcdd9 360 #ifndef MBED
ohneta 0:aae260bdcdd9 361 ostringstream errorString;
ohneta 0:aae260bdcdd9 362 errorString << "Got " << getTokenStr(tk) << " expected " << getTokenStr(expected_tk)
ohneta 0:aae260bdcdd9 363 << " at " << getPosition(tokenStart);
ohneta 0:aae260bdcdd9 364 throw new CScriptException(errorString.str());
ohneta 0:aae260bdcdd9 365 #else
ohneta 0:aae260bdcdd9 366 mbedErrorFlag = 1;
ohneta 0:aae260bdcdd9 367 mbedErrorMessage = "Got ";
ohneta 0:aae260bdcdd9 368 mbedErrorMessage += getTokenStr(tk);
ohneta 0:aae260bdcdd9 369 mbedErrorMessage += " expected ";
ohneta 0:aae260bdcdd9 370 mbedErrorMessage += getTokenStr(expected_tk);
ohneta 0:aae260bdcdd9 371 mbedErrorMessage += " at ";
ohneta 0:aae260bdcdd9 372 mbedErrorMessage += getPosition(tokenStart);
ohneta 0:aae260bdcdd9 373 return;
ohneta 0:aae260bdcdd9 374 #endif
ohneta 0:aae260bdcdd9 375 }
ohneta 0:aae260bdcdd9 376 getNextToken();
ohneta 0:aae260bdcdd9 377 }
ohneta 0:aae260bdcdd9 378
ohneta 0:aae260bdcdd9 379 string CScriptLex::getTokenStr(int token) {
ohneta 0:aae260bdcdd9 380 if (token>32 && token<128) {
ohneta 0:aae260bdcdd9 381 char buf[4] = "' '";
ohneta 0:aae260bdcdd9 382 buf[1] = (char)token;
ohneta 0:aae260bdcdd9 383 return buf;
ohneta 0:aae260bdcdd9 384 }
ohneta 0:aae260bdcdd9 385 switch (token) {
ohneta 0:aae260bdcdd9 386 case LEX_EOF : return "EOF";
ohneta 0:aae260bdcdd9 387 case LEX_ID : return "ID";
ohneta 0:aae260bdcdd9 388 case LEX_INT : return "INT";
ohneta 0:aae260bdcdd9 389 case LEX_FLOAT : return "FLOAT";
ohneta 0:aae260bdcdd9 390 case LEX_STR : return "STRING";
ohneta 0:aae260bdcdd9 391 case LEX_EQUAL : return "==";
ohneta 0:aae260bdcdd9 392 case LEX_TYPEEQUAL : return "===";
ohneta 0:aae260bdcdd9 393 case LEX_NEQUAL : return "!=";
ohneta 0:aae260bdcdd9 394 case LEX_NTYPEEQUAL : return "!==";
ohneta 0:aae260bdcdd9 395 case LEX_LEQUAL : return "<=";
ohneta 0:aae260bdcdd9 396 case LEX_LSHIFT : return "<<";
ohneta 0:aae260bdcdd9 397 case LEX_LSHIFTEQUAL : return "<<=";
ohneta 0:aae260bdcdd9 398 case LEX_GEQUAL : return ">=";
ohneta 0:aae260bdcdd9 399 case LEX_RSHIFT : return ">>";
ohneta 0:aae260bdcdd9 400 case LEX_RSHIFTUNSIGNED : return ">>";
ohneta 0:aae260bdcdd9 401 case LEX_RSHIFTEQUAL : return ">>=";
ohneta 0:aae260bdcdd9 402 case LEX_PLUSEQUAL : return "+=";
ohneta 0:aae260bdcdd9 403 case LEX_MINUSEQUAL : return "-=";
ohneta 0:aae260bdcdd9 404 case LEX_PLUSPLUS : return "++";
ohneta 0:aae260bdcdd9 405 case LEX_MINUSMINUS : return "--";
ohneta 0:aae260bdcdd9 406 case LEX_ANDEQUAL : return "&=";
ohneta 0:aae260bdcdd9 407 case LEX_ANDAND : return "&&";
ohneta 0:aae260bdcdd9 408 case LEX_OREQUAL : return "|=";
ohneta 0:aae260bdcdd9 409 case LEX_OROR : return "||";
ohneta 0:aae260bdcdd9 410 case LEX_XOREQUAL : return "^=";
ohneta 0:aae260bdcdd9 411 // reserved words
ohneta 0:aae260bdcdd9 412 case LEX_R_IF : return "if";
ohneta 0:aae260bdcdd9 413 case LEX_R_ELSE : return "else";
ohneta 0:aae260bdcdd9 414 case LEX_R_DO : return "do";
ohneta 0:aae260bdcdd9 415 case LEX_R_WHILE : return "while";
ohneta 0:aae260bdcdd9 416 case LEX_R_FOR : return "for";
ohneta 0:aae260bdcdd9 417 case LEX_R_BREAK : return "break";
ohneta 0:aae260bdcdd9 418 case LEX_R_CONTINUE : return "continue";
ohneta 0:aae260bdcdd9 419 case LEX_R_FUNCTION : return "function";
ohneta 0:aae260bdcdd9 420 case LEX_R_RETURN : return "return";
ohneta 0:aae260bdcdd9 421 case LEX_R_VAR : return "var";
ohneta 0:aae260bdcdd9 422 case LEX_R_TRUE : return "true";
ohneta 0:aae260bdcdd9 423 case LEX_R_FALSE : return "false";
ohneta 0:aae260bdcdd9 424 case LEX_R_NULL : return "null";
ohneta 0:aae260bdcdd9 425 case LEX_R_UNDEFINED : return "undefined";
ohneta 0:aae260bdcdd9 426 case LEX_R_NEW : return "new";
ohneta 0:aae260bdcdd9 427 }
ohneta 0:aae260bdcdd9 428
ohneta 0:aae260bdcdd9 429 #ifndef MBED
ohneta 0:aae260bdcdd9 430 ostringstream msg;
ohneta 0:aae260bdcdd9 431 msg << "?[" << token << "]";
ohneta 0:aae260bdcdd9 432 return msg.str();
ohneta 0:aae260bdcdd9 433 #else
ohneta 0:aae260bdcdd9 434 string msg;
ohneta 0:aae260bdcdd9 435 msg = "?[";
ohneta 0:aae260bdcdd9 436 msg += token;
ohneta 0:aae260bdcdd9 437 msg += "]";
ohneta 0:aae260bdcdd9 438 return msg;
ohneta 0:aae260bdcdd9 439 #endif
ohneta 0:aae260bdcdd9 440 }
ohneta 0:aae260bdcdd9 441
ohneta 0:aae260bdcdd9 442 void CScriptLex::getNextCh() {
ohneta 0:aae260bdcdd9 443 currCh = nextCh;
ohneta 0:aae260bdcdd9 444 if (dataPos < dataEnd)
ohneta 0:aae260bdcdd9 445 nextCh = data[dataPos];
ohneta 0:aae260bdcdd9 446 else
ohneta 0:aae260bdcdd9 447 nextCh = 0;
ohneta 0:aae260bdcdd9 448 dataPos++;
ohneta 0:aae260bdcdd9 449 }
ohneta 0:aae260bdcdd9 450
ohneta 0:aae260bdcdd9 451 void CScriptLex::getNextToken() {
ohneta 0:aae260bdcdd9 452 tk = LEX_EOF;
ohneta 0:aae260bdcdd9 453 tkStr.clear();
ohneta 0:aae260bdcdd9 454 while (currCh && isWhitespace(currCh)) getNextCh();
ohneta 0:aae260bdcdd9 455 // newline comments
ohneta 0:aae260bdcdd9 456 if (currCh=='/' && nextCh=='/') {
ohneta 0:aae260bdcdd9 457 while (currCh && currCh!='\n') getNextCh();
ohneta 0:aae260bdcdd9 458 getNextCh();
ohneta 0:aae260bdcdd9 459 getNextToken();
ohneta 0:aae260bdcdd9 460 return;
ohneta 0:aae260bdcdd9 461 }
ohneta 0:aae260bdcdd9 462 // block comments
ohneta 0:aae260bdcdd9 463 if (currCh=='/' && nextCh=='*') {
ohneta 0:aae260bdcdd9 464 while (currCh && (currCh!='*' || nextCh!='/')) getNextCh();
ohneta 0:aae260bdcdd9 465 getNextCh();
ohneta 0:aae260bdcdd9 466 getNextCh();
ohneta 0:aae260bdcdd9 467 getNextToken();
ohneta 0:aae260bdcdd9 468 return;
ohneta 0:aae260bdcdd9 469 }
ohneta 0:aae260bdcdd9 470 // record beginning of this token
ohneta 0:aae260bdcdd9 471 tokenStart = dataPos-2;
ohneta 0:aae260bdcdd9 472 // tokens
ohneta 0:aae260bdcdd9 473 if (isAlpha(currCh)) { // IDs
ohneta 0:aae260bdcdd9 474 while (isAlpha(currCh) || isNumeric(currCh)) {
ohneta 0:aae260bdcdd9 475 tkStr += currCh;
ohneta 0:aae260bdcdd9 476 getNextCh();
ohneta 0:aae260bdcdd9 477 }
ohneta 0:aae260bdcdd9 478 tk = LEX_ID;
ohneta 0:aae260bdcdd9 479 if (tkStr=="if") tk = LEX_R_IF;
ohneta 0:aae260bdcdd9 480 else if (tkStr=="else") tk = LEX_R_ELSE;
ohneta 0:aae260bdcdd9 481 else if (tkStr=="do") tk = LEX_R_DO;
ohneta 0:aae260bdcdd9 482 else if (tkStr=="while") tk = LEX_R_WHILE;
ohneta 0:aae260bdcdd9 483 else if (tkStr=="for") tk = LEX_R_FOR;
ohneta 0:aae260bdcdd9 484 else if (tkStr=="break") tk = LEX_R_BREAK;
ohneta 0:aae260bdcdd9 485 else if (tkStr=="continue") tk = LEX_R_CONTINUE;
ohneta 0:aae260bdcdd9 486 else if (tkStr=="function") tk = LEX_R_FUNCTION;
ohneta 0:aae260bdcdd9 487 else if (tkStr=="return") tk = LEX_R_RETURN;
ohneta 0:aae260bdcdd9 488 else if (tkStr=="var") tk = LEX_R_VAR;
ohneta 0:aae260bdcdd9 489 else if (tkStr=="true") tk = LEX_R_TRUE;
ohneta 0:aae260bdcdd9 490 else if (tkStr=="false") tk = LEX_R_FALSE;
ohneta 0:aae260bdcdd9 491 else if (tkStr=="null") tk = LEX_R_NULL;
ohneta 0:aae260bdcdd9 492 else if (tkStr=="undefined") tk = LEX_R_UNDEFINED;
ohneta 0:aae260bdcdd9 493 else if (tkStr=="new") tk = LEX_R_NEW;
ohneta 0:aae260bdcdd9 494 } else if (isNumeric(currCh)) { // Numbers
ohneta 0:aae260bdcdd9 495 bool isHex = false;
ohneta 0:aae260bdcdd9 496 if (currCh=='0') { tkStr += currCh; getNextCh(); }
ohneta 0:aae260bdcdd9 497 if (currCh=='x') {
ohneta 0:aae260bdcdd9 498 isHex = true;
ohneta 0:aae260bdcdd9 499 tkStr += currCh; getNextCh();
ohneta 0:aae260bdcdd9 500 }
ohneta 0:aae260bdcdd9 501 tk = LEX_INT;
ohneta 0:aae260bdcdd9 502 while (isNumeric(currCh) || (isHex && isHexadecimal(currCh))) {
ohneta 0:aae260bdcdd9 503 tkStr += currCh;
ohneta 0:aae260bdcdd9 504 getNextCh();
ohneta 0:aae260bdcdd9 505 }
ohneta 0:aae260bdcdd9 506 if (!isHex && currCh=='.') {
ohneta 0:aae260bdcdd9 507 tk = LEX_FLOAT;
ohneta 0:aae260bdcdd9 508 tkStr += '.';
ohneta 0:aae260bdcdd9 509 getNextCh();
ohneta 0:aae260bdcdd9 510 while (isNumeric(currCh)) {
ohneta 0:aae260bdcdd9 511 tkStr += currCh;
ohneta 0:aae260bdcdd9 512 getNextCh();
ohneta 0:aae260bdcdd9 513 }
ohneta 0:aae260bdcdd9 514 }
ohneta 0:aae260bdcdd9 515 // do fancy e-style floating point
ohneta 0:aae260bdcdd9 516 if (!isHex && (currCh=='e'||currCh=='E')) {
ohneta 0:aae260bdcdd9 517 tk = LEX_FLOAT;
ohneta 0:aae260bdcdd9 518 tkStr += currCh; getNextCh();
ohneta 0:aae260bdcdd9 519 if (currCh=='-') { tkStr += currCh; getNextCh(); }
ohneta 0:aae260bdcdd9 520 while (isNumeric(currCh)) {
ohneta 0:aae260bdcdd9 521 tkStr += currCh; getNextCh();
ohneta 0:aae260bdcdd9 522 }
ohneta 0:aae260bdcdd9 523 }
ohneta 0:aae260bdcdd9 524 } else if (currCh=='"') {
ohneta 0:aae260bdcdd9 525 // strings...
ohneta 0:aae260bdcdd9 526 getNextCh();
ohneta 0:aae260bdcdd9 527 while (currCh && currCh!='"') {
ohneta 0:aae260bdcdd9 528 if (currCh == '\\') {
ohneta 0:aae260bdcdd9 529 getNextCh();
ohneta 0:aae260bdcdd9 530 switch (currCh) {
ohneta 0:aae260bdcdd9 531 case 'n' : tkStr += '\n'; break;
ohneta 0:aae260bdcdd9 532 case '"' : tkStr += '"'; break;
ohneta 0:aae260bdcdd9 533 case '\\' : tkStr += '\\'; break;
ohneta 0:aae260bdcdd9 534 default: tkStr += currCh;
ohneta 0:aae260bdcdd9 535 }
ohneta 0:aae260bdcdd9 536 } else {
ohneta 0:aae260bdcdd9 537 tkStr += currCh;
ohneta 0:aae260bdcdd9 538 }
ohneta 0:aae260bdcdd9 539 getNextCh();
ohneta 0:aae260bdcdd9 540 }
ohneta 0:aae260bdcdd9 541 getNextCh();
ohneta 0:aae260bdcdd9 542 tk = LEX_STR;
ohneta 0:aae260bdcdd9 543 } else if (currCh=='\'') {
ohneta 0:aae260bdcdd9 544 // strings again...
ohneta 0:aae260bdcdd9 545 getNextCh();
ohneta 0:aae260bdcdd9 546 while (currCh && currCh!='\'') {
ohneta 0:aae260bdcdd9 547 if (currCh == '\\') {
ohneta 0:aae260bdcdd9 548 getNextCh();
ohneta 0:aae260bdcdd9 549 switch (currCh) {
ohneta 0:aae260bdcdd9 550 case 'n' : tkStr += '\n'; break;
ohneta 0:aae260bdcdd9 551 case 'a' : tkStr += '\a'; break;
ohneta 0:aae260bdcdd9 552 case 'r' : tkStr += '\r'; break;
ohneta 0:aae260bdcdd9 553 case 't' : tkStr += '\t'; break;
ohneta 0:aae260bdcdd9 554 case '\'' : tkStr += '\''; break;
ohneta 0:aae260bdcdd9 555 case '\\' : tkStr += '\\'; break;
ohneta 0:aae260bdcdd9 556 case 'x' : { // hex digits
ohneta 0:aae260bdcdd9 557 char buf[3] = "??";
ohneta 0:aae260bdcdd9 558 getNextCh(); buf[0] = currCh;
ohneta 0:aae260bdcdd9 559 getNextCh(); buf[1] = currCh;
ohneta 0:aae260bdcdd9 560 tkStr += (char)strtol(buf,0,16);
ohneta 0:aae260bdcdd9 561 } break;
ohneta 0:aae260bdcdd9 562 default: if (currCh>='0' && currCh<='7') {
ohneta 0:aae260bdcdd9 563 // octal digits
ohneta 0:aae260bdcdd9 564 char buf[4] = "???";
ohneta 0:aae260bdcdd9 565 buf[0] = currCh;
ohneta 0:aae260bdcdd9 566 getNextCh(); buf[1] = currCh;
ohneta 0:aae260bdcdd9 567 getNextCh(); buf[2] = currCh;
ohneta 0:aae260bdcdd9 568 tkStr += (char)strtol(buf,0,8);
ohneta 0:aae260bdcdd9 569 } else
ohneta 0:aae260bdcdd9 570 tkStr += currCh;
ohneta 0:aae260bdcdd9 571 }
ohneta 0:aae260bdcdd9 572 } else {
ohneta 0:aae260bdcdd9 573 tkStr += currCh;
ohneta 0:aae260bdcdd9 574 }
ohneta 0:aae260bdcdd9 575 getNextCh();
ohneta 0:aae260bdcdd9 576 }
ohneta 0:aae260bdcdd9 577 getNextCh();
ohneta 0:aae260bdcdd9 578 tk = LEX_STR;
ohneta 0:aae260bdcdd9 579 } else {
ohneta 0:aae260bdcdd9 580 // single chars
ohneta 0:aae260bdcdd9 581 tk = currCh;
ohneta 0:aae260bdcdd9 582 if (currCh) getNextCh();
ohneta 0:aae260bdcdd9 583 if (tk=='=' && currCh=='=') { // ==
ohneta 0:aae260bdcdd9 584 tk = LEX_EQUAL;
ohneta 0:aae260bdcdd9 585 getNextCh();
ohneta 0:aae260bdcdd9 586 if (currCh=='=') { // ===
ohneta 0:aae260bdcdd9 587 tk = LEX_TYPEEQUAL;
ohneta 0:aae260bdcdd9 588 getNextCh();
ohneta 0:aae260bdcdd9 589 }
ohneta 0:aae260bdcdd9 590 } else if (tk=='!' && currCh=='=') { // !=
ohneta 0:aae260bdcdd9 591 tk = LEX_NEQUAL;
ohneta 0:aae260bdcdd9 592 getNextCh();
ohneta 0:aae260bdcdd9 593 if (currCh=='=') { // !==
ohneta 0:aae260bdcdd9 594 tk = LEX_NTYPEEQUAL;
ohneta 0:aae260bdcdd9 595 getNextCh();
ohneta 0:aae260bdcdd9 596 }
ohneta 0:aae260bdcdd9 597 } else if (tk=='<' && currCh=='=') {
ohneta 0:aae260bdcdd9 598 tk = LEX_LEQUAL;
ohneta 0:aae260bdcdd9 599 getNextCh();
ohneta 0:aae260bdcdd9 600 } else if (tk=='<' && currCh=='<') {
ohneta 0:aae260bdcdd9 601 tk = LEX_LSHIFT;
ohneta 0:aae260bdcdd9 602 getNextCh();
ohneta 0:aae260bdcdd9 603 if (currCh=='=') { // <<=
ohneta 0:aae260bdcdd9 604 tk = LEX_LSHIFTEQUAL;
ohneta 0:aae260bdcdd9 605 getNextCh();
ohneta 0:aae260bdcdd9 606 }
ohneta 0:aae260bdcdd9 607 } else if (tk=='>' && currCh=='=') {
ohneta 0:aae260bdcdd9 608 tk = LEX_GEQUAL;
ohneta 0:aae260bdcdd9 609 getNextCh();
ohneta 0:aae260bdcdd9 610 } else if (tk=='>' && currCh=='>') {
ohneta 0:aae260bdcdd9 611 tk = LEX_RSHIFT;
ohneta 0:aae260bdcdd9 612 getNextCh();
ohneta 0:aae260bdcdd9 613 if (currCh=='=') { // >>=
ohneta 0:aae260bdcdd9 614 tk = LEX_RSHIFTEQUAL;
ohneta 0:aae260bdcdd9 615 getNextCh();
ohneta 0:aae260bdcdd9 616 } else if (currCh=='>') { // >>>
ohneta 0:aae260bdcdd9 617 tk = LEX_RSHIFTUNSIGNED;
ohneta 0:aae260bdcdd9 618 getNextCh();
ohneta 0:aae260bdcdd9 619 }
ohneta 0:aae260bdcdd9 620 } else if (tk=='+' && currCh=='=') {
ohneta 0:aae260bdcdd9 621 tk = LEX_PLUSEQUAL;
ohneta 0:aae260bdcdd9 622 getNextCh();
ohneta 0:aae260bdcdd9 623 } else if (tk=='-' && currCh=='=') {
ohneta 0:aae260bdcdd9 624 tk = LEX_MINUSEQUAL;
ohneta 0:aae260bdcdd9 625 getNextCh();
ohneta 0:aae260bdcdd9 626 } else if (tk=='+' && currCh=='+') {
ohneta 0:aae260bdcdd9 627 tk = LEX_PLUSPLUS;
ohneta 0:aae260bdcdd9 628 getNextCh();
ohneta 0:aae260bdcdd9 629 } else if (tk=='-' && currCh=='-') {
ohneta 0:aae260bdcdd9 630 tk = LEX_MINUSMINUS;
ohneta 0:aae260bdcdd9 631 getNextCh();
ohneta 0:aae260bdcdd9 632 } else if (tk=='&' && currCh=='=') {
ohneta 0:aae260bdcdd9 633 tk = LEX_ANDEQUAL;
ohneta 0:aae260bdcdd9 634 getNextCh();
ohneta 0:aae260bdcdd9 635 } else if (tk=='&' && currCh=='&') {
ohneta 0:aae260bdcdd9 636 tk = LEX_ANDAND;
ohneta 0:aae260bdcdd9 637 getNextCh();
ohneta 0:aae260bdcdd9 638 } else if (tk=='|' && currCh=='=') {
ohneta 0:aae260bdcdd9 639 tk = LEX_OREQUAL;
ohneta 0:aae260bdcdd9 640 getNextCh();
ohneta 0:aae260bdcdd9 641 } else if (tk=='|' && currCh=='|') {
ohneta 0:aae260bdcdd9 642 tk = LEX_OROR;
ohneta 0:aae260bdcdd9 643 getNextCh();
ohneta 0:aae260bdcdd9 644 } else if (tk=='^' && currCh=='=') {
ohneta 0:aae260bdcdd9 645 tk = LEX_XOREQUAL;
ohneta 0:aae260bdcdd9 646 getNextCh();
ohneta 0:aae260bdcdd9 647 }
ohneta 0:aae260bdcdd9 648 }
ohneta 0:aae260bdcdd9 649 /* This isn't quite right yet */
ohneta 0:aae260bdcdd9 650 tokenLastEnd = tokenEnd;
ohneta 0:aae260bdcdd9 651 tokenEnd = dataPos-3;
ohneta 0:aae260bdcdd9 652 }
ohneta 0:aae260bdcdd9 653
ohneta 0:aae260bdcdd9 654 string CScriptLex::getSubString(int lastPosition) {
ohneta 0:aae260bdcdd9 655 int lastCharIdx = tokenLastEnd+1;
ohneta 0:aae260bdcdd9 656 if (lastCharIdx < dataEnd) {
ohneta 0:aae260bdcdd9 657 /* save a memory alloc by using our data array to create the
ohneta 0:aae260bdcdd9 658 substring */
ohneta 0:aae260bdcdd9 659 char old = data[lastCharIdx];
ohneta 0:aae260bdcdd9 660 data[lastCharIdx] = 0;
ohneta 0:aae260bdcdd9 661 std::string value = &data[lastPosition];
ohneta 0:aae260bdcdd9 662 data[lastCharIdx] = old;
ohneta 0:aae260bdcdd9 663 return value;
ohneta 0:aae260bdcdd9 664 } else {
ohneta 0:aae260bdcdd9 665 return std::string(&data[lastPosition]);
ohneta 0:aae260bdcdd9 666 }
ohneta 0:aae260bdcdd9 667 }
ohneta 0:aae260bdcdd9 668
ohneta 0:aae260bdcdd9 669
ohneta 0:aae260bdcdd9 670 CScriptLex *CScriptLex::getSubLex(int lastPosition) {
ohneta 0:aae260bdcdd9 671 int lastCharIdx = tokenLastEnd+1;
ohneta 0:aae260bdcdd9 672 if (lastCharIdx < dataEnd)
ohneta 0:aae260bdcdd9 673 return new CScriptLex(this, lastPosition, lastCharIdx);
ohneta 0:aae260bdcdd9 674 else
ohneta 0:aae260bdcdd9 675 return new CScriptLex(this, lastPosition, dataEnd );
ohneta 0:aae260bdcdd9 676 }
ohneta 0:aae260bdcdd9 677
ohneta 0:aae260bdcdd9 678 string CScriptLex::getPosition(int pos) {
ohneta 0:aae260bdcdd9 679 if (pos<0) pos=tokenLastEnd;
ohneta 0:aae260bdcdd9 680 int line = 1,col = 1;
ohneta 0:aae260bdcdd9 681 for (int i=0;i<pos;i++) {
ohneta 0:aae260bdcdd9 682 char ch;
ohneta 0:aae260bdcdd9 683 if (i < dataEnd)
ohneta 0:aae260bdcdd9 684 ch = data[i];
ohneta 0:aae260bdcdd9 685 else
ohneta 0:aae260bdcdd9 686 ch = 0;
ohneta 0:aae260bdcdd9 687 col++;
ohneta 0:aae260bdcdd9 688 if (ch=='\n') {
ohneta 0:aae260bdcdd9 689 line++;
ohneta 0:aae260bdcdd9 690 col = 0;
ohneta 0:aae260bdcdd9 691 }
ohneta 0:aae260bdcdd9 692 }
ohneta 0:aae260bdcdd9 693 char buf[256];
ohneta 0:aae260bdcdd9 694 sprintf_s(buf, 256, "(line: %d, col: %d)", line, col);
ohneta 0:aae260bdcdd9 695 return buf;
ohneta 0:aae260bdcdd9 696 }
ohneta 0:aae260bdcdd9 697
ohneta 0:aae260bdcdd9 698 // ----------------------------------------------------------------------------------- CSCRIPTVARLINK
ohneta 0:aae260bdcdd9 699
ohneta 0:aae260bdcdd9 700 CScriptVarLink::CScriptVarLink(CScriptVar *var, const std::string &name) {
ohneta 0:aae260bdcdd9 701 #if DEBUG_MEMORY
ohneta 0:aae260bdcdd9 702 mark_allocated(this);
ohneta 0:aae260bdcdd9 703 #endif
ohneta 0:aae260bdcdd9 704 this->name = name;
ohneta 0:aae260bdcdd9 705 this->nextSibling = 0;
ohneta 0:aae260bdcdd9 706 this->prevSibling = 0;
ohneta 0:aae260bdcdd9 707 this->var = var->ref();
ohneta 0:aae260bdcdd9 708 this->owned = false;
ohneta 0:aae260bdcdd9 709 }
ohneta 0:aae260bdcdd9 710
ohneta 0:aae260bdcdd9 711 CScriptVarLink::CScriptVarLink(const CScriptVarLink &link) {
ohneta 0:aae260bdcdd9 712 // Copy constructor
ohneta 0:aae260bdcdd9 713 #if DEBUG_MEMORY
ohneta 0:aae260bdcdd9 714 mark_allocated(this);
ohneta 0:aae260bdcdd9 715 #endif
ohneta 0:aae260bdcdd9 716 this->name = link.name;
ohneta 0:aae260bdcdd9 717 this->nextSibling = 0;
ohneta 0:aae260bdcdd9 718 this->prevSibling = 0;
ohneta 0:aae260bdcdd9 719 this->var = link.var->ref();
ohneta 0:aae260bdcdd9 720 this->owned = false;
ohneta 0:aae260bdcdd9 721 }
ohneta 0:aae260bdcdd9 722
ohneta 0:aae260bdcdd9 723 CScriptVarLink::~CScriptVarLink() {
ohneta 0:aae260bdcdd9 724 #if DEBUG_MEMORY
ohneta 0:aae260bdcdd9 725 mark_deallocated(this);
ohneta 0:aae260bdcdd9 726 #endif
ohneta 0:aae260bdcdd9 727 var->unref();
ohneta 0:aae260bdcdd9 728 }
ohneta 0:aae260bdcdd9 729
ohneta 0:aae260bdcdd9 730 void CScriptVarLink::replaceWith(CScriptVar *newVar) {
ohneta 0:aae260bdcdd9 731 CScriptVar *oldVar = var;
ohneta 0:aae260bdcdd9 732 var = newVar->ref();
ohneta 0:aae260bdcdd9 733 oldVar->unref();
ohneta 0:aae260bdcdd9 734 }
ohneta 0:aae260bdcdd9 735
ohneta 0:aae260bdcdd9 736 void CScriptVarLink::replaceWith(CScriptVarLink *newVar) {
ohneta 0:aae260bdcdd9 737 if (newVar)
ohneta 0:aae260bdcdd9 738 replaceWith(newVar->var);
ohneta 0:aae260bdcdd9 739 else
ohneta 0:aae260bdcdd9 740 replaceWith(new CScriptVar());
ohneta 0:aae260bdcdd9 741 }
ohneta 0:aae260bdcdd9 742
ohneta 0:aae260bdcdd9 743 int CScriptVarLink::getIntName() {
ohneta 0:aae260bdcdd9 744 return atoi(name.c_str());
ohneta 0:aae260bdcdd9 745 }
ohneta 0:aae260bdcdd9 746 void CScriptVarLink::setIntName(int n) {
ohneta 0:aae260bdcdd9 747 char sIdx[64];
ohneta 0:aae260bdcdd9 748 sprintf_s(sIdx, sizeof(sIdx), "%d", n);
ohneta 0:aae260bdcdd9 749 name = sIdx;
ohneta 0:aae260bdcdd9 750 }
ohneta 0:aae260bdcdd9 751
ohneta 0:aae260bdcdd9 752 // ----------------------------------------------------------------------------------- CSCRIPTVAR
ohneta 0:aae260bdcdd9 753
ohneta 0:aae260bdcdd9 754 CScriptVar::CScriptVar() {
ohneta 0:aae260bdcdd9 755 refs = 0;
ohneta 0:aae260bdcdd9 756 #if DEBUG_MEMORY
ohneta 0:aae260bdcdd9 757 mark_allocated(this);
ohneta 0:aae260bdcdd9 758 #endif
ohneta 0:aae260bdcdd9 759 init();
ohneta 0:aae260bdcdd9 760 flags = SCRIPTVAR_UNDEFINED;
ohneta 0:aae260bdcdd9 761 }
ohneta 0:aae260bdcdd9 762
ohneta 0:aae260bdcdd9 763 CScriptVar::CScriptVar(const string &str) {
ohneta 0:aae260bdcdd9 764 refs = 0;
ohneta 0:aae260bdcdd9 765 #if DEBUG_MEMORY
ohneta 0:aae260bdcdd9 766 mark_allocated(this);
ohneta 0:aae260bdcdd9 767 #endif
ohneta 0:aae260bdcdd9 768 init();
ohneta 0:aae260bdcdd9 769 flags = SCRIPTVAR_STRING;
ohneta 0:aae260bdcdd9 770 data = str;
ohneta 0:aae260bdcdd9 771 }
ohneta 0:aae260bdcdd9 772
ohneta 0:aae260bdcdd9 773
ohneta 0:aae260bdcdd9 774 CScriptVar::CScriptVar(const string &varData, int varFlags) {
ohneta 0:aae260bdcdd9 775 refs = 0;
ohneta 0:aae260bdcdd9 776 #if DEBUG_MEMORY
ohneta 0:aae260bdcdd9 777 mark_allocated(this);
ohneta 0:aae260bdcdd9 778 #endif
ohneta 0:aae260bdcdd9 779 init();
ohneta 0:aae260bdcdd9 780 flags = varFlags;
ohneta 0:aae260bdcdd9 781 if (varFlags & SCRIPTVAR_INTEGER) {
ohneta 0:aae260bdcdd9 782 intData = strtol(varData.c_str(),0,0);
ohneta 0:aae260bdcdd9 783 } else if (varFlags & SCRIPTVAR_DOUBLE) {
ohneta 0:aae260bdcdd9 784 doubleData = strtod(varData.c_str(),0);
ohneta 0:aae260bdcdd9 785 } else
ohneta 0:aae260bdcdd9 786 data = varData;
ohneta 0:aae260bdcdd9 787 }
ohneta 0:aae260bdcdd9 788
ohneta 0:aae260bdcdd9 789 CScriptVar::CScriptVar(double val) {
ohneta 0:aae260bdcdd9 790 refs = 0;
ohneta 0:aae260bdcdd9 791 #if DEBUG_MEMORY
ohneta 0:aae260bdcdd9 792 mark_allocated(this);
ohneta 0:aae260bdcdd9 793 #endif
ohneta 0:aae260bdcdd9 794 init();
ohneta 0:aae260bdcdd9 795 setDouble(val);
ohneta 0:aae260bdcdd9 796 }
ohneta 0:aae260bdcdd9 797
ohneta 0:aae260bdcdd9 798 CScriptVar::CScriptVar(int val) {
ohneta 0:aae260bdcdd9 799 refs = 0;
ohneta 0:aae260bdcdd9 800 #if DEBUG_MEMORY
ohneta 0:aae260bdcdd9 801 mark_allocated(this);
ohneta 0:aae260bdcdd9 802 #endif
ohneta 0:aae260bdcdd9 803 init();
ohneta 0:aae260bdcdd9 804 setInt(val);
ohneta 0:aae260bdcdd9 805 }
ohneta 0:aae260bdcdd9 806
ohneta 0:aae260bdcdd9 807 CScriptVar::~CScriptVar(void) {
ohneta 0:aae260bdcdd9 808 #if DEBUG_MEMORY
ohneta 0:aae260bdcdd9 809 mark_deallocated(this);
ohneta 0:aae260bdcdd9 810 #endif
ohneta 0:aae260bdcdd9 811 removeAllChildren();
ohneta 0:aae260bdcdd9 812 }
ohneta 0:aae260bdcdd9 813
ohneta 0:aae260bdcdd9 814 void CScriptVar::init() {
ohneta 0:aae260bdcdd9 815 firstChild = 0;
ohneta 0:aae260bdcdd9 816 lastChild = 0;
ohneta 0:aae260bdcdd9 817 flags = 0;
ohneta 0:aae260bdcdd9 818 jsCallback = 0;
ohneta 0:aae260bdcdd9 819 jsCallbackUserData = 0;
ohneta 0:aae260bdcdd9 820 data = TINYJS_BLANK_DATA;
ohneta 0:aae260bdcdd9 821 intData = 0;
ohneta 0:aae260bdcdd9 822 doubleData = 0;
ohneta 0:aae260bdcdd9 823 }
ohneta 0:aae260bdcdd9 824
ohneta 0:aae260bdcdd9 825 CScriptVar *CScriptVar::getReturnVar() {
ohneta 0:aae260bdcdd9 826 return getParameter(TINYJS_RETURN_VAR);
ohneta 0:aae260bdcdd9 827 }
ohneta 0:aae260bdcdd9 828
ohneta 0:aae260bdcdd9 829 void CScriptVar::setReturnVar(CScriptVar *var) {
ohneta 0:aae260bdcdd9 830 findChildOrCreate(TINYJS_RETURN_VAR)->replaceWith(var);
ohneta 0:aae260bdcdd9 831 }
ohneta 0:aae260bdcdd9 832
ohneta 0:aae260bdcdd9 833
ohneta 0:aae260bdcdd9 834 CScriptVar *CScriptVar::getParameter(const std::string &name) {
ohneta 0:aae260bdcdd9 835 return findChildOrCreate(name)->var;
ohneta 0:aae260bdcdd9 836 }
ohneta 0:aae260bdcdd9 837
ohneta 0:aae260bdcdd9 838 CScriptVarLink *CScriptVar::findChild(const string &childName) {
ohneta 0:aae260bdcdd9 839 CScriptVarLink *v = firstChild;
ohneta 0:aae260bdcdd9 840 while (v) {
ohneta 0:aae260bdcdd9 841 if (v->name.compare(childName)==0)
ohneta 0:aae260bdcdd9 842 return v;
ohneta 0:aae260bdcdd9 843 v = v->nextSibling;
ohneta 0:aae260bdcdd9 844 }
ohneta 0:aae260bdcdd9 845 return 0;
ohneta 0:aae260bdcdd9 846 }
ohneta 0:aae260bdcdd9 847
ohneta 0:aae260bdcdd9 848 CScriptVarLink *CScriptVar::findChildOrCreate(const string &childName, int varFlags) {
ohneta 0:aae260bdcdd9 849 CScriptVarLink *l = findChild(childName);
ohneta 0:aae260bdcdd9 850 if (l) return l;
ohneta 0:aae260bdcdd9 851
ohneta 0:aae260bdcdd9 852 return addChild(childName, new CScriptVar(TINYJS_BLANK_DATA, varFlags));
ohneta 0:aae260bdcdd9 853 }
ohneta 0:aae260bdcdd9 854
ohneta 0:aae260bdcdd9 855 CScriptVarLink *CScriptVar::findChildOrCreateByPath(const std::string &path) {
ohneta 0:aae260bdcdd9 856 size_t p = path.find('.');
ohneta 0:aae260bdcdd9 857 if (p == string::npos)
ohneta 0:aae260bdcdd9 858 return findChildOrCreate(path);
ohneta 0:aae260bdcdd9 859
ohneta 0:aae260bdcdd9 860 return findChildOrCreate(path.substr(0,p), SCRIPTVAR_OBJECT)->var->
ohneta 0:aae260bdcdd9 861 findChildOrCreateByPath(path.substr(p+1));
ohneta 0:aae260bdcdd9 862 }
ohneta 0:aae260bdcdd9 863
ohneta 0:aae260bdcdd9 864 CScriptVarLink *CScriptVar::addChild(const std::string &childName, CScriptVar *child) {
ohneta 0:aae260bdcdd9 865 if (isUndefined()) {
ohneta 0:aae260bdcdd9 866 flags = SCRIPTVAR_OBJECT;
ohneta 0:aae260bdcdd9 867 }
ohneta 0:aae260bdcdd9 868 // if no child supplied, create one
ohneta 0:aae260bdcdd9 869 if (!child)
ohneta 0:aae260bdcdd9 870 child = new CScriptVar();
ohneta 0:aae260bdcdd9 871
ohneta 0:aae260bdcdd9 872 CScriptVarLink *link = new CScriptVarLink(child, childName);
ohneta 0:aae260bdcdd9 873 link->owned = true;
ohneta 0:aae260bdcdd9 874 if (lastChild) {
ohneta 0:aae260bdcdd9 875 lastChild->nextSibling = link;
ohneta 0:aae260bdcdd9 876 link->prevSibling = lastChild;
ohneta 0:aae260bdcdd9 877 lastChild = link;
ohneta 0:aae260bdcdd9 878 } else {
ohneta 0:aae260bdcdd9 879 firstChild = link;
ohneta 0:aae260bdcdd9 880 lastChild = link;
ohneta 0:aae260bdcdd9 881 }
ohneta 0:aae260bdcdd9 882 return link;
ohneta 0:aae260bdcdd9 883 }
ohneta 0:aae260bdcdd9 884
ohneta 0:aae260bdcdd9 885 CScriptVarLink *CScriptVar::addChildNoDup(const std::string &childName, CScriptVar *child) {
ohneta 0:aae260bdcdd9 886 // if no child supplied, create one
ohneta 0:aae260bdcdd9 887 if (!child)
ohneta 0:aae260bdcdd9 888 child = new CScriptVar();
ohneta 0:aae260bdcdd9 889
ohneta 0:aae260bdcdd9 890 CScriptVarLink *v = findChild(childName);
ohneta 0:aae260bdcdd9 891 if (v) {
ohneta 0:aae260bdcdd9 892 v->replaceWith(child);
ohneta 0:aae260bdcdd9 893 } else {
ohneta 0:aae260bdcdd9 894 v = addChild(childName, child);
ohneta 0:aae260bdcdd9 895 }
ohneta 0:aae260bdcdd9 896
ohneta 0:aae260bdcdd9 897 return v;
ohneta 0:aae260bdcdd9 898 }
ohneta 0:aae260bdcdd9 899
ohneta 0:aae260bdcdd9 900 void CScriptVar::removeChild(CScriptVar *child) {
ohneta 0:aae260bdcdd9 901 CScriptVarLink *link = firstChild;
ohneta 0:aae260bdcdd9 902 while (link) {
ohneta 0:aae260bdcdd9 903 if (link->var == child)
ohneta 0:aae260bdcdd9 904 break;
ohneta 0:aae260bdcdd9 905 link = link->nextSibling;
ohneta 0:aae260bdcdd9 906 }
ohneta 0:aae260bdcdd9 907 ASSERT(link);
ohneta 0:aae260bdcdd9 908 removeLink(link);
ohneta 0:aae260bdcdd9 909 }
ohneta 0:aae260bdcdd9 910
ohneta 0:aae260bdcdd9 911 void CScriptVar::removeLink(CScriptVarLink *link) {
ohneta 0:aae260bdcdd9 912 if (!link) return;
ohneta 0:aae260bdcdd9 913 if (link->nextSibling)
ohneta 0:aae260bdcdd9 914 link->nextSibling->prevSibling = link->prevSibling;
ohneta 0:aae260bdcdd9 915 if (link->prevSibling)
ohneta 0:aae260bdcdd9 916 link->prevSibling->nextSibling = link->nextSibling;
ohneta 0:aae260bdcdd9 917 if (lastChild == link)
ohneta 0:aae260bdcdd9 918 lastChild = link->prevSibling;
ohneta 0:aae260bdcdd9 919 if (firstChild == link)
ohneta 0:aae260bdcdd9 920 firstChild = link->nextSibling;
ohneta 0:aae260bdcdd9 921 delete link;
ohneta 0:aae260bdcdd9 922 }
ohneta 0:aae260bdcdd9 923
ohneta 0:aae260bdcdd9 924 void CScriptVar::removeAllChildren() {
ohneta 0:aae260bdcdd9 925 CScriptVarLink *c = firstChild;
ohneta 0:aae260bdcdd9 926 while (c) {
ohneta 0:aae260bdcdd9 927 CScriptVarLink *t = c->nextSibling;
ohneta 0:aae260bdcdd9 928 delete c;
ohneta 0:aae260bdcdd9 929 c = t;
ohneta 0:aae260bdcdd9 930 }
ohneta 0:aae260bdcdd9 931 firstChild = 0;
ohneta 0:aae260bdcdd9 932 lastChild = 0;
ohneta 0:aae260bdcdd9 933 }
ohneta 0:aae260bdcdd9 934
ohneta 0:aae260bdcdd9 935 CScriptVar *CScriptVar::getArrayIndex(int idx) {
ohneta 0:aae260bdcdd9 936 char sIdx[64];
ohneta 0:aae260bdcdd9 937 sprintf_s(sIdx, sizeof(sIdx), "%d", idx);
ohneta 0:aae260bdcdd9 938 CScriptVarLink *link = findChild(sIdx);
ohneta 0:aae260bdcdd9 939 if (link) return link->var;
ohneta 0:aae260bdcdd9 940 else return new CScriptVar(TINYJS_BLANK_DATA, SCRIPTVAR_NULL); // undefined
ohneta 0:aae260bdcdd9 941 }
ohneta 0:aae260bdcdd9 942
ohneta 0:aae260bdcdd9 943 void CScriptVar::setArrayIndex(int idx, CScriptVar *value) {
ohneta 0:aae260bdcdd9 944 char sIdx[64];
ohneta 0:aae260bdcdd9 945 sprintf_s(sIdx, sizeof(sIdx), "%d", idx);
ohneta 0:aae260bdcdd9 946 CScriptVarLink *link = findChild(sIdx);
ohneta 0:aae260bdcdd9 947
ohneta 0:aae260bdcdd9 948 if (link) {
ohneta 0:aae260bdcdd9 949 if (value->isUndefined())
ohneta 0:aae260bdcdd9 950 removeLink(link);
ohneta 0:aae260bdcdd9 951 else
ohneta 0:aae260bdcdd9 952 link->replaceWith(value);
ohneta 0:aae260bdcdd9 953 } else {
ohneta 0:aae260bdcdd9 954 if (!value->isUndefined())
ohneta 0:aae260bdcdd9 955 addChild(sIdx, value);
ohneta 0:aae260bdcdd9 956 }
ohneta 0:aae260bdcdd9 957 }
ohneta 0:aae260bdcdd9 958
ohneta 0:aae260bdcdd9 959 int CScriptVar::getArrayLength() {
ohneta 0:aae260bdcdd9 960 int highest = -1;
ohneta 0:aae260bdcdd9 961 if (!isArray()) return 0;
ohneta 0:aae260bdcdd9 962
ohneta 0:aae260bdcdd9 963 CScriptVarLink *link = firstChild;
ohneta 0:aae260bdcdd9 964 while (link) {
ohneta 0:aae260bdcdd9 965 if (isNumber(link->name)) {
ohneta 0:aae260bdcdd9 966 int val = atoi(link->name.c_str());
ohneta 0:aae260bdcdd9 967 if (val > highest) highest = val;
ohneta 0:aae260bdcdd9 968 }
ohneta 0:aae260bdcdd9 969 link = link->nextSibling;
ohneta 0:aae260bdcdd9 970 }
ohneta 0:aae260bdcdd9 971 return highest+1;
ohneta 0:aae260bdcdd9 972 }
ohneta 0:aae260bdcdd9 973
ohneta 0:aae260bdcdd9 974 int CScriptVar::getChildren() {
ohneta 0:aae260bdcdd9 975 int n = 0;
ohneta 0:aae260bdcdd9 976 CScriptVarLink *link = firstChild;
ohneta 0:aae260bdcdd9 977 while (link) {
ohneta 0:aae260bdcdd9 978 n++;
ohneta 0:aae260bdcdd9 979 link = link->nextSibling;
ohneta 0:aae260bdcdd9 980 }
ohneta 0:aae260bdcdd9 981 return n;
ohneta 0:aae260bdcdd9 982 }
ohneta 0:aae260bdcdd9 983
ohneta 0:aae260bdcdd9 984 int CScriptVar::getInt() {
ohneta 0:aae260bdcdd9 985 /* strtol understands about hex and octal */
ohneta 0:aae260bdcdd9 986 if (isInt()) return intData;
ohneta 0:aae260bdcdd9 987 if (isNull()) return 0;
ohneta 0:aae260bdcdd9 988 if (isUndefined()) return 0;
ohneta 0:aae260bdcdd9 989 if (isDouble()) return (int)doubleData;
ohneta 0:aae260bdcdd9 990 return 0;
ohneta 0:aae260bdcdd9 991 }
ohneta 0:aae260bdcdd9 992
ohneta 0:aae260bdcdd9 993 double CScriptVar::getDouble() {
ohneta 0:aae260bdcdd9 994 if (isDouble()) return doubleData;
ohneta 0:aae260bdcdd9 995 if (isInt()) return intData;
ohneta 0:aae260bdcdd9 996 if (isNull()) return 0;
ohneta 0:aae260bdcdd9 997 if (isUndefined()) return 0;
ohneta 0:aae260bdcdd9 998 return 0; /* or NaN? */
ohneta 0:aae260bdcdd9 999 }
ohneta 0:aae260bdcdd9 1000
ohneta 0:aae260bdcdd9 1001 const string &CScriptVar::getString() {
ohneta 0:aae260bdcdd9 1002 /* Because we can't return a string that is generated on demand.
ohneta 0:aae260bdcdd9 1003 * I should really just use char* :) */
ohneta 0:aae260bdcdd9 1004 static string s_null = "null";
ohneta 0:aae260bdcdd9 1005 static string s_undefined = "undefined";
ohneta 0:aae260bdcdd9 1006 if (isInt()) {
ohneta 0:aae260bdcdd9 1007 char buffer[32];
ohneta 0:aae260bdcdd9 1008 sprintf_s(buffer, sizeof(buffer), "%ld", intData);
ohneta 0:aae260bdcdd9 1009 data = buffer;
ohneta 0:aae260bdcdd9 1010 return data;
ohneta 0:aae260bdcdd9 1011 }
ohneta 0:aae260bdcdd9 1012 if (isDouble()) {
ohneta 0:aae260bdcdd9 1013 char buffer[32];
ohneta 0:aae260bdcdd9 1014 sprintf_s(buffer, sizeof(buffer), "%f", doubleData);
ohneta 0:aae260bdcdd9 1015 data = buffer;
ohneta 0:aae260bdcdd9 1016 return data;
ohneta 0:aae260bdcdd9 1017 }
ohneta 0:aae260bdcdd9 1018 if (isNull()) return s_null;
ohneta 0:aae260bdcdd9 1019 if (isUndefined()) return s_undefined;
ohneta 0:aae260bdcdd9 1020 // are we just a string here?
ohneta 0:aae260bdcdd9 1021 return data;
ohneta 0:aae260bdcdd9 1022 }
ohneta 0:aae260bdcdd9 1023
ohneta 0:aae260bdcdd9 1024 void CScriptVar::setInt(int val) {
ohneta 0:aae260bdcdd9 1025 flags = (flags&~SCRIPTVAR_VARTYPEMASK) | SCRIPTVAR_INTEGER;
ohneta 0:aae260bdcdd9 1026 intData = val;
ohneta 0:aae260bdcdd9 1027 doubleData = 0;
ohneta 0:aae260bdcdd9 1028 data = TINYJS_BLANK_DATA;
ohneta 0:aae260bdcdd9 1029 }
ohneta 0:aae260bdcdd9 1030
ohneta 0:aae260bdcdd9 1031 void CScriptVar::setDouble(double val) {
ohneta 0:aae260bdcdd9 1032 flags = (flags&~SCRIPTVAR_VARTYPEMASK) | SCRIPTVAR_DOUBLE;
ohneta 0:aae260bdcdd9 1033 doubleData = val;
ohneta 0:aae260bdcdd9 1034 intData = 0;
ohneta 0:aae260bdcdd9 1035 data = TINYJS_BLANK_DATA;
ohneta 0:aae260bdcdd9 1036 }
ohneta 0:aae260bdcdd9 1037
ohneta 0:aae260bdcdd9 1038 void CScriptVar::setString(const string &str) {
ohneta 0:aae260bdcdd9 1039 // name sure it's not still a number or integer
ohneta 0:aae260bdcdd9 1040 flags = (flags&~SCRIPTVAR_VARTYPEMASK) | SCRIPTVAR_STRING;
ohneta 0:aae260bdcdd9 1041 data = str;
ohneta 0:aae260bdcdd9 1042 intData = 0;
ohneta 0:aae260bdcdd9 1043 doubleData = 0;
ohneta 0:aae260bdcdd9 1044 }
ohneta 0:aae260bdcdd9 1045
ohneta 0:aae260bdcdd9 1046 void CScriptVar::setUndefined() {
ohneta 0:aae260bdcdd9 1047 // name sure it's not still a number or integer
ohneta 0:aae260bdcdd9 1048 flags = (flags&~SCRIPTVAR_VARTYPEMASK) | SCRIPTVAR_UNDEFINED;
ohneta 0:aae260bdcdd9 1049 data = TINYJS_BLANK_DATA;
ohneta 0:aae260bdcdd9 1050 intData = 0;
ohneta 0:aae260bdcdd9 1051 doubleData = 0;
ohneta 0:aae260bdcdd9 1052 removeAllChildren();
ohneta 0:aae260bdcdd9 1053 }
ohneta 0:aae260bdcdd9 1054
ohneta 0:aae260bdcdd9 1055 void CScriptVar::setArray() {
ohneta 0:aae260bdcdd9 1056 // name sure it's not still a number or integer
ohneta 0:aae260bdcdd9 1057 flags = (flags&~SCRIPTVAR_VARTYPEMASK) | SCRIPTVAR_ARRAY;
ohneta 0:aae260bdcdd9 1058 data = TINYJS_BLANK_DATA;
ohneta 0:aae260bdcdd9 1059 intData = 0;
ohneta 0:aae260bdcdd9 1060 doubleData = 0;
ohneta 0:aae260bdcdd9 1061 removeAllChildren();
ohneta 0:aae260bdcdd9 1062 }
ohneta 0:aae260bdcdd9 1063
ohneta 0:aae260bdcdd9 1064 bool CScriptVar::equals(CScriptVar *v) {
ohneta 0:aae260bdcdd9 1065 CScriptVar *resV = mathsOp(v, LEX_EQUAL);
ohneta 0:aae260bdcdd9 1066 bool res = resV->getBool();
ohneta 0:aae260bdcdd9 1067 delete resV;
ohneta 0:aae260bdcdd9 1068 return res;
ohneta 0:aae260bdcdd9 1069 }
ohneta 0:aae260bdcdd9 1070
ohneta 0:aae260bdcdd9 1071 CScriptVar *CScriptVar::mathsOp(CScriptVar *b, int op) {
ohneta 0:aae260bdcdd9 1072 CScriptVar *a = this;
ohneta 0:aae260bdcdd9 1073 // Type equality check
ohneta 0:aae260bdcdd9 1074 if (op == LEX_TYPEEQUAL || op == LEX_NTYPEEQUAL) {
ohneta 0:aae260bdcdd9 1075 // check type first, then call again to check data
ohneta 0:aae260bdcdd9 1076 bool eql = ((a->flags & SCRIPTVAR_VARTYPEMASK) ==
ohneta 0:aae260bdcdd9 1077 (b->flags & SCRIPTVAR_VARTYPEMASK));
ohneta 0:aae260bdcdd9 1078 if (eql) {
ohneta 0:aae260bdcdd9 1079 CScriptVar *contents = a->mathsOp(b, LEX_EQUAL);
ohneta 0:aae260bdcdd9 1080 if (!contents->getBool()) eql = false;
ohneta 0:aae260bdcdd9 1081 if (!contents->refs) delete contents;
ohneta 0:aae260bdcdd9 1082 }
ohneta 0:aae260bdcdd9 1083 ;
ohneta 0:aae260bdcdd9 1084 if (op == LEX_TYPEEQUAL)
ohneta 0:aae260bdcdd9 1085 return new CScriptVar(eql);
ohneta 0:aae260bdcdd9 1086 else
ohneta 0:aae260bdcdd9 1087 return new CScriptVar(!eql);
ohneta 0:aae260bdcdd9 1088 }
ohneta 0:aae260bdcdd9 1089 // do maths...
ohneta 0:aae260bdcdd9 1090 if (a->isUndefined() && b->isUndefined()) {
ohneta 0:aae260bdcdd9 1091 if (op == LEX_EQUAL) return new CScriptVar(true);
ohneta 0:aae260bdcdd9 1092 else if (op == LEX_NEQUAL) return new CScriptVar(false);
ohneta 0:aae260bdcdd9 1093 else return new CScriptVar(); // undefined
ohneta 0:aae260bdcdd9 1094 } else if ((a->isNumeric() || a->isUndefined()) &&
ohneta 0:aae260bdcdd9 1095 (b->isNumeric() || b->isUndefined())) {
ohneta 0:aae260bdcdd9 1096 if (!a->isDouble() && !b->isDouble()) {
ohneta 0:aae260bdcdd9 1097 // use ints
ohneta 0:aae260bdcdd9 1098 int da = a->getInt();
ohneta 0:aae260bdcdd9 1099 int db = b->getInt();
ohneta 0:aae260bdcdd9 1100 switch (op) {
ohneta 0:aae260bdcdd9 1101 case '+': return new CScriptVar(da+db);
ohneta 0:aae260bdcdd9 1102 case '-': return new CScriptVar(da-db);
ohneta 0:aae260bdcdd9 1103 case '*': return new CScriptVar(da*db);
ohneta 0:aae260bdcdd9 1104 case '/': return new CScriptVar(da/db);
ohneta 0:aae260bdcdd9 1105 case '&': return new CScriptVar(da&db);
ohneta 0:aae260bdcdd9 1106 case '|': return new CScriptVar(da|db);
ohneta 0:aae260bdcdd9 1107 case '^': return new CScriptVar(da^db);
ohneta 0:aae260bdcdd9 1108 case '%': return new CScriptVar(da%db);
ohneta 0:aae260bdcdd9 1109 case LEX_EQUAL: return new CScriptVar(da==db);
ohneta 0:aae260bdcdd9 1110 case LEX_NEQUAL: return new CScriptVar(da!=db);
ohneta 0:aae260bdcdd9 1111 case '<': return new CScriptVar(da<db);
ohneta 0:aae260bdcdd9 1112 case LEX_LEQUAL: return new CScriptVar(da<=db);
ohneta 0:aae260bdcdd9 1113 case '>': return new CScriptVar(da>db);
ohneta 0:aae260bdcdd9 1114 case LEX_GEQUAL: return new CScriptVar(da>=db);
ohneta 0:aae260bdcdd9 1115 #ifndef MBED
ohneta 0:aae260bdcdd9 1116 default: throw new CScriptException("Operation "+CScriptLex::getTokenStr(op)+" not supported on the Int datatype");
ohneta 0:aae260bdcdd9 1117 #else
ohneta 0:aae260bdcdd9 1118 default:
ohneta 0:aae260bdcdd9 1119 mbedErrorFlag = 1;
ohneta 0:aae260bdcdd9 1120 mbedErrorMessage = "Operation ";
ohneta 0:aae260bdcdd9 1121 mbedErrorMessage += CScriptLex::getTokenStr(op);
ohneta 0:aae260bdcdd9 1122 mbedErrorMessage += " not supported on the Int datatype";
ohneta 0:aae260bdcdd9 1123 return 0;
ohneta 0:aae260bdcdd9 1124 #endif
ohneta 0:aae260bdcdd9 1125 }
ohneta 0:aae260bdcdd9 1126 } else {
ohneta 0:aae260bdcdd9 1127 // use doubles
ohneta 0:aae260bdcdd9 1128 double da = a->getDouble();
ohneta 0:aae260bdcdd9 1129 double db = b->getDouble();
ohneta 0:aae260bdcdd9 1130 switch (op) {
ohneta 0:aae260bdcdd9 1131 case '+': return new CScriptVar(da+db);
ohneta 0:aae260bdcdd9 1132 case '-': return new CScriptVar(da-db);
ohneta 0:aae260bdcdd9 1133 case '*': return new CScriptVar(da*db);
ohneta 0:aae260bdcdd9 1134 case '/': return new CScriptVar(da/db);
ohneta 0:aae260bdcdd9 1135 case LEX_EQUAL: return new CScriptVar(da==db);
ohneta 0:aae260bdcdd9 1136 case LEX_NEQUAL: return new CScriptVar(da!=db);
ohneta 0:aae260bdcdd9 1137 case '<': return new CScriptVar(da<db);
ohneta 0:aae260bdcdd9 1138 case LEX_LEQUAL: return new CScriptVar(da<=db);
ohneta 0:aae260bdcdd9 1139 case '>': return new CScriptVar(da>db);
ohneta 0:aae260bdcdd9 1140 case LEX_GEQUAL: return new CScriptVar(da>=db);
ohneta 0:aae260bdcdd9 1141 #ifndef MBED
ohneta 0:aae260bdcdd9 1142 default: throw new CScriptException("Operation "+CScriptLex::getTokenStr(op)+" not supported on the Double datatype");
ohneta 0:aae260bdcdd9 1143 #else
ohneta 0:aae260bdcdd9 1144 default:
ohneta 0:aae260bdcdd9 1145 mbedErrorFlag = 1;
ohneta 0:aae260bdcdd9 1146 mbedErrorMessage = "Operation ";
ohneta 0:aae260bdcdd9 1147 mbedErrorMessage += CScriptLex::getTokenStr(op);
ohneta 0:aae260bdcdd9 1148 mbedErrorMessage += " not supported on the Double datatype";
ohneta 0:aae260bdcdd9 1149 return 0;
ohneta 0:aae260bdcdd9 1150 #endif
ohneta 0:aae260bdcdd9 1151 }
ohneta 0:aae260bdcdd9 1152 }
ohneta 0:aae260bdcdd9 1153 } else if (a->isArray()) {
ohneta 0:aae260bdcdd9 1154 /* Just check pointers */
ohneta 0:aae260bdcdd9 1155 switch (op) {
ohneta 0:aae260bdcdd9 1156 case LEX_EQUAL: return new CScriptVar(a==b);
ohneta 0:aae260bdcdd9 1157 case LEX_NEQUAL: return new CScriptVar(a!=b);
ohneta 0:aae260bdcdd9 1158 #ifndef MBED
ohneta 0:aae260bdcdd9 1159 default: throw new CScriptException("Operation "+CScriptLex::getTokenStr(op)+" not supported on the Array datatype");
ohneta 0:aae260bdcdd9 1160 #else
ohneta 0:aae260bdcdd9 1161 default:
ohneta 0:aae260bdcdd9 1162 mbedErrorFlag = 1;;
ohneta 0:aae260bdcdd9 1163 mbedErrorMessage = "Operation ";
ohneta 0:aae260bdcdd9 1164 mbedErrorMessage += CScriptLex::getTokenStr(op);
ohneta 0:aae260bdcdd9 1165 mbedErrorMessage += " not supported on the Array datatype";
ohneta 0:aae260bdcdd9 1166 return 0;
ohneta 0:aae260bdcdd9 1167
ohneta 0:aae260bdcdd9 1168 #endif
ohneta 0:aae260bdcdd9 1169 }
ohneta 0:aae260bdcdd9 1170 } else if (a->isObject()) {
ohneta 0:aae260bdcdd9 1171 /* Just check pointers */
ohneta 0:aae260bdcdd9 1172 switch (op) {
ohneta 0:aae260bdcdd9 1173 case LEX_EQUAL: return new CScriptVar(a==b);
ohneta 0:aae260bdcdd9 1174 case LEX_NEQUAL: return new CScriptVar(a!=b);
ohneta 0:aae260bdcdd9 1175 #ifndef MBED
ohneta 0:aae260bdcdd9 1176 default: throw new CScriptException("Operation "+CScriptLex::getTokenStr(op)+" not supported on the Object datatype");
ohneta 0:aae260bdcdd9 1177 #else
ohneta 0:aae260bdcdd9 1178 default:
ohneta 0:aae260bdcdd9 1179 mbedErrorFlag = 1;
ohneta 0:aae260bdcdd9 1180 mbedErrorMessage = "Operation ";
ohneta 0:aae260bdcdd9 1181 mbedErrorMessage += CScriptLex::getTokenStr(op);
ohneta 0:aae260bdcdd9 1182 mbedErrorMessage += " not supported on the Object datatype";
ohneta 0:aae260bdcdd9 1183 return 0;
ohneta 0:aae260bdcdd9 1184 #endif
ohneta 0:aae260bdcdd9 1185 }
ohneta 0:aae260bdcdd9 1186 } else {
ohneta 0:aae260bdcdd9 1187 string da = a->getString();
ohneta 0:aae260bdcdd9 1188 string db = b->getString();
ohneta 0:aae260bdcdd9 1189 // use strings
ohneta 0:aae260bdcdd9 1190 switch (op) {
ohneta 0:aae260bdcdd9 1191 case '+': return new CScriptVar(da+db, SCRIPTVAR_STRING);
ohneta 0:aae260bdcdd9 1192 case LEX_EQUAL: return new CScriptVar(da==db);
ohneta 0:aae260bdcdd9 1193 case LEX_NEQUAL: return new CScriptVar(da!=db);
ohneta 0:aae260bdcdd9 1194 case '<': return new CScriptVar(da<db);
ohneta 0:aae260bdcdd9 1195 case LEX_LEQUAL: return new CScriptVar(da<=db);
ohneta 0:aae260bdcdd9 1196 case '>': return new CScriptVar(da>db);
ohneta 0:aae260bdcdd9 1197 case LEX_GEQUAL: return new CScriptVar(da>=db);
ohneta 0:aae260bdcdd9 1198 #ifndef MBED
ohneta 0:aae260bdcdd9 1199 default: throw new CScriptException("Operation "+CScriptLex::getTokenStr(op)+" not supported on the string datatype");
ohneta 0:aae260bdcdd9 1200 #else
ohneta 0:aae260bdcdd9 1201 default:
ohneta 0:aae260bdcdd9 1202 mbedErrorFlag = 1;
ohneta 0:aae260bdcdd9 1203 mbedErrorMessage = "Operation ";
ohneta 0:aae260bdcdd9 1204 mbedErrorMessage += CScriptLex::getTokenStr(op);
ohneta 0:aae260bdcdd9 1205 mbedErrorMessage += " not supported on the string datatype";
ohneta 0:aae260bdcdd9 1206 return 0;
ohneta 0:aae260bdcdd9 1207 #endif
ohneta 0:aae260bdcdd9 1208 }
ohneta 0:aae260bdcdd9 1209 }
ohneta 0:aae260bdcdd9 1210 ASSERT(0);
ohneta 0:aae260bdcdd9 1211 return 0;
ohneta 0:aae260bdcdd9 1212 }
ohneta 0:aae260bdcdd9 1213
ohneta 0:aae260bdcdd9 1214 void CScriptVar::copySimpleData(CScriptVar *val) {
ohneta 0:aae260bdcdd9 1215 data = val->data;
ohneta 0:aae260bdcdd9 1216 intData = val->intData;
ohneta 0:aae260bdcdd9 1217 doubleData = val->doubleData;
ohneta 0:aae260bdcdd9 1218 flags = (flags & ~SCRIPTVAR_VARTYPEMASK) | (val->flags & SCRIPTVAR_VARTYPEMASK);
ohneta 0:aae260bdcdd9 1219 }
ohneta 0:aae260bdcdd9 1220
ohneta 0:aae260bdcdd9 1221 void CScriptVar::copyValue(CScriptVar *val) {
ohneta 0:aae260bdcdd9 1222 if (val) {
ohneta 0:aae260bdcdd9 1223 copySimpleData(val);
ohneta 0:aae260bdcdd9 1224 // remove all current children
ohneta 0:aae260bdcdd9 1225 removeAllChildren();
ohneta 0:aae260bdcdd9 1226 // copy children of 'val'
ohneta 0:aae260bdcdd9 1227 CScriptVarLink *child = val->firstChild;
ohneta 0:aae260bdcdd9 1228 while (child) {
ohneta 0:aae260bdcdd9 1229 CScriptVar *copied;
ohneta 0:aae260bdcdd9 1230 // don't copy the 'parent' object...
ohneta 0:aae260bdcdd9 1231 if (child->name != TINYJS_PROTOTYPE_CLASS)
ohneta 0:aae260bdcdd9 1232 copied = child->var->deepCopy();
ohneta 0:aae260bdcdd9 1233 else
ohneta 0:aae260bdcdd9 1234 copied = child->var;
ohneta 0:aae260bdcdd9 1235
ohneta 0:aae260bdcdd9 1236 addChild(child->name, copied);
ohneta 0:aae260bdcdd9 1237
ohneta 0:aae260bdcdd9 1238 child = child->nextSibling;
ohneta 0:aae260bdcdd9 1239 }
ohneta 0:aae260bdcdd9 1240 } else {
ohneta 0:aae260bdcdd9 1241 setUndefined();
ohneta 0:aae260bdcdd9 1242 }
ohneta 0:aae260bdcdd9 1243 }
ohneta 0:aae260bdcdd9 1244
ohneta 0:aae260bdcdd9 1245 CScriptVar *CScriptVar::deepCopy() {
ohneta 0:aae260bdcdd9 1246 CScriptVar *newVar = new CScriptVar();
ohneta 0:aae260bdcdd9 1247 newVar->copySimpleData(this);
ohneta 0:aae260bdcdd9 1248 // copy children
ohneta 0:aae260bdcdd9 1249 CScriptVarLink *child = firstChild;
ohneta 0:aae260bdcdd9 1250 while (child) {
ohneta 0:aae260bdcdd9 1251 CScriptVar *copied;
ohneta 0:aae260bdcdd9 1252 // don't copy the 'parent' object...
ohneta 0:aae260bdcdd9 1253 if (child->name != TINYJS_PROTOTYPE_CLASS)
ohneta 0:aae260bdcdd9 1254 copied = child->var->deepCopy();
ohneta 0:aae260bdcdd9 1255 else
ohneta 0:aae260bdcdd9 1256 copied = child->var;
ohneta 0:aae260bdcdd9 1257
ohneta 0:aae260bdcdd9 1258 newVar->addChild(child->name, copied);
ohneta 0:aae260bdcdd9 1259 child = child->nextSibling;
ohneta 0:aae260bdcdd9 1260 }
ohneta 0:aae260bdcdd9 1261 return newVar;
ohneta 0:aae260bdcdd9 1262 }
ohneta 0:aae260bdcdd9 1263
ohneta 0:aae260bdcdd9 1264 void CScriptVar::trace(string indentStr, const string &name) {
ohneta 0:aae260bdcdd9 1265 TRACE("%s'%s' = '%s' %s\n",
ohneta 0:aae260bdcdd9 1266 indentStr.c_str(),
ohneta 0:aae260bdcdd9 1267 name.c_str(),
ohneta 0:aae260bdcdd9 1268 getString().c_str(),
ohneta 0:aae260bdcdd9 1269 getFlagsAsString().c_str());
ohneta 0:aae260bdcdd9 1270 string indent = indentStr+" ";
ohneta 0:aae260bdcdd9 1271 CScriptVarLink *link = firstChild;
ohneta 0:aae260bdcdd9 1272 while (link) {
ohneta 0:aae260bdcdd9 1273 link->var->trace(indent, link->name);
ohneta 0:aae260bdcdd9 1274 link = link->nextSibling;
ohneta 0:aae260bdcdd9 1275 }
ohneta 0:aae260bdcdd9 1276 }
ohneta 0:aae260bdcdd9 1277
ohneta 0:aae260bdcdd9 1278 string CScriptVar::getFlagsAsString() {
ohneta 0:aae260bdcdd9 1279 string flagstr = "";
ohneta 0:aae260bdcdd9 1280 if (flags&SCRIPTVAR_FUNCTION) flagstr = flagstr + "FUNCTION ";
ohneta 0:aae260bdcdd9 1281 if (flags&SCRIPTVAR_OBJECT) flagstr = flagstr + "OBJECT ";
ohneta 0:aae260bdcdd9 1282 if (flags&SCRIPTVAR_ARRAY) flagstr = flagstr + "ARRAY ";
ohneta 0:aae260bdcdd9 1283 if (flags&SCRIPTVAR_NATIVE) flagstr = flagstr + "NATIVE ";
ohneta 0:aae260bdcdd9 1284 if (flags&SCRIPTVAR_DOUBLE) flagstr = flagstr + "DOUBLE ";
ohneta 0:aae260bdcdd9 1285 if (flags&SCRIPTVAR_INTEGER) flagstr = flagstr + "INTEGER ";
ohneta 0:aae260bdcdd9 1286 if (flags&SCRIPTVAR_STRING) flagstr = flagstr + "STRING ";
ohneta 0:aae260bdcdd9 1287 return flagstr;
ohneta 0:aae260bdcdd9 1288 }
ohneta 0:aae260bdcdd9 1289
ohneta 0:aae260bdcdd9 1290 string CScriptVar::getParsableString() {
ohneta 0:aae260bdcdd9 1291 // Numbers can just be put in directly
ohneta 0:aae260bdcdd9 1292 if (isNumeric())
ohneta 0:aae260bdcdd9 1293 return getString();
ohneta 0:aae260bdcdd9 1294 if (isFunction()) {
ohneta 0:aae260bdcdd9 1295 #ifndef MBED
ohneta 0:aae260bdcdd9 1296 ostringstream funcStr;
ohneta 0:aae260bdcdd9 1297 funcStr << "function (";
ohneta 0:aae260bdcdd9 1298 // get list of parameters
ohneta 0:aae260bdcdd9 1299 CScriptVarLink *link = firstChild;
ohneta 0:aae260bdcdd9 1300 while (link) {
ohneta 0:aae260bdcdd9 1301 funcStr << link->name;
ohneta 0:aae260bdcdd9 1302 if (link->nextSibling) funcStr << ",";
ohneta 0:aae260bdcdd9 1303 link = link->nextSibling;
ohneta 0:aae260bdcdd9 1304 }
ohneta 0:aae260bdcdd9 1305 // add function body
ohneta 0:aae260bdcdd9 1306 funcStr << ") " << getString();
ohneta 0:aae260bdcdd9 1307 return funcStr.str();
ohneta 0:aae260bdcdd9 1308 #else
ohneta 0:aae260bdcdd9 1309 string funcStr;
ohneta 0:aae260bdcdd9 1310 funcStr = "function (";
ohneta 0:aae260bdcdd9 1311 CScriptVarLink *link = firstChild;
ohneta 0:aae260bdcdd9 1312 while (link) {
ohneta 0:aae260bdcdd9 1313 funcStr += link->name;
ohneta 0:aae260bdcdd9 1314 if (link->nextSibling) funcStr += ",";
ohneta 0:aae260bdcdd9 1315 link = link->nextSibling;
ohneta 0:aae260bdcdd9 1316 }
ohneta 0:aae260bdcdd9 1317 // add function body
ohneta 0:aae260bdcdd9 1318 funcStr += ") ";
ohneta 0:aae260bdcdd9 1319 funcStr += getString();
ohneta 0:aae260bdcdd9 1320 return funcStr;
ohneta 0:aae260bdcdd9 1321 #endif
ohneta 0:aae260bdcdd9 1322 }
ohneta 0:aae260bdcdd9 1323 // if it is a string then we quote it
ohneta 0:aae260bdcdd9 1324 if (isString())
ohneta 0:aae260bdcdd9 1325 return getJSString(getString());
ohneta 0:aae260bdcdd9 1326 if (isNull())
ohneta 0:aae260bdcdd9 1327 return "null";
ohneta 0:aae260bdcdd9 1328 return "undefined";
ohneta 0:aae260bdcdd9 1329 }
ohneta 0:aae260bdcdd9 1330
ohneta 0:aae260bdcdd9 1331 #ifndef MBED
ohneta 0:aae260bdcdd9 1332 void CScriptVar::getJSON(ostringstream &destination, const string linePrefix) {
ohneta 0:aae260bdcdd9 1333 if (isObject()) {
ohneta 0:aae260bdcdd9 1334 string indentedLinePrefix = linePrefix+" ";
ohneta 0:aae260bdcdd9 1335 // children - handle with bracketed list
ohneta 0:aae260bdcdd9 1336 destination << "{ \n";
ohneta 0:aae260bdcdd9 1337 CScriptVarLink *link = firstChild;
ohneta 0:aae260bdcdd9 1338 while (link) {
ohneta 0:aae260bdcdd9 1339 destination << indentedLinePrefix;
ohneta 0:aae260bdcdd9 1340 destination << getJSString(link->name);
ohneta 0:aae260bdcdd9 1341 destination << " : ";
ohneta 0:aae260bdcdd9 1342 link->var->getJSON(destination, indentedLinePrefix);
ohneta 0:aae260bdcdd9 1343 link = link->nextSibling;
ohneta 0:aae260bdcdd9 1344 if (link) {
ohneta 0:aae260bdcdd9 1345 destination << ",\n";
ohneta 0:aae260bdcdd9 1346 }
ohneta 0:aae260bdcdd9 1347 }
ohneta 0:aae260bdcdd9 1348 destination << "\n" << linePrefix << "}";
ohneta 0:aae260bdcdd9 1349 } else if (isArray()) {
ohneta 0:aae260bdcdd9 1350 string indentedLinePrefix = linePrefix+" ";
ohneta 0:aae260bdcdd9 1351 destination << "[\n";
ohneta 0:aae260bdcdd9 1352 int len = getArrayLength();
ohneta 0:aae260bdcdd9 1353 if (len>10000) len=10000; // we don't want to get stuck here!
ohneta 0:aae260bdcdd9 1354
ohneta 0:aae260bdcdd9 1355 for (int i=0;i<len;i++) {
ohneta 0:aae260bdcdd9 1356 getArrayIndex(i)->getJSON(destination, indentedLinePrefix);
ohneta 0:aae260bdcdd9 1357 if (i<len-1) destination << ",\n";
ohneta 0:aae260bdcdd9 1358 }
ohneta 0:aae260bdcdd9 1359
ohneta 0:aae260bdcdd9 1360 destination << "\n" << linePrefix << "]";
ohneta 0:aae260bdcdd9 1361 } else {
ohneta 0:aae260bdcdd9 1362 // no children or a function... just write value directly
ohneta 0:aae260bdcdd9 1363 destination << getParsableString();
ohneta 0:aae260bdcdd9 1364 }
ohneta 0:aae260bdcdd9 1365 }
ohneta 0:aae260bdcdd9 1366 #else
ohneta 0:aae260bdcdd9 1367 void CScriptVar::getJSON(string &destination, const string linePrefix) {
ohneta 0:aae260bdcdd9 1368 if (isObject()) {
ohneta 0:aae260bdcdd9 1369 string indentedLinePrefix = linePrefix+" ";
ohneta 0:aae260bdcdd9 1370 // children - handle with bracketed list
ohneta 0:aae260bdcdd9 1371 destination += "{ \n";
ohneta 0:aae260bdcdd9 1372 CScriptVarLink *link = firstChild;
ohneta 0:aae260bdcdd9 1373 while (link) {
ohneta 0:aae260bdcdd9 1374 destination += indentedLinePrefix;
ohneta 0:aae260bdcdd9 1375 destination += getJSString(link->name);
ohneta 0:aae260bdcdd9 1376 destination += " : ";
ohneta 0:aae260bdcdd9 1377 link->var->getJSON(destination, indentedLinePrefix);
ohneta 0:aae260bdcdd9 1378 link = link->nextSibling;
ohneta 0:aae260bdcdd9 1379 if (link) {
ohneta 0:aae260bdcdd9 1380 destination += ",\n";
ohneta 0:aae260bdcdd9 1381 }
ohneta 0:aae260bdcdd9 1382 }
ohneta 0:aae260bdcdd9 1383 destination += "\n";
ohneta 0:aae260bdcdd9 1384 destination += linePrefix;
ohneta 0:aae260bdcdd9 1385 destination += "}";
ohneta 0:aae260bdcdd9 1386 } else if (isArray()) {
ohneta 0:aae260bdcdd9 1387 string indentedLinePrefix = linePrefix+" ";
ohneta 0:aae260bdcdd9 1388 destination + "[\n";
ohneta 0:aae260bdcdd9 1389 int len = getArrayLength();
ohneta 0:aae260bdcdd9 1390 if (len>10000) len=10000; // we don't want to get stuck here!
ohneta 0:aae260bdcdd9 1391
ohneta 0:aae260bdcdd9 1392 for (int i=0;i<len;i++) {
ohneta 0:aae260bdcdd9 1393 getArrayIndex(i)->getJSON(destination, indentedLinePrefix);
ohneta 0:aae260bdcdd9 1394 if (i<len-1) {
ohneta 0:aae260bdcdd9 1395 destination += ",\n";
ohneta 0:aae260bdcdd9 1396 }
ohneta 0:aae260bdcdd9 1397 }
ohneta 0:aae260bdcdd9 1398
ohneta 0:aae260bdcdd9 1399 destination += "\n";
ohneta 0:aae260bdcdd9 1400 destination += linePrefix;
ohneta 0:aae260bdcdd9 1401 destination += "]";
ohneta 0:aae260bdcdd9 1402 } else {
ohneta 0:aae260bdcdd9 1403 // no children or a function... just write value directly
ohneta 0:aae260bdcdd9 1404 destination += getParsableString();
ohneta 0:aae260bdcdd9 1405 }
ohneta 0:aae260bdcdd9 1406 }
ohneta 0:aae260bdcdd9 1407 #endif
ohneta 0:aae260bdcdd9 1408
ohneta 0:aae260bdcdd9 1409 void CScriptVar::setCallback(JSCallback callback, void *userdata) {
ohneta 0:aae260bdcdd9 1410 jsCallback = callback;
ohneta 0:aae260bdcdd9 1411 jsCallbackUserData = userdata;
ohneta 0:aae260bdcdd9 1412 }
ohneta 0:aae260bdcdd9 1413
ohneta 0:aae260bdcdd9 1414 CScriptVar *CScriptVar::ref() {
ohneta 0:aae260bdcdd9 1415 refs++;
ohneta 0:aae260bdcdd9 1416 return this;
ohneta 0:aae260bdcdd9 1417 }
ohneta 0:aae260bdcdd9 1418
ohneta 0:aae260bdcdd9 1419 void CScriptVar::unref() {
ohneta 0:aae260bdcdd9 1420 if (refs<=0) printf("OMFG, we have unreffed too far!\n");
ohneta 0:aae260bdcdd9 1421 if ((--refs)==0) {
ohneta 0:aae260bdcdd9 1422 delete this;
ohneta 0:aae260bdcdd9 1423 }
ohneta 0:aae260bdcdd9 1424 }
ohneta 0:aae260bdcdd9 1425
ohneta 0:aae260bdcdd9 1426 int CScriptVar::getRefs() {
ohneta 0:aae260bdcdd9 1427 return refs;
ohneta 0:aae260bdcdd9 1428 }
ohneta 0:aae260bdcdd9 1429
ohneta 0:aae260bdcdd9 1430
ohneta 0:aae260bdcdd9 1431 // ----------------------------------------------------------------------------------- CSCRIPT
ohneta 0:aae260bdcdd9 1432
ohneta 0:aae260bdcdd9 1433 CTinyJS::CTinyJS() {
ohneta 0:aae260bdcdd9 1434 l = 0;
ohneta 0:aae260bdcdd9 1435 root = (new CScriptVar(TINYJS_BLANK_DATA, SCRIPTVAR_OBJECT))->ref();
ohneta 0:aae260bdcdd9 1436 // Add built-in classes
ohneta 0:aae260bdcdd9 1437 stringClass = (new CScriptVar(TINYJS_BLANK_DATA, SCRIPTVAR_OBJECT))->ref();
ohneta 0:aae260bdcdd9 1438 arrayClass = (new CScriptVar(TINYJS_BLANK_DATA, SCRIPTVAR_OBJECT))->ref();
ohneta 0:aae260bdcdd9 1439 objectClass = (new CScriptVar(TINYJS_BLANK_DATA, SCRIPTVAR_OBJECT))->ref();
ohneta 0:aae260bdcdd9 1440 root->addChild("String", stringClass);
ohneta 0:aae260bdcdd9 1441 root->addChild("Array", arrayClass);
ohneta 0:aae260bdcdd9 1442 root->addChild("Object", objectClass);
ohneta 0:aae260bdcdd9 1443 }
ohneta 0:aae260bdcdd9 1444
ohneta 0:aae260bdcdd9 1445 CTinyJS::~CTinyJS() {
ohneta 0:aae260bdcdd9 1446 ASSERT(!l);
ohneta 0:aae260bdcdd9 1447 scopes.clear();
ohneta 0:aae260bdcdd9 1448 stringClass->unref();
ohneta 0:aae260bdcdd9 1449 arrayClass->unref();
ohneta 0:aae260bdcdd9 1450 objectClass->unref();
ohneta 0:aae260bdcdd9 1451 root->unref();
ohneta 0:aae260bdcdd9 1452
ohneta 0:aae260bdcdd9 1453 #if DEBUG_MEMORY
ohneta 0:aae260bdcdd9 1454 show_allocated();
ohneta 0:aae260bdcdd9 1455 #endif
ohneta 0:aae260bdcdd9 1456 }
ohneta 0:aae260bdcdd9 1457
ohneta 0:aae260bdcdd9 1458 void CTinyJS::trace() {
ohneta 0:aae260bdcdd9 1459 root->trace();
ohneta 0:aae260bdcdd9 1460 }
ohneta 0:aae260bdcdd9 1461
ohneta 0:aae260bdcdd9 1462 void CTinyJS::execute(const string &code) {
ohneta 0:aae260bdcdd9 1463 CScriptLex *oldLex = l;
ohneta 0:aae260bdcdd9 1464 vector<CScriptVar*> oldScopes = scopes;
ohneta 0:aae260bdcdd9 1465 l = new CScriptLex(code);
ohneta 0:aae260bdcdd9 1466 #ifdef TINYJS_CALL_STACK
ohneta 0:aae260bdcdd9 1467 call_stack.clear();
ohneta 0:aae260bdcdd9 1468 #endif
ohneta 0:aae260bdcdd9 1469 scopes.clear();
ohneta 0:aae260bdcdd9 1470 scopes.push_back(root);
ohneta 0:aae260bdcdd9 1471
ohneta 0:aae260bdcdd9 1472 #ifndef MBED
ohneta 0:aae260bdcdd9 1473 try {
ohneta 0:aae260bdcdd9 1474 bool execute = true;
ohneta 0:aae260bdcdd9 1475 while (l->tk) statement(execute);
ohneta 0:aae260bdcdd9 1476 } catch (CScriptException *e) {
ohneta 0:aae260bdcdd9 1477 ostringstream msg;
ohneta 0:aae260bdcdd9 1478 msg << "Error " << e->text;
ohneta 0:aae260bdcdd9 1479 #ifdef TINYJS_CALL_STACK
ohneta 0:aae260bdcdd9 1480 for (int i=(int)call_stack.size()-1;i>=0;i--)
ohneta 0:aae260bdcdd9 1481 msg << "\n" << i << ": " << call_stack.at(i);
ohneta 0:aae260bdcdd9 1482 #endif
ohneta 0:aae260bdcdd9 1483 msg << " at " << l->getPosition();
ohneta 0:aae260bdcdd9 1484 delete l;
ohneta 0:aae260bdcdd9 1485 l = oldLex;
ohneta 0:aae260bdcdd9 1486
ohneta 0:aae260bdcdd9 1487 throw new CScriptException(msg.str());
ohneta 0:aae260bdcdd9 1488 }
ohneta 0:aae260bdcdd9 1489 #else
ohneta 0:aae260bdcdd9 1490 {
ohneta 0:aae260bdcdd9 1491 bool execute = true;
ohneta 0:aae260bdcdd9 1492 while (l->tk) {
ohneta 0:aae260bdcdd9 1493 mbedErrorFlag = 0;
ohneta 0:aae260bdcdd9 1494 statement(execute);
ohneta 0:aae260bdcdd9 1495 if (mbedErrorFlag != 0) {
ohneta 0:aae260bdcdd9 1496 string msg;
ohneta 0:aae260bdcdd9 1497 msg = "Error ";
ohneta 0:aae260bdcdd9 1498 msg += mbedErrorMessage;
ohneta 0:aae260bdcdd9 1499 #ifdef TINYJS_CALL_STACK
ohneta 0:aae260bdcdd9 1500 for (int i=(int)call_stack.size()-1;i>=0;i--) {
ohneta 0:aae260bdcdd9 1501 msg += "\n";
ohneta 0:aae260bdcdd9 1502 msg += i;
ohneta 0:aae260bdcdd9 1503 msg += ": ";
ohneta 0:aae260bdcdd9 1504 msg += call_stack.at(i);
ohneta 0:aae260bdcdd9 1505 }
ohneta 0:aae260bdcdd9 1506 #endif
ohneta 0:aae260bdcdd9 1507 msg += " at ";
ohneta 0:aae260bdcdd9 1508 msg += l->getPosition();
ohneta 0:aae260bdcdd9 1509
ohneta 0:aae260bdcdd9 1510 delete l;
ohneta 0:aae260bdcdd9 1511 l = oldLex;
ohneta 0:aae260bdcdd9 1512
ohneta 0:aae260bdcdd9 1513 mbedErrorFlag = 1;
ohneta 0:aae260bdcdd9 1514 mbedErrorMessage = msg;
ohneta 0:aae260bdcdd9 1515 return;
ohneta 0:aae260bdcdd9 1516 }
ohneta 0:aae260bdcdd9 1517 }
ohneta 0:aae260bdcdd9 1518 }
ohneta 0:aae260bdcdd9 1519 #endif
ohneta 0:aae260bdcdd9 1520
ohneta 0:aae260bdcdd9 1521
ohneta 0:aae260bdcdd9 1522 delete l;
ohneta 0:aae260bdcdd9 1523 l = oldLex;
ohneta 0:aae260bdcdd9 1524 scopes = oldScopes;
ohneta 0:aae260bdcdd9 1525 }
ohneta 0:aae260bdcdd9 1526
ohneta 0:aae260bdcdd9 1527 CScriptVarLink CTinyJS::evaluateComplex(const string &code) {
ohneta 0:aae260bdcdd9 1528 CScriptLex *oldLex = l;
ohneta 0:aae260bdcdd9 1529 vector<CScriptVar*> oldScopes = scopes;
ohneta 0:aae260bdcdd9 1530
ohneta 0:aae260bdcdd9 1531 l = new CScriptLex(code);
ohneta 0:aae260bdcdd9 1532 #ifdef TINYJS_CALL_STACK
ohneta 0:aae260bdcdd9 1533 call_stack.clear();
ohneta 0:aae260bdcdd9 1534 #endif
ohneta 0:aae260bdcdd9 1535 scopes.clear();
ohneta 0:aae260bdcdd9 1536 scopes.push_back(root);
ohneta 0:aae260bdcdd9 1537 CScriptVarLink *v = 0;
ohneta 0:aae260bdcdd9 1538 #ifndef MBED
ohneta 0:aae260bdcdd9 1539 try {
ohneta 0:aae260bdcdd9 1540 bool execute = true;
ohneta 0:aae260bdcdd9 1541 do {
ohneta 0:aae260bdcdd9 1542 CLEAN(v);
ohneta 0:aae260bdcdd9 1543 v = base(execute);
ohneta 0:aae260bdcdd9 1544 if (l->tk!=LEX_EOF) l->match(';');
ohneta 0:aae260bdcdd9 1545 } while (l->tk!=LEX_EOF);
ohneta 0:aae260bdcdd9 1546 } catch (CScriptException *e) {
ohneta 0:aae260bdcdd9 1547 ostringstream msg;
ohneta 0:aae260bdcdd9 1548 msg << "Error " << e->text;
ohneta 0:aae260bdcdd9 1549 #ifdef TINYJS_CALL_STACK
ohneta 0:aae260bdcdd9 1550 for (int i=(int)call_stack.size()-1;i>=0;i--)
ohneta 0:aae260bdcdd9 1551 msg << "\n" << i << ": " << call_stack.at(i);
ohneta 0:aae260bdcdd9 1552 #endif
ohneta 0:aae260bdcdd9 1553 msg << " at " << l->getPosition();
ohneta 0:aae260bdcdd9 1554 delete l;
ohneta 0:aae260bdcdd9 1555 l = oldLex;
ohneta 0:aae260bdcdd9 1556
ohneta 0:aae260bdcdd9 1557 throw new CScriptException(msg.str());
ohneta 0:aae260bdcdd9 1558 }
ohneta 0:aae260bdcdd9 1559 #else
ohneta 0:aae260bdcdd9 1560 {
ohneta 0:aae260bdcdd9 1561 bool execute = true;
ohneta 0:aae260bdcdd9 1562 do {
ohneta 0:aae260bdcdd9 1563 CLEAN(v);
ohneta 0:aae260bdcdd9 1564 mbedErrorFlag = 0;
ohneta 0:aae260bdcdd9 1565 v = base(execute);
ohneta 0:aae260bdcdd9 1566 if (mbedErrorFlag != 0) {
ohneta 0:aae260bdcdd9 1567 string msg;
ohneta 0:aae260bdcdd9 1568 msg = "Error ";
ohneta 0:aae260bdcdd9 1569 msg += mbedErrorMessage;
ohneta 0:aae260bdcdd9 1570 #ifdef TINYJS_CALL_STACK
ohneta 0:aae260bdcdd9 1571 for (int i=(int)call_stack.size()-1;i>=0;i--) {
ohneta 0:aae260bdcdd9 1572 msg += "\n";
ohneta 0:aae260bdcdd9 1573 msg += i;
ohneta 0:aae260bdcdd9 1574 msg += ": ";
ohneta 0:aae260bdcdd9 1575 msg += call_stack.at(i);
ohneta 0:aae260bdcdd9 1576 }
ohneta 0:aae260bdcdd9 1577 #endif
ohneta 0:aae260bdcdd9 1578 msg += " at ";
ohneta 0:aae260bdcdd9 1579 msg += l->getPosition();
ohneta 0:aae260bdcdd9 1580 delete l;
ohneta 0:aae260bdcdd9 1581 l = oldLex;
ohneta 0:aae260bdcdd9 1582
ohneta 0:aae260bdcdd9 1583 mbedErrorFlag = 1;
ohneta 0:aae260bdcdd9 1584 mbedErrorMessage = msg;
ohneta 0:aae260bdcdd9 1585 return 0;
ohneta 0:aae260bdcdd9 1586 }
ohneta 0:aae260bdcdd9 1587
ohneta 0:aae260bdcdd9 1588 if (l->tk!=LEX_EOF) {
ohneta 0:aae260bdcdd9 1589 mbedErrorFlag = 0;
ohneta 0:aae260bdcdd9 1590 l->match(';');
ohneta 0:aae260bdcdd9 1591 if (mbedErrorFlag != 0) return 0;
ohneta 0:aae260bdcdd9 1592 }
ohneta 0:aae260bdcdd9 1593 } while (l->tk!=LEX_EOF);
ohneta 0:aae260bdcdd9 1594 }
ohneta 0:aae260bdcdd9 1595 #endif
ohneta 0:aae260bdcdd9 1596 delete l;
ohneta 0:aae260bdcdd9 1597 l = oldLex;
ohneta 0:aae260bdcdd9 1598 scopes = oldScopes;
ohneta 0:aae260bdcdd9 1599
ohneta 0:aae260bdcdd9 1600 if (v) {
ohneta 0:aae260bdcdd9 1601 CScriptVarLink r = *v;
ohneta 0:aae260bdcdd9 1602 CLEAN(v);
ohneta 0:aae260bdcdd9 1603 return r;
ohneta 0:aae260bdcdd9 1604 }
ohneta 0:aae260bdcdd9 1605 // return undefined...
ohneta 0:aae260bdcdd9 1606 return CScriptVarLink(new CScriptVar());
ohneta 0:aae260bdcdd9 1607 }
ohneta 0:aae260bdcdd9 1608
ohneta 0:aae260bdcdd9 1609 string CTinyJS::evaluate(const string &code) {
ohneta 0:aae260bdcdd9 1610 return evaluateComplex(code).var->getString();
ohneta 0:aae260bdcdd9 1611 }
ohneta 0:aae260bdcdd9 1612
ohneta 0:aae260bdcdd9 1613 void CTinyJS::parseFunctionArguments(CScriptVar *funcVar) {
ohneta 0:aae260bdcdd9 1614 #ifndef MBED
ohneta 0:aae260bdcdd9 1615 l->match('(');
ohneta 0:aae260bdcdd9 1616 while (l->tk!=')') {
ohneta 0:aae260bdcdd9 1617 funcVar->addChildNoDup(l->tkStr);
ohneta 0:aae260bdcdd9 1618 l->match(LEX_ID);
ohneta 0:aae260bdcdd9 1619 if (l->tk!=')') l->match(',');
ohneta 0:aae260bdcdd9 1620 }
ohneta 0:aae260bdcdd9 1621 l->match(')');
ohneta 0:aae260bdcdd9 1622 #else
ohneta 0:aae260bdcdd9 1623 LMATCH_VOID('(');
ohneta 0:aae260bdcdd9 1624 while (l->tk!=')') {
ohneta 0:aae260bdcdd9 1625 funcVar->addChildNoDup(l->tkStr);
ohneta 0:aae260bdcdd9 1626 LMATCH_VOID(LEX_ID);
ohneta 0:aae260bdcdd9 1627 if (l->tk!=')') {
ohneta 0:aae260bdcdd9 1628 LMATCH_VOID(',');
ohneta 0:aae260bdcdd9 1629 }
ohneta 0:aae260bdcdd9 1630 }
ohneta 0:aae260bdcdd9 1631 LMATCH_VOID(')');
ohneta 0:aae260bdcdd9 1632 #endif
ohneta 0:aae260bdcdd9 1633 }
ohneta 0:aae260bdcdd9 1634
ohneta 0:aae260bdcdd9 1635 void CTinyJS::addNative(const string &funcDesc, JSCallback ptr, void *userdata) {
ohneta 0:aae260bdcdd9 1636 CScriptLex *oldLex = l;
ohneta 0:aae260bdcdd9 1637 l = new CScriptLex(funcDesc);
ohneta 0:aae260bdcdd9 1638
ohneta 0:aae260bdcdd9 1639 CScriptVar *base = root;
ohneta 0:aae260bdcdd9 1640 #ifndef MBED
ohneta 0:aae260bdcdd9 1641 l->match(LEX_R_FUNCTION);
ohneta 0:aae260bdcdd9 1642 #else
ohneta 0:aae260bdcdd9 1643 LMATCH_VOID(LEX_R_FUNCTION);
ohneta 0:aae260bdcdd9 1644 #endif
ohneta 0:aae260bdcdd9 1645 string funcName = l->tkStr;
ohneta 0:aae260bdcdd9 1646 #ifndef MBED
ohneta 0:aae260bdcdd9 1647 l->match(LEX_ID);
ohneta 0:aae260bdcdd9 1648 #else
ohneta 0:aae260bdcdd9 1649 LMATCH_VOID(LEX_ID);
ohneta 0:aae260bdcdd9 1650 #endif
ohneta 0:aae260bdcdd9 1651 /* Check for dots, we might want to do something like function String.substring ... */
ohneta 0:aae260bdcdd9 1652 while (l->tk == '.') {
ohneta 0:aae260bdcdd9 1653 #ifndef MBED
ohneta 0:aae260bdcdd9 1654 l->match('.');
ohneta 0:aae260bdcdd9 1655 #else
ohneta 0:aae260bdcdd9 1656 LMATCH_VOID('.');
ohneta 0:aae260bdcdd9 1657 #endif
ohneta 0:aae260bdcdd9 1658 CScriptVarLink *link = base->findChild(funcName);
ohneta 0:aae260bdcdd9 1659 // if it doesn't exist, make an object class
ohneta 0:aae260bdcdd9 1660 if (!link) link = base->addChild(funcName, new CScriptVar(TINYJS_BLANK_DATA, SCRIPTVAR_OBJECT));
ohneta 0:aae260bdcdd9 1661 base = link->var;
ohneta 0:aae260bdcdd9 1662 funcName = l->tkStr;
ohneta 0:aae260bdcdd9 1663 #ifndef MBED
ohneta 0:aae260bdcdd9 1664 l->match(LEX_ID);
ohneta 0:aae260bdcdd9 1665 #else
ohneta 0:aae260bdcdd9 1666 LMATCH_VOID(LEX_ID);
ohneta 0:aae260bdcdd9 1667 #endif
ohneta 0:aae260bdcdd9 1668 }
ohneta 0:aae260bdcdd9 1669
ohneta 0:aae260bdcdd9 1670 CScriptVar *funcVar = new CScriptVar(TINYJS_BLANK_DATA, SCRIPTVAR_FUNCTION | SCRIPTVAR_NATIVE);
ohneta 0:aae260bdcdd9 1671 funcVar->setCallback(ptr, userdata);
ohneta 0:aae260bdcdd9 1672 parseFunctionArguments(funcVar);
ohneta 0:aae260bdcdd9 1673 delete l;
ohneta 0:aae260bdcdd9 1674 l = oldLex;
ohneta 0:aae260bdcdd9 1675
ohneta 0:aae260bdcdd9 1676 base->addChild(funcName, funcVar);
ohneta 0:aae260bdcdd9 1677 }
ohneta 0:aae260bdcdd9 1678
ohneta 0:aae260bdcdd9 1679 CScriptVarLink *CTinyJS::parseFunctionDefinition() {
ohneta 0:aae260bdcdd9 1680 // actually parse a function...
ohneta 0:aae260bdcdd9 1681 #ifndef MBED
ohneta 0:aae260bdcdd9 1682 l->match(LEX_R_FUNCTION);
ohneta 0:aae260bdcdd9 1683 #else
ohneta 0:aae260bdcdd9 1684 LMATCH(LEX_R_FUNCTION);
ohneta 0:aae260bdcdd9 1685 #endif
ohneta 0:aae260bdcdd9 1686 string funcName = TINYJS_TEMP_NAME;
ohneta 0:aae260bdcdd9 1687 /* we can have functions without names */
ohneta 0:aae260bdcdd9 1688 if (l->tk==LEX_ID) {
ohneta 0:aae260bdcdd9 1689 funcName = l->tkStr;
ohneta 0:aae260bdcdd9 1690 #ifndef MBED
ohneta 0:aae260bdcdd9 1691 l->match(LEX_ID);
ohneta 0:aae260bdcdd9 1692 #else
ohneta 0:aae260bdcdd9 1693 LMATCH(LEX_ID);
ohneta 0:aae260bdcdd9 1694 #endif
ohneta 0:aae260bdcdd9 1695 }
ohneta 0:aae260bdcdd9 1696 CScriptVarLink *funcVar = new CScriptVarLink(new CScriptVar(TINYJS_BLANK_DATA, SCRIPTVAR_FUNCTION), funcName);
ohneta 0:aae260bdcdd9 1697 parseFunctionArguments(funcVar->var);
ohneta 0:aae260bdcdd9 1698 int funcBegin = l->tokenStart;
ohneta 0:aae260bdcdd9 1699 bool noexecute = false;
ohneta 0:aae260bdcdd9 1700 block(noexecute);
ohneta 0:aae260bdcdd9 1701 funcVar->var->data = l->getSubString(funcBegin);
ohneta 0:aae260bdcdd9 1702 return funcVar;
ohneta 0:aae260bdcdd9 1703 }
ohneta 0:aae260bdcdd9 1704
ohneta 0:aae260bdcdd9 1705 /** Handle a function call (assumes we've parsed the function name and we're
ohneta 0:aae260bdcdd9 1706 * on the start bracket). 'parent' is the object that contains this method,
ohneta 0:aae260bdcdd9 1707 * if there was one (otherwise it's just a normnal function).
ohneta 0:aae260bdcdd9 1708 */
ohneta 0:aae260bdcdd9 1709 CScriptVarLink *CTinyJS::functionCall(bool &execute, CScriptVarLink *function, CScriptVar *parent) {
ohneta 0:aae260bdcdd9 1710 if (execute) {
ohneta 0:aae260bdcdd9 1711 if (!function->var->isFunction()) {
ohneta 0:aae260bdcdd9 1712 string errorMsg = "Expecting '";
ohneta 0:aae260bdcdd9 1713 errorMsg = errorMsg + function->name + "' to be a function";
ohneta 0:aae260bdcdd9 1714 #ifndef MBED
ohneta 0:aae260bdcdd9 1715 throw new CScriptException(errorMsg.c_str());
ohneta 0:aae260bdcdd9 1716 #else
ohneta 0:aae260bdcdd9 1717 mbedErrorFlag = 1;
ohneta 0:aae260bdcdd9 1718 mbedErrorMessage = errorMsg;
ohneta 0:aae260bdcdd9 1719 return 0;
ohneta 0:aae260bdcdd9 1720 #endif
ohneta 0:aae260bdcdd9 1721 }
ohneta 0:aae260bdcdd9 1722 #ifndef MBED
ohneta 0:aae260bdcdd9 1723 l->match('(');
ohneta 0:aae260bdcdd9 1724 #else
ohneta 0:aae260bdcdd9 1725 LMATCH('(');
ohneta 0:aae260bdcdd9 1726 #endif
ohneta 0:aae260bdcdd9 1727 // create a new symbol table entry for execution of this function
ohneta 0:aae260bdcdd9 1728 CScriptVar *functionRoot = new CScriptVar(TINYJS_BLANK_DATA, SCRIPTVAR_FUNCTION);
ohneta 0:aae260bdcdd9 1729 if (parent)
ohneta 0:aae260bdcdd9 1730 functionRoot->addChildNoDup("this", parent);
ohneta 0:aae260bdcdd9 1731 // grab in all parameters
ohneta 0:aae260bdcdd9 1732 CScriptVarLink *v = function->var->firstChild;
ohneta 0:aae260bdcdd9 1733 while (v) {
ohneta 0:aae260bdcdd9 1734 CScriptVarLink *value = base(execute);
ohneta 0:aae260bdcdd9 1735 if (execute) {
ohneta 0:aae260bdcdd9 1736 if (value->var->isBasic()) {
ohneta 0:aae260bdcdd9 1737 // pass by value
ohneta 0:aae260bdcdd9 1738 functionRoot->addChild(v->name, value->var->deepCopy());
ohneta 0:aae260bdcdd9 1739 } else {
ohneta 0:aae260bdcdd9 1740 // pass by reference
ohneta 0:aae260bdcdd9 1741 functionRoot->addChild(v->name, value->var);
ohneta 0:aae260bdcdd9 1742 }
ohneta 0:aae260bdcdd9 1743 }
ohneta 0:aae260bdcdd9 1744 CLEAN(value);
ohneta 0:aae260bdcdd9 1745 #ifndef MBED
ohneta 0:aae260bdcdd9 1746 if (l->tk!=')') l->match(',');
ohneta 0:aae260bdcdd9 1747 #else
ohneta 0:aae260bdcdd9 1748 if (l->tk!=')') LMATCH(',');
ohneta 0:aae260bdcdd9 1749 #endif
ohneta 0:aae260bdcdd9 1750 v = v->nextSibling;
ohneta 0:aae260bdcdd9 1751 }
ohneta 0:aae260bdcdd9 1752 #ifndef MBED
ohneta 0:aae260bdcdd9 1753 l->match(')');
ohneta 0:aae260bdcdd9 1754 #else
ohneta 0:aae260bdcdd9 1755 LMATCH(')');
ohneta 0:aae260bdcdd9 1756 #endif
ohneta 0:aae260bdcdd9 1757 // setup a return variable
ohneta 0:aae260bdcdd9 1758 CScriptVarLink *returnVar = NULL;
ohneta 0:aae260bdcdd9 1759 // execute function!
ohneta 0:aae260bdcdd9 1760 // add the function's execute space to the symbol table so we can recurse
ohneta 0:aae260bdcdd9 1761 CScriptVarLink *returnVarLink = functionRoot->addChild(TINYJS_RETURN_VAR);
ohneta 0:aae260bdcdd9 1762 scopes.push_back(functionRoot);
ohneta 0:aae260bdcdd9 1763 #ifdef TINYJS_CALL_STACK
ohneta 0:aae260bdcdd9 1764 call_stack.push_back(function->name + " from " + l->getPosition());
ohneta 0:aae260bdcdd9 1765 #endif
ohneta 0:aae260bdcdd9 1766
ohneta 0:aae260bdcdd9 1767 if (function->var->isNative()) {
ohneta 0:aae260bdcdd9 1768 ASSERT(function->var->jsCallback);
ohneta 0:aae260bdcdd9 1769 function->var->jsCallback(functionRoot, function->var->jsCallbackUserData);
ohneta 0:aae260bdcdd9 1770 } else {
ohneta 0:aae260bdcdd9 1771 /* we just want to execute the block, but something could
ohneta 0:aae260bdcdd9 1772 * have messed up and left us with the wrong ScriptLex, so
ohneta 0:aae260bdcdd9 1773 * we want to be careful here... */
ohneta 0:aae260bdcdd9 1774 #ifndef MBED
ohneta 0:aae260bdcdd9 1775 CScriptException *exception = 0;
ohneta 0:aae260bdcdd9 1776 CScriptLex *oldLex = l;
ohneta 0:aae260bdcdd9 1777 CScriptLex *newLex = new CScriptLex(function->var->getString());
ohneta 0:aae260bdcdd9 1778 l = newLex;
ohneta 0:aae260bdcdd9 1779
ohneta 0:aae260bdcdd9 1780 try {
ohneta 0:aae260bdcdd9 1781 block(execute);
ohneta 0:aae260bdcdd9 1782 // because return will probably have called this, and set execute to false
ohneta 0:aae260bdcdd9 1783 execute = true;
ohneta 0:aae260bdcdd9 1784 } catch (CScriptException *e) {
ohneta 0:aae260bdcdd9 1785 exception = e;
ohneta 0:aae260bdcdd9 1786 }
ohneta 0:aae260bdcdd9 1787 delete newLex;
ohneta 0:aae260bdcdd9 1788 l = oldLex;
ohneta 0:aae260bdcdd9 1789
ohneta 0:aae260bdcdd9 1790 if (exception)
ohneta 0:aae260bdcdd9 1791 throw exception;
ohneta 0:aae260bdcdd9 1792 #else
ohneta 0:aae260bdcdd9 1793 CScriptLex *oldLex = l;
ohneta 0:aae260bdcdd9 1794 CScriptLex *newLex = new CScriptLex(function->var->getString());
ohneta 0:aae260bdcdd9 1795 l = newLex;
ohneta 0:aae260bdcdd9 1796
ohneta 0:aae260bdcdd9 1797 {
ohneta 0:aae260bdcdd9 1798 mbedErrorFlag = 0;
ohneta 0:aae260bdcdd9 1799 block(execute);
ohneta 0:aae260bdcdd9 1800 if (mbedErrorFlag != 0) {
ohneta 0:aae260bdcdd9 1801 delete newLex;
ohneta 0:aae260bdcdd9 1802 l = oldLex;
ohneta 0:aae260bdcdd9 1803 return 0;
ohneta 0:aae260bdcdd9 1804 } else {
ohneta 0:aae260bdcdd9 1805 execute = true;
ohneta 0:aae260bdcdd9 1806
ohneta 0:aae260bdcdd9 1807 delete newLex;
ohneta 0:aae260bdcdd9 1808 l = oldLex;
ohneta 0:aae260bdcdd9 1809 }
ohneta 0:aae260bdcdd9 1810 }
ohneta 0:aae260bdcdd9 1811 #endif
ohneta 0:aae260bdcdd9 1812
ohneta 0:aae260bdcdd9 1813 }
ohneta 0:aae260bdcdd9 1814 #ifdef TINYJS_CALL_STACK
ohneta 0:aae260bdcdd9 1815 if (!call_stack.empty()) call_stack.pop_back();
ohneta 0:aae260bdcdd9 1816 #endif
ohneta 0:aae260bdcdd9 1817 scopes.pop_back();
ohneta 0:aae260bdcdd9 1818 /* get the real return var before we remove it from our function */
ohneta 0:aae260bdcdd9 1819 returnVar = new CScriptVarLink(returnVarLink->var);
ohneta 0:aae260bdcdd9 1820 functionRoot->removeLink(returnVarLink);
ohneta 0:aae260bdcdd9 1821 delete functionRoot;
ohneta 0:aae260bdcdd9 1822 if (returnVar)
ohneta 0:aae260bdcdd9 1823 return returnVar;
ohneta 0:aae260bdcdd9 1824 else
ohneta 0:aae260bdcdd9 1825 return new CScriptVarLink(new CScriptVar());
ohneta 0:aae260bdcdd9 1826 } else {
ohneta 0:aae260bdcdd9 1827 // function, but not executing - just parse args and be done
ohneta 0:aae260bdcdd9 1828 #ifndef MBED
ohneta 0:aae260bdcdd9 1829 l->match('(');
ohneta 0:aae260bdcdd9 1830 while (l->tk != ')') {
ohneta 0:aae260bdcdd9 1831 CScriptVarLink *value = base(execute);
ohneta 0:aae260bdcdd9 1832 CLEAN(value);
ohneta 0:aae260bdcdd9 1833 if (l->tk!=')') l->match(',');
ohneta 0:aae260bdcdd9 1834 }
ohneta 0:aae260bdcdd9 1835 l->match(')');
ohneta 0:aae260bdcdd9 1836 #else
ohneta 0:aae260bdcdd9 1837 LMATCH('(');
ohneta 0:aae260bdcdd9 1838 while (l->tk != ')') {
ohneta 0:aae260bdcdd9 1839 CScriptVarLink *value = base(execute);
ohneta 0:aae260bdcdd9 1840 CLEAN(value);
ohneta 0:aae260bdcdd9 1841 if (l->tk!=')') LMATCH(',');
ohneta 0:aae260bdcdd9 1842 }
ohneta 0:aae260bdcdd9 1843 LMATCH(')');
ohneta 0:aae260bdcdd9 1844 #endif
ohneta 0:aae260bdcdd9 1845 if (l->tk == '{') { // TODO: why is this here?
ohneta 0:aae260bdcdd9 1846 block(execute);
ohneta 0:aae260bdcdd9 1847 }
ohneta 0:aae260bdcdd9 1848 /* function will be a blank scriptvarlink if we're not executing,
ohneta 0:aae260bdcdd9 1849 * so just return it rather than an alloc/free */
ohneta 0:aae260bdcdd9 1850 return function;
ohneta 0:aae260bdcdd9 1851 }
ohneta 0:aae260bdcdd9 1852 }
ohneta 0:aae260bdcdd9 1853
ohneta 0:aae260bdcdd9 1854 #ifndef MBED
ohneta 0:aae260bdcdd9 1855 CScriptVarLink *CTinyJS::factor(bool &execute) {
ohneta 0:aae260bdcdd9 1856 if (l->tk=='(') {
ohneta 0:aae260bdcdd9 1857 l->match('(');
ohneta 0:aae260bdcdd9 1858 CScriptVarLink *a = base(execute);
ohneta 0:aae260bdcdd9 1859 l->match(')');
ohneta 0:aae260bdcdd9 1860 return a;
ohneta 0:aae260bdcdd9 1861 }
ohneta 0:aae260bdcdd9 1862 if (l->tk==LEX_R_TRUE) {
ohneta 0:aae260bdcdd9 1863 l->match(LEX_R_TRUE);
ohneta 0:aae260bdcdd9 1864 return new CScriptVarLink(new CScriptVar(1));
ohneta 0:aae260bdcdd9 1865 }
ohneta 0:aae260bdcdd9 1866 if (l->tk==LEX_R_FALSE) {
ohneta 0:aae260bdcdd9 1867 l->match(LEX_R_FALSE);
ohneta 0:aae260bdcdd9 1868 return new CScriptVarLink(new CScriptVar(0));
ohneta 0:aae260bdcdd9 1869 }
ohneta 0:aae260bdcdd9 1870 if (l->tk==LEX_R_NULL) {
ohneta 0:aae260bdcdd9 1871 l->match(LEX_R_NULL);
ohneta 0:aae260bdcdd9 1872 return new CScriptVarLink(new CScriptVar(TINYJS_BLANK_DATA,SCRIPTVAR_NULL));
ohneta 0:aae260bdcdd9 1873 }
ohneta 0:aae260bdcdd9 1874 if (l->tk==LEX_R_UNDEFINED) {
ohneta 0:aae260bdcdd9 1875 l->match(LEX_R_UNDEFINED);
ohneta 0:aae260bdcdd9 1876 return new CScriptVarLink(new CScriptVar(TINYJS_BLANK_DATA,SCRIPTVAR_UNDEFINED));
ohneta 0:aae260bdcdd9 1877 }
ohneta 0:aae260bdcdd9 1878 if (l->tk==LEX_ID) {
ohneta 0:aae260bdcdd9 1879 CScriptVarLink *a = execute ? findInScopes(l->tkStr) : new CScriptVarLink(new CScriptVar());
ohneta 0:aae260bdcdd9 1880 //printf("0x%08X for %s at %s\n", (unsigned int)a, l->tkStr.c_str(), l->getPosition().c_str());
ohneta 0:aae260bdcdd9 1881 /* The parent if we're executing a method call */
ohneta 0:aae260bdcdd9 1882 CScriptVar *parent = 0;
ohneta 0:aae260bdcdd9 1883
ohneta 0:aae260bdcdd9 1884 if (execute && !a) {
ohneta 0:aae260bdcdd9 1885 /* Variable doesn't exist! JavaScript says we should create it
ohneta 0:aae260bdcdd9 1886 * (we won't add it here. This is done in the assignment operator)*/
ohneta 0:aae260bdcdd9 1887 a = new CScriptVarLink(new CScriptVar(), l->tkStr);
ohneta 0:aae260bdcdd9 1888 }
ohneta 0:aae260bdcdd9 1889 l->match(LEX_ID);
ohneta 0:aae260bdcdd9 1890 while (l->tk=='(' || l->tk=='.' || l->tk=='[') {
ohneta 0:aae260bdcdd9 1891 if (l->tk=='(') { // ------------------------------------- Function Call
ohneta 0:aae260bdcdd9 1892 a = functionCall(execute, a, parent);
ohneta 0:aae260bdcdd9 1893 } else if (l->tk == '.') { // ------------------------------------- Record Access
ohneta 0:aae260bdcdd9 1894 l->match('.');
ohneta 0:aae260bdcdd9 1895 if (execute) {
ohneta 0:aae260bdcdd9 1896 const string &name = l->tkStr;
ohneta 0:aae260bdcdd9 1897 CScriptVarLink *child = a->var->findChild(name);
ohneta 0:aae260bdcdd9 1898 if (!child) child = findInParentClasses(a->var, name);
ohneta 0:aae260bdcdd9 1899 if (!child) {
ohneta 0:aae260bdcdd9 1900 /* if we haven't found this defined yet, use the built-in
ohneta 0:aae260bdcdd9 1901 'length' properly */
ohneta 0:aae260bdcdd9 1902 if (a->var->isArray() && name == "length") {
ohneta 0:aae260bdcdd9 1903 int l = a->var->getArrayLength();
ohneta 0:aae260bdcdd9 1904 child = new CScriptVarLink(new CScriptVar(l));
ohneta 0:aae260bdcdd9 1905 } else if (a->var->isString() && name == "length") {
ohneta 0:aae260bdcdd9 1906 int l = a->var->getString().size();
ohneta 0:aae260bdcdd9 1907 child = new CScriptVarLink(new CScriptVar(l));
ohneta 0:aae260bdcdd9 1908 } else {
ohneta 0:aae260bdcdd9 1909 child = a->var->addChild(name);
ohneta 0:aae260bdcdd9 1910 }
ohneta 0:aae260bdcdd9 1911 }
ohneta 0:aae260bdcdd9 1912 parent = a->var;
ohneta 0:aae260bdcdd9 1913 a = child;
ohneta 0:aae260bdcdd9 1914 }
ohneta 0:aae260bdcdd9 1915 l->match(LEX_ID);
ohneta 0:aae260bdcdd9 1916 } else if (l->tk == '[') { // ------------------------------------- Array Access
ohneta 0:aae260bdcdd9 1917 l->match('[');
ohneta 0:aae260bdcdd9 1918 CScriptVarLink *index = base(execute);
ohneta 0:aae260bdcdd9 1919 l->match(']');
ohneta 0:aae260bdcdd9 1920 if (execute) {
ohneta 0:aae260bdcdd9 1921 CScriptVarLink *child = a->var->findChildOrCreate(index->var->getString());
ohneta 0:aae260bdcdd9 1922 parent = a->var;
ohneta 0:aae260bdcdd9 1923 a = child;
ohneta 0:aae260bdcdd9 1924 }
ohneta 0:aae260bdcdd9 1925 CLEAN(index);
ohneta 0:aae260bdcdd9 1926 } else ASSERT(0);
ohneta 0:aae260bdcdd9 1927 }
ohneta 0:aae260bdcdd9 1928 return a;
ohneta 0:aae260bdcdd9 1929 }
ohneta 0:aae260bdcdd9 1930 if (l->tk==LEX_INT || l->tk==LEX_FLOAT) {
ohneta 0:aae260bdcdd9 1931 CScriptVar *a = new CScriptVar(l->tkStr,
ohneta 0:aae260bdcdd9 1932 ((l->tk==LEX_INT)?SCRIPTVAR_INTEGER:SCRIPTVAR_DOUBLE));
ohneta 0:aae260bdcdd9 1933 l->match(l->tk);
ohneta 0:aae260bdcdd9 1934 return new CScriptVarLink(a);
ohneta 0:aae260bdcdd9 1935 }
ohneta 0:aae260bdcdd9 1936 if (l->tk==LEX_STR) {
ohneta 0:aae260bdcdd9 1937 CScriptVar *a = new CScriptVar(l->tkStr, SCRIPTVAR_STRING);
ohneta 0:aae260bdcdd9 1938 l->match(LEX_STR);
ohneta 0:aae260bdcdd9 1939 return new CScriptVarLink(a);
ohneta 0:aae260bdcdd9 1940 }
ohneta 0:aae260bdcdd9 1941 if (l->tk=='{') {
ohneta 0:aae260bdcdd9 1942 CScriptVar *contents = new CScriptVar(TINYJS_BLANK_DATA, SCRIPTVAR_OBJECT);
ohneta 0:aae260bdcdd9 1943 /* JSON-style object definition */
ohneta 0:aae260bdcdd9 1944 l->match('{');
ohneta 0:aae260bdcdd9 1945 while (l->tk != '}') {
ohneta 0:aae260bdcdd9 1946 string id = l->tkStr;
ohneta 0:aae260bdcdd9 1947 // we only allow strings or IDs on the left hand side of an initialisation
ohneta 0:aae260bdcdd9 1948 if (l->tk==LEX_STR) l->match(LEX_STR);
ohneta 0:aae260bdcdd9 1949 else l->match(LEX_ID);
ohneta 0:aae260bdcdd9 1950 l->match(':');
ohneta 0:aae260bdcdd9 1951 if (execute) {
ohneta 0:aae260bdcdd9 1952 CScriptVarLink *a = base(execute);
ohneta 0:aae260bdcdd9 1953 contents->addChild(id, a->var);
ohneta 0:aae260bdcdd9 1954 CLEAN(a);
ohneta 0:aae260bdcdd9 1955 }
ohneta 0:aae260bdcdd9 1956 // no need to clean here, as it will definitely be used
ohneta 0:aae260bdcdd9 1957 if (l->tk != '}') l->match(',');
ohneta 0:aae260bdcdd9 1958 }
ohneta 0:aae260bdcdd9 1959
ohneta 0:aae260bdcdd9 1960 l->match('}');
ohneta 0:aae260bdcdd9 1961 return new CScriptVarLink(contents);
ohneta 0:aae260bdcdd9 1962 }
ohneta 0:aae260bdcdd9 1963 if (l->tk=='[') {
ohneta 0:aae260bdcdd9 1964 CScriptVar *contents = new CScriptVar(TINYJS_BLANK_DATA, SCRIPTVAR_ARRAY);
ohneta 0:aae260bdcdd9 1965 /* JSON-style array */
ohneta 0:aae260bdcdd9 1966 l->match('[');
ohneta 0:aae260bdcdd9 1967 int idx = 0;
ohneta 0:aae260bdcdd9 1968 while (l->tk != ']') {
ohneta 0:aae260bdcdd9 1969 if (execute) {
ohneta 0:aae260bdcdd9 1970 char idx_str[16]; // big enough for 2^32
ohneta 0:aae260bdcdd9 1971 sprintf_s(idx_str, sizeof(idx_str), "%d",idx);
ohneta 0:aae260bdcdd9 1972
ohneta 0:aae260bdcdd9 1973 CScriptVarLink *a = base(execute);
ohneta 0:aae260bdcdd9 1974 contents->addChild(idx_str, a->var);
ohneta 0:aae260bdcdd9 1975 CLEAN(a);
ohneta 0:aae260bdcdd9 1976 }
ohneta 0:aae260bdcdd9 1977 // no need to clean here, as it will definitely be used
ohneta 0:aae260bdcdd9 1978 if (l->tk != ']') l->match(',');
ohneta 0:aae260bdcdd9 1979 idx++;
ohneta 0:aae260bdcdd9 1980 }
ohneta 0:aae260bdcdd9 1981 l->match(']');
ohneta 0:aae260bdcdd9 1982 return new CScriptVarLink(contents);
ohneta 0:aae260bdcdd9 1983 }
ohneta 0:aae260bdcdd9 1984 if (l->tk==LEX_R_FUNCTION) {
ohneta 0:aae260bdcdd9 1985 CScriptVarLink *funcVar = parseFunctionDefinition();
ohneta 0:aae260bdcdd9 1986 if (funcVar->name != TINYJS_TEMP_NAME)
ohneta 0:aae260bdcdd9 1987 TRACE("Functions not defined at statement-level are not meant to have a name");
ohneta 0:aae260bdcdd9 1988 return funcVar;
ohneta 0:aae260bdcdd9 1989 }
ohneta 0:aae260bdcdd9 1990 if (l->tk==LEX_R_NEW) {
ohneta 0:aae260bdcdd9 1991 // new -> create a new object
ohneta 0:aae260bdcdd9 1992 l->match(LEX_R_NEW);
ohneta 0:aae260bdcdd9 1993 const string &className = l->tkStr;
ohneta 0:aae260bdcdd9 1994 if (execute) {
ohneta 0:aae260bdcdd9 1995 CScriptVarLink *objClassOrFunc = findInScopes(className);
ohneta 0:aae260bdcdd9 1996 if (!objClassOrFunc) {
ohneta 0:aae260bdcdd9 1997 TRACE("%s is not a valid class name", className.c_str());
ohneta 0:aae260bdcdd9 1998 return new CScriptVarLink(new CScriptVar());
ohneta 0:aae260bdcdd9 1999 }
ohneta 0:aae260bdcdd9 2000 l->match(LEX_ID);
ohneta 0:aae260bdcdd9 2001 CScriptVar *obj = new CScriptVar(TINYJS_BLANK_DATA, SCRIPTVAR_OBJECT);
ohneta 0:aae260bdcdd9 2002 CScriptVarLink *objLink = new CScriptVarLink(obj);
ohneta 0:aae260bdcdd9 2003 if (objClassOrFunc->var->isFunction()) {
ohneta 0:aae260bdcdd9 2004 CLEAN(functionCall(execute, objClassOrFunc, obj));
ohneta 0:aae260bdcdd9 2005 } else {
ohneta 0:aae260bdcdd9 2006 obj->addChild(TINYJS_PROTOTYPE_CLASS, objClassOrFunc->var);
ohneta 0:aae260bdcdd9 2007 if (l->tk == '(') {
ohneta 0:aae260bdcdd9 2008 l->match('(');
ohneta 0:aae260bdcdd9 2009 l->match(')');
ohneta 0:aae260bdcdd9 2010 }
ohneta 0:aae260bdcdd9 2011 }
ohneta 0:aae260bdcdd9 2012 return objLink;
ohneta 0:aae260bdcdd9 2013 } else {
ohneta 0:aae260bdcdd9 2014 l->match(LEX_ID);
ohneta 0:aae260bdcdd9 2015 if (l->tk == '(') {
ohneta 0:aae260bdcdd9 2016 l->match('(');
ohneta 0:aae260bdcdd9 2017 l->match(')');
ohneta 0:aae260bdcdd9 2018 }
ohneta 0:aae260bdcdd9 2019 }
ohneta 0:aae260bdcdd9 2020 }
ohneta 0:aae260bdcdd9 2021 // Nothing we can do here... just hope it's the end...
ohneta 0:aae260bdcdd9 2022 l->match(LEX_EOF);
ohneta 0:aae260bdcdd9 2023 return 0;
ohneta 0:aae260bdcdd9 2024 }
ohneta 0:aae260bdcdd9 2025 #else
ohneta 0:aae260bdcdd9 2026 CScriptVarLink *CTinyJS::factor(bool &execute) {
ohneta 0:aae260bdcdd9 2027 if (l->tk=='(') {
ohneta 0:aae260bdcdd9 2028 LMATCH('(');
ohneta 0:aae260bdcdd9 2029 CScriptVarLink *a = base(execute);
ohneta 0:aae260bdcdd9 2030 LMATCH(')');
ohneta 0:aae260bdcdd9 2031 return a;
ohneta 0:aae260bdcdd9 2032 }
ohneta 0:aae260bdcdd9 2033 if (l->tk==LEX_R_TRUE) {
ohneta 0:aae260bdcdd9 2034 LMATCH(LEX_R_TRUE);
ohneta 0:aae260bdcdd9 2035 return new CScriptVarLink(new CScriptVar(1));
ohneta 0:aae260bdcdd9 2036 }
ohneta 0:aae260bdcdd9 2037 if (l->tk==LEX_R_FALSE) {
ohneta 0:aae260bdcdd9 2038 LMATCH(LEX_R_FALSE);
ohneta 0:aae260bdcdd9 2039 return new CScriptVarLink(new CScriptVar(0));
ohneta 0:aae260bdcdd9 2040 }
ohneta 0:aae260bdcdd9 2041 if (l->tk==LEX_R_NULL) {
ohneta 0:aae260bdcdd9 2042 LMATCH(LEX_R_NULL);
ohneta 0:aae260bdcdd9 2043 return new CScriptVarLink(new CScriptVar(TINYJS_BLANK_DATA,SCRIPTVAR_NULL));
ohneta 0:aae260bdcdd9 2044 }
ohneta 0:aae260bdcdd9 2045 if (l->tk==LEX_R_UNDEFINED) {
ohneta 0:aae260bdcdd9 2046 LMATCH(LEX_R_UNDEFINED);
ohneta 0:aae260bdcdd9 2047 return new CScriptVarLink(new CScriptVar(TINYJS_BLANK_DATA,SCRIPTVAR_UNDEFINED));
ohneta 0:aae260bdcdd9 2048 }
ohneta 0:aae260bdcdd9 2049 if (l->tk==LEX_ID) {
ohneta 0:aae260bdcdd9 2050 CScriptVarLink *a = execute ? findInScopes(l->tkStr) : new CScriptVarLink(new CScriptVar());
ohneta 0:aae260bdcdd9 2051 //printf("0x%08X for %s at %s\n", (unsigned int)a, l->tkStr.c_str(), l->getPosition().c_str());
ohneta 0:aae260bdcdd9 2052 /* The parent if we're executing a method call */
ohneta 0:aae260bdcdd9 2053 CScriptVar *parent = 0;
ohneta 0:aae260bdcdd9 2054
ohneta 0:aae260bdcdd9 2055 if (execute && !a) {
ohneta 0:aae260bdcdd9 2056 /* Variable doesn't exist! JavaScript says we should create it
ohneta 0:aae260bdcdd9 2057 * (we won't add it here. This is done in the assignment operator)*/
ohneta 0:aae260bdcdd9 2058 a = new CScriptVarLink(new CScriptVar(), l->tkStr);
ohneta 0:aae260bdcdd9 2059 }
ohneta 0:aae260bdcdd9 2060 LMATCH(LEX_ID);
ohneta 0:aae260bdcdd9 2061 while (l->tk=='(' || l->tk=='.' || l->tk=='[') {
ohneta 0:aae260bdcdd9 2062 if (l->tk=='(') { // ------------------------------------- Function Call
ohneta 0:aae260bdcdd9 2063 a = functionCall(execute, a, parent);
ohneta 0:aae260bdcdd9 2064 } else if (l->tk == '.') { // ------------------------------------- Record Access
ohneta 0:aae260bdcdd9 2065 LMATCH('.');
ohneta 0:aae260bdcdd9 2066 if (execute) {
ohneta 0:aae260bdcdd9 2067 const string &name = l->tkStr;
ohneta 0:aae260bdcdd9 2068 CScriptVarLink *child = a->var->findChild(name);
ohneta 0:aae260bdcdd9 2069 if (!child) child = findInParentClasses(a->var, name);
ohneta 0:aae260bdcdd9 2070 if (!child) {
ohneta 0:aae260bdcdd9 2071 /* if we haven't found this defined yet, use the built-in
ohneta 0:aae260bdcdd9 2072 'length' properly */
ohneta 0:aae260bdcdd9 2073 if (a->var->isArray() && name == "length") {
ohneta 0:aae260bdcdd9 2074 int l = a->var->getArrayLength();
ohneta 0:aae260bdcdd9 2075 child = new CScriptVarLink(new CScriptVar(l));
ohneta 0:aae260bdcdd9 2076 } else if (a->var->isString() && name == "length") {
ohneta 0:aae260bdcdd9 2077 int l = a->var->getString().size();
ohneta 0:aae260bdcdd9 2078 child = new CScriptVarLink(new CScriptVar(l));
ohneta 0:aae260bdcdd9 2079 } else {
ohneta 0:aae260bdcdd9 2080 child = a->var->addChild(name);
ohneta 0:aae260bdcdd9 2081 }
ohneta 0:aae260bdcdd9 2082 }
ohneta 0:aae260bdcdd9 2083 parent = a->var;
ohneta 0:aae260bdcdd9 2084 a = child;
ohneta 0:aae260bdcdd9 2085 }
ohneta 0:aae260bdcdd9 2086 LMATCH(LEX_ID);
ohneta 0:aae260bdcdd9 2087 } else if (l->tk == '[') { // ------------------------------------- Array Access
ohneta 0:aae260bdcdd9 2088 LMATCH('[');
ohneta 0:aae260bdcdd9 2089 CScriptVarLink *index = base(execute);
ohneta 0:aae260bdcdd9 2090 LMATCH(']');
ohneta 0:aae260bdcdd9 2091 if (execute) {
ohneta 0:aae260bdcdd9 2092 CScriptVarLink *child = a->var->findChildOrCreate(index->var->getString());
ohneta 0:aae260bdcdd9 2093 parent = a->var;
ohneta 0:aae260bdcdd9 2094 a = child;
ohneta 0:aae260bdcdd9 2095 }
ohneta 0:aae260bdcdd9 2096 CLEAN(index);
ohneta 0:aae260bdcdd9 2097 } else ASSERT(0);
ohneta 0:aae260bdcdd9 2098 }
ohneta 0:aae260bdcdd9 2099 return a;
ohneta 0:aae260bdcdd9 2100 }
ohneta 0:aae260bdcdd9 2101 if (l->tk==LEX_INT || l->tk==LEX_FLOAT) {
ohneta 0:aae260bdcdd9 2102 CScriptVar *a = new CScriptVar(l->tkStr,
ohneta 0:aae260bdcdd9 2103 ((l->tk==LEX_INT)?SCRIPTVAR_INTEGER:SCRIPTVAR_DOUBLE));
ohneta 0:aae260bdcdd9 2104 LMATCH(l->tk);
ohneta 0:aae260bdcdd9 2105 return new CScriptVarLink(a);
ohneta 0:aae260bdcdd9 2106 }
ohneta 0:aae260bdcdd9 2107 if (l->tk==LEX_STR) {
ohneta 0:aae260bdcdd9 2108 CScriptVar *a = new CScriptVar(l->tkStr, SCRIPTVAR_STRING);
ohneta 0:aae260bdcdd9 2109 LMATCH(LEX_STR);
ohneta 0:aae260bdcdd9 2110 return new CScriptVarLink(a);
ohneta 0:aae260bdcdd9 2111 }
ohneta 0:aae260bdcdd9 2112 if (l->tk=='{') {
ohneta 0:aae260bdcdd9 2113 CScriptVar *contents = new CScriptVar(TINYJS_BLANK_DATA, SCRIPTVAR_OBJECT);
ohneta 0:aae260bdcdd9 2114 /* JSON-style object definition */
ohneta 0:aae260bdcdd9 2115 LMATCH('{');
ohneta 0:aae260bdcdd9 2116 while (l->tk != '}') {
ohneta 0:aae260bdcdd9 2117 string id = l->tkStr;
ohneta 0:aae260bdcdd9 2118 // we only allow strings or IDs on the left hand side of an initialisation
ohneta 0:aae260bdcdd9 2119 if (l->tk==LEX_STR) {
ohneta 0:aae260bdcdd9 2120 LMATCH(LEX_STR);
ohneta 0:aae260bdcdd9 2121 } else {
ohneta 0:aae260bdcdd9 2122 LMATCH(LEX_ID);
ohneta 0:aae260bdcdd9 2123 }
ohneta 0:aae260bdcdd9 2124 LMATCH(':');
ohneta 0:aae260bdcdd9 2125 if (execute) {
ohneta 0:aae260bdcdd9 2126 CScriptVarLink *a = base(execute);
ohneta 0:aae260bdcdd9 2127 contents->addChild(id, a->var);
ohneta 0:aae260bdcdd9 2128 CLEAN(a);
ohneta 0:aae260bdcdd9 2129 }
ohneta 0:aae260bdcdd9 2130 // no need to clean here, as it will definitely be used
ohneta 0:aae260bdcdd9 2131 if (l->tk != '}') LMATCH(',');
ohneta 0:aae260bdcdd9 2132 }
ohneta 0:aae260bdcdd9 2133
ohneta 0:aae260bdcdd9 2134 LMATCH('}');
ohneta 0:aae260bdcdd9 2135 return new CScriptVarLink(contents);
ohneta 0:aae260bdcdd9 2136 }
ohneta 0:aae260bdcdd9 2137 if (l->tk=='[') {
ohneta 0:aae260bdcdd9 2138 CScriptVar *contents = new CScriptVar(TINYJS_BLANK_DATA, SCRIPTVAR_ARRAY);
ohneta 0:aae260bdcdd9 2139 /* JSON-style array */
ohneta 0:aae260bdcdd9 2140 LMATCH('[');
ohneta 0:aae260bdcdd9 2141 int idx = 0;
ohneta 0:aae260bdcdd9 2142 while (l->tk != ']') {
ohneta 0:aae260bdcdd9 2143 if (execute) {
ohneta 0:aae260bdcdd9 2144 char idx_str[16]; // big enough for 2^32
ohneta 0:aae260bdcdd9 2145 sprintf_s(idx_str, sizeof(idx_str), "%d",idx);
ohneta 0:aae260bdcdd9 2146
ohneta 0:aae260bdcdd9 2147 CScriptVarLink *a = base(execute);
ohneta 0:aae260bdcdd9 2148 contents->addChild(idx_str, a->var);
ohneta 0:aae260bdcdd9 2149 CLEAN(a);
ohneta 0:aae260bdcdd9 2150 }
ohneta 0:aae260bdcdd9 2151 // no need to clean here, as it will definitely be used
ohneta 0:aae260bdcdd9 2152 if (l->tk != ']') LMATCH(',');
ohneta 0:aae260bdcdd9 2153 idx++;
ohneta 0:aae260bdcdd9 2154 }
ohneta 0:aae260bdcdd9 2155 LMATCH(']');
ohneta 0:aae260bdcdd9 2156 return new CScriptVarLink(contents);
ohneta 0:aae260bdcdd9 2157 }
ohneta 0:aae260bdcdd9 2158 if (l->tk==LEX_R_FUNCTION) {
ohneta 0:aae260bdcdd9 2159 CScriptVarLink *funcVar = parseFunctionDefinition();
ohneta 0:aae260bdcdd9 2160 if (funcVar->name != TINYJS_TEMP_NAME)
ohneta 0:aae260bdcdd9 2161 TRACE("Functions not defined at statement-level are not meant to have a name");
ohneta 0:aae260bdcdd9 2162 return funcVar;
ohneta 0:aae260bdcdd9 2163 }
ohneta 0:aae260bdcdd9 2164 if (l->tk==LEX_R_NEW) {
ohneta 0:aae260bdcdd9 2165 // new -> create a new object
ohneta 0:aae260bdcdd9 2166 LMATCH(LEX_R_NEW);
ohneta 0:aae260bdcdd9 2167 const string &className = l->tkStr;
ohneta 0:aae260bdcdd9 2168 if (execute) {
ohneta 0:aae260bdcdd9 2169 CScriptVarLink *objClassOrFunc = findInScopes(className);
ohneta 0:aae260bdcdd9 2170 if (!objClassOrFunc) {
ohneta 0:aae260bdcdd9 2171 TRACE("%s is not a valid class name", className.c_str());
ohneta 0:aae260bdcdd9 2172 return new CScriptVarLink(new CScriptVar());
ohneta 0:aae260bdcdd9 2173 }
ohneta 0:aae260bdcdd9 2174 LMATCH(LEX_ID);
ohneta 0:aae260bdcdd9 2175 CScriptVar *obj = new CScriptVar(TINYJS_BLANK_DATA, SCRIPTVAR_OBJECT);
ohneta 0:aae260bdcdd9 2176 CScriptVarLink *objLink = new CScriptVarLink(obj);
ohneta 0:aae260bdcdd9 2177 if (objClassOrFunc->var->isFunction()) {
ohneta 0:aae260bdcdd9 2178 CLEAN(functionCall(execute, objClassOrFunc, obj));
ohneta 0:aae260bdcdd9 2179 } else {
ohneta 0:aae260bdcdd9 2180 obj->addChild(TINYJS_PROTOTYPE_CLASS, objClassOrFunc->var);
ohneta 0:aae260bdcdd9 2181 if (l->tk == '(') {
ohneta 0:aae260bdcdd9 2182 LMATCH('(');
ohneta 0:aae260bdcdd9 2183 LMATCH(')');
ohneta 0:aae260bdcdd9 2184 }
ohneta 0:aae260bdcdd9 2185 }
ohneta 0:aae260bdcdd9 2186 return objLink;
ohneta 0:aae260bdcdd9 2187 } else {
ohneta 0:aae260bdcdd9 2188 LMATCH(LEX_ID);
ohneta 0:aae260bdcdd9 2189 if (l->tk == '(') {
ohneta 0:aae260bdcdd9 2190 LMATCH('(');
ohneta 0:aae260bdcdd9 2191 LMATCH(')');
ohneta 0:aae260bdcdd9 2192 }
ohneta 0:aae260bdcdd9 2193 }
ohneta 0:aae260bdcdd9 2194 }
ohneta 0:aae260bdcdd9 2195 // Nothing we can do here... just hope it's the end...
ohneta 0:aae260bdcdd9 2196 LMATCH(LEX_EOF);
ohneta 0:aae260bdcdd9 2197 return 0;
ohneta 0:aae260bdcdd9 2198 }
ohneta 0:aae260bdcdd9 2199 #endif
ohneta 0:aae260bdcdd9 2200
ohneta 0:aae260bdcdd9 2201 CScriptVarLink *CTinyJS::unary(bool &execute) {
ohneta 0:aae260bdcdd9 2202 CScriptVarLink *a;
ohneta 0:aae260bdcdd9 2203 if (l->tk=='!') {
ohneta 0:aae260bdcdd9 2204 #ifndef MBED
ohneta 0:aae260bdcdd9 2205 l->match('!'); // binary not
ohneta 0:aae260bdcdd9 2206 #else
ohneta 0:aae260bdcdd9 2207 LMATCH('!'); // binary not
ohneta 0:aae260bdcdd9 2208 #endif
ohneta 0:aae260bdcdd9 2209 a = factor(execute);
ohneta 0:aae260bdcdd9 2210 if (execute) {
ohneta 0:aae260bdcdd9 2211 CScriptVar zero(0);
ohneta 0:aae260bdcdd9 2212 CScriptVar *res = a->var->mathsOp(&zero, LEX_EQUAL);
ohneta 0:aae260bdcdd9 2213 CREATE_LINK(a, res);
ohneta 0:aae260bdcdd9 2214 }
ohneta 0:aae260bdcdd9 2215 } else
ohneta 0:aae260bdcdd9 2216 a = factor(execute);
ohneta 0:aae260bdcdd9 2217 return a;
ohneta 0:aae260bdcdd9 2218 }
ohneta 0:aae260bdcdd9 2219
ohneta 0:aae260bdcdd9 2220 CScriptVarLink *CTinyJS::term(bool &execute) {
ohneta 0:aae260bdcdd9 2221 CScriptVarLink *a = unary(execute);
ohneta 0:aae260bdcdd9 2222 while (l->tk=='*' || l->tk=='/' || l->tk=='%') {
ohneta 0:aae260bdcdd9 2223 int op = l->tk;
ohneta 0:aae260bdcdd9 2224 #ifndef MBED
ohneta 0:aae260bdcdd9 2225 l->match(l->tk);
ohneta 0:aae260bdcdd9 2226 #else
ohneta 0:aae260bdcdd9 2227 LMATCH(l->tk);
ohneta 0:aae260bdcdd9 2228 #endif
ohneta 0:aae260bdcdd9 2229 CScriptVarLink *b = unary(execute);
ohneta 0:aae260bdcdd9 2230 if (execute) {
ohneta 0:aae260bdcdd9 2231 CScriptVar *res = a->var->mathsOp(b->var, op);
ohneta 0:aae260bdcdd9 2232 CREATE_LINK(a, res);
ohneta 0:aae260bdcdd9 2233 }
ohneta 0:aae260bdcdd9 2234 CLEAN(b);
ohneta 0:aae260bdcdd9 2235 }
ohneta 0:aae260bdcdd9 2236 return a;
ohneta 0:aae260bdcdd9 2237 }
ohneta 0:aae260bdcdd9 2238
ohneta 0:aae260bdcdd9 2239 CScriptVarLink *CTinyJS::expression(bool &execute) {
ohneta 0:aae260bdcdd9 2240 bool negate = false;
ohneta 0:aae260bdcdd9 2241 if (l->tk=='-') {
ohneta 0:aae260bdcdd9 2242 #ifndef MBED
ohneta 0:aae260bdcdd9 2243 l->match('-');
ohneta 0:aae260bdcdd9 2244 #else
ohneta 0:aae260bdcdd9 2245 LMATCH('-');
ohneta 0:aae260bdcdd9 2246 #endif
ohneta 0:aae260bdcdd9 2247 negate = true;
ohneta 0:aae260bdcdd9 2248 }
ohneta 0:aae260bdcdd9 2249 CScriptVarLink *a = term(execute);
ohneta 0:aae260bdcdd9 2250 if (negate) {
ohneta 0:aae260bdcdd9 2251 CScriptVar zero(0);
ohneta 0:aae260bdcdd9 2252 CScriptVar *res = zero.mathsOp(a->var, '-');
ohneta 0:aae260bdcdd9 2253 CREATE_LINK(a, res);
ohneta 0:aae260bdcdd9 2254 }
ohneta 0:aae260bdcdd9 2255
ohneta 0:aae260bdcdd9 2256 while (l->tk=='+' || l->tk=='-' ||
ohneta 0:aae260bdcdd9 2257 l->tk==LEX_PLUSPLUS || l->tk==LEX_MINUSMINUS) {
ohneta 0:aae260bdcdd9 2258 int op = l->tk;
ohneta 0:aae260bdcdd9 2259 #ifndef MBED
ohneta 0:aae260bdcdd9 2260 l->match(l->tk);
ohneta 0:aae260bdcdd9 2261 #else
ohneta 0:aae260bdcdd9 2262 LMATCH(l->tk);
ohneta 0:aae260bdcdd9 2263 #endif
ohneta 0:aae260bdcdd9 2264 if (op==LEX_PLUSPLUS || op==LEX_MINUSMINUS) {
ohneta 0:aae260bdcdd9 2265 if (execute) {
ohneta 0:aae260bdcdd9 2266 CScriptVar one(1);
ohneta 0:aae260bdcdd9 2267 CScriptVar *res = a->var->mathsOp(&one, op==LEX_PLUSPLUS ? '+' : '-');
ohneta 0:aae260bdcdd9 2268 CScriptVarLink *oldValue = new CScriptVarLink(a->var);
ohneta 0:aae260bdcdd9 2269 // in-place add/subtract
ohneta 0:aae260bdcdd9 2270 a->replaceWith(res);
ohneta 0:aae260bdcdd9 2271 CLEAN(a);
ohneta 0:aae260bdcdd9 2272 a = oldValue;
ohneta 0:aae260bdcdd9 2273 }
ohneta 0:aae260bdcdd9 2274 } else {
ohneta 0:aae260bdcdd9 2275 CScriptVarLink *b = term(execute);
ohneta 0:aae260bdcdd9 2276 if (execute) {
ohneta 0:aae260bdcdd9 2277 // not in-place, so just replace
ohneta 0:aae260bdcdd9 2278 CScriptVar *res = a->var->mathsOp(b->var, op);
ohneta 0:aae260bdcdd9 2279 CREATE_LINK(a, res);
ohneta 0:aae260bdcdd9 2280 }
ohneta 0:aae260bdcdd9 2281 CLEAN(b);
ohneta 0:aae260bdcdd9 2282 }
ohneta 0:aae260bdcdd9 2283 }
ohneta 0:aae260bdcdd9 2284 return a;
ohneta 0:aae260bdcdd9 2285 }
ohneta 0:aae260bdcdd9 2286
ohneta 0:aae260bdcdd9 2287 CScriptVarLink *CTinyJS::shift(bool &execute) {
ohneta 0:aae260bdcdd9 2288 CScriptVarLink *a = expression(execute);
ohneta 0:aae260bdcdd9 2289 if (l->tk==LEX_LSHIFT || l->tk==LEX_RSHIFT || l->tk==LEX_RSHIFTUNSIGNED) {
ohneta 0:aae260bdcdd9 2290 int op = l->tk;
ohneta 0:aae260bdcdd9 2291 #ifndef MBED
ohneta 0:aae260bdcdd9 2292 l->match(op);
ohneta 0:aae260bdcdd9 2293 #else
ohneta 0:aae260bdcdd9 2294 LMATCH(op);
ohneta 0:aae260bdcdd9 2295 #endif
ohneta 0:aae260bdcdd9 2296 CScriptVarLink *b = base(execute);
ohneta 0:aae260bdcdd9 2297 int shift = execute ? b->var->getInt() : 0;
ohneta 0:aae260bdcdd9 2298 CLEAN(b);
ohneta 0:aae260bdcdd9 2299 if (execute) {
ohneta 0:aae260bdcdd9 2300 if (op==LEX_LSHIFT) a->var->setInt(a->var->getInt() << shift);
ohneta 0:aae260bdcdd9 2301 if (op==LEX_RSHIFT) a->var->setInt(a->var->getInt() >> shift);
ohneta 0:aae260bdcdd9 2302 if (op==LEX_RSHIFTUNSIGNED) a->var->setInt(((unsigned int)a->var->getInt()) >> shift);
ohneta 0:aae260bdcdd9 2303 }
ohneta 0:aae260bdcdd9 2304 }
ohneta 0:aae260bdcdd9 2305 return a;
ohneta 0:aae260bdcdd9 2306 }
ohneta 0:aae260bdcdd9 2307
ohneta 0:aae260bdcdd9 2308 CScriptVarLink *CTinyJS::condition(bool &execute) {
ohneta 0:aae260bdcdd9 2309 CScriptVarLink *a = shift(execute);
ohneta 0:aae260bdcdd9 2310 CScriptVarLink *b;
ohneta 0:aae260bdcdd9 2311 while (l->tk==LEX_EQUAL || l->tk==LEX_NEQUAL ||
ohneta 0:aae260bdcdd9 2312 l->tk==LEX_TYPEEQUAL || l->tk==LEX_NTYPEEQUAL ||
ohneta 0:aae260bdcdd9 2313 l->tk==LEX_LEQUAL || l->tk==LEX_GEQUAL ||
ohneta 0:aae260bdcdd9 2314 l->tk=='<' || l->tk=='>') {
ohneta 0:aae260bdcdd9 2315 int op = l->tk;
ohneta 0:aae260bdcdd9 2316 #ifndef MBED
ohneta 0:aae260bdcdd9 2317 l->match(l->tk);
ohneta 0:aae260bdcdd9 2318 #else
ohneta 0:aae260bdcdd9 2319 LMATCH(l->tk);
ohneta 0:aae260bdcdd9 2320 #endif
ohneta 0:aae260bdcdd9 2321 b = shift(execute);
ohneta 0:aae260bdcdd9 2322 if (execute) {
ohneta 0:aae260bdcdd9 2323 CScriptVar *res = a->var->mathsOp(b->var, op);
ohneta 0:aae260bdcdd9 2324 CREATE_LINK(a,res);
ohneta 0:aae260bdcdd9 2325 }
ohneta 0:aae260bdcdd9 2326 CLEAN(b);
ohneta 0:aae260bdcdd9 2327 }
ohneta 0:aae260bdcdd9 2328 return a;
ohneta 0:aae260bdcdd9 2329 }
ohneta 0:aae260bdcdd9 2330
ohneta 0:aae260bdcdd9 2331 CScriptVarLink *CTinyJS::logic(bool &execute) {
ohneta 0:aae260bdcdd9 2332 CScriptVarLink *a = condition(execute);
ohneta 0:aae260bdcdd9 2333 CScriptVarLink *b;
ohneta 0:aae260bdcdd9 2334 while (l->tk=='&' || l->tk=='|' || l->tk=='^' || l->tk==LEX_ANDAND || l->tk==LEX_OROR) {
ohneta 0:aae260bdcdd9 2335 bool noexecute = false;
ohneta 0:aae260bdcdd9 2336 int op = l->tk;
ohneta 0:aae260bdcdd9 2337 #ifndef MBED
ohneta 0:aae260bdcdd9 2338 l->match(l->tk);
ohneta 0:aae260bdcdd9 2339 #else
ohneta 0:aae260bdcdd9 2340 LMATCH(l->tk);
ohneta 0:aae260bdcdd9 2341 #endif
ohneta 0:aae260bdcdd9 2342 bool shortCircuit = false;
ohneta 0:aae260bdcdd9 2343 bool boolean = false;
ohneta 0:aae260bdcdd9 2344 // if we have short-circuit ops, then if we know the outcome
ohneta 0:aae260bdcdd9 2345 // we don't bother to execute the other op. Even if not
ohneta 0:aae260bdcdd9 2346 // we need to tell mathsOp it's an & or |
ohneta 0:aae260bdcdd9 2347 if (op==LEX_ANDAND) {
ohneta 0:aae260bdcdd9 2348 op = '&';
ohneta 0:aae260bdcdd9 2349 shortCircuit = !a->var->getBool();
ohneta 0:aae260bdcdd9 2350 boolean = true;
ohneta 0:aae260bdcdd9 2351 } else if (op==LEX_OROR) {
ohneta 0:aae260bdcdd9 2352 op = '|';
ohneta 0:aae260bdcdd9 2353 shortCircuit = a->var->getBool();
ohneta 0:aae260bdcdd9 2354 boolean = true;
ohneta 0:aae260bdcdd9 2355 }
ohneta 0:aae260bdcdd9 2356 b = condition(shortCircuit ? noexecute : execute);
ohneta 0:aae260bdcdd9 2357 if (execute && !shortCircuit) {
ohneta 0:aae260bdcdd9 2358 if (boolean) {
ohneta 0:aae260bdcdd9 2359 CScriptVar *newa = new CScriptVar(a->var->getBool());
ohneta 0:aae260bdcdd9 2360 CScriptVar *newb = new CScriptVar(b->var->getBool());
ohneta 0:aae260bdcdd9 2361 CREATE_LINK(a, newa);
ohneta 0:aae260bdcdd9 2362 CREATE_LINK(b, newb);
ohneta 0:aae260bdcdd9 2363 }
ohneta 0:aae260bdcdd9 2364 CScriptVar *res = a->var->mathsOp(b->var, op);
ohneta 0:aae260bdcdd9 2365 CREATE_LINK(a, res);
ohneta 0:aae260bdcdd9 2366 }
ohneta 0:aae260bdcdd9 2367 CLEAN(b);
ohneta 0:aae260bdcdd9 2368 }
ohneta 0:aae260bdcdd9 2369 return a;
ohneta 0:aae260bdcdd9 2370 }
ohneta 0:aae260bdcdd9 2371
ohneta 0:aae260bdcdd9 2372 CScriptVarLink *CTinyJS::ternary(bool &execute) {
ohneta 0:aae260bdcdd9 2373 CScriptVarLink *lhs = logic(execute);
ohneta 0:aae260bdcdd9 2374 bool noexec = false;
ohneta 0:aae260bdcdd9 2375 if (l->tk=='?') {
ohneta 0:aae260bdcdd9 2376 #ifndef MBED
ohneta 0:aae260bdcdd9 2377 l->match('?');
ohneta 0:aae260bdcdd9 2378 #else
ohneta 0:aae260bdcdd9 2379 LMATCH('?');
ohneta 0:aae260bdcdd9 2380 #endif
ohneta 0:aae260bdcdd9 2381 if (!execute) {
ohneta 0:aae260bdcdd9 2382 CLEAN(lhs);
ohneta 0:aae260bdcdd9 2383 CLEAN(base(noexec));
ohneta 0:aae260bdcdd9 2384 #ifndef MBED
ohneta 0:aae260bdcdd9 2385 l->match(':');
ohneta 0:aae260bdcdd9 2386 #else
ohneta 0:aae260bdcdd9 2387 LMATCH(':');
ohneta 0:aae260bdcdd9 2388 #endif
ohneta 0:aae260bdcdd9 2389 CLEAN(base(noexec));
ohneta 0:aae260bdcdd9 2390 } else {
ohneta 0:aae260bdcdd9 2391 bool first = lhs->var->getBool();
ohneta 0:aae260bdcdd9 2392 CLEAN(lhs);
ohneta 0:aae260bdcdd9 2393 if (first) {
ohneta 0:aae260bdcdd9 2394 lhs = base(execute);
ohneta 0:aae260bdcdd9 2395 #ifndef MBED
ohneta 0:aae260bdcdd9 2396 l->match(':');
ohneta 0:aae260bdcdd9 2397 #else
ohneta 0:aae260bdcdd9 2398 LMATCH(':');
ohneta 0:aae260bdcdd9 2399 #endif
ohneta 0:aae260bdcdd9 2400 CLEAN(base(noexec));
ohneta 0:aae260bdcdd9 2401 } else {
ohneta 0:aae260bdcdd9 2402 CLEAN(base(noexec));
ohneta 0:aae260bdcdd9 2403 #ifndef MBED
ohneta 0:aae260bdcdd9 2404 l->match(':');
ohneta 0:aae260bdcdd9 2405 #else
ohneta 0:aae260bdcdd9 2406 LMATCH(':');
ohneta 0:aae260bdcdd9 2407 #endif
ohneta 0:aae260bdcdd9 2408 lhs = base(execute);
ohneta 0:aae260bdcdd9 2409 }
ohneta 0:aae260bdcdd9 2410 }
ohneta 0:aae260bdcdd9 2411 }
ohneta 0:aae260bdcdd9 2412
ohneta 0:aae260bdcdd9 2413 return lhs;
ohneta 0:aae260bdcdd9 2414 }
ohneta 0:aae260bdcdd9 2415
ohneta 0:aae260bdcdd9 2416 CScriptVarLink *CTinyJS::base(bool &execute) {
ohneta 0:aae260bdcdd9 2417 CScriptVarLink *lhs = ternary(execute);
ohneta 0:aae260bdcdd9 2418 if (l->tk=='=' || l->tk==LEX_PLUSEQUAL || l->tk==LEX_MINUSEQUAL) {
ohneta 0:aae260bdcdd9 2419 /* If we're assigning to this and we don't have a parent,
ohneta 0:aae260bdcdd9 2420 * add it to the symbol table root as per JavaScript. */
ohneta 0:aae260bdcdd9 2421 if (execute && !lhs->owned) {
ohneta 0:aae260bdcdd9 2422 if (lhs->name.length()>0) {
ohneta 0:aae260bdcdd9 2423 CScriptVarLink *realLhs = root->addChildNoDup(lhs->name, lhs->var);
ohneta 0:aae260bdcdd9 2424 CLEAN(lhs);
ohneta 0:aae260bdcdd9 2425 lhs = realLhs;
ohneta 0:aae260bdcdd9 2426 } else
ohneta 0:aae260bdcdd9 2427 TRACE("Trying to assign to an un-named type\n");
ohneta 0:aae260bdcdd9 2428 }
ohneta 0:aae260bdcdd9 2429
ohneta 0:aae260bdcdd9 2430 int op = l->tk;
ohneta 0:aae260bdcdd9 2431 #ifndef MBED
ohneta 0:aae260bdcdd9 2432 l->match(l->tk);
ohneta 0:aae260bdcdd9 2433 #else
ohneta 0:aae260bdcdd9 2434 LMATCH(l->tk);
ohneta 0:aae260bdcdd9 2435 #endif
ohneta 0:aae260bdcdd9 2436 CScriptVarLink *rhs = base(execute);
ohneta 0:aae260bdcdd9 2437 if (execute) {
ohneta 0:aae260bdcdd9 2438 if (op=='=') {
ohneta 0:aae260bdcdd9 2439 lhs->replaceWith(rhs);
ohneta 0:aae260bdcdd9 2440 } else if (op==LEX_PLUSEQUAL) {
ohneta 0:aae260bdcdd9 2441 CScriptVar *res = lhs->var->mathsOp(rhs->var, '+');
ohneta 0:aae260bdcdd9 2442 lhs->replaceWith(res);
ohneta 0:aae260bdcdd9 2443 } else if (op==LEX_MINUSEQUAL) {
ohneta 0:aae260bdcdd9 2444 CScriptVar *res = lhs->var->mathsOp(rhs->var, '-');
ohneta 0:aae260bdcdd9 2445 lhs->replaceWith(res);
ohneta 0:aae260bdcdd9 2446 } else ASSERT(0);
ohneta 0:aae260bdcdd9 2447 }
ohneta 0:aae260bdcdd9 2448 CLEAN(rhs);
ohneta 0:aae260bdcdd9 2449 }
ohneta 0:aae260bdcdd9 2450 return lhs;
ohneta 0:aae260bdcdd9 2451 }
ohneta 0:aae260bdcdd9 2452
ohneta 0:aae260bdcdd9 2453 #ifndef MBED
ohneta 0:aae260bdcdd9 2454 void CTinyJS::block(bool &execute) {
ohneta 0:aae260bdcdd9 2455 l->match('{');
ohneta 0:aae260bdcdd9 2456 if (execute) {
ohneta 0:aae260bdcdd9 2457 while (l->tk && l->tk!='}')
ohneta 0:aae260bdcdd9 2458 statement(execute);
ohneta 0:aae260bdcdd9 2459 l->match('}');
ohneta 0:aae260bdcdd9 2460 } else {
ohneta 0:aae260bdcdd9 2461 // fast skip of blocks
ohneta 0:aae260bdcdd9 2462 int brackets = 1;
ohneta 0:aae260bdcdd9 2463 while (l->tk && brackets) {
ohneta 0:aae260bdcdd9 2464 if (l->tk == '{') brackets++;
ohneta 0:aae260bdcdd9 2465 if (l->tk == '}') brackets--;
ohneta 0:aae260bdcdd9 2466 l->match(l->tk);
ohneta 0:aae260bdcdd9 2467 }
ohneta 0:aae260bdcdd9 2468 }
ohneta 0:aae260bdcdd9 2469 }
ohneta 0:aae260bdcdd9 2470 #else
ohneta 0:aae260bdcdd9 2471 void CTinyJS::block(bool &execute) {
ohneta 0:aae260bdcdd9 2472 LMATCH_VOID('{');
ohneta 0:aae260bdcdd9 2473 if (execute) {
ohneta 0:aae260bdcdd9 2474 while (l->tk && l->tk!='}')
ohneta 0:aae260bdcdd9 2475 statement(execute);
ohneta 0:aae260bdcdd9 2476 LMATCH_VOID('}');
ohneta 0:aae260bdcdd9 2477 } else {
ohneta 0:aae260bdcdd9 2478 // fast skip of blocks
ohneta 0:aae260bdcdd9 2479 int brackets = 1;
ohneta 0:aae260bdcdd9 2480 while (l->tk && brackets) {
ohneta 0:aae260bdcdd9 2481 if (l->tk == '{') brackets++;
ohneta 0:aae260bdcdd9 2482 if (l->tk == '}') brackets--;
ohneta 0:aae260bdcdd9 2483 LMATCH_VOID(l->tk);
ohneta 0:aae260bdcdd9 2484 }
ohneta 0:aae260bdcdd9 2485 }
ohneta 0:aae260bdcdd9 2486 }
ohneta 0:aae260bdcdd9 2487 #endif
ohneta 0:aae260bdcdd9 2488
ohneta 0:aae260bdcdd9 2489 #ifndef MBED
ohneta 0:aae260bdcdd9 2490 void CTinyJS::statement(bool &execute) {
ohneta 0:aae260bdcdd9 2491 if (l->tk==LEX_ID ||
ohneta 0:aae260bdcdd9 2492 l->tk==LEX_INT ||
ohneta 0:aae260bdcdd9 2493 l->tk==LEX_FLOAT ||
ohneta 0:aae260bdcdd9 2494 l->tk==LEX_STR ||
ohneta 0:aae260bdcdd9 2495 l->tk=='-') {
ohneta 0:aae260bdcdd9 2496 /* Execute a simple statement that only contains basic arithmetic... */
ohneta 0:aae260bdcdd9 2497 CLEAN(base(execute));
ohneta 0:aae260bdcdd9 2498 l->match(';');
ohneta 0:aae260bdcdd9 2499 } else if (l->tk=='{') {
ohneta 0:aae260bdcdd9 2500 /* A block of code */
ohneta 0:aae260bdcdd9 2501 block(execute);
ohneta 0:aae260bdcdd9 2502 } else if (l->tk==';') {
ohneta 0:aae260bdcdd9 2503 /* Empty statement - to allow things like ;;; */
ohneta 0:aae260bdcdd9 2504 l->match(';');
ohneta 0:aae260bdcdd9 2505 } else if (l->tk==LEX_R_VAR) {
ohneta 0:aae260bdcdd9 2506 /* variable creation. TODO - we need a better way of parsing the left
ohneta 0:aae260bdcdd9 2507 * hand side. Maybe just have a flag called can_create_var that we
ohneta 0:aae260bdcdd9 2508 * set and then we parse as if we're doing a normal equals.*/
ohneta 0:aae260bdcdd9 2509 l->match(LEX_R_VAR);
ohneta 0:aae260bdcdd9 2510 while (l->tk != ';') {
ohneta 0:aae260bdcdd9 2511 CScriptVarLink *a = 0;
ohneta 0:aae260bdcdd9 2512 if (execute)
ohneta 0:aae260bdcdd9 2513 a = scopes.back()->findChildOrCreate(l->tkStr);
ohneta 0:aae260bdcdd9 2514 l->match(LEX_ID);
ohneta 0:aae260bdcdd9 2515 // now do stuff defined with dots
ohneta 0:aae260bdcdd9 2516 while (l->tk == '.') {
ohneta 0:aae260bdcdd9 2517 l->match('.');
ohneta 0:aae260bdcdd9 2518 if (execute) {
ohneta 0:aae260bdcdd9 2519 CScriptVarLink *lastA = a;
ohneta 0:aae260bdcdd9 2520 a = lastA->var->findChildOrCreate(l->tkStr);
ohneta 0:aae260bdcdd9 2521 }
ohneta 0:aae260bdcdd9 2522 l->match(LEX_ID);
ohneta 0:aae260bdcdd9 2523 }
ohneta 0:aae260bdcdd9 2524 // sort out initialiser
ohneta 0:aae260bdcdd9 2525 if (l->tk == '=') {
ohneta 0:aae260bdcdd9 2526 l->match('=');
ohneta 0:aae260bdcdd9 2527 CScriptVarLink *var = base(execute);
ohneta 0:aae260bdcdd9 2528 if (execute)
ohneta 0:aae260bdcdd9 2529 a->replaceWith(var);
ohneta 0:aae260bdcdd9 2530 CLEAN(var);
ohneta 0:aae260bdcdd9 2531 }
ohneta 0:aae260bdcdd9 2532 if (l->tk != ';')
ohneta 0:aae260bdcdd9 2533 l->match(',');
ohneta 0:aae260bdcdd9 2534 }
ohneta 0:aae260bdcdd9 2535 l->match(';');
ohneta 0:aae260bdcdd9 2536 } else if (l->tk==LEX_R_IF) {
ohneta 0:aae260bdcdd9 2537 l->match(LEX_R_IF);
ohneta 0:aae260bdcdd9 2538 l->match('(');
ohneta 0:aae260bdcdd9 2539 CScriptVarLink *var = base(execute);
ohneta 0:aae260bdcdd9 2540 l->match(')');
ohneta 0:aae260bdcdd9 2541 bool cond = execute && var->var->getBool();
ohneta 0:aae260bdcdd9 2542 CLEAN(var);
ohneta 0:aae260bdcdd9 2543 bool noexecute = false; // because we need to be abl;e to write to it
ohneta 0:aae260bdcdd9 2544 statement(cond ? execute : noexecute);
ohneta 0:aae260bdcdd9 2545 if (l->tk==LEX_R_ELSE) {
ohneta 0:aae260bdcdd9 2546 l->match(LEX_R_ELSE);
ohneta 0:aae260bdcdd9 2547 statement(cond ? noexecute : execute);
ohneta 0:aae260bdcdd9 2548 }
ohneta 0:aae260bdcdd9 2549 } else if (l->tk==LEX_R_WHILE) {
ohneta 0:aae260bdcdd9 2550 // We do repetition by pulling out the string representing our statement
ohneta 0:aae260bdcdd9 2551 // there's definitely some opportunity for optimisation here
ohneta 0:aae260bdcdd9 2552 l->match(LEX_R_WHILE);
ohneta 0:aae260bdcdd9 2553 l->match('(');
ohneta 0:aae260bdcdd9 2554 int whileCondStart = l->tokenStart;
ohneta 0:aae260bdcdd9 2555 bool noexecute = false;
ohneta 0:aae260bdcdd9 2556 CScriptVarLink *cond = base(execute);
ohneta 0:aae260bdcdd9 2557 bool loopCond = execute && cond->var->getBool();
ohneta 0:aae260bdcdd9 2558 CLEAN(cond);
ohneta 0:aae260bdcdd9 2559 CScriptLex *whileCond = l->getSubLex(whileCondStart);
ohneta 0:aae260bdcdd9 2560 l->match(')');
ohneta 0:aae260bdcdd9 2561 int whileBodyStart = l->tokenStart;
ohneta 0:aae260bdcdd9 2562 statement(loopCond ? execute : noexecute);
ohneta 0:aae260bdcdd9 2563 CScriptLex *whileBody = l->getSubLex(whileBodyStart);
ohneta 0:aae260bdcdd9 2564 CScriptLex *oldLex = l;
ohneta 0:aae260bdcdd9 2565 int loopCount = TINYJS_LOOP_MAX_ITERATIONS;
ohneta 0:aae260bdcdd9 2566 while (loopCond && loopCount-->0) {
ohneta 0:aae260bdcdd9 2567 whileCond->reset();
ohneta 0:aae260bdcdd9 2568 l = whileCond;
ohneta 0:aae260bdcdd9 2569 cond = base(execute);
ohneta 0:aae260bdcdd9 2570 loopCond = execute && cond->var->getBool();
ohneta 0:aae260bdcdd9 2571 CLEAN(cond);
ohneta 0:aae260bdcdd9 2572 if (loopCond) {
ohneta 0:aae260bdcdd9 2573 whileBody->reset();
ohneta 0:aae260bdcdd9 2574 l = whileBody;
ohneta 0:aae260bdcdd9 2575 statement(execute);
ohneta 0:aae260bdcdd9 2576 }
ohneta 0:aae260bdcdd9 2577 }
ohneta 0:aae260bdcdd9 2578 l = oldLex;
ohneta 0:aae260bdcdd9 2579 delete whileCond;
ohneta 0:aae260bdcdd9 2580 delete whileBody;
ohneta 0:aae260bdcdd9 2581
ohneta 0:aae260bdcdd9 2582 if (loopCount<=0) {
ohneta 0:aae260bdcdd9 2583 root->trace();
ohneta 0:aae260bdcdd9 2584 TRACE("WHILE Loop exceeded %d iterations at %s\n", TINYJS_LOOP_MAX_ITERATIONS, l->getPosition().c_str());
ohneta 0:aae260bdcdd9 2585 throw new CScriptException("LOOP_ERROR");
ohneta 0:aae260bdcdd9 2586 }
ohneta 0:aae260bdcdd9 2587 } else if (l->tk==LEX_R_FOR) {
ohneta 0:aae260bdcdd9 2588 l->match(LEX_R_FOR);
ohneta 0:aae260bdcdd9 2589 l->match('(');
ohneta 0:aae260bdcdd9 2590 statement(execute); // initialisation
ohneta 0:aae260bdcdd9 2591 //l->match(';');
ohneta 0:aae260bdcdd9 2592 int forCondStart = l->tokenStart;
ohneta 0:aae260bdcdd9 2593 bool noexecute = false;
ohneta 0:aae260bdcdd9 2594 CScriptVarLink *cond = base(execute); // condition
ohneta 0:aae260bdcdd9 2595 bool loopCond = execute && cond->var->getBool();
ohneta 0:aae260bdcdd9 2596 CLEAN(cond);
ohneta 0:aae260bdcdd9 2597 CScriptLex *forCond = l->getSubLex(forCondStart);
ohneta 0:aae260bdcdd9 2598 l->match(';');
ohneta 0:aae260bdcdd9 2599 int forIterStart = l->tokenStart;
ohneta 0:aae260bdcdd9 2600 CLEAN(base(noexecute)); // iterator
ohneta 0:aae260bdcdd9 2601 CScriptLex *forIter = l->getSubLex(forIterStart);
ohneta 0:aae260bdcdd9 2602 l->match(')');
ohneta 0:aae260bdcdd9 2603 int forBodyStart = l->tokenStart;
ohneta 0:aae260bdcdd9 2604 statement(loopCond ? execute : noexecute);
ohneta 0:aae260bdcdd9 2605 CScriptLex *forBody = l->getSubLex(forBodyStart);
ohneta 0:aae260bdcdd9 2606 CScriptLex *oldLex = l;
ohneta 0:aae260bdcdd9 2607 if (loopCond) {
ohneta 0:aae260bdcdd9 2608 forIter->reset();
ohneta 0:aae260bdcdd9 2609 l = forIter;
ohneta 0:aae260bdcdd9 2610 CLEAN(base(execute));
ohneta 0:aae260bdcdd9 2611 }
ohneta 0:aae260bdcdd9 2612 int loopCount = TINYJS_LOOP_MAX_ITERATIONS;
ohneta 0:aae260bdcdd9 2613 while (execute && loopCond && loopCount-->0) {
ohneta 0:aae260bdcdd9 2614 forCond->reset();
ohneta 0:aae260bdcdd9 2615 l = forCond;
ohneta 0:aae260bdcdd9 2616 cond = base(execute);
ohneta 0:aae260bdcdd9 2617 loopCond = cond->var->getBool();
ohneta 0:aae260bdcdd9 2618 CLEAN(cond);
ohneta 0:aae260bdcdd9 2619 if (execute && loopCond) {
ohneta 0:aae260bdcdd9 2620 forBody->reset();
ohneta 0:aae260bdcdd9 2621 l = forBody;
ohneta 0:aae260bdcdd9 2622 statement(execute);
ohneta 0:aae260bdcdd9 2623 }
ohneta 0:aae260bdcdd9 2624 if (execute && loopCond) {
ohneta 0:aae260bdcdd9 2625 forIter->reset();
ohneta 0:aae260bdcdd9 2626 l = forIter;
ohneta 0:aae260bdcdd9 2627 CLEAN(base(execute));
ohneta 0:aae260bdcdd9 2628 }
ohneta 0:aae260bdcdd9 2629 }
ohneta 0:aae260bdcdd9 2630 l = oldLex;
ohneta 0:aae260bdcdd9 2631 delete forCond;
ohneta 0:aae260bdcdd9 2632 delete forIter;
ohneta 0:aae260bdcdd9 2633 delete forBody;
ohneta 0:aae260bdcdd9 2634 if (loopCount<=0) {
ohneta 0:aae260bdcdd9 2635 root->trace();
ohneta 0:aae260bdcdd9 2636 TRACE("FOR Loop exceeded %d iterations at %s\n", TINYJS_LOOP_MAX_ITERATIONS, l->getPosition().c_str());
ohneta 0:aae260bdcdd9 2637 throw new CScriptException("LOOP_ERROR");
ohneta 0:aae260bdcdd9 2638 }
ohneta 0:aae260bdcdd9 2639 } else if (l->tk==LEX_R_RETURN) {
ohneta 0:aae260bdcdd9 2640 l->match(LEX_R_RETURN);
ohneta 0:aae260bdcdd9 2641 CScriptVarLink *result = 0;
ohneta 0:aae260bdcdd9 2642 if (l->tk != ';')
ohneta 0:aae260bdcdd9 2643 result = base(execute);
ohneta 0:aae260bdcdd9 2644 if (execute) {
ohneta 0:aae260bdcdd9 2645 CScriptVarLink *resultVar = scopes.back()->findChild(TINYJS_RETURN_VAR);
ohneta 0:aae260bdcdd9 2646 if (resultVar)
ohneta 0:aae260bdcdd9 2647 resultVar->replaceWith(result);
ohneta 0:aae260bdcdd9 2648 else
ohneta 0:aae260bdcdd9 2649 TRACE("RETURN statement, but not in a function.\n");
ohneta 0:aae260bdcdd9 2650 execute = false;
ohneta 0:aae260bdcdd9 2651 }
ohneta 0:aae260bdcdd9 2652 CLEAN(result);
ohneta 0:aae260bdcdd9 2653 l->match(';');
ohneta 0:aae260bdcdd9 2654 } else if (l->tk==LEX_R_FUNCTION) {
ohneta 0:aae260bdcdd9 2655 CScriptVarLink *funcVar = parseFunctionDefinition();
ohneta 0:aae260bdcdd9 2656 if (execute) {
ohneta 0:aae260bdcdd9 2657 if (funcVar->name == TINYJS_TEMP_NAME)
ohneta 0:aae260bdcdd9 2658 TRACE("Functions defined at statement-level are meant to have a name\n");
ohneta 0:aae260bdcdd9 2659 else
ohneta 0:aae260bdcdd9 2660 scopes.back()->addChildNoDup(funcVar->name, funcVar->var);
ohneta 0:aae260bdcdd9 2661 }
ohneta 0:aae260bdcdd9 2662 CLEAN(funcVar);
ohneta 0:aae260bdcdd9 2663 } else l->match(LEX_EOF);
ohneta 0:aae260bdcdd9 2664 }
ohneta 0:aae260bdcdd9 2665
ohneta 0:aae260bdcdd9 2666 #else
ohneta 0:aae260bdcdd9 2667
ohneta 0:aae260bdcdd9 2668 void CTinyJS::statement(bool &execute) {
ohneta 0:aae260bdcdd9 2669 if (l->tk==LEX_ID ||
ohneta 0:aae260bdcdd9 2670 l->tk==LEX_INT ||
ohneta 0:aae260bdcdd9 2671 l->tk==LEX_FLOAT ||
ohneta 0:aae260bdcdd9 2672 l->tk==LEX_STR ||
ohneta 0:aae260bdcdd9 2673 l->tk=='-') {
ohneta 0:aae260bdcdd9 2674 /* Execute a simple statement that only contains basic arithmetic... */
ohneta 0:aae260bdcdd9 2675 CLEAN(base(execute));
ohneta 0:aae260bdcdd9 2676 LMATCH_VOID(';');
ohneta 0:aae260bdcdd9 2677 } else if (l->tk=='{') {
ohneta 0:aae260bdcdd9 2678 /* A block of code */
ohneta 0:aae260bdcdd9 2679 block(execute);
ohneta 0:aae260bdcdd9 2680 } else if (l->tk==';') {
ohneta 0:aae260bdcdd9 2681 /* Empty statement - to allow things like ;;; */
ohneta 0:aae260bdcdd9 2682 LMATCH_VOID(';');
ohneta 0:aae260bdcdd9 2683 } else if (l->tk==LEX_R_VAR) {
ohneta 0:aae260bdcdd9 2684 /* variable creation. TODO - we need a better way of parsing the left
ohneta 0:aae260bdcdd9 2685 * hand side. Maybe just have a flag called can_create_var that we
ohneta 0:aae260bdcdd9 2686 * set and then we parse as if we're doing a normal equals.*/
ohneta 0:aae260bdcdd9 2687 LMATCH_VOID(LEX_R_VAR);
ohneta 0:aae260bdcdd9 2688 while (l->tk != ';') {
ohneta 0:aae260bdcdd9 2689 CScriptVarLink *a = 0;
ohneta 0:aae260bdcdd9 2690 if (execute)
ohneta 0:aae260bdcdd9 2691 a = scopes.back()->findChildOrCreate(l->tkStr);
ohneta 0:aae260bdcdd9 2692 LMATCH_VOID(LEX_ID);
ohneta 0:aae260bdcdd9 2693 // now do stuff defined with dots
ohneta 0:aae260bdcdd9 2694 while (l->tk == '.') {
ohneta 0:aae260bdcdd9 2695 LMATCH_VOID('.');
ohneta 0:aae260bdcdd9 2696 if (execute) {
ohneta 0:aae260bdcdd9 2697 CScriptVarLink *lastA = a;
ohneta 0:aae260bdcdd9 2698 a = lastA->var->findChildOrCreate(l->tkStr);
ohneta 0:aae260bdcdd9 2699 }
ohneta 0:aae260bdcdd9 2700 LMATCH_VOID(LEX_ID);
ohneta 0:aae260bdcdd9 2701 }
ohneta 0:aae260bdcdd9 2702 // sort out initialiser
ohneta 0:aae260bdcdd9 2703 if (l->tk == '=') {
ohneta 0:aae260bdcdd9 2704 LMATCH_VOID('=');
ohneta 0:aae260bdcdd9 2705 CScriptVarLink *var = base(execute);
ohneta 0:aae260bdcdd9 2706 if (execute)
ohneta 0:aae260bdcdd9 2707 a->replaceWith(var);
ohneta 0:aae260bdcdd9 2708 CLEAN(var);
ohneta 0:aae260bdcdd9 2709 }
ohneta 0:aae260bdcdd9 2710 if (l->tk != ';')
ohneta 0:aae260bdcdd9 2711 LMATCH_VOID(',');
ohneta 0:aae260bdcdd9 2712 }
ohneta 0:aae260bdcdd9 2713 LMATCH_VOID(';');
ohneta 0:aae260bdcdd9 2714 } else if (l->tk==LEX_R_IF) {
ohneta 0:aae260bdcdd9 2715 LMATCH_VOID(LEX_R_IF);
ohneta 0:aae260bdcdd9 2716 LMATCH_VOID('(');
ohneta 0:aae260bdcdd9 2717 CScriptVarLink *var = base(execute);
ohneta 0:aae260bdcdd9 2718 LMATCH_VOID(')');
ohneta 0:aae260bdcdd9 2719 bool cond = execute && var->var->getBool();
ohneta 0:aae260bdcdd9 2720 CLEAN(var);
ohneta 0:aae260bdcdd9 2721 bool noexecute = false; // because we need to be abl;e to write to it
ohneta 0:aae260bdcdd9 2722 statement(cond ? execute : noexecute);
ohneta 0:aae260bdcdd9 2723 if (l->tk==LEX_R_ELSE) {
ohneta 0:aae260bdcdd9 2724 LMATCH_VOID(LEX_R_ELSE);
ohneta 0:aae260bdcdd9 2725 statement(cond ? noexecute : execute);
ohneta 0:aae260bdcdd9 2726 }
ohneta 0:aae260bdcdd9 2727 } else if (l->tk==LEX_R_WHILE) {
ohneta 0:aae260bdcdd9 2728 // We do repetition by pulling out the string representing our statement
ohneta 0:aae260bdcdd9 2729 // there's definitely some opportunity for optimisation here
ohneta 0:aae260bdcdd9 2730 LMATCH_VOID(LEX_R_WHILE);
ohneta 0:aae260bdcdd9 2731 LMATCH_VOID('(');
ohneta 0:aae260bdcdd9 2732 int whileCondStart = l->tokenStart;
ohneta 0:aae260bdcdd9 2733 bool noexecute = false;
ohneta 0:aae260bdcdd9 2734 CScriptVarLink *cond = base(execute);
ohneta 0:aae260bdcdd9 2735 bool loopCond = execute && cond->var->getBool();
ohneta 0:aae260bdcdd9 2736 CLEAN(cond);
ohneta 0:aae260bdcdd9 2737 CScriptLex *whileCond = l->getSubLex(whileCondStart);
ohneta 0:aae260bdcdd9 2738 LMATCH_VOID(')');
ohneta 0:aae260bdcdd9 2739 int whileBodyStart = l->tokenStart;
ohneta 0:aae260bdcdd9 2740 statement(loopCond ? execute : noexecute);
ohneta 0:aae260bdcdd9 2741 CScriptLex *whileBody = l->getSubLex(whileBodyStart);
ohneta 0:aae260bdcdd9 2742 CScriptLex *oldLex = l;
ohneta 0:aae260bdcdd9 2743 int loopCount = TINYJS_LOOP_MAX_ITERATIONS;
ohneta 0:aae260bdcdd9 2744 while (loopCond && loopCount-->0) {
ohneta 0:aae260bdcdd9 2745 whileCond->reset();
ohneta 0:aae260bdcdd9 2746 l = whileCond;
ohneta 0:aae260bdcdd9 2747 cond = base(execute);
ohneta 0:aae260bdcdd9 2748 loopCond = execute && cond->var->getBool();
ohneta 0:aae260bdcdd9 2749 CLEAN(cond);
ohneta 0:aae260bdcdd9 2750 if (loopCond) {
ohneta 0:aae260bdcdd9 2751 whileBody->reset();
ohneta 0:aae260bdcdd9 2752 l = whileBody;
ohneta 0:aae260bdcdd9 2753 statement(execute);
ohneta 0:aae260bdcdd9 2754 }
ohneta 0:aae260bdcdd9 2755 }
ohneta 0:aae260bdcdd9 2756 l = oldLex;
ohneta 0:aae260bdcdd9 2757 delete whileCond;
ohneta 0:aae260bdcdd9 2758 delete whileBody;
ohneta 0:aae260bdcdd9 2759
ohneta 0:aae260bdcdd9 2760 if (loopCount<=0) {
ohneta 0:aae260bdcdd9 2761 root->trace();
ohneta 0:aae260bdcdd9 2762 TRACE("WHILE Loop exceeded %d iterations at %s\n", TINYJS_LOOP_MAX_ITERATIONS, l->getPosition().c_str());
ohneta 0:aae260bdcdd9 2763 mbedErrorFlag = 1;
ohneta 0:aae260bdcdd9 2764 mbedErrorMessage = "LOOP_ERROR";
ohneta 0:aae260bdcdd9 2765 return;
ohneta 0:aae260bdcdd9 2766 }
ohneta 0:aae260bdcdd9 2767 } else if (l->tk==LEX_R_FOR) {
ohneta 0:aae260bdcdd9 2768 LMATCH_VOID(LEX_R_FOR);
ohneta 0:aae260bdcdd9 2769 LMATCH_VOID('(');
ohneta 0:aae260bdcdd9 2770 statement(execute); // initialisation
ohneta 0:aae260bdcdd9 2771 //LMATCH(';');
ohneta 0:aae260bdcdd9 2772 int forCondStart = l->tokenStart;
ohneta 0:aae260bdcdd9 2773 bool noexecute = false;
ohneta 0:aae260bdcdd9 2774 CScriptVarLink *cond = base(execute); // condition
ohneta 0:aae260bdcdd9 2775 bool loopCond = execute && cond->var->getBool();
ohneta 0:aae260bdcdd9 2776 CLEAN(cond);
ohneta 0:aae260bdcdd9 2777 CScriptLex *forCond = l->getSubLex(forCondStart);
ohneta 0:aae260bdcdd9 2778 LMATCH_VOID(';');
ohneta 0:aae260bdcdd9 2779 int forIterStart = l->tokenStart;
ohneta 0:aae260bdcdd9 2780 CLEAN(base(noexecute)); // iterator
ohneta 0:aae260bdcdd9 2781 CScriptLex *forIter = l->getSubLex(forIterStart);
ohneta 0:aae260bdcdd9 2782 LMATCH_VOID(')');
ohneta 0:aae260bdcdd9 2783 int forBodyStart = l->tokenStart;
ohneta 0:aae260bdcdd9 2784 statement(loopCond ? execute : noexecute);
ohneta 0:aae260bdcdd9 2785 CScriptLex *forBody = l->getSubLex(forBodyStart);
ohneta 0:aae260bdcdd9 2786 CScriptLex *oldLex = l;
ohneta 0:aae260bdcdd9 2787 if (loopCond) {
ohneta 0:aae260bdcdd9 2788 forIter->reset();
ohneta 0:aae260bdcdd9 2789 l = forIter;
ohneta 0:aae260bdcdd9 2790 CLEAN(base(execute));
ohneta 0:aae260bdcdd9 2791 }
ohneta 0:aae260bdcdd9 2792 int loopCount = TINYJS_LOOP_MAX_ITERATIONS;
ohneta 0:aae260bdcdd9 2793 while (execute && loopCond && loopCount-->0) {
ohneta 0:aae260bdcdd9 2794 forCond->reset();
ohneta 0:aae260bdcdd9 2795 l = forCond;
ohneta 0:aae260bdcdd9 2796 cond = base(execute);
ohneta 0:aae260bdcdd9 2797 loopCond = cond->var->getBool();
ohneta 0:aae260bdcdd9 2798 CLEAN(cond);
ohneta 0:aae260bdcdd9 2799 if (execute && loopCond) {
ohneta 0:aae260bdcdd9 2800 forBody->reset();
ohneta 0:aae260bdcdd9 2801 l = forBody;
ohneta 0:aae260bdcdd9 2802 statement(execute);
ohneta 0:aae260bdcdd9 2803 }
ohneta 0:aae260bdcdd9 2804 if (execute && loopCond) {
ohneta 0:aae260bdcdd9 2805 forIter->reset();
ohneta 0:aae260bdcdd9 2806 l = forIter;
ohneta 0:aae260bdcdd9 2807 CLEAN(base(execute));
ohneta 0:aae260bdcdd9 2808 }
ohneta 0:aae260bdcdd9 2809 }
ohneta 0:aae260bdcdd9 2810 l = oldLex;
ohneta 0:aae260bdcdd9 2811 delete forCond;
ohneta 0:aae260bdcdd9 2812 delete forIter;
ohneta 0:aae260bdcdd9 2813 delete forBody;
ohneta 0:aae260bdcdd9 2814 if (loopCount<=0) {
ohneta 0:aae260bdcdd9 2815 root->trace();
ohneta 0:aae260bdcdd9 2816 TRACE("FOR Loop exceeded %d iterations at %s\n", TINYJS_LOOP_MAX_ITERATIONS, l->getPosition().c_str());
ohneta 0:aae260bdcdd9 2817 mbedErrorFlag = 1;
ohneta 0:aae260bdcdd9 2818 mbedErrorMessage = "LOOP_ERROR";
ohneta 0:aae260bdcdd9 2819 return;
ohneta 0:aae260bdcdd9 2820 }
ohneta 0:aae260bdcdd9 2821 } else if (l->tk==LEX_R_RETURN) {
ohneta 0:aae260bdcdd9 2822 LMATCH_VOID(LEX_R_RETURN);
ohneta 0:aae260bdcdd9 2823 CScriptVarLink *result = 0;
ohneta 0:aae260bdcdd9 2824 if (l->tk != ';')
ohneta 0:aae260bdcdd9 2825 result = base(execute);
ohneta 0:aae260bdcdd9 2826 if (execute) {
ohneta 0:aae260bdcdd9 2827 CScriptVarLink *resultVar = scopes.back()->findChild(TINYJS_RETURN_VAR);
ohneta 0:aae260bdcdd9 2828 if (resultVar)
ohneta 0:aae260bdcdd9 2829 resultVar->replaceWith(result);
ohneta 0:aae260bdcdd9 2830 else
ohneta 0:aae260bdcdd9 2831 TRACE("RETURN statement, but not in a function.\n");
ohneta 0:aae260bdcdd9 2832 execute = false;
ohneta 0:aae260bdcdd9 2833 }
ohneta 0:aae260bdcdd9 2834 CLEAN(result);
ohneta 0:aae260bdcdd9 2835 LMATCH_VOID(';');
ohneta 0:aae260bdcdd9 2836 } else if (l->tk==LEX_R_FUNCTION) {
ohneta 0:aae260bdcdd9 2837 CScriptVarLink *funcVar = parseFunctionDefinition();
ohneta 0:aae260bdcdd9 2838 if (execute) {
ohneta 0:aae260bdcdd9 2839 if (funcVar->name == TINYJS_TEMP_NAME)
ohneta 0:aae260bdcdd9 2840 TRACE("Functions defined at statement-level are meant to have a name\n");
ohneta 0:aae260bdcdd9 2841 else
ohneta 0:aae260bdcdd9 2842 scopes.back()->addChildNoDup(funcVar->name, funcVar->var);
ohneta 0:aae260bdcdd9 2843 }
ohneta 0:aae260bdcdd9 2844 CLEAN(funcVar);
ohneta 0:aae260bdcdd9 2845 } else LMATCH_VOID(LEX_EOF);
ohneta 0:aae260bdcdd9 2846 }
ohneta 0:aae260bdcdd9 2847 #endif
ohneta 0:aae260bdcdd9 2848
ohneta 0:aae260bdcdd9 2849 /// Get the given variable specified by a path (var1.var2.etc), or return 0
ohneta 0:aae260bdcdd9 2850 CScriptVar *CTinyJS::getScriptVariable(const string &path) {
ohneta 0:aae260bdcdd9 2851 // traverse path
ohneta 0:aae260bdcdd9 2852 size_t prevIdx = 0;
ohneta 0:aae260bdcdd9 2853 size_t thisIdx = path.find('.');
ohneta 0:aae260bdcdd9 2854 if (thisIdx == string::npos) thisIdx = path.length();
ohneta 0:aae260bdcdd9 2855 CScriptVar *var = root;
ohneta 0:aae260bdcdd9 2856 while (var && prevIdx<path.length()) {
ohneta 0:aae260bdcdd9 2857 string el = path.substr(prevIdx, thisIdx-prevIdx);
ohneta 0:aae260bdcdd9 2858 CScriptVarLink *varl = var->findChild(el);
ohneta 0:aae260bdcdd9 2859 var = varl?varl->var:0;
ohneta 0:aae260bdcdd9 2860 prevIdx = thisIdx+1;
ohneta 0:aae260bdcdd9 2861 thisIdx = path.find('.', prevIdx);
ohneta 0:aae260bdcdd9 2862 if (thisIdx == string::npos) thisIdx = path.length();
ohneta 0:aae260bdcdd9 2863 }
ohneta 0:aae260bdcdd9 2864 return var;
ohneta 0:aae260bdcdd9 2865 }
ohneta 0:aae260bdcdd9 2866
ohneta 0:aae260bdcdd9 2867 /// Get the value of the given variable, or return 0
ohneta 0:aae260bdcdd9 2868 const string *CTinyJS::getVariable(const string &path) {
ohneta 0:aae260bdcdd9 2869 CScriptVar *var = getScriptVariable(path);
ohneta 0:aae260bdcdd9 2870 // return result
ohneta 0:aae260bdcdd9 2871 if (var)
ohneta 0:aae260bdcdd9 2872 return &var->getString();
ohneta 0:aae260bdcdd9 2873 else
ohneta 0:aae260bdcdd9 2874 return 0;
ohneta 0:aae260bdcdd9 2875 }
ohneta 0:aae260bdcdd9 2876
ohneta 0:aae260bdcdd9 2877 /// set the value of the given variable, return trur if it exists and gets set
ohneta 0:aae260bdcdd9 2878 bool CTinyJS::setVariable(const std::string &path, const std::string &varData) {
ohneta 0:aae260bdcdd9 2879 CScriptVar *var = getScriptVariable(path);
ohneta 0:aae260bdcdd9 2880 // return result
ohneta 0:aae260bdcdd9 2881 if (var) {
ohneta 0:aae260bdcdd9 2882 if (var->isInt())
ohneta 0:aae260bdcdd9 2883 var->setInt((int)strtol(varData.c_str(),0,0));
ohneta 0:aae260bdcdd9 2884 else if (var->isDouble())
ohneta 0:aae260bdcdd9 2885 var->setDouble(strtod(varData.c_str(),0));
ohneta 0:aae260bdcdd9 2886 else
ohneta 0:aae260bdcdd9 2887 var->setString(varData.c_str());
ohneta 0:aae260bdcdd9 2888 return true;
ohneta 0:aae260bdcdd9 2889 }
ohneta 0:aae260bdcdd9 2890 else
ohneta 0:aae260bdcdd9 2891 return false;
ohneta 0:aae260bdcdd9 2892 }
ohneta 0:aae260bdcdd9 2893
ohneta 0:aae260bdcdd9 2894 /// Finds a child, looking recursively up the scopes
ohneta 0:aae260bdcdd9 2895 CScriptVarLink *CTinyJS::findInScopes(const std::string &childName) {
ohneta 0:aae260bdcdd9 2896 for (int s=scopes.size()-1;s>=0;s--) {
ohneta 0:aae260bdcdd9 2897 CScriptVarLink *v = scopes[s]->findChild(childName);
ohneta 0:aae260bdcdd9 2898 if (v) return v;
ohneta 0:aae260bdcdd9 2899 }
ohneta 0:aae260bdcdd9 2900 return NULL;
ohneta 0:aae260bdcdd9 2901
ohneta 0:aae260bdcdd9 2902 }
ohneta 0:aae260bdcdd9 2903
ohneta 0:aae260bdcdd9 2904 /// Look up in any parent classes of the given object
ohneta 0:aae260bdcdd9 2905 CScriptVarLink *CTinyJS::findInParentClasses(CScriptVar *object, const std::string &name) {
ohneta 0:aae260bdcdd9 2906 // Look for links to actual parent classes
ohneta 0:aae260bdcdd9 2907 CScriptVarLink *parentClass = object->findChild(TINYJS_PROTOTYPE_CLASS);
ohneta 0:aae260bdcdd9 2908 while (parentClass) {
ohneta 0:aae260bdcdd9 2909 CScriptVarLink *implementation = parentClass->var->findChild(name);
ohneta 0:aae260bdcdd9 2910 if (implementation) return implementation;
ohneta 0:aae260bdcdd9 2911 parentClass = parentClass->var->findChild(TINYJS_PROTOTYPE_CLASS);
ohneta 0:aae260bdcdd9 2912 }
ohneta 0:aae260bdcdd9 2913 // else fake it for strings and finally objects
ohneta 0:aae260bdcdd9 2914 if (object->isString()) {
ohneta 0:aae260bdcdd9 2915 CScriptVarLink *implementation = stringClass->findChild(name);
ohneta 0:aae260bdcdd9 2916 if (implementation) return implementation;
ohneta 0:aae260bdcdd9 2917 }
ohneta 0:aae260bdcdd9 2918 if (object->isArray()) {
ohneta 0:aae260bdcdd9 2919 CScriptVarLink *implementation = arrayClass->findChild(name);
ohneta 0:aae260bdcdd9 2920 if (implementation) return implementation;
ohneta 0:aae260bdcdd9 2921 }
ohneta 0:aae260bdcdd9 2922 CScriptVarLink *implementation = objectClass->findChild(name);
ohneta 0:aae260bdcdd9 2923 if (implementation) return implementation;
ohneta 0:aae260bdcdd9 2924
ohneta 0:aae260bdcdd9 2925 return 0;
ohneta 0:aae260bdcdd9 2926 }
ohneta 0:aae260bdcdd9 2927