Example #1
0
void jslSeekToP(JsLex *lex, JslCharPos *seekToChar) {
  jsvStringIteratorFree(&lex->it);
  lex->it = jsvStringIteratorClone(&seekToChar->it);
  lex->currCh = seekToChar->currCh;
  lex->tokenStart.it.var = 0;
  lex->tokenStart.currCh = 0;
  jslGetNextToken(lex);
}
Example #2
0
/// Match, and return true on success, false on failure
bool jslMatch(int expected_tk) {
  if (lex->tk != expected_tk) {
    jslMatchError(expected_tk);
    return false;
  }
  jslGetNextToken();
  return true;
}
Example #3
0
/// Match, and return true on success, false on failure
bool jslMatch(int expected_tk) {
  if (lex->tk != expected_tk) {
    char gotStr[20];
    char expStr[20];
    jslGetTokenString(gotStr, sizeof(gotStr));
    jslTokenAsString(expected_tk, expStr, sizeof(expStr));

    size_t oldPos = lex->tokenLastStart;
    lex->tokenLastStart = jsvStringIteratorGetIndex(&lex->tokenStart.it)-1;
    jsExceptionHere(JSET_SYNTAXERROR, "Got %s expected %s", gotStr, expStr);
    lex->tokenLastStart = oldPos;
    // Sod it, skip this token anyway - stops us looping
    jslGetNextToken();
    return false;
  }
  jslGetNextToken();
  return true;
}
Example #4
0
void jslSeekToP(JslCharPos *seekToChar) {
  if (lex->it.var) jsvLockAgain(lex->it.var); // see jslGetNextCh
  jsvStringIteratorFree(&lex->it);
  lex->it = jsvStringIteratorClone(&seekToChar->it);
  jsvUnLock(lex->it.var); // see jslGetNextCh
  lex->currCh = seekToChar->currCh;
  lex->tokenStart.it.var = 0;
  lex->tokenStart.currCh = 0;
  jslGetNextToken();
}
Example #5
0
/// Match, and return true on success, false on failure
bool jslMatch(JsLex *lex, int expected_tk) {
  if (lex->tk!=expected_tk) {
      char buf[JS_ERROR_BUF_SIZE];
      size_t bufpos = 0;
      strncpy(&buf[bufpos], "Got ", JS_ERROR_BUF_SIZE-bufpos);
      bufpos = strlen(buf);
      jslGetTokenString(lex, &buf[bufpos], JS_ERROR_BUF_SIZE-bufpos);
      bufpos = strlen(buf);
      strncpy(&buf[bufpos], " expected ", JS_ERROR_BUF_SIZE-bufpos);
      bufpos = strlen(buf);
      jslTokenAsString(expected_tk, &buf[bufpos], JS_ERROR_BUF_SIZE-bufpos);
      jsErrorAt(buf, lex, jsvStringIteratorGetIndex(&lex->tokenStart.it));
      // Sod it, skip this token anyway - stops us looping
      jslGetNextToken(lex);
      return false;
  }
  jslGetNextToken(lex);
  return true;
}
Example #6
0
static bool _parse_time(JsLex *lex, TimeInDay *time, int initialChars) {
  time->hour = (int)stringToIntWithRadix(&jslGetTokenValueAsString(lex)[initialChars], 10, 0);
  jslGetNextToken(lex);
  if (lex->tk==':') {
    jslGetNextToken(lex);
    if (lex->tk == LEX_INT) {
      time->min = _parse_int(lex);
      jslGetNextToken(lex);
      if (lex->tk==':') {
        jslGetNextToken(lex);
        if (lex->tk == LEX_INT || lex->tk == LEX_FLOAT) {
          JsVarFloat f = stringToFloat(jslGetTokenValueAsString(lex));
          time->sec = (int)f;
          time->ms = (int)(f*1000) % 1000;
          jslGetNextToken(lex);
          if (lex->tk == LEX_ID && strcmp(jslGetTokenValueAsString(lex),"GMT")==0) {
            jslGetNextToken(lex);
          }
          if (lex->tk == '+' || lex->tk == '-') {
            int sign = lex->tk == '+' ? 1 : -1;
            jslGetNextToken(lex);
            if (lex->tk == LEX_INT) {
              int i = _parse_int(lex);
              // correct the fact that it's HHMM and turn it into just minutes
              i = (i%100) + ((i/100)*60);
              time->zone = i*sign;
              jslGetNextToken(lex);
            }
          }

          return true;
        }
      }
    }
  }
  return false;
}
Example #7
0
JsVar *jswrap_json_parse_internal() {
  switch (lex->tk) {
  case LEX_R_TRUE:  jslGetNextToken(lex); return jsvNewFromBool(true);
  case LEX_R_FALSE: jslGetNextToken(lex); return jsvNewFromBool(false);
  case LEX_R_NULL:  jslGetNextToken(lex); return jsvNewWithFlags(JSV_NULL);
  case '-': {
    jslGetNextToken(lex);
    if (lex->tk!=LEX_INT && lex->tk!=LEX_FLOAT) return 0;
    JsVar *v = jswrap_json_parse_internal(lex);
    JsVar *zero = jsvNewFromInteger(0);
    JsVar *r = jsvMathsOp(zero, v, '-');
    jsvUnLock2(v, zero);
    return r;
  }
  case LEX_INT: {
    long long v = stringToInt(jslGetTokenValueAsString(lex));
    jslGetNextToken(lex);
    return jsvNewFromLongInteger(v);
  }
  case LEX_FLOAT: {
    JsVarFloat v = stringToFloat(jslGetTokenValueAsString(lex));
    jslGetNextToken(lex);
    return jsvNewFromFloat(v);
  }
  case LEX_STR: {
    JsVar *a = jslGetTokenValueAsVar(lex);
    jslGetNextToken(lex);
    return a;
  }
  case '[': {
    JsVar *arr = jsvNewEmptyArray(); if (!arr) return 0;
    jslGetNextToken(lex); // [
    while (lex->tk != ']' && !jspHasError()) {
      JsVar *value = jswrap_json_parse_internal(lex);
      if (!value ||
          (lex->tk!=']' && !jslMatch(','))) {
        jsvUnLock2(value, arr);
        return 0;
      }
      jsvArrayPush(arr, value);
      jsvUnLock(value);
    }
    if (!jslMatch(']')) {
      jsvUnLock(arr);
      return 0;
    }
    return arr;
  }
  case '{': {
    JsVar *obj = jsvNewObject(); if (!obj) return 0;
    jslGetNextToken(lex); // {
    while (lex->tk == LEX_STR && !jspHasError()) {
      JsVar *key = jsvAsArrayIndexAndUnLock(jslGetTokenValueAsVar(lex));
      jslGetNextToken(lex);
      JsVar *value = 0;
      if (!jslMatch(':') ||
          !(value=jswrap_json_parse_internal(lex)) ||
          (lex->tk!='}' && !jslMatch(','))) {
        jsvUnLock3(key, value, obj);
        return 0;
      }
      jsvAddName(obj, jsvMakeIntoVariableName(key, value));
      jsvUnLock2(value, key);
    }
    if (!jslMatch('}')) {
      jsvUnLock(obj);
      return 0;
    }
    return obj;
  }
  default: {
    char buf[32];
    jslTokenAsString(lex->tk, buf, 32);
    jsExceptionHere(JSET_SYNTAXERROR, "Expecting a valid value, got %s", buf);
    return 0; // undefined = error
  }
  }
}
Example #8
0
JsVar *jswrap_json_parse_internal(JsLex *lex) {
  switch (lex->tk) {
    case LEX_R_TRUE:  jslGetNextToken(lex); return jsvNewFromBool(true);
    case LEX_R_FALSE: jslGetNextToken(lex); return jsvNewFromBool(false);
    case LEX_R_NULL:  jslGetNextToken(lex); return jsvNewWithFlags(JSV_NULL);
    case '-': {
      jslGetNextToken(lex);
      if (lex->tk!=LEX_INT && lex->tk!=LEX_FLOAT) return 0;
      JsVar *v = jswrap_json_parse_internal(lex);
      JsVar *zero = jsvNewFromInteger(0);
      JsVar *r = jsvMathsOp(zero, v, '-');
      jsvUnLock(v);
      jsvUnLock(zero);
      return r;
    }
    case LEX_INT: {
      long long v = stringToInt(jslGetTokenValueAsString(lex));
      jslGetNextToken(lex);
      return jsvNewFromLongInteger(v);
    }
    case LEX_FLOAT: {
      JsVarFloat v = stringToFloat(jslGetTokenValueAsString(lex));
      jslGetNextToken(lex);
      return jsvNewFromFloat(v);
    }
    case LEX_STR: {
      JsVar *a = jslGetTokenValueAsVar(lex);
      jslGetNextToken(lex);
      return a;
    }
    case '[': {
      JsVar *arr = jsvNewWithFlags(JSV_ARRAY); if (!arr) return 0;
      jslGetNextToken(lex); // [
      while (lex->tk != ']') {
        JsVar *value = jswrap_json_parse_internal(lex);
        if (!value ||
            (lex->tk!=']' && !jslMatch(lex, ','))) {
          jsvUnLock(value);
          jsvUnLock(arr);
          return 0;
        }
        jsvArrayPush(arr, value);
        jsvUnLock(value);
      }
      if (!jslMatch(lex, ']')) {
        jsvUnLock(arr);
        return 0;
      }
      return arr;
    }
    case '{': {
      JsVar *obj = jsvNewWithFlags(JSV_OBJECT); if (!obj) return 0;
      jslGetNextToken(lex); // {
      while (lex->tk == LEX_STR) {
        JsVar *key = jsvAsArrayIndexAndUnLock(jslGetTokenValueAsVar(lex));
        jslGetNextToken(lex);
        JsVar *value = 0;
        if (!jslMatch(lex, ':') ||
            !(value=jswrap_json_parse_internal(lex)) ||
            (lex->tk!='}' && !jslMatch(lex, ','))) {
          jsvUnLock(key);
          jsvUnLock(value);
          jsvUnLock(obj);
          return 0;
        }
        jsvAddName(obj, jsvMakeIntoVariableName(key, value));
        jsvUnLock(value);
        jsvUnLock(key);
      }
      if (!jslMatch(lex, '}')) {
        jsvUnLock(obj);
        return 0;
      }
      return obj;
    }
    default: return 0; // undefined = error
  }
}
Example #9
0
/*JSON{
  "type" : "staticmethod",
  "class" : "Date",
  "name" : "parse",
  "generate" : "jswrap_date_parse",
  "params" : [
    ["str","JsVar","A String"]
  ],
  "return" : ["float","The number of milliseconds since 1970"]
}
Parse a date string and return milliseconds since 1970. Data can be either '2011-10-20T14:48:00', '2011-10-20' or 'Mon, 25 Dec 1995 13:30:00 +0430' 
*/
JsVarFloat jswrap_date_parse(JsVar *str) {
  if (!jsvIsString(str)) return 0;
  TimeInDay time;
  time.daysSinceEpoch = 0;
  time.hour = 0;
  time.min = 0;
  time.sec = 0;
  time.ms = 0;
  time.zone = 0;
  CalendarDate date = getCalendarDate(0);

  JsLex lex;
  jslInit(&lex, str);

  if (lex.tk == LEX_ID) {
    date.month = getMonth(jslGetTokenValueAsString(&lex));
    date.dow = getDay(jslGetTokenValueAsString(&lex));
    if (date.month>=0) {
      // Aug 9, 1995
      jslGetNextToken(&lex);
      if (lex.tk == LEX_INT) {
        date.day = _parse_int(&lex);
        jslGetNextToken(&lex);
        if (lex.tk==',') {
          jslGetNextToken(&lex);
          if (lex.tk == LEX_INT) {
            date.year = _parse_int(&lex);
            jslGetNextToken(&lex);
            if (lex.tk == LEX_INT) {
              _parse_time(&lex, &time, 0);
            }
          }
        }
      }
    } else if (date.dow>=0) {
      date.month = 0;
      jslGetNextToken(&lex);
      if (lex.tk==',') {
        jslGetNextToken(&lex);
        if (lex.tk == LEX_INT) {
          date.day = _parse_int(&lex);
          jslGetNextToken(&lex);
          if (lex.tk == LEX_ID && getMonth(jslGetTokenValueAsString(&lex))>=0) {
            date.month = getMonth(jslGetTokenValueAsString(&lex));
            jslGetNextToken(&lex);
            if (lex.tk == LEX_INT) {
               date.year = _parse_int(&lex);
               jslGetNextToken(&lex);
               if (lex.tk == LEX_INT) {
                 _parse_time(&lex, &time, 0);
               }
            }
          }
        }
      }
    } else {
      date.dow = 0;
      date.month = 0;
    }
  } else if (lex.tk == LEX_INT) {
    // assume 2011-10-10T14:48:00 format
    date.year = _parse_int(&lex);
    jslGetNextToken(&lex);
    if (lex.tk=='-') {
      jslGetNextToken(&lex);
      if (lex.tk == LEX_INT) {
        date.month = _parse_int(&lex) - 1;
        jslGetNextToken(&lex);
        if (lex.tk=='-') {
          jslGetNextToken(&lex);
          if (lex.tk == LEX_INT) {
            date.day = _parse_int(&lex);
            jslGetNextToken(&lex);
            if (lex.tk == LEX_ID && jslGetTokenValueAsString(&lex)[0]=='T') {
              _parse_time(&lex, &time, 1);
            }
          }
        }
      }
    }
  }

  jslKill(&lex);
  time.daysSinceEpoch = fromCalenderDate(&date);
  return fromTimeInDay(&time);
}
Example #10
0
static ALWAYS_INLINE void jslPreload() {
  // set up..
  jslGetNextCh();
  jslGetNextToken();
}
Example #11
0
static inline void jslPreload(JsLex *lex) {
  // set up..
  jslGetNextCh(lex);
  jslGetNextToken(lex);
}
Example #12
0
static ALWAYS_INLINE void jslPreload(JsLex *lex) {
  // set up..
  jslGetNextCh(lex);
  jslGetNextToken(lex);
}
Example #13
0
JsVar *jslNewTokenisedStringFromLexer(JslCharPos *charFrom, size_t charTo) {
  // New method - tokenise functions
  // save old lex
  JsLex *oldLex = lex;
  JsLex newLex;
  lex = &newLex;
  // work out length
  size_t length = 0;
  jslInit(oldLex->sourceVar);
  jslSeekToP(charFrom);
  int lastTk = LEX_EOF;
  while (lex->tk!=LEX_EOF && jsvStringIteratorGetIndex(&lex->it)<=charTo+1) {
    if ((lex->tk==LEX_ID || lex->tk==LEX_FLOAT || lex->tk==LEX_INT) &&
        ( lastTk==LEX_ID ||  lastTk==LEX_FLOAT ||  lastTk==LEX_INT)) {
      jsExceptionHere(JSET_SYNTAXERROR, "ID/number following ID/number isn't valid JS");
      length = 0;
      break;
    }
    if (lex->tk==LEX_ID ||
        lex->tk==LEX_INT ||
        lex->tk==LEX_FLOAT ||
        lex->tk==LEX_STR ||
        lex->tk==LEX_TEMPLATE_LITERAL) {
      length += jsvStringIteratorGetIndex(&lex->it)-jsvStringIteratorGetIndex(&lex->tokenStart.it);
    } else {
      length++;
    }
    lastTk = lex->tk;
    jslGetNextToken();
  }

  // Try and create a flat string first
  JsVar *var = jsvNewStringOfLength((unsigned int)length, NULL);
  if (var) { // out of memory
    JsvStringIterator dstit;
    jsvStringIteratorNew(&dstit, var, 0);
    // now start appending
    jslSeekToP(charFrom);
    while (lex->tk!=LEX_EOF && jsvStringIteratorGetIndex(&lex->it)<=charTo+1) {
      if (lex->tk==LEX_ID ||
          lex->tk==LEX_INT ||
          lex->tk==LEX_FLOAT ||
          lex->tk==LEX_STR ||
          lex->tk==LEX_TEMPLATE_LITERAL) {
        jsvStringIteratorSetCharAndNext(&dstit, lex->tokenStart.currCh);
        JsvStringIterator it = jsvStringIteratorClone(&lex->tokenStart.it);
        while (jsvStringIteratorGetIndex(&it)+1 < jsvStringIteratorGetIndex(&lex->it)) {
          jsvStringIteratorSetCharAndNext(&dstit, jsvStringIteratorGetChar(&it));
          jsvStringIteratorNext(&it);
        }
        jsvStringIteratorFree(&it);
      } else {
        jsvStringIteratorSetCharAndNext(&dstit, (char)lex->tk);
      }
      lastTk = lex->tk;
      jslGetNextToken();
    }
    jsvStringIteratorFree(&dstit);
  }
  // restore lex
  jslKill();
  lex = oldLex;

  return var;
}