@@ -504,3 +504,172 @@ WARN_UNUSED error_code dom_parser_implementation::stage2(dom::document &_doc) no
504504error:
505505 return parser.error ();
506506}
507+
508+ namespace stage2 {
509+
510+ struct streaming_structural_parser : structural_parser {
511+ really_inline streaming_structural_parser (dom_parser_implementation &_parser) : structural_parser(_parser, _parser.next_structural_index) {}
512+
513+ // override to add streaming
514+ WARN_UNUSED really_inline error_code start (ret_address_t finish_parser) {
515+ // If there are no structurals left, return EMPTY
516+ if (structurals.at_end (parser.n_structural_indexes )) {
517+ return parser.error = EMPTY;
518+ }
519+
520+ log_start ();
521+ init ();
522+
523+ // Capacity ain't no thang for streaming, so we don't check it.
524+ // Advance to the first character as soon as possible
525+ advance_char ();
526+ // Push the root scope (there is always at least one scope)
527+ if (start_document (finish_parser)) {
528+ return parser.error = DEPTH_ERROR;
529+ }
530+ return SUCCESS;
531+ }
532+
533+ // override to add streaming
534+ WARN_UNUSED really_inline error_code finish () {
535+ if ( structurals.past_end (parser.n_structural_indexes ) ) {
536+ log_error (" IMPOSSIBLE: past the end of the JSON!" );
537+ return parser.error = TAPE_ERROR;
538+ }
539+ end_document ();
540+ parser.next_structural_index = uint32_t (structurals.next_structural_index ());
541+ if (depth != 0 ) {
542+ log_error (" Unclosed objects or arrays!" );
543+ return parser.error = TAPE_ERROR;
544+ }
545+ if (parser.containing_scope [depth].tape_index != 0 ) {
546+ log_error (" IMPOSSIBLE: root scope tape index did not start at 0!" );
547+ return parser.error = TAPE_ERROR;
548+ }
549+ return SUCCESS;
550+ }
551+ };
552+
553+ } // namespace stage2
554+
555+ /* ***********
556+ * The JSON is parsed to a tape, see the accompanying tape.md file
557+ * for documentation.
558+ ***********/
559+ WARN_UNUSED error_code dom_parser_implementation::stage2_next (dom::document &_doc) noexcept {
560+ this ->doc = &_doc;
561+ static constexpr stage2::unified_machine_addresses addresses = INIT_ADDRESSES ();
562+ stage2::streaming_structural_parser parser (*this );
563+ error_code result = parser.start (addresses.finish );
564+ if (result) { return result; }
565+ //
566+ // Read first value
567+ //
568+ switch (parser.structurals .current_char ()) {
569+ case ' {' :
570+ FAIL_IF ( parser.start_object (addresses.finish ) );
571+ goto object_begin;
572+ case ' [' :
573+ FAIL_IF ( parser.start_array (addresses.finish ) );
574+ goto array_begin;
575+ case ' "' :
576+ FAIL_IF ( parser.parse_string () );
577+ goto finish;
578+ case ' t' : case ' f' : case ' n' :
579+ FAIL_IF ( parser.parse_single_atom () );
580+ goto finish;
581+ case ' 0' : case ' 1' : case ' 2' : case ' 3' : case ' 4' :
582+ case ' 5' : case ' 6' : case ' 7' : case ' 8' : case ' 9' :
583+ FAIL_IF (
584+ parser.structurals .with_space_terminated_copy ([&](const uint8_t *copy, size_t idx) {
585+ return parser.parse_number (©[idx], false );
586+ })
587+ );
588+ goto finish;
589+ case ' -' :
590+ FAIL_IF (
591+ parser.structurals .with_space_terminated_copy ([&](const uint8_t *copy, size_t idx) {
592+ return parser.parse_number (©[idx], true );
593+ })
594+ );
595+ goto finish;
596+ default :
597+ parser.log_error (" Document starts with a non-value character" );
598+ goto error;
599+ }
600+
601+ //
602+ // Object parser parsers
603+ //
604+ object_begin:
605+ switch (parser.advance_char ()) {
606+ case ' "' : {
607+ FAIL_IF ( parser.parse_string (true ) );
608+ goto object_key_parser;
609+ }
610+ case ' }' :
611+ parser.end_object ();
612+ goto scope_end;
613+ default :
614+ parser.log_error (" Object does not start with a key" );
615+ goto error;
616+ }
617+
618+ object_key_parser:
619+ if (parser.advance_char () != ' :' ) { parser.log_error (" Missing colon after key in object" ); goto error; }
620+ parser.increment_count ();
621+ parser.advance_char ();
622+ GOTO ( parser.parse_value (addresses, addresses.object_continue ) );
623+
624+ object_continue:
625+ switch (parser.advance_char ()) {
626+ case ' ,' :
627+ if (parser.advance_char () != ' "' ) { parser.log_error (" Key string missing at beginning of field in object" ); goto error; }
628+ FAIL_IF ( parser.parse_string (true ) );
629+ goto object_key_parser;
630+ case ' }' :
631+ parser.end_object ();
632+ goto scope_end;
633+ default :
634+ parser.log_error (" No comma between object fields" );
635+ goto error;
636+ }
637+
638+ scope_end:
639+ CONTINUE ( parser.parser .ret_address [parser.depth ] );
640+
641+ //
642+ // Array parser parsers
643+ //
644+ array_begin:
645+ if (parser.advance_char () == ' ]' ) {
646+ parser.end_array ();
647+ goto scope_end;
648+ }
649+ parser.increment_count ();
650+
651+ main_array_switch:
652+ /* we call update char on all paths in, so we can peek at parser.c on the
653+ * on paths that can accept a close square brace (post-, and at start) */
654+ GOTO ( parser.parse_value (addresses, addresses.array_continue ) );
655+
656+ array_continue:
657+ switch (parser.advance_char ()) {
658+ case ' ,' :
659+ parser.increment_count ();
660+ parser.advance_char ();
661+ goto main_array_switch;
662+ case ' ]' :
663+ parser.end_array ();
664+ goto scope_end;
665+ default :
666+ parser.log_error (" Missing comma between array values" );
667+ goto error;
668+ }
669+
670+ finish:
671+ return parser.finish ();
672+
673+ error:
674+ return parser.error ();
675+ }
0 commit comments