if (c == '-' || (c >= '0' && c <= '9'))
{
- /* for numbers look for possible numeric continuations */
-
+ /*
+ * Accumulate numeric continuations, respecting JSON number
+ * grammar: -? int [frac] [exp]
+ *
+ * We must track what parts of the number we've already seen
+ * so we don't over-consume. '.' is valid only once and not
+ * after 'e'/'E'; 'e'/'E' is valid only once; '+'/'-' are
+ * valid only immediately after 'e'/'E'.
+ */
bool numend = false;
+ bool seen_dot = false;
+ bool seen_exp = false;
+ char prev;
+
+ /* Scan existing partial token for state */
+ for (int j = 0; j < ptok->len; j++)
+ {
+ char pc = ptok->data[j];
+
+ if (pc == '.')
+ seen_dot = true;
+ else if (pc == 'e' || pc == 'E')
+ seen_exp = true;
+ }
+ prev = ptok->data[ptok->len - 1];
for (size_t i = 0; i < lex->input_length && !numend; i++)
{
{
case '+':
case '-':
+ if (prev != 'e' && prev != 'E')
+ {
+ numend = true;
+ break;
+ }
+ jsonapi_appendStringInfoCharMacro(ptok, cc);
+ added++;
+ break;
+ case '.':
+ if (seen_dot || seen_exp)
+ {
+ numend = true;
+ break;
+ }
+ seen_dot = true;
+ jsonapi_appendStringInfoCharMacro(ptok, cc);
+ added++;
+ break;
case 'e':
case 'E':
+ if (seen_exp)
+ {
+ numend = true;
+ break;
+ }
+ seen_exp = true;
+ jsonapi_appendStringInfoCharMacro(ptok, cc);
+ added++;
+ break;
case '0':
case '1':
case '2':
case '7':
case '8':
case '9':
- {
- jsonapi_appendStringInfoCharMacro(ptok, cc);
- added++;
- }
+ jsonapi_appendStringInfoCharMacro(ptok, cc);
+ added++;
break;
default:
numend = true;
}
+ if (!numend)
+ prev = cc;
}
}