qemu-e2k/qapi
Markus Armbruster 62815d85ae json: Redesign the callback to consume JSON values
The classical way to structure parser and lexer is to have the client
call the parser to get an abstract syntax tree, the parser call the
lexer to get the next token, and the lexer call some function to get
input characters.

Another way to structure them would be to have the client feed
characters to the lexer, the lexer feed tokens to the parser, and the
parser feed abstract syntax trees to some callback provided by the
client.  This way is more easily integrated into an event loop that
dispatches input characters as they arrive.

Our JSON parser is kind of between the two.  The lexer feeds tokens to
a "streamer" instead of a real parser.  The streamer accumulates
tokens until it got the sequence of tokens that comprise a single JSON
value (it counts curly braces and square brackets to decide).  It
feeds those token sequences to a callback provided by the client.  The
callback passes each token sequence to the parser, and gets back an
abstract syntax tree.

I figure it was done that way to make a straightforward recursive
descent parser possible.  "Get next token" becomes "pop the first
token off the token sequence".  Drawback: we need to store a complete
token sequence.  Each token eats 13 + input characters + malloc
overhead bytes.

Observations:

1. This is not the only way to use recursive descent.  If we replaced
   "get next token" by a coroutine yield, we could do without a
   streamer.

2. The lexer reports errors by passing a JSON_ERROR token to the
   streamer.  This communicates the offending input characters and
   their location, but no more.

3. The streamer reports errors by passing a null token sequence to the
   callback.  The (already poor) lexical error information is thrown
   away.

4. Having the callback receive a token sequence duplicates the code to
   convert token sequence to abstract syntax tree in every callback.

5. Known bug: the streamer silently drops incomplete token sequences.

This commit rectifies 4. by lifting the call of the parser from the
callbacks into the streamer.  Later commits will address 3. and 5.

The lifting removes a bug from qjson.c's parse_json(): it passed a
pointer to a non-null Error * in certain cases, as demonstrated by
check-qjson.c.

json_parser_parse() is now unused.  It's a stupid wrapper around
json_parser_parse_err().  Drop it, and rename json_parser_parse_err()
to json_parser_parse().

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180823164025.12553-35-armbru@redhat.com>
2018-08-24 20:26:37 +02:00
..
Makefile.objs qapi: rename *qmp-*-visitor* to *qobject-*-visitor* 2016-10-25 16:25:48 +02:00
block-core.json qapi: block: Remove mentions of error types which were removed 2018-08-15 12:50:39 +02:00
block.json pr-manager-helper: report event on connection/disconnection 2018-06-28 19:05:35 +02:00
char.json qapi: add conditions to SPICE type/commands/events on the schema 2018-07-03 18:38:54 +02:00
common.json qapi: Change "since 2.13" annotations to "since 3.0" 2018-05-29 11:28:46 +01:00
crypto.json qapi: remove empty flat union branches and types 2018-06-22 16:33:46 +02:00
introspect.json qapi: Make 'allow-oob' optional in SchemaInfoCommand 2018-07-23 13:57:52 +02:00
job.json qapi/job: The next release will be 3.0 2018-06-29 14:20:56 +02:00
migration.json migration: Create multifd_bytes ram_counter 2018-06-27 13:28:11 +02:00
misc.json cli qmp: Mark --preconfig, exit-preconfig experimental 2018-07-16 15:38:19 +02:00
net.json qapi: remove empty flat union branches and types 2018-06-22 16:33:46 +02:00
opts-visitor.c qapi: Fix QemuOpts visitor regression on unvisited input 2017-03-22 19:24:34 +01:00
qapi-clone-visitor.c qapi/qnull: Add own header 2017-11-17 18:21:30 +01:00
qapi-dealloc-visitor.c qobject: Replace qobject_incref/QINCREF qobject_decref/QDECREF 2018-05-04 08:27:53 +02:00
qapi-schema.json job: Introduce qapi/job.json 2018-05-23 14:30:51 +02:00
qapi-util.c qapi: Change data type of the FOO_lookup generated for enum FOO 2017-09-04 13:09:13 +02:00
qapi-visit-core.c Include qapi/qmp/qobject.h exactly where needed 2018-02-09 13:52:15 +01:00
qmp-dispatch.c json: Redesign the callback to consume JSON values 2018-08-24 20:26:37 +02:00
qmp-event.c qmp: Switch timestamp_put() to qdict_from_jsonf_nofail() 2018-07-03 23:18:56 +02:00
qmp-registry.c qapi: Support multiple command registries per program 2017-03-05 09:12:25 +01:00
qobject-input-visitor.c qobject: Modify qobject_ref() to return obj 2018-05-04 08:27:53 +02:00
qobject-output-visitor.c qobject: Modify qobject_ref() to return obj 2018-05-04 08:27:53 +02:00
rocker.json qapi: The #optional tag is redundant, drop 2017-03-16 07:13:02 +01:00
run-state.json qapi: introduce new cmd option "allow-preconfig" 2018-05-30 13:19:09 -03:00
sockets.json sockets: allow SocketAddress 'fd' to reference numeric file descriptors 2018-03-13 18:06:06 +00:00
string-input-visitor.c qapi/qnull: Add own header 2017-11-17 18:21:30 +01:00
string-output-visitor.c qapi: Use QNull for a more regular visit_type_null() 2017-07-24 13:35:11 +02:00
tpm.json tpm: add CRB device 2018-01-29 14:22:50 -05:00
trace-events trace: forbid floating point types 2018-06-27 11:09:29 +01:00
trace.json qapi-schema: Improve section headings 2017-09-04 13:09:12 +02:00
transaction.json qmp: transaction support for x-block-dirty-bitmap-enable/disable 2018-06-11 14:53:32 -04:00
ui.json qapi: add conditions to SPICE type/commands/events on the schema 2018-07-03 18:38:54 +02:00