internal.h (23045B)
1 #ifndef KIT_GRAM_INTERNAL_H 2 #define KIT_GRAM_INTERNAL_H 3 4 #include <ctype.h> 5 #include <limits.h> 6 #include <setjmp.h> 7 #include <stdarg.h> 8 #include <stdbool.h> 9 #include <stddef.h> 10 #include <stdint.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <string.h> 14 15 #include <kit/gram.h> 16 #include <kit/support/gram_lex_tables.h> 17 #include <kit/support/gram_parse_tables.h> 18 #include <kit/gram_unicode.h> 19 20 #define diag_vset kit_gram_diag_vset 21 #define diag_set kit_gram_diag_set 22 #define die_oom kit_gram_die_oom 23 #define xmalloc kit_gram_xmalloc 24 #define xrealloc kit_gram_xrealloc 25 #define xcalloc kit_gram_xcalloc 26 #define xfree kit_gram_xfree 27 #define mem_release kit_gram_mem_release 28 #define scratch_enter kit_gram_scratch_enter 29 #define scratch_leave kit_gram_scratch_leave 30 #define scratch_release kit_gram_scratch_release 31 #define xstrndup kit_gram_xstrndup 32 #define xstrdup kit_gram_xstrdup 33 #define xasprintf kit_gram_xasprintf 34 #define buf_init kit_gram_buf_init 35 #define buf_init_writer kit_gram_buf_init_writer 36 #define buf_reserve kit_gram_buf_reserve 37 #define buf_appendn kit_gram_buf_appendn 38 #define buf_append kit_gram_buf_append 39 #define buf_append_uint kit_gram_buf_append_uint 40 #define buf_take kit_gram_buf_take 41 #define str_from_owned kit_gram_str_from_owned 42 #define str_dup_len kit_gram_str_dup_len 43 #define str_dup_c kit_gram_str_dup_c 44 #define str_eq kit_gram_str_eq 45 #define str_eq_c kit_gram_str_eq_c 46 #define str_to_c kit_gram_str_to_c 47 #define intern_len kit_gram_intern_len 48 #define intern_c kit_gram_intern_c 49 #define name_index_find kit_gram_name_index_find 50 #define name_index_put kit_gram_name_index_put 51 #define ast_seq_new kit_gram_ast_seq_new 52 #define ast_alt_new kit_gram_ast_alt_new 53 #define ast_node_new kit_gram_ast_node_new 54 #define ast_lex_seq_new kit_gram_ast_lex_seq_new 55 #define ast_lex_alt_new kit_gram_ast_lex_alt_new 56 #define ast_lex_node_new kit_gram_ast_lex_node_new 57 #define ast_seq_append kit_gram_ast_seq_append 58 #define ast_alt_append kit_gram_ast_alt_append 59 #define ast_lex_seq_append kit_gram_ast_lex_seq_append 60 #define ast_lex_alt_append kit_gram_ast_lex_alt_append 61 #define hex_val kit_gram_hex_val 62 #define is_c_ident_str kit_gram_is_c_ident_str 63 #define is_rule_name kit_gram_is_rule_name 64 #define is_token_name kit_gram_is_token_name 65 #define intset_contains kit_gram_intset_contains 66 #define intset_add kit_gram_intset_add 67 #define intset_union kit_gram_intset_union 68 #define intset_copy kit_gram_intset_copy 69 #define intset_sorted kit_gram_intset_sorted 70 #define intset_equal kit_gram_intset_equal 71 #define intset_intersection_min kit_gram_intset_intersection_min 72 #define c_string_str kit_gram_c_string_str 73 74 typedef struct GramgenContext GramgenContext; 75 typedef struct ScalarSetCacheEntry ScalarSetCacheEntry; 76 77 typedef struct { 78 const char* path; 79 uint32_t line, col; 80 } Loc; 81 82 /* Pending diagnostic, captured into the GramgenContext and flushed to the 83 * caller's KitContext.diag sink at the public-API boundary. (Replaces the 84 * upstream gramgen_diagnostic out-param; kit routes diagnostics through 85 * KitContext.diag.) */ 86 typedef struct { 87 const char* path; 88 uint32_t line, col; 89 char message[512]; 90 } GramDiag; 91 92 typedef struct { 93 char* s; 94 size_t len; 95 } Str; 96 97 typedef struct { 98 GramgenContext* ctx; 99 char* s; 100 size_t len, cap; 101 KitWriter* writer; /* streaming sink; NULL => accumulate into `s` */ 102 const char* write_path; /* for the "codegen write failed" diagnostic */ 103 } Buf; 104 105 /* Bump-allocated arena block. Allocations within a block are a pointer bump; 106 * each carries a 16-byte size header so the most-recent allocation can be freed 107 * (LIFO rewind) and realloc can grow in place. Non-LIFO frees are no-ops and 108 * the space is reclaimed when the whole arena is released. */ 109 typedef struct ArenaBlock { 110 struct ArenaBlock* next; 111 size_t cap; /* usable bytes in the data area */ 112 size_t used; /* bytes consumed so far */ 113 } ArenaBlock; 114 115 /* Tracked block for the freeing (list) allocator. Used for the scratch region 116 * so a phase with large, simultaneously-live intermediates (the UTF-8 lexer 117 * build) frees incrementally and keeps peak memory low — a bump arena can only 118 * reclaim at the end, which would balloon mid-build peak. */ 119 typedef struct MemBlock { 120 void* ptr; 121 size_t size; 122 struct MemBlock* next; 123 } MemBlock; 124 125 typedef struct InternEntry { 126 char* s; 127 size_t len; 128 uint64_t hash; 129 struct InternEntry* next; 130 } InternEntry; 131 132 /* A region allocator in one of two modes. MEM_BUMP (the permanent arena) bumps 133 * a pointer and frees everything at once. MEM_LIST (the scratch region) tracks 134 * each allocation so individual frees reclaim immediately, bounding peak. */ 135 typedef enum { MEM_BUMP, MEM_LIST } MemKind; 136 typedef struct { 137 KitHeap* heap; 138 MemKind kind; 139 ArenaBlock* head; /* MEM_BUMP: first block (for release) */ 140 ArenaBlock* cur; /* MEM_BUMP: active bump block */ 141 MemBlock* blocks; /* MEM_LIST: tracked allocations */ 142 } GramgenMem; 143 144 struct GramgenContext { 145 GramgenMem mem; /* permanent arena: owned by the compiled object */ 146 GramgenMem scratch; /* transient arena: released after a scoped phase */ 147 GramgenMem* active; /* arena that x* allocate from (NULL => &mem) */ 148 InternEntry** intern_buckets; 149 size_t intern_nbuckets, intern_count; 150 ScalarSetCacheEntry* scalar_set_cache; 151 int* union_tmp; /* reused scratch for intset_union merges (perm) */ 152 size_t union_tmp_cap; 153 const KitContext* kit; /* caller context: heap + diag sink */ 154 GramDiag* diag; /* -> diag_storage; populated then flushed to kit */ 155 GramDiag diag_storage; 156 jmp_buf jmp; 157 int can_jump; 158 }; 159 160 typedef enum { AST_NAME, AST_LITERAL, AST_GROUP, AST_OPT, AST_REP } AstNodeKind; 161 /* LEX_ANCHOR (edge anchor), LEX_REPEAT (counted/`+` quantifier), and LEX_NAME 162 * (`%def` fragment reference) are front-end-only kinds: the anchor-extraction 163 * and desugaring passes strip/expand/inline them on the lex AST before NFA 164 * construction, so the byte and scalar pipelines never encounter them. */ 165 typedef enum { 166 LEX_LITERAL, 167 LEX_CLASS, 168 LEX_PROP, 169 LEX_ANY, 170 LEX_GROUP, 171 LEX_OPT, 172 LEX_REP, 173 LEX_ANCHOR, 174 LEX_REPEAT, 175 LEX_NAME 176 } AstLexNodeKind; 177 typedef enum { PRATT_NAME, PRATT_LITERAL } PrattAtomKind; 178 /* LEX_LINE_DEF is a `%def` fragment definition: inlined and dropped during 179 * desugaring, it never becomes a recognizer. LEX_LINE_KEYWORDS is a `%keywords` 180 * block: its entries are extracted literals, never DFA recognizers. */ 181 typedef enum { 182 LEX_LINE_TOKEN, 183 LEX_LINE_SKIP, 184 LEX_LINE_DEF, 185 LEX_LINE_KEYWORDS 186 } LexLineKind; 187 188 /* Counted-repetition bound cap. `A{n,m}` bodies are unrolled into NFA states, 189 * so both bounds are capped; overflow is a located error. */ 190 #define KIT_GRAM_MAX_REPEAT 255 191 192 #define KIT_GRAM_HASH_OFFSET_BASIS 1469598103934665603ull 193 #define KIT_GRAM_HASH_PRIME 1099511628211ull 194 #define GROW_CAP(cap, init) ((cap) ? (cap) * 2 : (init)) 195 196 typedef struct AstNode AstNode; 197 typedef struct AstSeq AstSeq; 198 typedef struct AstAlt AstAlt; 199 typedef struct AstLexNode AstLexNode; 200 typedef struct AstLexSeq AstLexSeq; 201 typedef struct AstLexAlt AstLexAlt; 202 203 struct AstSeq { 204 GramgenContext* ctx; 205 AstNode** items; 206 size_t nitems, cap; 207 Loc loc; 208 }; 209 210 struct AstAlt { 211 GramgenContext* ctx; 212 AstSeq** seqs; 213 size_t nseqs, cap; 214 Loc loc; 215 }; 216 217 struct AstNode { 218 AstNodeKind kind; 219 Loc loc; 220 Str value; 221 AstAlt* alts; 222 }; 223 224 struct AstLexSeq { 225 GramgenContext* ctx; 226 AstLexNode** items; 227 size_t nitems, cap; 228 Loc loc; 229 }; 230 231 struct AstLexAlt { 232 GramgenContext* ctx; 233 AstLexSeq** seqs; 234 size_t nseqs, cap; 235 Loc loc; 236 }; 237 238 struct AstLexNode { 239 AstLexNodeKind kind; 240 Loc loc; 241 Str value; 242 Str scalar_value; 243 AstLexAlt* alts; 244 }; 245 246 typedef struct { 247 PrattAtomKind kind; 248 Loc loc; 249 Str value; 250 } AstPrattAtom; 251 252 typedef struct { 253 GramgenContext* ctx; 254 char* kind; 255 Loc loc; 256 AstPrattAtom** atoms; 257 size_t natoms, cap; 258 } AstPrattLine; 259 260 typedef struct { 261 GramgenContext* ctx; 262 AstPrattLine** lines; 263 size_t nlines, cap; 264 } AstPrattSpec; 265 266 typedef struct { 267 char* name; 268 Loc loc; 269 AstAlt* alts; 270 AstPrattSpec* pratt; 271 } AstRule; 272 273 typedef struct { 274 Str literal; 275 char* name; 276 Loc loc; 277 int used; 278 } TokenDecl; 279 280 /* One %keywords entry. A token name, a literal, or both; the missing side is 281 * resolved by the builder (string -> auto-named token; bare name -> its %token 282 * literal). */ 283 typedef struct { 284 char* name; /* token name, or NULL for the string-only form */ 285 Str literal; /* literal bytes when has_literal */ 286 int has_literal; 287 Loc loc; 288 } AstKwEntry; 289 290 typedef struct { 291 LexLineKind kind; 292 char* name; /* token/skip/def name; the host name for KEYWORDS */ 293 Loc loc; 294 AstLexAlt* alts; /* NULL for a KEYWORDS line */ 295 AstKwEntry* kw_entries; 296 size_t nkw_entries; 297 } AstLexLine; 298 299 typedef struct { 300 GramgenContext* ctx; 301 char* name; 302 Loc loc; 303 KitGramLexInputMode mode; 304 AstLexLine** lines; 305 size_t nlines, cap; 306 } AstLexBlock; 307 308 typedef struct { 309 GramgenContext* ctx; 310 AstRule** rules; 311 size_t nrules, cap_rules; 312 TokenDecl** token_decls; 313 size_t ntoken_decls, cap_token_decls; 314 AstLexBlock** lex_blocks; 315 size_t nlex_blocks, cap_lex_blocks; 316 } ParsedGrammar; 317 318 typedef struct { 319 int* v; 320 size_t n, cap; 321 } IntSet; 322 323 typedef struct { 324 const char** keys; 325 int* values; 326 size_t n, cap; 327 } NameIndexMap; 328 329 typedef enum { SYM_TERM, SYM_RULE, SYM_REP, SYM_OPT } SymKind; 330 331 typedef struct Sym Sym; 332 struct Sym { 333 SymKind kind; 334 Loc loc; 335 int value; 336 Sym* sub; 337 int set_index; 338 int sub_array_id; 339 }; 340 341 typedef struct { 342 Sym* syms; 343 size_t nsyms, cap; 344 Loc loc; 345 IntSet first; 346 int nullable; 347 } Prod; 348 349 typedef struct { 350 char* role; 351 int tok; /* prefix/postfix/infix op; ternary op1; circumfix open */ 352 int tok2; /* ternary op2; circumfix close (0 for unary/binary) */ 353 int inner_rule; /* circumfix inner rule index (-1 otherwise) */ 354 int prod; 355 int lbp, rbp; 356 Loc loc; 357 char* enum_name; 358 } PrattOp; 359 360 typedef struct { 361 int primary_rule; 362 int primary_prod; 363 PrattOp* ops; 364 size_t nops, cap; 365 } PrattInfo; 366 367 typedef struct { 368 char* name; 369 Str display; 370 Loc loc; 371 } TokenDef; 372 373 typedef struct { 374 char* name; 375 Loc loc; 376 int public_rule; 377 int index; 378 Prod* prods; 379 size_t nprods, cap_prods; 380 PrattInfo* pratt; 381 IntSet first, follow; 382 int nullable; 383 int empty_prod; 384 } Rule; 385 386 typedef struct { 387 char* name; 388 Loc loc; 389 AstLexAlt* alts; 390 int tok; 391 int skip; 392 int seq; 393 int has_literal_key; 394 Str literal_key; 395 int start_anchor; /* KitGramLexAnchor */ 396 int end_anchor; /* KitGramLexAnchor */ 397 } LexRecognizer; 398 399 /* One extracted literal: its bytes and the token kind to rewrite to. */ 400 typedef struct { 401 Str literal; 402 int tok; 403 } LexKeyword; 404 405 /* All literals extracted under one host kind, addressed by a minimal perfect 406 * hash. `slots` holds nslots keywords placed at their hash positions and 407 * `seeds` holds the CHD bucket displacements. Mirrors the runtime 408 * KitGramLexKeywordTable. */ 409 typedef struct { 410 int host; /* host token kind whose lexemes are looked up */ 411 LexKeyword* slots; /* nslots entries; keyword i at its perfect slot */ 412 size_t nslots; 413 uint32_t* seeds; /* nseeds CHD displacements */ 414 size_t nseeds; 415 size_t min_len; 416 size_t max_len; 417 } LexKeywordTable; 418 419 /* A declared %keywords entry, resolved to (lexeme, token) plus its host name 420 * and owning lexer. Collected before parser rules so a parser literal matching 421 * a keyword resolves to its token without creating a DFA recognizer. */ 422 typedef struct { 423 Str literal; 424 int tok; 425 char* host; /* host token name; resolved to a kind in prepare_lexer */ 426 char* group; /* lexer (lex-block) name this keyword belongs to */ 427 Loc loc; 428 } KeywordBinding; 429 430 typedef struct { 431 char* name; 432 Loc loc; 433 LexRecognizer* recognizers; 434 size_t nrecognizers; 435 KitGramLexInputMode input; 436 uint8_t class_of[256]; 437 uint16_t nclasses; 438 uint16_t* trans; 439 uint16_t nstates; 440 uint16_t* accept; 441 /* End-of-match context accepts (zero-width `\z`/`$` edges). NULL when no end 442 * anchors. start_text/start_line are alternate start states for the start-of- 443 * match context (`\A`/`^`); 0 when no start anchors (state 0 serves all). */ 444 uint16_t* accept_text; 445 uint16_t* accept_line; 446 uint16_t start_text; 447 uint16_t start_line; 448 /* Automatic keyword extraction: literals moved out of the DFA, grouped by 449 * host kind (sorted by host, then lexeme). Empty when nothing was extracted. 450 */ 451 LexKeywordTable* keyword_tables; 452 size_t nkeyword_tables; 453 /* ---- Token-machine (%machine) fields; NULL/0 for byte/scalar lexers. ---- 454 * A token machine is a regular language over an abstract symbol alphabet, 455 * compiled codegen-only (it never materializes an KitGramLexGrammar). 456 * class_of[] above is byte-only and unused here; the symbol->class map is 457 * sym_class_of (uint16, NSYM-wide, no 256 cap), and `accept`/`trans` carry 458 * the atom DFA directly (no UTF-8 lowering). Each recognizer is a named rule; 459 * the accept id is the winning rule's source-order index (the kind report). 460 */ 461 int is_machine; 462 uint16_t* sym_class_of; /* nsym symbol -> class id */ 463 uint16_t nsym; /* number of alphabet symbols */ 464 char** sym_names; /* nsym symbol names, by id (first-use order) */ 465 uint8_t* live; /* per state: an accepting state still reachable */ 466 } LexDFA; 467 468 typedef struct { 469 GramgenContext* ctx; 470 ParsedGrammar* pg; 471 Rule* rules; 472 size_t nrules, cap_rules; 473 size_t public_count; 474 TokenDef* tokens; 475 size_t ntokens, cap_tokens; 476 NameIndexMap token_index; 477 NameIndexMap rule_index; 478 /* O(1) lookups keyed by interned-pointer identity (every name/literal is 479 * interned to a canonical pointer, so pointer identity == byte identity). 480 * literal_* key on the literal's interned bytes; decl_name on a token 481 * declaration's name. They replace what were linear scans over these lists. 482 */ 483 NameIndexMap literal_decl_index; /* interned literal -> token_decls index */ 484 NameIndexMap decl_name_index; /* token decl name -> token_decls index */ 485 NameIndexMap kw_literal_index; /* interned literal -> kw_bindings index */ 486 NameIndexMap literal_rec_index; /* interned literal -> literal_recs index */ 487 LexRecognizer* literal_recs; 488 size_t nliteral_recs, cap_literal_recs; 489 KeywordBinding* kw_bindings; /* declared %keywords entries (all lexers) */ 490 size_t nkw_bindings, cap_kw_bindings; 491 LexDFA* lex_dfa; /* main lexer, when present */ 492 LexDFA* lex_dfas; 493 size_t nlex_dfas, cap_lex_dfas; 494 /* Token machines (%machine blocks). Kept separate from lex_dfas so they never 495 * enter the byte/scalar KitGramLexGrammar emission or the TOK_* enum. */ 496 LexDFA* machines; 497 size_t nmachines, cap_machines; 498 IntSet* sets; 499 size_t nsets, cap_sets; 500 Sym** wrapper_syms; 501 size_t nwrapper_syms, cap_wrapper_syms; 502 int rec_seq; 503 int multiline; /* bake newline-aware ^/$ into emitted lexers */ 504 int lexer_standalone; /* emit a self-contained tokenizer + match API, 505 table-free (re2c-style scanner, no runtime link) */ 506 int fold_keywords; /* standalone: fold %keywords into the DFA instead of 507 the default minimal-perfect-hash lookup */ 508 int position_lazy; /* standalone: omit per-token line/col (emit 0) */ 509 int parser_codegen; /* also emit a recursive-descent parser (experimental) */ 510 int parser_recover; /* emit RD error-recovery machinery (opt-in) */ 511 /* Interned Pratt role/kind tokens. line->kind and op->role are interned, so 512 * classification compares against these by pointer identity rather than 513 * strcmp. Interned once in the compile context and carried on the builder, 514 * so codegen (a separate context) compares against them too. */ 515 struct { 516 char *primary, *prefix, *postfix, *infixl, *infixr, *infix, *ternary, 517 *circumfix; 518 } role; 519 } Builder; 520 521 typedef struct { 522 uint32_t lo, hi; 523 } ScalarRange; 524 525 #define UNICODE_MAX_SCALAR 0x10FFFFu 526 #define UNICODE_SURROGATE_FIRST 0xD800u 527 #define UNICODE_SURROGATE_LAST 0xDFFFu 528 529 typedef struct { 530 GramgenContext* ctx; 531 ScalarRange* v; 532 size_t n, cap; 533 } ScalarSet; 534 535 struct ScalarSetCacheEntry { 536 char* key; 537 size_t key_len; 538 uint64_t hash; 539 ScalarSet set; 540 ScalarSetCacheEntry* next; 541 }; 542 543 /* Shared NFA->DFA core (subset construction, minimization, canonical relabel) 544 * used by both the byte and scalar lexer pipelines. */ 545 #include "lex_dfa.h" 546 547 /* Alphabet-neutral range-set NFA + atom partition + determinization, shared by 548 * the utf8 scalar pipeline and the token-alphabet (%machine) pipeline. */ 549 #include "lex_range.h" 550 551 void diag_vset(GramgenContext* ctx, Loc loc, const char* fmt, va_list ap); 552 void diag_set(GramgenContext* ctx, Loc loc, const char* fmt, ...); 553 void die_oom(GramgenContext* ctx); 554 555 void* xmalloc(GramgenContext* ctx, size_t n); 556 void* xrealloc(GramgenContext* ctx, void* p, size_t n); 557 void* xcalloc(GramgenContext* ctx, size_t n, size_t size); 558 void xfree(GramgenContext* ctx, void* p); 559 void mem_release(GramgenMem* m); 560 void scratch_enter(GramgenContext* ctx); /* route x* to the scratch arena */ 561 void scratch_leave(GramgenContext* ctx); /* route x* back to the perm arena */ 562 void scratch_release(GramgenContext* ctx); /* free everything in the scratch */ 563 char* xstrndup(GramgenContext* ctx, const char* s, size_t n); 564 char* xstrdup(GramgenContext* ctx, const char* s); 565 char* xasprintf(GramgenContext* ctx, const char* fmt, ...); 566 567 void buf_init(GramgenContext* ctx, Buf* b); 568 void buf_init_writer(GramgenContext* ctx, Buf* b, KitWriter* writer, 569 const char* path); 570 void buf_reserve(Buf* b, size_t add); 571 void buf_appendn(Buf* b, const char* s, size_t n); 572 void buf_append(Buf* b, const char* s); 573 void buf_append_uint(Buf* b, unsigned v); 574 char* buf_take(Buf* b); 575 576 Str str_from_owned(char* s, size_t len); 577 Str str_dup_len(GramgenContext* ctx, const char* s, size_t len); 578 Str str_dup_c(GramgenContext* ctx, const char* s); 579 int str_eq(Str a, Str b); 580 int str_eq_c(Str a, const char* b); 581 char* str_to_c(GramgenContext* ctx, Str s); 582 char* intern_len(GramgenContext* ctx, const char* s, size_t len); 583 char* intern_c(GramgenContext* ctx, const char* s); 584 int name_index_find(const NameIndexMap* map, const char* key, int* out); 585 void name_index_put(GramgenContext* ctx, NameIndexMap* map, const char* key, 586 int value); 587 588 AstSeq* ast_seq_new(GramgenContext* ctx, Loc loc); 589 AstAlt* ast_alt_new(GramgenContext* ctx, Loc loc); 590 AstNode* ast_node_new(GramgenContext* ctx, AstNodeKind kind, Loc loc); 591 AstLexSeq* ast_lex_seq_new(GramgenContext* ctx, Loc loc); 592 AstLexAlt* ast_lex_alt_new(GramgenContext* ctx, Loc loc); 593 AstLexNode* ast_lex_node_new(GramgenContext* ctx, AstLexNodeKind kind, Loc loc); 594 void ast_seq_append(AstSeq* seq, AstNode* node); 595 void ast_alt_append(AstAlt* alt, AstSeq* seq); 596 void ast_lex_seq_append(AstLexSeq* seq, AstLexNode* node); 597 void ast_lex_alt_append(AstLexAlt* alt, AstLexSeq* seq); 598 599 void kit_gram_error(GramgenContext* ctx, Loc loc, const char* fmt, ...); 600 int hex_val(int c); 601 int is_c_ident_str(Str s); 602 int is_rule_name(const char* name); 603 int is_token_name(const char* name); 604 605 int intset_contains(const IntSet* s, int v); 606 int intset_add(GramgenContext* ctx, IntSet* s, int v); 607 int intset_union(GramgenContext* ctx, IntSet* dst, const IntSet* src); 608 IntSet intset_copy(GramgenContext* ctx, const IntSet* src); 609 int* intset_sorted(GramgenContext* ctx, const IntSet* s); 610 int intset_equal(const IntSet* a, const IntSet* b); 611 int intset_intersection_min(const IntSet* a, const IntSet* b); 612 613 char* c_string_str(GramgenContext* ctx, Str s); 614 char* kit_gram_pratt_prod_enum_name(GramgenContext* ctx, Builder* b, 615 const char* rule_name, const char* role, 616 int tok); 617 618 Builder* kit_gram_builder_new(GramgenContext* ctx, ParsedGrammar* pg); 619 Builder* kit_gram_builder_build(Builder* b); 620 void kit_gram_prepare_lexer(Builder* b); 621 int kit_gram_token_for_ident(Builder* b, const char* name, Loc loc); 622 int kit_gram_next_rec_seq(Builder* b); 623 624 /* Token-alphabet (%machine) compile: desugared `recognizers` (each a named 625 * rule) over an abstract symbol alphabet -> a codegen-only token-machine 626 * LexDFA. Fills is_machine/sym_class_of/nsym/sym_names/live plus the shared 627 * atom DFA tables (nclasses/trans/nstates/accept). `sets` are the machine's 628 * %def lines (LEX_LINE_DEF): a %def whose body is a set doubles as a named 629 * symbol set that a `[ … ]` may reference by lowercase name; resolved and 630 * inlined into the bracket text up front. gen/kit_gram_lex_tokens.c. */ 631 LexDFA* kit_gram_compile_machine(GramgenContext* ctx, const char* name, 632 LexRecognizer* recognizers, size_t nrecognizers, 633 AstLexLine** sets, size_t nsets, Loc loc); 634 635 /* Parse a %machine `[ A B ]` / `[^ A B ]` set node into interned member names; 636 * shared by the NFA leaves and the sampler. *complement set for `[^ … ]`. 637 * Members must be UPPERCASE symbol names: lowercase set references are resolved 638 * and inlined into the bracket text before this runs (see 639 * kit_gram_compile_machine), so reaching one here is a grammar/internal error. 640 */ 641 char* const* kit_gram_machine_class_names(GramgenContext* ctx, Str raw, Loc loc, 642 size_t* nout, int* complement); 643 644 /* In-memory AST-directed sampler for a token machine: generate one valid trace 645 * of rule `which` into out[0..cap) as symbol-name pointers (into m->sym_names); 646 * *n is the produced length (may exceed cap if truncated). Deterministic for a 647 * given *seed (advanced on return). Returns KIT_GRAM_GEN_DONE, or KIT_GRAM_GEN_LIMIT if 648 * max_tokens was hit. Matches the emitted gen_* sampler bit-for-bit. */ 649 KitGramGenStatus kit_gram_machine_sample(GramgenContext* ctx, const LexDFA* m, 650 size_t which, uint64_t* seed, 651 double stop_prob, size_t max_repeat, 652 size_t max_tokens, const char** out, 653 size_t cap, size_t* n); 654 655 ScalarSet kit_gram_scalar_set_universe(GramgenContext* ctx); 656 void kit_gram_scalar_set_require_nonempty(GramgenContext* ctx, 657 const ScalarSet* set, Loc loc); 658 ScalarSet kit_gram_unicode_char_class_set(GramgenContext* ctx, Str raw, Loc loc); 659 ScalarSet kit_gram_unicode_prop_atom_set(GramgenContext* ctx, Str raw, Loc loc); 660 661 #ifndef KIT_GRAM_NO_UNICODE 662 /* utf8 lexer pipeline entry point (gen/kit_gram_lex_scalar.c); the byte driver 663 * in gen/kit_gram_lex_byte.c calls this for %lex :utf8 grammars. */ 664 void kit_gram_compile_lexer_utf8( 665 GramgenContext* ctx, Loc loc, LexRecognizer* recognizers, 666 const size_t* compile_indices, size_t ncompile, uint8_t class_of[256], 667 uint16_t* nclasses_out, uint16_t** trans_out, uint16_t* nstates_out, 668 uint16_t** accept_out, uint16_t** accept_text_out, 669 uint16_t** accept_line_out, uint16_t* start_text_out, 670 uint16_t* start_line_out); 671 #endif 672 673 #endif /* KIT_GRAM_INTERNAL_H */