summaryrefslogtreecommitdiff
path: root/upb/json/parser.rl
diff options
context:
space:
mode:
Diffstat (limited to 'upb/json/parser.rl')
-rw-r--r--upb/json/parser.rl146
1 files changed, 64 insertions, 82 deletions
diff --git a/upb/json/parser.rl b/upb/json/parser.rl
index 389a09a..9e60c5d 100644
--- a/upb/json/parser.rl
+++ b/upb/json/parser.rl
@@ -107,6 +107,12 @@ struct upb_json_parser {
/* Whether to proceed if unknown field is met. */
bool ignore_json_unknown;
+
+ /* Whether to end parsing. */
+ bool ready_to_end;
+
+ /* Indicate whehter last paring ended while parsing number */
+ bool parsing_number;
};
struct upb_json_parsermethod {
@@ -616,6 +622,7 @@ static bool end_text(upb_json_parser *p, const char *ptr) {
}
static void start_number(upb_json_parser *p, const char *ptr) {
+ p->parsing_number = true;
multipart_startaccum(p);
capture_begin(p, ptr);
}
@@ -623,6 +630,7 @@ static void start_number(upb_json_parser *p, const char *ptr) {
static bool parse_number(upb_json_parser *p, bool is_quoted);
static bool end_number(upb_json_parser *p, const char *ptr) {
+ p->parsing_number = false;
if (!capture_end(p, ptr)) {
return false;
}
@@ -1306,6 +1314,10 @@ static void end_wrapper_object(upb_json_parser *p) {
end_object(p);
}
+static bool is_top_level(upb_json_parser *p) {
+ return p->top == p->stack && p->top->f == NULL;
+}
+
static bool does_number_wrapper_start(upb_json_parser *p) {
return p->top->f != NULL &&
upb_fielddef_issubmsg(p->top->f) &&
@@ -1379,6 +1391,11 @@ static bool is_boolean_wrapper_object(upb_json_parser *p) {
number_machine :=
("-"? integer decimal? exponent?)
+ %/{
+ if (parser->ready_to_end) {
+ fhold; fret;
+ }
+ }
<: any
>{ fhold; fret; }
;
@@ -1433,67 +1450,6 @@ static bool is_boolean_wrapper_object(upb_json_parser *p) {
>{ end_object(parser); }
;
- true_object =
- "true"
- >{
- CHECK_RETURN_TOP(is_boolean_wrapper_object(parser));
- start_wrapper_object(parser);
- }
- %{
- CHECK_RETURN_TOP(parser_putbool(parser, true));
- end_wrapper_object(parser);
- }
- ;
-
- false_object =
- "false"
- >{
- CHECK_RETURN_TOP(is_boolean_wrapper_object(parser));
- start_wrapper_object(parser);
- }
- %{
- CHECK_RETURN_TOP(parser_putbool(parser, false));
- end_wrapper_object(parser);
- }
- ;
-
- number_object_machine :=
- ("-"? integer decimal? exponent?)
- >{
- CHECK_RETURN_TOP(is_number_wrapper_object(parser));
- start_wrapper_object(parser);
- start_number(parser, p);
- }
- </{
- CHECK_RETURN_TOP(end_number(parser, p));
- end_wrapper_object(parser);
- fhold; fret;
- }
- ;
- number_object =
- /[0-9\-]/
- >{
- fhold; fcall number_object_machine;
- }
- ;
-
- string_object_machine :=
- (text | unicode_char | escape_char)**
- >{
- CHECK_RETURN_TOP(is_string_wrapper_object(parser));
- start_wrapper_object(parser);
- CHECK_RETURN_TOP(start_stringval(parser));
- }
- '"'
- </{
- CHECK_RETURN_TOP(end_stringval(parser));
- end_wrapper_object(parser);
- fhold; fret;
- }
- ;
-
- string_object = '"' @{ fcall string_object_machine; } '"';
-
element = ws value2 ws;
array =
"["
@@ -1507,7 +1463,10 @@ static bool is_boolean_wrapper_object(upb_json_parser *p) {
value =
number
>{
- if (does_number_wrapper_start(parser)) {
+ if (is_top_level(parser)) {
+ CHECK_RETURN_TOP(is_number_wrapper_object(parser));
+ start_wrapper_object(parser);
+ } else if (does_number_wrapper_start(parser)) {
CHECK_RETURN_TOP(start_subobject(parser));
start_wrapper_object(parser);
}
@@ -1517,12 +1476,17 @@ static bool is_boolean_wrapper_object(upb_json_parser *p) {
CHECK_RETURN_TOP(end_number(parser, p));
if (does_number_wrapper_end(parser)) {
end_wrapper_object(parser);
- end_subobject(parser);
+ if (!is_top_level(parser)) {
+ end_subobject(parser);
+ }
}
}
| string
>{
- if (does_string_wrapper_start(parser)) {
+ if (is_top_level(parser)) {
+ CHECK_RETURN_TOP(is_string_wrapper_object(parser));
+ start_wrapper_object(parser);
+ } else if (does_string_wrapper_start(parser)) {
CHECK_RETURN_TOP(start_subobject(parser));
start_wrapper_object(parser);
}
@@ -1532,12 +1496,17 @@ static bool is_boolean_wrapper_object(upb_json_parser *p) {
CHECK_RETURN_TOP(end_stringval(parser));
if (does_string_wrapper_end(parser)) {
end_wrapper_object(parser);
- end_subobject(parser);
+ if (!is_top_level(parser)) {
+ end_subobject(parser);
+ }
}
}
| "true"
>{
- if (does_boolean_wrapper_start(parser)) {
+ if (is_top_level(parser)) {
+ CHECK_RETURN_TOP(is_boolean_wrapper_object(parser));
+ start_wrapper_object(parser);
+ } else if (does_boolean_wrapper_start(parser)) {
CHECK_RETURN_TOP(start_subobject(parser));
start_wrapper_object(parser);
}
@@ -1546,12 +1515,17 @@ static bool is_boolean_wrapper_object(upb_json_parser *p) {
CHECK_RETURN_TOP(parser_putbool(parser, true));
if (does_boolean_wrapper_end(parser)) {
end_wrapper_object(parser);
- end_subobject(parser);
+ if (!is_top_level(parser)) {
+ end_subobject(parser);
+ }
}
}
| "false"
>{
- if (does_boolean_wrapper_start(parser)) {
+ if (is_top_level(parser)) {
+ CHECK_RETURN_TOP(is_boolean_wrapper_object(parser));
+ start_wrapper_object(parser);
+ } else if (does_boolean_wrapper_start(parser)) {
CHECK_RETURN_TOP(start_subobject(parser));
start_wrapper_object(parser);
}
@@ -1560,24 +1534,31 @@ static bool is_boolean_wrapper_object(upb_json_parser *p) {
CHECK_RETURN_TOP(parser_putbool(parser, false));
if (does_boolean_wrapper_end(parser)) {
end_wrapper_object(parser);
- end_subobject(parser);
+ if (!is_top_level(parser)) {
+ end_subobject(parser);
+ }
}
}
| "null"
%{ /* null value */ }
| object
- >{ CHECK_RETURN_TOP(start_subobject(parser)); }
- %{ end_subobject(parser); }
+ >{
+ if (!is_top_level(parser)) {
+ CHECK_RETURN_TOP(start_subobject(parser));
+ }
+ }
+ %{
+ if (!is_top_level(parser)) {
+ end_subobject(parser);
+ }
+ }
| array;
value_machine :=
value
<: any >{ fhold; fret; } ;
- main :=
- ws
- (object | number_object | true_object | false_object | string_object)
- ws;
+ main := ws value ws;
}%%
%% write data noerror nofinal;
@@ -1620,18 +1601,17 @@ error:
}
bool end(void *closure, const void *hd) {
- UPB_UNUSED(closure);
- UPB_UNUSED(hd);
+ upb_json_parser *parser = closure;
/* Prevent compile warning on unused static constants. */
UPB_UNUSED(json_start);
- UPB_UNUSED(json_en_number_machine);
- UPB_UNUSED(json_en_number_object_machine);
- UPB_UNUSED(json_en_string_machine);
- UPB_UNUSED(json_en_string_object_machine);
UPB_UNUSED(json_en_value_machine);
UPB_UNUSED(json_en_main);
- return true;
+
+ parser->ready_to_end = true;
+ parse(parser, hd, NULL, 0, NULL);
+
+ return parser->current_state >= %%{ write first_final; }%%;
}
static void json_parser_reset(upb_json_parser *p) {
@@ -1652,6 +1632,7 @@ static void json_parser_reset(upb_json_parser *p) {
p->capture = NULL;
p->accumulated = NULL;
upb_status_clear(&p->status);
+ p->parsing_number = false;
}
static void visit_json_parsermethod(const upb_refcounted *r,
@@ -1752,6 +1733,7 @@ upb_json_parser *upb_json_parser_create(upb_env *env,
set_name_table(p, p->top);
p->ignore_json_unknown = ignore_json_unknown;
+ p->ready_to_end = false;
/* If this fails, uncomment and increase the value in parser.h. */
/* fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before); */
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback