/* ToNumber() on a string */ double jsV_stringtonumber(js_State *J, const char *s) { char *e; double n; while (jsY_iswhite(*s) || jsY_isnewline(*s)) ++s; if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X') && s[2] != 0) n = strtol(s + 2, &e, 16); else if (!strncmp(s, "Infinity", 8)) n = INFINITY, e = (char*)s + 8; else if (!strncmp(s, "+Infinity", 9)) n = INFINITY, e = (char*)s + 9; else if (!strncmp(s, "-Infinity", 9)) n = -INFINITY, e = (char*)s + 9; else n = js_stringtofloat(s, &e); while (jsY_iswhite(*e) || jsY_isnewline(*e)) ++e; if (*e) return NAN; return n; }
int jsY_lexjson(js_State *J) { while (1) { J->lexline = J->line; /* save location of beginning of token */ while (jsY_iswhite(J->lexchar) || J->lexchar == '\n') jsY_next(J); if (J->lexchar >= '0' && J->lexchar <= '9') { return lexnumber(J); } switch (J->lexchar) { case ',': jsY_next(J); return ','; case ':': jsY_next(J); return ':'; case '[': jsY_next(J); return '['; case ']': jsY_next(J); return ']'; case '{': jsY_next(J); return '{'; case '}': jsY_next(J); return '}'; case '"': return lexstring(J); case '.': return lexnumber(J); case 'f': jsY_next(J); jsY_expect(J, 'a'); jsY_expect(J, 'l'); jsY_expect(J, 's'); jsY_expect(J, 'e'); return TK_FALSE; case 'n': jsY_next(J); jsY_expect(J, 'u'); jsY_expect(J, 'l'); jsY_expect(J, 'l'); return TK_NULL; case 't': jsY_next(J); jsY_expect(J, 'r'); jsY_expect(J, 'u'); jsY_expect(J, 'e'); return TK_TRUE; case 0: return 0; /* EOF */ } if (J->lexchar >= 0x20 && J->lexchar <= 0x7E) jsY_error(J, "unexpected character: '%c'", J->lexchar); jsY_error(J, "unexpected character: \\u%04X", J->lexchar); } }
static void jsB_parseInt(js_State *J) { const char *s = js_tostring(J, 1); double radix = js_isdefined(J, 2) ? js_tonumber(J, 2) : 10; char *e; double n; while (jsY_iswhite(*s) || jsY_isnewline(*s)) ++s; if (radix == 0) radix = 10; if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) { s += 2; radix = 16; } n = strtol(s, &e, radix); if (s == e) js_pushnumber(J, NAN); else js_pushnumber(J, n); }
static void jsB_parseFloat(js_State *J) { const char *s = js_tostring(J, 1); char *e; double n; while (jsY_iswhite(*s) || jsY_isnewline(*s)) ++s; if (!strncmp(s, "Infinity", 8)) js_pushnumber(J, INFINITY); else if (!strncmp(s, "+Infinity", 9)) js_pushnumber(J, INFINITY); else if (!strncmp(s, "-Infinity", 9)) js_pushnumber(J, -INFINITY); else { n = js_stringtofloat(s, &e); if (e == s) js_pushnumber(J, NAN); else js_pushnumber(J, n); } }
static int jsY_lexx(js_State *J) { J->newline = 0; while (1) { J->lexline = J->line; /* save location of beginning of token */ while (jsY_iswhite(J->lexchar)) jsY_next(J); if (jsY_accept(J, '\n')) { J->newline = 1; if (isnlthcontext(J->lasttoken)) return ';'; continue; } if (jsY_accept(J, '/')) { if (jsY_accept(J, '/')) { lexlinecomment(J); continue; } else if (jsY_accept(J, '*')) { if (lexcomment(J)) jsY_error(J, "multi-line comment not terminated"); continue; } else if (isregexpcontext(J->lasttoken)) { return lexregexp(J); } else if (jsY_accept(J, '=')) { return TK_DIV_ASS; } else { return '/'; } } if (J->lexchar >= '0' && J->lexchar <= '9') { return lexnumber(J); } switch (J->lexchar) { case '(': jsY_next(J); return '('; case ')': jsY_next(J); return ')'; case ',': jsY_next(J); return ','; case ':': jsY_next(J); return ':'; case ';': jsY_next(J); return ';'; case '?': jsY_next(J); return '?'; case '[': jsY_next(J); return '['; case ']': jsY_next(J); return ']'; case '{': jsY_next(J); return '{'; case '}': jsY_next(J); return '}'; case '~': jsY_next(J); return '~'; case '\'': case '"': return lexstring(J); case '.': return lexnumber(J); case '<': jsY_next(J); if (jsY_accept(J, '<')) { if (jsY_accept(J, '=')) return TK_SHL_ASS; return TK_SHL; } if (jsY_accept(J, '=')) return TK_LE; return '<'; case '>': jsY_next(J); if (jsY_accept(J, '>')) { if (jsY_accept(J, '>')) { if (jsY_accept(J, '=')) return TK_USHR_ASS; return TK_USHR; } if (jsY_accept(J, '=')) return TK_SHR_ASS; return TK_SHR; } if (jsY_accept(J, '=')) return TK_GE; return '>'; case '=': jsY_next(J); if (jsY_accept(J, '=')) { if (jsY_accept(J, '=')) return TK_STRICTEQ; return TK_EQ; } return '='; case '!': jsY_next(J); if (jsY_accept(J, '=')) { if (jsY_accept(J, '=')) return TK_STRICTNE; return TK_NE; } return '!'; case '+': jsY_next(J); if (jsY_accept(J, '+')) return TK_INC; if (jsY_accept(J, '=')) return TK_ADD_ASS; return '+'; case '-': jsY_next(J); if (jsY_accept(J, '-')) return TK_DEC; if (jsY_accept(J, '=')) return TK_SUB_ASS; return '-'; case '*': jsY_next(J); if (jsY_accept(J, '=')) return TK_MUL_ASS; return '*'; case '%': jsY_next(J); if (jsY_accept(J, '=')) return TK_MOD_ASS; return '%'; case '&': jsY_next(J); if (jsY_accept(J, '&')) return TK_AND; if (jsY_accept(J, '=')) return TK_AND_ASS; return '&'; case '|': jsY_next(J); if (jsY_accept(J, '|')) return TK_OR; if (jsY_accept(J, '=')) return TK_OR_ASS; return '|'; case '^': jsY_next(J); if (jsY_accept(J, '=')) return TK_XOR_ASS; return '^'; case 0: return 0; /* EOF */ } /* Handle \uXXXX escapes in identifiers */ jsY_unescape(J); if (jsY_isidentifierstart(J->lexchar)) { textinit(J); textpush(J, J->lexchar); jsY_next(J); jsY_unescape(J); while (jsY_isidentifierpart(J->lexchar)) { textpush(J, J->lexchar); jsY_next(J); jsY_unescape(J); } textend(J); return jsY_findkeyword(J, J->lexbuf.text); } if (J->lexchar >= 0x20 && J->lexchar <= 0x7E) jsY_error(J, "unexpected character: '%c'", J->lexchar); jsY_error(J, "unexpected character: \\u%04X", J->lexchar); } }