yeptris 0.6.26.2-arm-linux-eabihf → 0.6.28.1-arm-linux-eabihf

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19,8 +19,12 @@
19
19
 
20
20
  #include "dom/dom.h"
21
21
  #include "memory/allocator.h"
22
+ #include "memory/pool.h"
23
+ #include "resolve/resolver.h"
22
24
  #include "scan/json.h"
23
25
  #include "scan/scan.h"
26
+ #include "tape_in.h"
27
+ #include "yeptris/tape.h"
24
28
  #include "ytape.h"
25
29
 
26
30
  /* ---- word packing ---- */
@@ -58,6 +62,11 @@ int ytap_init(yep_ytape* t, const char* input, size_t len, int max_depth) {
58
62
  }
59
63
 
60
64
  void ytap_free(yep_ytape* t) {
65
+ if (t->flow_scratch != NULL) {
66
+ yeptris_tape_free((yeptris_json_tape*)t->flow_scratch);
67
+ yep_free(yep_system_allocator(), t->flow_scratch);
68
+ t->flow_scratch = NULL;
69
+ }
61
70
  if (t->w != NULL) {
62
71
  yep_free(yep_system_allocator(), t->w);
63
72
  t->w = NULL;
@@ -315,36 +324,207 @@ static int yt_on_block_item(void* ctx, const yep_block_value* v) {
315
324
  return 1;
316
325
  }
317
326
 
327
+ /* the >1024 simple-key law, read off the scratch records: a STR at a
328
+ * map's key slot over the limit answers the general walk's long_key
329
+ * verdict (the fused walk carries no such flag). Members alternate
330
+ * key/value in a map frame; a container in the value slot completes
331
+ * at its CLOSE. len == 0xFFFFFF (a CONT-extended token, >16 MiB) is
332
+ * over the limit by definition. */
333
+ static uint32_t yt_flow_scan(const yeptris_json_tape* s, int* long_key) {
334
+ /* the record-walk verdicts the fused walk does not carry: the
335
+ * >1024 simple-key law (a STR at a map's key slot over the limit;
336
+ * the law counts the RAW token — a quoted key's record holds the
337
+ * INNER span, so the two quotes add back on; 0xFFFFFF = a
338
+ * CONT-extended >16 MiB token, over by definition) and the span's
339
+ * maximum nesting (the fused walk's depth cap is its own, not the
340
+ * engine's max_depth — the caller falls back when exceeded) */
341
+ struct {
342
+ uint8_t map;
343
+ uint8_t key_next;
344
+ } st[257];
345
+ int d = 0;
346
+ uint32_t maxd = 0;
347
+ st[0].map = 0;
348
+ st[0].key_next = 0;
349
+ for (uint32_t i = 1; i < s->count; i++) { /* recs[0] is the DOC */
350
+ uint64_t r = s->recs[i];
351
+ uint8_t kind = (uint8_t)(r & 0xFFu);
352
+ if (kind == YEP_T_MAP_OPEN || kind == YEP_T_SEQ_OPEN) {
353
+ if (d >= 256) {
354
+ *long_key = 0;
355
+ return 0xFFFFu; /* deeper than the scratch stack: the
356
+ * general kernel's depth path decides */
357
+ }
358
+ d++;
359
+ if ((uint32_t)d > maxd) {
360
+ maxd = (uint32_t)d;
361
+ }
362
+ st[d].map = (uint8_t)(kind == YEP_T_MAP_OPEN);
363
+ st[d].key_next = 0;
364
+ continue;
365
+ }
366
+ if (kind == YEP_T_CLOSE) {
367
+ if (d > 0) {
368
+ d--;
369
+ }
370
+ continue;
371
+ }
372
+ if (st[d].map && st[d].key_next == 0) {
373
+ uint32_t mlen = (uint32_t)(r >> 8) & 0xFFFFFFu;
374
+ if (kind == YEP_T_STR && mlen + 2u > 1024u) {
375
+ *long_key = 1;
376
+ }
377
+ st[d].key_next = 1;
378
+ } else if (st[d].map) {
379
+ st[d].key_next = 0;
380
+ }
381
+ }
382
+ return maxd;
383
+ }
384
+
385
+ static int yt_flow_classify_record(yep_ytape* t, const char* p, size_t open, size_t len,
386
+ const yep_view* anchor, const yep_view* tag, uint32_t anchor_id,
387
+ int max_depth, size_t* close);
388
+
318
389
  static int yt_on_flow_build(void* ctx, const char* p, size_t open, size_t len, uint32_t line,
319
390
  size_t line_start, yep_view anchor, yep_view tag, uint32_t anchor_id,
320
391
  int max_depth, size_t* close) {
321
392
  (void)line;
322
393
  (void)line_start; /* the flow builder reads neither */
323
- yep_ytape* t = (yep_ytape*)ctx;
394
+ return yt_flow_classify_record((yep_ytape*)ctx, p, open, len, &anchor, &tag, anchor_id,
395
+ max_depth, close);
396
+ }
397
+
398
+ /* the shared flow-span classification + ONE-record emission (the
399
+ * sink's entry and the flow-rooted fast path both land here). Returns
400
+ * the sink's verdict codes: 0 = not JSON-class (the general kernel),
401
+ * 1 = recorded (with *close set), 2 = long-key (pass 2 owns the
402
+ * error). */
403
+ static int yt_flow_classify_record(yep_ytape* t, const char* p, size_t open, size_t len,
404
+ const yep_view* anchor, const yep_view* tag, uint32_t anchor_id,
405
+ int max_depth, size_t* close) {
324
406
  if (t->depth >= YEP_DOM_MAX_DEPTH) {
325
407
  return 0; /* the event path owns the error shape */
326
408
  }
327
409
  /* classification = the DOM's own walk with the builds stripped:
328
410
  * the same reject/long-key verdicts, then ONE record for the
329
411
  * whole staged span (replay runs the full build through
330
- * dom_on_flow_build). */
412
+ * dom_on_flow_build). The verdict comes from the FUSED lenient
413
+ * walk into a reused scratch tape — 3.5x the naive token loop on
414
+ * the spike corpora (item 86); any refusal keeps the naive loop,
415
+ * whose accept/reject contract is the same by construction. */
416
+ if (t->flow_scratch == NULL) {
417
+ t->flow_scratch = yep_alloc(yep_system_allocator(), sizeof(yeptris_json_tape));
418
+ if (t->flow_scratch != NULL) {
419
+ memset(t->flow_scratch, 0, sizeof(yeptris_json_tape));
420
+ }
421
+ }
331
422
  t->max_depth = max_depth; /* replay re-walks at the engine's limit */
332
- yep_json_walk w;
333
- yep_json_tok tok;
334
- yep_json_walk_init(&w, p, len, open, max_depth);
335
- w.strict = t->flow_strict;
336
- for (;;) {
337
- yep_jw_status st = yep_json_walk_next(&w, &tok);
338
- if (st == YEP_JW_REJECT) {
339
- return 0; /* not JSON-class: the general kernel */
423
+ /* the naive token loop with a BYTE BUDGET: small spans (the common
424
+ * per-line flow map) finish it — the loop carries the exact close
425
+ * and long_key verdicts for free; a budget exhaustion hands the
426
+ * span to the fused lenient walk, which amortizes its fixed entry
427
+ * cost on large spans (2.1x the naive loop at 6.6 MB, item 86) */
428
+ {
429
+ yep_json_walk w;
430
+ yep_json_tok tok;
431
+ yep_json_walk_init(&w, p, len, open, max_depth);
432
+ w.strict = t->flow_strict;
433
+ int exhausted = 0;
434
+ for (;;) {
435
+ if (w.i - open > 256) {
436
+ exhausted = 1;
437
+ break;
438
+ }
439
+ yep_jw_status st = yep_json_walk_next(&w, &tok);
440
+ if (st == YEP_JW_REJECT) {
441
+ return 0; /* not JSON-class: the general kernel */
442
+ }
443
+ if (st == YEP_JW_DONE) {
444
+ if (w.long_key) {
445
+ return 2; /* pass 2 owns the simple-key error */
446
+ }
447
+ *close = w.close; /* the walk's own position: exact */
448
+ goto record;
449
+ }
340
450
  }
341
- if (st == YEP_JW_DONE) {
342
- break;
451
+ if (exhausted) {
452
+ yeptris_json_tape* s = t->flow_scratch;
453
+ if (s == NULL) {
454
+ s = (yeptris_json_tape*)yep_alloc(yep_system_allocator(),
455
+ sizeof(yeptris_json_tape));
456
+ if (s != NULL) {
457
+ memset(s, 0, sizeof(yeptris_json_tape));
458
+ t->flow_scratch = s;
459
+ }
460
+ }
461
+ if (s != NULL) {
462
+ /* the carve reuses the block through the _srclen
463
+ * watermark — no per-span free (flow-json walks 200k
464
+ * spans per parse) */
465
+ /* strict_nums=1: the general walk validates number runs
466
+ * even at strict=0 (M5DY's 2001-07-02 dates — an
467
+ * unvalidated accept here diverges from the engine's
468
+ * own reject) */
469
+ if (s->_block != NULL && s->_srclen < len + 2) {
470
+ /* the block cannot hold this span: release it so the
471
+ * walk's carve sizes a fresh one (carve's own growth
472
+ * semantics belong to the strict route's live
473
+ * pointers) */
474
+ yeptris_tape_free(s);
475
+ memset(s, 0, sizeof(yeptris_json_tape));
476
+ }
477
+ if (yep_tape_walk_lenient_fused(p, len, open, s, 1, 0, 1) == YEPTRIS_OK) {
478
+ if (s->_srclen < len + 2) {
479
+ s->_srclen = len + 2; /* the reuse watermark */
480
+ }
481
+ int lk = 0;
482
+ uint32_t smax = yt_flow_scan(s, &lk);
483
+ if (lk) {
484
+ return 2; /* pass 2 owns the simple-key error */
485
+ }
486
+ if (smax > (uint32_t)max_depth) {
487
+ return 0; /* over the engine's depth limit: the
488
+ * general walk owns the exact DEPTH
489
+ * error shape */
490
+ }
491
+ goto record_fused;
492
+ }
493
+ return 0; /* the fused walk refused: the general kernel */
494
+ }
495
+ return 0; /* scratch alloc refused: the general kernel */
343
496
  }
344
497
  }
345
- if (w.long_key) {
346
- return 2; /* pass 2 owns the simple-key error, as the DOM's */
498
+ return -1; /* unreachable */
499
+ record_fused: {
500
+ size_t c = open;
501
+ int depth = 0;
502
+ for (;;) {
503
+ unsigned char ch = (unsigned char)p[c];
504
+ if (ch == '"') { /* the walk validated the string; skip runs */
505
+ c++;
506
+ while (p[c] != '"') {
507
+ if (p[c] == '\\') {
508
+ c++;
509
+ }
510
+ c++;
511
+ }
512
+ c++;
513
+ continue;
514
+ }
515
+ if (ch == '{' || ch == '[') {
516
+ depth++;
517
+ } else if (ch == '}' || ch == ']') {
518
+ depth--;
519
+ if (depth == 0) {
520
+ break;
521
+ }
522
+ }
523
+ c++;
347
524
  }
525
+ *close = c;
526
+ }
527
+ record:
348
528
  t->flow_mark = t->count;
349
529
  uint32_t anchor_hi = 0;
350
530
  uint32_t aid = anchor_id;
@@ -352,8 +532,8 @@ static int yt_on_flow_build(void* ctx, const char* p, size_t open, size_t len, u
352
532
  anchor_hi = 1;
353
533
  aid = 0xFFFFFFu;
354
534
  }
355
- uint32_t tag_mode = (uint32_t)yt_mode(t, &tag);
356
- uint32_t anchor_mode = (uint32_t)yt_mode(t, &anchor);
535
+ uint32_t tag_mode = (uint32_t)yt_mode(t, tag);
536
+ uint32_t anchor_mode = (uint32_t)yt_mode(t, anchor);
357
537
  uint32_t flags = tag_mode | (anchor_mode << 2) | (anchor_hi << 4);
358
538
  if (yt_put(t, yt_props(YTP_FLOW, aid, flags)) != 0) {
359
539
  return -1;
@@ -361,16 +541,15 @@ static int yt_on_flow_build(void* ctx, const char* p, size_t open, size_t len, u
361
541
  if (yt_put(t, (uint64_t)open | ((uint64_t)len << 32)) != 0) {
362
542
  return -1;
363
543
  }
364
- if (tag_mode != YTM_ABSENT && yt_span_by_mode(t, &tag) != 0) {
544
+ if (tag_mode != YTM_ABSENT && yt_span_by_mode(t, tag) != 0) {
365
545
  return -1;
366
546
  }
367
- if (anchor_mode != YTM_ABSENT && yt_span_by_mode(t, &anchor) != 0) {
547
+ if (anchor_mode != YTM_ABSENT && yt_span_by_mode(t, anchor) != 0) {
368
548
  return -1;
369
549
  }
370
550
  if (anchor_hi && yt_put(t, (uint64_t)anchor_id) != 0) {
371
551
  return -1;
372
552
  }
373
- *close = w.close;
374
553
  return 1;
375
554
  }
376
555
 
@@ -640,3 +819,1187 @@ int dom_from_ytape(yep_dom* d, const yep_ytape* t) {
640
819
  }
641
820
  return 0;
642
821
  }
822
+
823
+ /* ---- the fused block runner (TODO.restructure/79, session 3) -------
824
+ *
825
+ * ONE SWAR sweep per line + inline classification + an indent stack,
826
+ * emitting the same record stream the engine's sink would — without
827
+ * the engine. Byte-exact against the engine over the block-family
828
+ * corpora (wide 600k / block 1.0M / deep 17k words, differential
829
+ * pinned by the FusedTape test). Any line the loop does not own bails
830
+ * to 1 and the caller re-runs the engine route (restart fallback).
831
+ *
832
+ * Bails (the engine route owns them): quoted/tagged/flow/folded/block
833
+ * scalar values, compact map items, anchored CONTAINER keys (the
834
+ * first pair inside one rides a two-SCALAR form with content-typed
835
+ * tag ids — capture before owning), doc markers/directives, empty
836
+ * "key:" at EOF or mid-doc, undefined aliases, root sequences. */
837
+
838
+ #define YT_FUSED_MAX_FRAMES 256
839
+ #define YT_FUSED_ANCHORS 65536
840
+
841
+ typedef struct {
842
+ uint32_t indent; /* the frame's key column */
843
+ uint8_t kind; /* 0 map, 1 seq */
844
+ uint8_t pending; /* a "key:" awaiting its child */
845
+ uint8_t started; /* the content container's start event went out */
846
+ uint8_t
847
+ own_map; /* the frame carries its own map (OPEN/root/seq); the key-SCALAR form does not */
848
+ uint8_t phantom; /* a content map opened by this frame's pairs is still live */
849
+ uint32_t content_col; /* the column this frame's pairs live at, +1 (0 = none) */
850
+ uint32_t key_off, key_len;
851
+ uint32_t aid; /* anchor ordinal on the pending container */
852
+ uint32_t a_off, a_len; /* the pending anchor's name span */
853
+ uint8_t anchored_first; /* the first pair/item rides the two-SCALAR form */
854
+ } yt_frame;
855
+
856
+ typedef struct {
857
+ yep_ytape* t;
858
+ const char* p;
859
+ size_t len;
860
+ uint32_t anchor_seq;
861
+ const yep_resolver* resolver; /* the first pair inside an anchored container
862
+ * bakes the engine's tag classification */
863
+ yep_pool* pool; /* block-scalar content (transferred to the doc) */
864
+ /* the repeat-alias memo (engine anchor_id_of): the last alias
865
+ * resolution answers by name bytes before any probe, and anchor
866
+ * definitions never invalidate it — re-aliasing after a
867
+ * redefinition still reports the memoized ordinal */
868
+ uint32_t memo_off, memo_len, memo_ord;
869
+ /* anchor name -> ordinal (the alias records carry the target's
870
+ * id; a miss bails: the engine owns undefined aliases). The table
871
+ * is heap-allocated on the first definition — small parses never
872
+ * pay for the 64k slots anchor-heavy documents need. */
873
+ struct {
874
+ uint32_t off, len, aid, tag;
875
+ }* anchors;
876
+ uint8_t* anchors_opened; /* per-aid: the anchored container's start event went out */
877
+ } yt_fused;
878
+
879
+ /* Frame model (engine-verified): st[] frames are the engine's *silent*
880
+ * containers — one OPEN record per frame (or one key SCALAR for the
881
+ * sibling form, which carries no map of its own). Pairs inside a frame
882
+ * open a *phantom* content map at the pair column (one start event per
883
+ * column); a later pair at the frame's own indent closes the phantom
884
+ * and rides the frame silently (the engine's sibling-continue). Maps
885
+ * pop strictly shallower; seqs also leave at their column when a
886
+ * non-dash arrives. The root closes only when its start event fired. */
887
+
888
+ /* chunked name hash: 8 bytes per round, one mix per round (the
889
+ * byte-wise FNV chain cost ~6 cycles/byte on this corpus's 80k
890
+ * lookups+puts per parse). The tail masks to the real bytes so only
891
+ * equal names hash equal. */
892
+ static uint32_t yt_anchor_hash(const char* p, uint32_t off, uint32_t len) {
893
+ uint64_t h = 2166136261u;
894
+ uint32_t i = 0;
895
+ for (; i < len;) {
896
+ uint32_t room = len - i;
897
+ uint64_t w;
898
+ if (room >= 8) {
899
+ memcpy(&w, p + off + i, 8);
900
+ i += 8;
901
+ } else {
902
+ uint64_t tail = 0;
903
+ memcpy(&tail, p + off + i, room);
904
+ w = tail;
905
+ i = len;
906
+ }
907
+ h = (h ^ w) * 11400714819323198485ull;
908
+ h ^= h >> 29;
909
+ }
910
+ return (uint32_t)(h ^ (h >> 32));
911
+ }
912
+
913
+ static int yt_anchor_table(yt_fused* F) {
914
+ if (F->anchors == NULL) {
915
+ F->anchors =
916
+ (void*)yep_alloc(yep_system_allocator(), YT_FUSED_ANCHORS * sizeof(*F->anchors));
917
+ if (F->anchors == NULL) {
918
+ return 0;
919
+ }
920
+ memset(F->anchors, 0, YT_FUSED_ANCHORS * sizeof(*F->anchors));
921
+ F->anchors_opened =
922
+ (void*)yep_alloc(yep_system_allocator(), YT_FUSED_ANCHORS * sizeof(uint8_t));
923
+ if (F->anchors_opened == NULL) {
924
+ return 0;
925
+ }
926
+ memset(F->anchors_opened, 0, YT_FUSED_ANCHORS * sizeof(uint8_t));
927
+ }
928
+ return 1;
929
+ }
930
+
931
+ static void yt_anchor_open(yt_fused* F, uint32_t aid) {
932
+ if (F->anchors_opened != NULL && aid != 0 && aid <= YT_FUSED_ANCHORS) {
933
+ F->anchors_opened[aid - 1] = 1;
934
+ }
935
+ }
936
+
937
+ static void yt_anchor_put(yt_fused* F, uint32_t off, uint32_t len, uint32_t aid) {
938
+ uint32_t m = YT_FUSED_ANCHORS - 1;
939
+ uint32_t tag = yt_anchor_hash(F->p, off, len);
940
+ uint32_t i = tag & m;
941
+ for (uint32_t n = 0; n < 64; n++) {
942
+ if (F->anchors[i].len == 0) {
943
+ F->anchors[i].off = off;
944
+ F->anchors[i].len = len;
945
+ F->anchors[i].aid = aid;
946
+ F->anchors[i].tag = tag;
947
+ return;
948
+ }
949
+ if (F->anchors[i].tag == tag && F->anchors[i].len == len &&
950
+ memcmp(F->p + F->anchors[i].off, F->p + off, len) == 0) {
951
+ F->anchors[i].aid = aid; /* redefinition: latest wins */
952
+ return;
953
+ }
954
+ i = (i + 1) & m;
955
+ }
956
+ /* chain too long: leave unfindable — aliases to it will bail */
957
+ }
958
+
959
+ static int yt_anchor_get(yt_fused* F, uint32_t off, uint32_t len, uint32_t* aid) {
960
+ if (F->anchors == NULL) {
961
+ return 0; /* no definitions yet: the engine owns the error */
962
+ }
963
+ if (F->memo_len != 0 && F->memo_len == len &&
964
+ memcmp(F->p + F->memo_off, F->p + off, len) == 0) {
965
+ *aid = F->memo_ord;
966
+ return 1;
967
+ }
968
+ uint32_t m = YT_FUSED_ANCHORS - 1;
969
+ uint32_t tag = yt_anchor_hash(F->p, off, len);
970
+ uint32_t i = tag & m;
971
+ for (uint32_t n = 0; n < 64; n++) {
972
+ if (F->anchors[i].len == 0) {
973
+ return 0;
974
+ }
975
+ if (F->anchors[i].tag == tag && F->anchors[i].len == len &&
976
+ memcmp(F->p + F->anchors[i].off, F->p + off, len) == 0) {
977
+ *aid = F->anchors[i].aid;
978
+ F->memo_off = off;
979
+ F->memo_len = len;
980
+ F->memo_ord = *aid;
981
+ return 1;
982
+ }
983
+ i = (i + 1) & m;
984
+ }
985
+ return 0;
986
+ }
987
+
988
+ static void yt_f_empty_span(yt_fused* F) {
989
+ /* the dead value-span pair the container events always carry */
990
+ (void)yt_put(F->t, ((uint64_t)YTP_SPAN_POOL << 56) | 0u);
991
+ (void)yt_put(F->t, 0);
992
+ }
993
+
994
+ static void yt_f_start(yt_fused* F, yt_frame* fr) {
995
+ if (fr->started) {
996
+ return;
997
+ }
998
+ fr->started = 1;
999
+ (void)yt_put(F->t, yt_props(YTP_EVENT, 0, fr->kind == 1 ? 5u : 7u));
1000
+ yt_f_empty_span(F);
1001
+ F->t->depth++;
1002
+ if (fr->kind == 0) {
1003
+ fr->phantom = 1;
1004
+ }
1005
+ }
1006
+
1007
+ static void yt_f_close(yt_fused* F, uint8_t kind) {
1008
+ (void)yt_put(F->t, yt_props(YTP_EVENT, 0, kind == 1 ? 6u : 8u));
1009
+ yt_f_empty_span(F);
1010
+ F->t->depth--;
1011
+ }
1012
+
1013
+ /* the OPEN-vs-SCALAR key form: the engine opens via on_block_open
1014
+ * unless its top frame is already a map continuing at this key's
1015
+ * column (a sibling key) — the contentless root always opens */
1016
+ static uint8_t yt_f_open_form(const yt_frame* parent, int parent_is_root, uint32_t key_col) {
1017
+ if (parent_is_root && parent->content_col == 0) {
1018
+ return 1;
1019
+ }
1020
+ if (parent->content_col != 0) {
1021
+ return (uint8_t)(key_col + 1 != parent->content_col && key_col != parent->indent);
1022
+ }
1023
+ return (uint8_t)(key_col != parent->indent);
1024
+ }
1025
+
1026
+ /* resolve a pending "key:": the OPEN record materializes the key's
1027
+ * map (it closes later); the SCALAR form is the bare key — the value
1028
+ * container that follows IS the pair's, no map of its own */
1029
+ static void yt_f_open(yt_fused* F, yt_frame* fr, uint8_t open_form) {
1030
+ if (open_form && fr->aid == 0 && fr->key_len < 0x1000000u && fr->key_off <= F->t->input_len) {
1031
+ (void)yt_put(F->t, yt_span_in(fr->key_off, fr->key_len, YTP_OPEN));
1032
+ fr->own_map = 1;
1033
+ } else {
1034
+ (void)yt_put(F->t, yt_props(YTP_SCALAR, 0, 0x2900u));
1035
+ (void)yt_put(F->t, yt_span_in(fr->key_off, fr->key_len, YTP_SPAN_IN));
1036
+ fr->own_map = 0;
1037
+ }
1038
+ fr->started = 0;
1039
+ fr->phantom = 0;
1040
+ F->t->depth++;
1041
+ }
1042
+
1043
+ /* The flat-map specialist (item 86): plain `key: value` lines at one
1044
+ * fixed content column, one map frame, nothing else. A separate FUNCTION
1045
+ * so its code stays inside the I-cache — the equivalent inline loop
1046
+ * measured 26% SLOWER by bloating yt_f_run past the cache edge. Returns
1047
+ * the position it stopped at; the caller reprocesses that line through
1048
+ * the full arms, so every bail here is a strict subset of what yt_f_run
1049
+ * would decide — parity holds by construction. */
1050
+ static size_t yt_flat_run(yep_ytape* t, const char* p, size_t pos, size_t len, uint32_t run_cc) {
1051
+ const uint64_t k_nl = 0x0A0A0A0A0A0A0A0Aull, k_cr = 0x0D0D0D0D0D0D0D0Dull,
1052
+ k_sp = 0x2020202020202020ull, k_co = 0x3A3A3A3A3A3A3A3Aull,
1053
+ k_ha = 0x2323232323232323ull;
1054
+ for (;;) {
1055
+ if (pos >= len) {
1056
+ return pos;
1057
+ }
1058
+ /* the sweep: the main loop's line facts, unchanged */
1059
+ size_t whole = len - pos;
1060
+ size_t end = whole, ind = whole;
1061
+ int have_ind = 0;
1062
+ size_t i = 0;
1063
+ size_t stop = whole;
1064
+ int stop_set = 0;
1065
+ while (i < whole) {
1066
+ size_t avail = whole - i < 8 ? whole - i : 8;
1067
+ uint64_t x;
1068
+ if (avail == 8) {
1069
+ memcpy(&x, p + pos + i, 8);
1070
+ } else {
1071
+ char buf[8] = {0, 0, 0, 0, 0, 0, 0, 0};
1072
+ memcpy(buf, p + pos + i, avail);
1073
+ memcpy(&x, buf, 8);
1074
+ }
1075
+ uint64_t valid = avail == 8 ? ~(uint64_t)0 : (((uint64_t)1 << (avail * 8)) - 1);
1076
+ uint64_t br = (yep_swar_eq8(x, k_nl) | yep_swar_eq8(x, k_cr)) & valid;
1077
+ uint64_t room = (br ? ((br & (~br + 1)) - 1) : valid) & YEP_SWAR_FLAGS & valid;
1078
+ if (!have_ind) {
1079
+ uint64_t nons = ~(yep_swar_eq8(x, k_sp)) & room;
1080
+ if (nons) {
1081
+ ind = i + (size_t)(yep_ctz64(nons) >> 3);
1082
+ have_ind = 1;
1083
+ }
1084
+ }
1085
+ if (have_ind && !stop_set) {
1086
+ uint64_t stm = (yep_swar_eq8(x, k_co) | yep_swar_eq8(x, k_ha)) & room;
1087
+ if (stm) {
1088
+ size_t cand = i + (size_t)(yep_ctz64(stm) >> 3);
1089
+ if (cand >= ind) {
1090
+ stop = cand;
1091
+ stop_set = 1;
1092
+ }
1093
+ }
1094
+ }
1095
+ if (br) {
1096
+ end = i + (size_t)(yep_ctz64(br) >> 3);
1097
+ break;
1098
+ }
1099
+ i += 8;
1100
+ }
1101
+ if (!have_ind) {
1102
+ ind = end;
1103
+ }
1104
+ if (!stop_set) {
1105
+ stop = end;
1106
+ }
1107
+ uint32_t le = (uint32_t)(pos + end);
1108
+ uint32_t li = (uint32_t)(pos + ind);
1109
+ uint32_t ls = (uint32_t)(pos + stop);
1110
+ uint32_t col = (uint32_t)(li - pos);
1111
+ /* blank and comment lines ride silently — the main loop skips
1112
+ * them with no state change */
1113
+ if (ind >= end || (p[li] == '#' && (li == 0 || p[li - 1] == ' ' || p[li - 1] == '\t' ||
1114
+ p[li - 1] == '\n'))) {
1115
+ pos = le < len ? (size_t)le + 1 : len;
1116
+ continue;
1117
+ }
1118
+ if (col + 1 != run_cc) {
1119
+ return pos; /* off-column: the pop/nest logic owns it */
1120
+ }
1121
+ unsigned char c = (unsigned char)p[li];
1122
+ if (c == '\t' || c == '-' || c == '&' || c == '!' || c == '*' || c == '\'' || c == '"' ||
1123
+ c == '[' || c == '{' || c == '|' || c == '>' || c == '%' || c == '?') {
1124
+ return pos; /* indicators, tab-led: the full arms */
1125
+ }
1126
+ if (!stop_set || p[ls] != ':' || (ls + 1 < le && p[ls + 1] != ' ' && p[ls + 1] != '\t')) {
1127
+ return pos; /* not a plain key: value line */
1128
+ }
1129
+ size_t t0 = li;
1130
+ uint32_t kend = ls;
1131
+ while (kend > t0 && (p[kend - 1] == ' ' || p[kend - 1] == '\t')) {
1132
+ kend--;
1133
+ }
1134
+ if (kend == t0 || (uint32_t)(kend - t0) > 1024u) {
1135
+ return pos; /* empty key / the simple-key length law */
1136
+ }
1137
+ size_t vt = ls + 1;
1138
+ while (vt < le && (p[vt] == ' ' || p[vt] == '\t')) {
1139
+ vt++;
1140
+ }
1141
+ if (vt >= le || p[vt] == '#') {
1142
+ return pos; /* "key:" pending: the main loop's frame arm */
1143
+ }
1144
+ unsigned char vc = (unsigned char)p[vt];
1145
+ if (vc == '"' || vc == '\'') {
1146
+ /* the quoted plain-value arm, same law as the main loop:
1147
+ * same-line close, no backslash, no '' doubling, a comment
1148
+ * needs separating whitespace */
1149
+ size_t ce = vt + 1;
1150
+ int esc = 0;
1151
+ while (ce < le) {
1152
+ if (p[ce] == '\\') {
1153
+ esc = 1;
1154
+ break;
1155
+ }
1156
+ if (p[ce] == vc) {
1157
+ break;
1158
+ }
1159
+ ce++;
1160
+ }
1161
+ if (ce >= le || esc) {
1162
+ return pos; /* unterminated or escaped: the engine */
1163
+ }
1164
+ if (vc == '\'' && ce + 1 < le && p[ce + 1] == '\'') {
1165
+ return pos; /* the '' escape: the engine */
1166
+ }
1167
+ size_t te = ce + 1;
1168
+ while (te < le && (p[te] == ' ' || p[te] == '\t')) {
1169
+ te++;
1170
+ }
1171
+ if (te < le && (p[te] != '#' || te == ce + 1)) {
1172
+ return pos; /* trailing content after the close */
1173
+ }
1174
+ (void)yt_put(t, yt_props(YTP_SCALAR, 0, 0x2900u));
1175
+ (void)yt_put(t, yt_span_in((uint32_t)t0, kend - (uint32_t)t0, YTP_SPAN_IN));
1176
+ (void)yt_put(t, yt_props(YTP_SCALAR, 0, vc == '"' ? 0x2300u : 0x2200u));
1177
+ (void)yt_put(t, yt_span_in((uint32_t)(vt + 1), (uint32_t)(ce - vt - 1), YTP_SPAN_IN));
1178
+ pos = le < len ? (size_t)le + 1 : len;
1179
+ continue;
1180
+ }
1181
+ if (vc == '*' || vc == '|' || vc == '>' || vc == '[' || vc == '{' || vc == '!' ||
1182
+ vc == '%' || vc == '&' ||
1183
+ ((vc == '-' || vc == '?') &&
1184
+ (vt + 1 >= le || p[vt + 1] == ' ' || p[vt + 1] == '\t' || p[vt + 1] == '#'))) {
1185
+ return pos; /* block/flow/anchor values: the full arms */
1186
+ }
1187
+ /* a terminating ':' inside the value is the mapping-values error */
1188
+ {
1189
+ const char* h = (const char*)memchr(p + vt, ':', le - vt);
1190
+ while (h != NULL) {
1191
+ if (h + 1 >= p + le || h[1] == ' ' || h[1] == '\t') {
1192
+ return pos; /* the engine's error route */
1193
+ }
1194
+ h = (const char*)memchr(h + 1, ':', le - (size_t)(h + 1 - p));
1195
+ }
1196
+ }
1197
+ uint32_t vend = le;
1198
+ {
1199
+ const char* hh = (const char*)memchr(p + vt, '#', le - vt);
1200
+ while (hh != NULL) {
1201
+ if (hh > p + vt && (hh[-1] == ' ' || hh[-1] == '\t')) {
1202
+ vend = (uint32_t)(hh - p);
1203
+ break;
1204
+ }
1205
+ hh = (const char*)memchr(hh + 1, '#', le - (size_t)(hh + 1 - p));
1206
+ }
1207
+ }
1208
+ while (vend > vt && (p[vend - 1] == ' ' || p[vend - 1] == '\t')) {
1209
+ vend--;
1210
+ }
1211
+ (void)yt_put(t, yt_props(YTP_PAIR, 0, 2u | (1u << 3)));
1212
+ (void)yt_put(t, yt_span_in((uint32_t)t0, kend - (uint32_t)t0, YTP_SPAN_IN));
1213
+ (void)yt_put(t, yt_span_in((uint32_t)vt, vend - (uint32_t)vt, YTP_SPAN_IN));
1214
+ pos = le < len ? (size_t)le + 1 : len;
1215
+ }
1216
+ }
1217
+
1218
+ static int yt_f_run(yt_fused* F) {
1219
+ const char* p = F->p;
1220
+ size_t len = F->len;
1221
+ yep_ytape* t = F->t;
1222
+ yt_frame st[YT_FUSED_MAX_FRAMES];
1223
+ int depth = 0;
1224
+ memset(&st[0], 0, sizeof(st[0]));
1225
+ st[0].started = 1; /* the root's start event defers to its first pair */
1226
+ int root_open = 0;
1227
+ int root_evented = 0;
1228
+ (void)yt_put(t, ((uint64_t)YTP_EV_COMPACT << 56) | 1u);
1229
+ (void)yt_put(t, ((uint64_t)YTP_EV_COMPACT << 56) | 3u);
1230
+ size_t pos = 0;
1231
+ while (pos < len) {
1232
+ /* the sweep: one NUL-padded SWAR walk per line */
1233
+ const uint64_t k_nl = 0x0A0A0A0A0A0A0A0Aull, k_cr = 0x0D0D0D0D0D0D0D0Dull,
1234
+ k_sp = 0x2020202020202020ull, k_co = 0x3A3A3A3A3A3A3A3Aull,
1235
+ k_ha = 0x2323232323232323ull;
1236
+ size_t whole = len - pos;
1237
+ size_t end = whole, indent = whole, stop = whole;
1238
+ int have_indent = 0, stop_set = 0;
1239
+ size_t i = 0;
1240
+ while (i < whole) {
1241
+ size_t avail = whole - i < 8 ? whole - i : 8;
1242
+ uint64_t x;
1243
+ if (avail == 8) {
1244
+ memcpy(&x, p + pos + i, 8);
1245
+ } else {
1246
+ char buf[8] = {0, 0, 0, 0, 0, 0, 0, 0};
1247
+ memcpy(buf, p + pos + i, avail);
1248
+ memcpy(&x, buf, 8);
1249
+ }
1250
+ uint64_t valid = avail == 8 ? ~(uint64_t)0 : (((uint64_t)1 << (avail * 8)) - 1);
1251
+ uint64_t br = (yep_swar_eq8(x, k_nl) | yep_swar_eq8(x, k_cr)) & valid;
1252
+ uint64_t room = (br ? ((br & (~br + 1)) - 1) : valid) & YEP_SWAR_FLAGS & valid;
1253
+ if (!have_indent) {
1254
+ uint64_t nons = ~(yep_swar_eq8(x, k_sp)) & room;
1255
+ if (nons) {
1256
+ indent = i + (size_t)(yep_ctz64(nons) >> 3);
1257
+ have_indent = 1;
1258
+ }
1259
+ }
1260
+ if (have_indent && !stop_set) {
1261
+ uint64_t stm = (yep_swar_eq8(x, k_co) | yep_swar_eq8(x, k_ha)) & room;
1262
+ if (stm) {
1263
+ size_t cand = i + (size_t)(yep_ctz64(stm) >> 3);
1264
+ if (cand >= indent) {
1265
+ stop = cand;
1266
+ stop_set = 1;
1267
+ }
1268
+ }
1269
+ }
1270
+ if (br) {
1271
+ end = i + (size_t)(yep_ctz64(br) >> 3);
1272
+ break;
1273
+ }
1274
+ i += 8;
1275
+ }
1276
+ if (!have_indent) {
1277
+ indent = end;
1278
+ }
1279
+ if (!stop_set) {
1280
+ stop = end;
1281
+ }
1282
+ uint32_t line_end = (uint32_t)(pos + end);
1283
+ uint32_t line_indent = (uint32_t)(pos + indent);
1284
+ uint32_t line_stop = (uint32_t)(pos + stop);
1285
+ uint8_t blank = (uint8_t)(indent >= end);
1286
+ unsigned char c = blank ? 0 : (unsigned char)p[line_indent];
1287
+ uint8_t comment =
1288
+ (uint8_t)(c == '#' && (line_indent == 0 || p[line_indent - 1] == ' ' ||
1289
+ p[line_indent - 1] == '\t' || p[line_indent - 1] == '\n'));
1290
+ uint8_t dash = 0;
1291
+ if (c == '-' && line_indent + 1 < line_end) {
1292
+ unsigned char n1 = (unsigned char)p[line_indent + 1];
1293
+ if (n1 == ' ' || n1 == '\t') {
1294
+ dash = 1;
1295
+ }
1296
+ }
1297
+ size_t next = line_end < len ? (size_t)line_end + 1 : len;
1298
+ if (!blank && !comment) {
1299
+ size_t t0 = line_indent;
1300
+ uint32_t col = (uint32_t)(line_indent - pos);
1301
+ if (c == '\t') {
1302
+ return 1; /* tab-led content: the engine's error */
1303
+ }
1304
+ if (dash && depth > 0 && st[depth].pending && col >= st[depth].indent) {
1305
+ /* the pending key resolves into a sequence: its own
1306
+ * frame (the key's map survives below it) */
1307
+ if (depth >= YT_FUSED_MAX_FRAMES - 1) {
1308
+ return 1; /* the frame stack is full: the engine route */
1309
+ }
1310
+ int anchored = st[depth].aid != 0;
1311
+ if (anchored) {
1312
+ if (col == st[depth].indent) {
1313
+ return 1; /* indentless anchored seq: the engine owns it
1314
+ * (the frame-close pairing assumes the seq's
1315
+ * own column, deeper than the key's) */
1316
+ }
1317
+ /* anchored sequence: S2900 key + the anchored SEQ start */
1318
+ if (depth == 1) {
1319
+ if (!root_open) {
1320
+ (void)yt_put(t, yt_props(YTP_EVENT, 0, 7u));
1321
+ yt_f_empty_span(F);
1322
+ t->depth++;
1323
+ root_open = 1;
1324
+ root_evented = 1;
1325
+ st[0].started = 1;
1326
+ }
1327
+ } else if (!st[depth - 1].started && col != st[depth - 1].indent) {
1328
+ yt_f_start(F, &st[depth - 1]);
1329
+ }
1330
+ uint32_t xaid = st[depth].aid;
1331
+ uint32_t xoff = st[depth].a_off;
1332
+ uint32_t xlen = st[depth].a_len;
1333
+ (void)yt_put(t, yt_props(YTP_SCALAR, 0, 0x2900u));
1334
+ (void)yt_put(t, yt_span_in(st[depth].key_off, st[depth].key_len, YTP_SPAN_IN));
1335
+ (void)yt_put(t, yt_props(YTP_EVENT, xaid, 5u | (1u << 13)));
1336
+ yt_f_empty_span(F);
1337
+ (void)yt_put(t, yt_span_in(xoff, xlen, YTP_SPAN_IN));
1338
+ yt_anchor_open(F, xaid);
1339
+ st[depth].pending = 0; /* the seq frame shadows this slot */
1340
+ } else {
1341
+ uint8_t of = yt_f_open_form(&st[depth - 1], depth == 1, st[depth].indent);
1342
+ yt_f_open(F, &st[depth], of);
1343
+ root_open = 1;
1344
+ st[depth].pending = 0;
1345
+ }
1346
+ depth++;
1347
+ memset(&st[depth], 0, sizeof(st[depth]));
1348
+ st[depth].kind = 1;
1349
+ st[depth].indent = col;
1350
+ st[depth].own_map = 1;
1351
+ st[depth].anchored_first = (uint8_t)anchored;
1352
+ if (anchored) {
1353
+ st[depth].started = 1; /* the E5 went out above */
1354
+ } else {
1355
+ yt_f_start(F, &st[depth]);
1356
+ }
1357
+ } else {
1358
+ while (depth > 0 && (st[depth].kind == 1 ? (col < st[depth].indent ||
1359
+ (col <= st[depth].indent && !dash))
1360
+ : col < st[depth].indent)) {
1361
+ if (st[depth].pending) {
1362
+ return 1; /* empty "key:" mid-doc: the engine owns it */
1363
+ }
1364
+ if (st[depth].phantom) {
1365
+ yt_f_close(F, st[depth].kind);
1366
+ st[depth].phantom = 0;
1367
+ }
1368
+ if (st[depth].own_map) {
1369
+ yt_f_close(F, st[depth].kind);
1370
+ }
1371
+ depth--;
1372
+ }
1373
+ }
1374
+ if (dash) {
1375
+ if (st[depth].kind == 1 && col == st[depth].indent) {
1376
+ yt_f_start(F, &st[depth]);
1377
+ size_t vt = t0 + 1;
1378
+ while (vt < line_end && (p[vt] == ' ' || p[vt] == '\t')) {
1379
+ vt++;
1380
+ }
1381
+ uint32_t vend = line_end;
1382
+ while (vend > vt && (p[vend - 1] == ' ' || p[vend - 1] == '\t')) {
1383
+ vend--;
1384
+ }
1385
+ if (vend == vt) {
1386
+ return 1; /* empty item */
1387
+ }
1388
+ unsigned char vc = (unsigned char)p[vt];
1389
+ if (vc == '"' || vc == '\'' || vc == '*' || vc == '&' || vc == '[' ||
1390
+ vc == '{' || vc == '!' || vc == '|' || vc == '>' || vc == '%' ||
1391
+ vc == '?') {
1392
+ return 1;
1393
+ }
1394
+ if (vc == '-' && vt + 1 < line_end && (p[vt + 1] == ' ' || p[vt + 1] == '\t')) {
1395
+ return 1; /* nested dash: the engine's nested seq */
1396
+ }
1397
+ /* compact map item "- k: v"? */
1398
+ for (size_t ic = vt; ic < vend; ic++) {
1399
+ if (p[ic] == ':') {
1400
+ size_t nn = ic + 1;
1401
+ if (nn >= vend || p[nn] == ' ' || p[nn] == '\t') {
1402
+ return 1; /* compact items: the engine */
1403
+ }
1404
+ }
1405
+ }
1406
+ if (st[depth].anchored_first && F->resolver != NULL) {
1407
+ yep_tag_id tid =
1408
+ F->resolver->resolve(F->resolver->ctx, p + vt, (uint32_t)(vend - vt));
1409
+ (void)yt_put(t, yt_props(YTP_SCALAR, 0, 0x2900u | (uint32_t)tid));
1410
+ (void)yt_put(t, yt_span_in((uint32_t)vt, vend - (uint32_t)vt, YTP_SPAN_IN));
1411
+ st[depth].anchored_first = 0;
1412
+ } else {
1413
+ (void)yt_put(t, yt_span_in((uint32_t)vt, vend - (uint32_t)vt, YTP_ITEM));
1414
+ }
1415
+ if (!st[depth].content_col) {
1416
+ st[depth].content_col = col + 1;
1417
+ }
1418
+ } else {
1419
+ return 1;
1420
+ }
1421
+ } else if (stop_set && p[line_stop] == ':' &&
1422
+ (line_stop + 1 >= line_end || p[line_stop + 1] == ' ' ||
1423
+ p[line_stop + 1] == '\t') &&
1424
+ !(c == '&' || c == '!' || c == '*' || c == '\'' || c == '"' || c == '[' ||
1425
+ c == '{' || c == '|' || c == '>' || c == '%' || c == '?' || c == '-')) {
1426
+ uint32_t kend = line_stop;
1427
+ while (kend > t0 && (p[kend - 1] == ' ' || p[kend - 1] == '\t')) {
1428
+ kend--;
1429
+ }
1430
+ if (kend == t0) {
1431
+ return 1; /* empty plain key (": v"): the engine's two-scalar form */
1432
+ }
1433
+ if ((uint32_t)(kend - t0) > 1024u) {
1434
+ return 1; /* the simple-key length law: the engine errors */
1435
+ }
1436
+ size_t vt = line_stop + 1;
1437
+ while (vt < line_end && (p[vt] == ' ' || p[vt] == '\t')) {
1438
+ vt++;
1439
+ }
1440
+ uint32_t aoff = 0, alen = 0, aid = 0;
1441
+ if (vt < line_end && p[vt] == '&') {
1442
+ size_t ne = vt + 1;
1443
+ while (ne < line_end && ne < len) {
1444
+ unsigned char pc = (unsigned char)p[ne];
1445
+ if (pc <= ' ' || pc == ',' || pc == '[' || pc == ']' || pc == '{' ||
1446
+ pc == '}' || pc == '#') {
1447
+ break;
1448
+ }
1449
+ ne++;
1450
+ }
1451
+ aoff = (uint32_t)(vt + 1);
1452
+ alen = (uint32_t)(ne - vt - 1);
1453
+ F->anchor_seq++;
1454
+ aid = F->anchor_seq;
1455
+ if (!yt_anchor_table(F)) {
1456
+ return 1;
1457
+ }
1458
+ yt_anchor_put(F, aoff, alen, aid);
1459
+ vt = ne;
1460
+ while (vt < line_end && (p[vt] == ' ' || p[vt] == '\t')) {
1461
+ vt++;
1462
+ }
1463
+ }
1464
+ if (vt >= line_end || p[vt] == '#') {
1465
+ /* "key:" with a following-lines container: push pending
1466
+ * (aid rides it: an anchored container resolves through
1467
+ * the S2900 + anchored-start form, not on_block_open) */
1468
+ if (st[depth].kind == 0 && st[depth].content_col != 0 &&
1469
+ col + 1 != st[depth].content_col && col != st[depth].indent) {
1470
+ return 1; /* off-column: a continuation line — the multiline arm */
1471
+ }
1472
+ if (st[depth].kind == 0 && st[depth].content_col != 0 &&
1473
+ col + 1 != st[depth].content_col && st[depth].phantom) {
1474
+ yt_f_close(F, st[depth].kind);
1475
+ st[depth].phantom = 0;
1476
+ }
1477
+ if (depth > 0 && st[depth].pending) {
1478
+ uint8_t of = yt_f_open_form(&st[depth - 1], depth == 1, st[depth].indent);
1479
+ yt_f_open(F, &st[depth], of);
1480
+ root_open = 1;
1481
+ st[depth].pending = 0;
1482
+ }
1483
+ /* a spent key-SCALAR frame (resolved, phantom closed,
1484
+ * no map of its own) gives its slot to the sibling —
1485
+ * chained same-column pendings would otherwise grow
1486
+ * the stack by one per record (the frame-full bail) */
1487
+ if (!(depth > 0 && !st[depth].pending && !st[depth].phantom &&
1488
+ !st[depth].own_map)) {
1489
+ if (depth >= YT_FUSED_MAX_FRAMES - 1) {
1490
+ return 1;
1491
+ }
1492
+ depth++;
1493
+ }
1494
+ memset(&st[depth], 0, sizeof(st[depth]));
1495
+ st[depth].indent = col;
1496
+ st[depth].pending = 1;
1497
+ st[depth].key_off = (uint32_t)t0;
1498
+ st[depth].key_len = kend - (uint32_t)t0;
1499
+ st[depth].aid = aid;
1500
+ st[depth].a_off = aoff;
1501
+ st[depth].a_len = alen;
1502
+ st[depth].anchored_first = (uint8_t)(aid != 0);
1503
+ } else {
1504
+ if (st[depth].kind == 0 && st[depth].content_col != 0 &&
1505
+ col + 1 != st[depth].content_col && col != st[depth].indent) {
1506
+ return 1; /* off-column: a continuation line — the multiline arm */
1507
+ }
1508
+ if (depth > 0 && st[depth].pending && st[depth].aid != 0) {
1509
+ if (col <= st[depth].indent) {
1510
+ return 1; /* same-column "content": the anchored value is
1511
+ * null and this line is a sibling — the engine */
1512
+ }
1513
+ /* an anchored container resolves through the event
1514
+ * path: the parent's content map opens for the key
1515
+ * first, then the key SCALAR + the anchored start */
1516
+ if (depth == 1) {
1517
+ if (!root_open) {
1518
+ (void)yt_put(t, yt_props(YTP_EVENT, 0, 7u));
1519
+ yt_f_empty_span(F);
1520
+ t->depth++;
1521
+ root_open = 1;
1522
+ root_evented = 1;
1523
+ st[0].started = 1;
1524
+ }
1525
+ /* the root now has content: later sibling pendings
1526
+ * take the key-SCALAR form, not OPEN */
1527
+ if (st[0].content_col == 0) {
1528
+ st[0].content_col = st[depth].indent + 1;
1529
+ }
1530
+ } else if (!st[depth - 1].started && col != st[depth - 1].indent) {
1531
+ yt_f_start(F, &st[depth - 1]);
1532
+ }
1533
+ uint32_t xaid = st[depth].aid;
1534
+ uint32_t xoff = st[depth].a_off;
1535
+ uint32_t xlen = st[depth].a_len;
1536
+ (void)yt_put(t, yt_props(YTP_SCALAR, 0, 0x2900u));
1537
+ (void)yt_put(t,
1538
+ yt_span_in(st[depth].key_off, st[depth].key_len, YTP_SPAN_IN));
1539
+ (void)yt_put(t, yt_props(YTP_EVENT, xaid, 7u | (1u << 13)));
1540
+ yt_f_empty_span(F);
1541
+ (void)yt_put(t, yt_span_in(xoff, xlen, YTP_SPAN_IN));
1542
+ yt_anchor_open(F, xaid);
1543
+ memset(&st[depth], 0, sizeof(st[depth]));
1544
+ st[depth].indent = col; /* the engine's frame pops on the CONTENT
1545
+ * column, not the anchored key's */
1546
+ st[depth].own_map = 1;
1547
+ st[depth].started = 1;
1548
+ st[depth].anchored_first = 1;
1549
+ t->depth++;
1550
+ } else if (depth > 0 && st[depth].pending) {
1551
+ uint8_t of = yt_f_open_form(&st[depth - 1], depth == 1, st[depth].indent);
1552
+ yt_f_open(F, &st[depth], of);
1553
+ root_open = 1;
1554
+ st[depth].pending = 0;
1555
+ if (col == st[depth].indent) {
1556
+ /* a same-column sibling pair resolves the pending
1557
+ * key to null (the engine's empty-value scalar) */
1558
+ (void)yt_put(t, yt_props(YTP_SCALAR, 0, 0x0904u));
1559
+ yt_f_empty_span(F);
1560
+ }
1561
+ } else if (!root_open && depth == 0) {
1562
+ (void)yt_put(t, yt_props(YTP_EVENT, 0, 7u));
1563
+ yt_f_empty_span(F);
1564
+ t->depth++;
1565
+ root_open = 1;
1566
+ root_evented = 1;
1567
+ st[0].started = 1;
1568
+ }
1569
+ if (col == st[depth].indent) {
1570
+ /* the engine's sibling-continue: the live phantom
1571
+ * content map closes, the pair rides the frame's
1572
+ * own map without a start event */
1573
+ if (st[depth].phantom) {
1574
+ yt_f_close(F, st[depth].kind);
1575
+ st[depth].phantom = 0;
1576
+ }
1577
+ } else {
1578
+ yt_f_start(F, &st[depth]);
1579
+ }
1580
+ if (st[depth].kind != 0) {
1581
+ return 1;
1582
+ }
1583
+ unsigned char vc = (unsigned char)p[vt];
1584
+ uint32_t flags;
1585
+ if ((vc == '*' && aid != 0) || (vc == '*' && st[depth].anchored_first)) {
1586
+ return 1; /* an anchored/first alias: the engine owns it */
1587
+ }
1588
+ if (vc == '*') {
1589
+ size_t ne = vt + 1;
1590
+ while (ne < line_end) {
1591
+ unsigned char pc = (unsigned char)p[ne];
1592
+ if (pc <= ' ' || pc == ',' || pc == '[' || pc == ']' || pc == '{' ||
1593
+ pc == '}' || pc == '#') {
1594
+ break;
1595
+ }
1596
+ ne++;
1597
+ }
1598
+ uint32_t taid = 0;
1599
+ if (!yt_anchor_get(F, (uint32_t)(vt + 1), (uint32_t)(ne - vt - 1), &taid)) {
1600
+ return 1; /* undefined alias: the engine errors */
1601
+ }
1602
+ if (taid == 0 || taid > YT_FUSED_ANCHORS || F->anchors_opened == NULL ||
1603
+ !F->anchors_opened[taid - 1]) {
1604
+ return 1; /* alias to an anchor whose container never opened
1605
+ * (null-valued or still pending): the engine */
1606
+ }
1607
+ (void)yt_put(t, yt_props(YTP_PAIR, taid, 3u /*ALIAS*/));
1608
+ (void)yt_put(t, yt_span_in((uint32_t)t0, kend - (uint32_t)t0, YTP_SPAN_IN));
1609
+ (void)yt_put(t, yt_span_in((uint32_t)(vt + 1), (uint32_t)(ne - vt - 1),
1610
+ YTP_SPAN_IN));
1611
+ if (!st[depth].content_col) {
1612
+ st[depth].content_col = col + 1;
1613
+ }
1614
+ goto line_done;
1615
+ }
1616
+ if ((vc == '"' || vc == '\'') && aid == 0) {
1617
+ /* same-line quoted value: the two-SCALAR form (the
1618
+ * key plain + the styled value, quotes stripped);
1619
+ * escapes and multiline quotes stay with the engine */
1620
+ size_t ce = vt + 1;
1621
+ int esc = 0;
1622
+ while (ce < line_end) {
1623
+ if (p[ce] == '\\') {
1624
+ esc = 1;
1625
+ break;
1626
+ }
1627
+ if (p[ce] == vc) {
1628
+ break;
1629
+ }
1630
+ ce++;
1631
+ }
1632
+ if (ce >= line_end || esc) {
1633
+ return 1; /* unterminated or escaped: the engine */
1634
+ }
1635
+ if (vc == '\'' && ce + 1 < line_end && p[ce + 1] == '\'') {
1636
+ return 1; /* the '' escape: the engine */
1637
+ }
1638
+ size_t te = ce + 1;
1639
+ while (te < line_end && (p[te] == ' ' || p[te] == '\t')) {
1640
+ te++;
1641
+ }
1642
+ /* a comment needs separating whitespace — "#"
1643
+ * glued to the quote is content (the engine errors) */
1644
+ if (te < line_end && (p[te] != '#' || te == ce + 1)) {
1645
+ return 1; /* trailing content after the close */
1646
+ }
1647
+ (void)yt_put(t, yt_props(YTP_SCALAR, 0, 0x2900u));
1648
+ (void)yt_put(t, yt_span_in((uint32_t)t0, kend - (uint32_t)t0, YTP_SPAN_IN));
1649
+ (void)yt_put(t, yt_props(YTP_SCALAR, 0, vc == '"' ? 0x2300u : 0x2200u));
1650
+ (void)yt_put(t, yt_span_in((uint32_t)(vt + 1), (uint32_t)(ce - vt - 1),
1651
+ YTP_SPAN_IN));
1652
+ st[depth].anchored_first = 0;
1653
+ if (!st[depth].content_col) {
1654
+ st[depth].content_col = col + 1;
1655
+ }
1656
+ goto line_done;
1657
+ }
1658
+ if (vc == '|' && aid == 0 && !st[depth].anchored_first &&
1659
+ (vt + 1 >= line_end || p[vt + 1] == ' ' || p[vt + 1] == '\t')) {
1660
+ /* bare literal block, clip chomp: measure the block,
1661
+ * copy it into the finish pool, emit the pool form */
1662
+ size_t scan = next;
1663
+ uint32_t bindent = 0;
1664
+ int have_bi = 0, have_content = 0;
1665
+ size_t clen = 0, tb = 0;
1666
+ size_t end_scan = scan;
1667
+ /* per-line copy facts: blocks whose lines fit
1668
+ * the array copy straight from it — the second,
1669
+ * boundary-rederiving walk disappears. Larger
1670
+ * blocks (nested in block-heavy) keep the walk
1671
+ * below. */
1672
+ struct {
1673
+ uint32_t off;
1674
+ uint32_t n;
1675
+ uint8_t blank;
1676
+ } ln[16];
1677
+ size_t nl = 0;
1678
+ int spilled = 0;
1679
+ while (scan < len) {
1680
+ size_t ls = scan;
1681
+ size_t le = ls;
1682
+ while (le < len && p[le] != '\n' && p[le] != '\r') {
1683
+ le++;
1684
+ }
1685
+ size_t ie = ls;
1686
+ while (ie < le && p[ie] == ' ') {
1687
+ ie++;
1688
+ }
1689
+ uint32_t cpy_off = 0, cpy_n = 0;
1690
+ uint8_t cpy_blank = 0;
1691
+ if (ie == le) {
1692
+ /* a blank line: spaces past the block indent are
1693
+ * CONTENT; only stripped-empty lines clip away */
1694
+ size_t ind = ie - ls;
1695
+ size_t res = have_bi && ind > bindent ? ind - bindent : 0;
1696
+ clen += res + 1;
1697
+ if (res == 0) {
1698
+ tb += 1;
1699
+ } else {
1700
+ tb = 0;
1701
+ }
1702
+ cpy_n = (uint32_t)res;
1703
+ cpy_blank = 1;
1704
+ } else {
1705
+ uint32_t ind = (uint32_t)(ie - ls);
1706
+ if (!have_bi) {
1707
+ if (ind <= col) {
1708
+ break; /* dedented past the block */
1709
+ }
1710
+ bindent = ind;
1711
+ have_bi = 1;
1712
+ } else if (ind < bindent) {
1713
+ break; /* the block ends */
1714
+ }
1715
+ if (memchr(p + ls, '\t', le - ls) != NULL) {
1716
+ return 1; /* tabs: the engine's error */
1717
+ }
1718
+ clen += (le - (ls + bindent)) + 1;
1719
+ have_content = 1;
1720
+ tb = 0;
1721
+ cpy_off = (uint32_t)(ls + bindent);
1722
+ cpy_n = (uint32_t)(le - (ls + bindent));
1723
+ }
1724
+ if (nl < 16) {
1725
+ ln[nl].off = cpy_off;
1726
+ ln[nl].n = cpy_n;
1727
+ ln[nl].blank = cpy_blank;
1728
+ nl++;
1729
+ } else {
1730
+ spilled = 1;
1731
+ }
1732
+ end_scan =
1733
+ (le < len && p[le] == '\r' && le + 1 < len) ? le + 2 : le + 1;
1734
+ scan = end_scan;
1735
+ }
1736
+ if (!have_content) {
1737
+ return 1; /* empty/blank-only block: the engine */
1738
+ }
1739
+ size_t flen = clen - tb; /* clip: the trailing stripped-empty lines */
1740
+ if (F->pool == NULL) {
1741
+ F->pool = yep_pool_create(yep_system_allocator(), 4096);
1742
+ if (F->pool == NULL) {
1743
+ return 1;
1744
+ }
1745
+ }
1746
+ char* dst = (char*)yep_pool_alloc(F->pool, flen, 16);
1747
+ if (dst == NULL) {
1748
+ return 1;
1749
+ }
1750
+ {
1751
+ char* q = dst;
1752
+ if (!spilled) {
1753
+ /* the array path: sizing and copy derive
1754
+ * from the SAME facts — exact by
1755
+ * construction, no re-walk */
1756
+ for (size_t x = 0; x < nl; x++) {
1757
+ if (ln[x].blank) {
1758
+ if (ln[x].n > 0) {
1759
+ memset(q, ' ', ln[x].n);
1760
+ q += ln[x].n;
1761
+ }
1762
+ } else {
1763
+ memcpy(q, p + ln[x].off, ln[x].n);
1764
+ q += ln[x].n;
1765
+ }
1766
+ *q++ = '\n';
1767
+ }
1768
+ } else {
1769
+ size_t s2 = next;
1770
+ while (s2 < scan) {
1771
+ size_t ls = s2;
1772
+ size_t le = ls;
1773
+ while (le < len && p[le] != '\n' && p[le] != '\r') {
1774
+ le++;
1775
+ }
1776
+ size_t ie = ls;
1777
+ while (ie < le && p[ie] == ' ') {
1778
+ ie++;
1779
+ }
1780
+ if (ie == le) {
1781
+ size_t ind = ie - ls;
1782
+ size_t res = have_bi && ind > bindent ? ind - bindent : 0;
1783
+ if (res > 0) {
1784
+ memset(q, ' ', res);
1785
+ q += res;
1786
+ }
1787
+ *q++ = '\n';
1788
+ } else {
1789
+ memcpy(q, p + ls + bindent, le - (ls + bindent));
1790
+ q += le - (ls + bindent);
1791
+ *q++ = '\n';
1792
+ }
1793
+ s2 = (le < len && p[le] == '\r' && le + 1 < len) ? le + 2
1794
+ : le + 1;
1795
+ }
1796
+ }
1797
+ if ((size_t)(q - dst) != clen) {
1798
+ return 1; /* drift: bail, not corrupt */
1799
+ }
1800
+ }
1801
+ (void)yt_put(t, yt_props(YTP_SCALAR, 0, 0x2900u));
1802
+ (void)yt_put(t, yt_span_in((uint32_t)t0, kend - (uint32_t)t0, YTP_SPAN_IN));
1803
+ (void)yt_put(t, yt_props(YTP_SCALAR, 0, 0x0400u));
1804
+ (void)yt_put(t, ((uint64_t)YTP_SPAN_POOL << 56) | (uint64_t)flen);
1805
+ (void)yt_put(t, (uint64_t)(uintptr_t)dst);
1806
+ if (!st[depth].content_col) {
1807
+ st[depth].content_col = col + 1;
1808
+ }
1809
+ next = scan;
1810
+ goto line_done;
1811
+ }
1812
+ if (vc == '"' || vc == '\'' || vc == '|' || vc == '>' || vc == '[' ||
1813
+ vc == '{' || vc == '!' || vc == '%') {
1814
+ return 1; /* quoted/block/flow/tag values: the engine */
1815
+ }
1816
+ if ((vc == '-' || vc == '?') && (vt + 1 >= line_end || p[vt + 1] == ' ' ||
1817
+ p[vt + 1] == '\t' || p[vt + 1] == '#')) {
1818
+ return 1; /* an indicator-as-value: the engine errors */
1819
+ }
1820
+ /* a terminating ':' inside the value is the
1821
+ * mapping-values error — the engine owns it */
1822
+ for (const char* h = (const char*)memchr(p + vt, ':', line_end - vt);
1823
+ h != NULL && h < p + line_end;
1824
+ h = (const char*)memchr(h + 1, ':', line_end - (size_t)(h + 1 - p))) {
1825
+ if (h + 1 >= p + line_end || h[1] == ' ' || h[1] == '\t') {
1826
+ return 1;
1827
+ }
1828
+ }
1829
+ /* trailing comment bounds the plain value */
1830
+ uint32_t vend = line_end;
1831
+ {
1832
+ const char* h = (const char*)memchr(p + vt, '#', line_end - vt);
1833
+ while (h != NULL) {
1834
+ if (h > p + vt && (h[-1] == ' ' || h[-1] == '\t')) {
1835
+ vend = (uint32_t)(h - p);
1836
+ break;
1837
+ }
1838
+ h = (const char*)memchr(h + 1, '#', line_end - (size_t)(h + 1 - p));
1839
+ }
1840
+ }
1841
+ while (vend > vt && (p[vend - 1] == ' ' || p[vend - 1] == '\t')) {
1842
+ vend--;
1843
+ }
1844
+ if (st[depth].anchored_first) {
1845
+ /* the first pair inside an anchored container: the
1846
+ * two-SCALAR form with the engine's tag bake */
1847
+ if (aid != 0 || F->resolver == NULL) {
1848
+ return 1;
1849
+ }
1850
+ yep_tag_id tid =
1851
+ F->resolver->resolve(F->resolver->ctx, p + vt, (uint32_t)(vend - vt));
1852
+ (void)yt_put(t, yt_props(YTP_SCALAR, 0, 0x2900u));
1853
+ (void)yt_put(t, yt_span_in((uint32_t)t0, kend - (uint32_t)t0, YTP_SPAN_IN));
1854
+ (void)yt_put(t, yt_props(YTP_SCALAR, 0, 0x2900u | (uint32_t)tid));
1855
+ (void)yt_put(t, yt_span_in((uint32_t)vt, vend - (uint32_t)vt, YTP_SPAN_IN));
1856
+ st[depth].anchored_first = 0;
1857
+ if (!st[depth].content_col) {
1858
+ st[depth].content_col = col + 1;
1859
+ }
1860
+ goto line_done;
1861
+ }
1862
+ if (aid != 0) {
1863
+ flags = 4u | (1u << 3) | (1u << 4);
1864
+ } else {
1865
+ flags = 2u | (1u << 3);
1866
+ }
1867
+ (void)yt_put(t, yt_props(YTP_PAIR, aid, flags));
1868
+ (void)yt_put(t, yt_span_in((uint32_t)t0, kend - (uint32_t)t0, YTP_SPAN_IN));
1869
+ (void)yt_put(t, yt_span_in((uint32_t)vt, vend - (uint32_t)vt, YTP_SPAN_IN));
1870
+ if (aid != 0) {
1871
+ (void)yt_put(t, yt_span_in(aoff, alen, YTP_SPAN_IN));
1872
+ }
1873
+ if (!st[depth].content_col) {
1874
+ st[depth].content_col = col + 1;
1875
+ }
1876
+ if (aid == 0 && !st[depth].phantom && st[depth].content_col == col + 1) {
1877
+ /* the specialist takes the run at ANY frame's
1878
+ * content column: nested flat runs (anchored
1879
+ * containers, leaf maps) qualify; an off-column
1880
+ * line bails to the pop/nest arms as usual.
1881
+ * anchored_first is already cleared whenever a
1882
+ * plain emission reaches here (the anchored arm
1883
+ * leaves early), so no extra gate is owed. */
1884
+ size_t sp = yt_flat_run(t, p, next, len, st[depth].content_col);
1885
+ if (sp != next) {
1886
+ pos = sp;
1887
+ goto line_done_keep;
1888
+ }
1889
+ }
1890
+ }
1891
+ } else {
1892
+ return 1; /* unclassified line: the engine route */
1893
+ }
1894
+ }
1895
+ line_done:
1896
+ pos = next;
1897
+ line_done_keep: /* the specialist's stop line: reprocess it in place */
1898
+ ;
1899
+ }
1900
+ if (!root_open) {
1901
+ return 1; /* empty document: the engine owns it */
1902
+ }
1903
+ while (depth > 0) {
1904
+ if (st[depth].pending) {
1905
+ return 1; /* empty "key:" at EOF: the engine */
1906
+ }
1907
+ if (st[depth].phantom) {
1908
+ yt_f_close(F, st[depth].kind);
1909
+ st[depth].phantom = 0;
1910
+ }
1911
+ if (st[depth].own_map) {
1912
+ yt_f_close(F, st[depth].kind);
1913
+ }
1914
+ depth--;
1915
+ }
1916
+ if (root_evented) {
1917
+ yt_f_close(F, 0); /* only an event-started root closes */
1918
+ }
1919
+ (void)yt_put(t, ((uint64_t)YTP_EV_COMPACT << 56) | 4u);
1920
+ (void)yt_put(t, ((uint64_t)YTP_EV_COMPACT << 56) | 2u);
1921
+ t->docs = 1;
1922
+ return 0;
1923
+ }
1924
+
1925
+ /* The flow-rooted fast path (item 86): a document whose entire content
1926
+ * is ONE flow collection plus whitespace skips both the block runner
1927
+ * and the engine — the budgeted classification runs once and the
1928
+ * engine's exact five-word scaffolding lands directly. Any marker,
1929
+ * comment, anchor-bearing prefix, or second content falls back. */
1930
+ int ytap_flow_rooted(yep_ytape* t) {
1931
+ const char* p = t->input;
1932
+ size_t len = t->input_len;
1933
+ size_t i = 0;
1934
+ while (i < len && (p[i] == ' ' || p[i] == '\t' || p[i] == '\n' || p[i] == '\r')) {
1935
+ i++;
1936
+ }
1937
+ if (i >= len || (p[i] != '[' && p[i] != '{')) {
1938
+ return 1; /* not flow-rooted: the block runner's turn */
1939
+ }
1940
+ size_t mark = t->count;
1941
+ size_t open = i;
1942
+ yep_view none = {NULL, 0};
1943
+ (void)yt_put(t, ((uint64_t)YTP_EV_COMPACT << 56) | 1u);
1944
+ (void)yt_put(t, ((uint64_t)YTP_EV_COMPACT << 56) | 3u);
1945
+ size_t close = 0;
1946
+ int v = yt_flow_classify_record(t, p, open, len - open, &none, &none, 0,
1947
+ 1000 /* YEP_MAX_DEPTH: the engine's
1948
+ * default limit (engine.c) */
1949
+ ,
1950
+ &close);
1951
+ if (v != 1) {
1952
+ t->count = (uint32_t)mark; /* unwind: the engine route owns it */
1953
+ t->depth = 0;
1954
+ return 1;
1955
+ }
1956
+ for (size_t e = close + 1; e < len; e++) {
1957
+ if (p[e] != ' ' && p[e] != '\t' && p[e] != '\n' && p[e] != '\r') {
1958
+ t->count = (uint32_t)mark; /* trailing content: the engine */
1959
+ t->depth = 0;
1960
+ return 1;
1961
+ }
1962
+ }
1963
+ (void)yt_put(t, ((uint64_t)YTP_EV_COMPACT << 56) | 4u);
1964
+ (void)yt_put(t, ((uint64_t)YTP_EV_COMPACT << 56) | 2u);
1965
+ t->docs = 1;
1966
+ return 0;
1967
+ }
1968
+
1969
+ int ytap_fused_run(yep_ytape* t, const yep_resolver* resolver) {
1970
+ yt_fused* F = (yt_fused*)yep_alloc(yep_system_allocator(), sizeof(*F));
1971
+ if (F == NULL) {
1972
+ return 1; /* allocation refused: the engine route */
1973
+ }
1974
+ memset(F, 0, sizeof(*F));
1975
+ F->t = t;
1976
+ F->p = t->input;
1977
+ F->len = t->input_len;
1978
+ F->resolver = resolver;
1979
+ size_t mark = t->count;
1980
+ int rc = yt_f_run(F);
1981
+ yep_pool* rpool = F->pool; /* capture before the runner frees */
1982
+ yep_free(yep_system_allocator(), F->anchors);
1983
+ yep_free(yep_system_allocator(), F->anchors_opened);
1984
+ yep_free(yep_system_allocator(), F);
1985
+ if (rc != 0) {
1986
+ t->count = (uint32_t)mark; /* unwind: the caller resets and re-runs */
1987
+ t->depth = 0;
1988
+ if (rpool != NULL) {
1989
+ yep_pool_destroy(rpool);
1990
+ }
1991
+ return 1;
1992
+ }
1993
+ if (rpool != NULL) {
1994
+ t->pool = rpool; /* transferred to the document with the tape */
1995
+ }
1996
+ return 0;
1997
+ }
1998
+
1999
+ void ytap_reset(yep_ytape* t) {
2000
+ t->count = 0;
2001
+ t->depth = 0;
2002
+ t->docs = 0;
2003
+ t->oom = 0;
2004
+ t->flow_mark = 0;
2005
+ }