| Modernisation | ✅ | .NET 10 / C# 14 / AOT, byte-DFA lexer pipeline (PipeBytesLexer), xUnit v3 on MTP, fail-fast diagnostics across all layers (GrammarConflictException, LexerException, ParseErrorException), Item.SourcePosition. |
| Schema layer (1) | ✅ | Schema/GrammarSchema.cs POCOs, Schema/IRxParser.cs regex dialect, Schema/SchemaCompiler.cs. Pure C# data → (Grammar, LexRule[]). |
| Source generator (2) | ✅ | LALR.CC.SourceGenerators — Roslyn IIncrementalGenerator consumes *.lalr.yaml AdditionalFiles, emits <ClassName>.g.cs with GrammarSchema Schema { get; }. YamlDotNet build-time only. |
| Typed AST (3a) | ✅ | AstEmitter writes <ClassName>.Ast.g.cs — public sealed record <Action>(Item Arg0, …) per distinct action. Arity conflicts surface as LALR0002. |
| Visitor + wiring (3b) | ✅ | VisitorEmitter writes <ClassName>.Visitor.g.cs — nested IVisitor with one Visit(<Record>) overload per action. BuildActions(IVisitor) constructs the record from the parser's reduction frame and dispatches by C# overload resolution. |
| Self-host (4) | ✅ | Bootstrap.Stage1/ consumes bnf.lalr.yaml end-to-end. Bootstrap/ (stage0) keeps the inline grammar as the no-generator-no-YAML reference; both produce byte-identical Accept output. |
| JSON example | ✅ | examples/Json/ parses real JSON with a 50-line visitor that builds Dictionary<string,object> / List<object> / primitives. Demonstrates the pipeline on a grammar nobody designed for this parser. |
| NuGet packaging + CI | ✅ | Runtime project packs LALR.CC.{nupkg,snupkg} with the source generator + YamlDotNet bundled in analyzers/dotnet/cs/ (so PackageReference consumers don't need the analyzer-DLL workaround). Deterministic + SourceLink + symbols. .github/workflows/dotnet.yml builds + tests + stage-parity-checks on push, packs + uploads artifact on master, publishes to NuGet on v* tag using NUGET_API_KEY (SharpAstro org-level secret). |
| 2.1.0 features | ✅ | (a) SourcePosition.GetCodepointColumn(ReadOnlySpan<byte> source) for diagnostics-quality non-ASCII columns. (b) Generic IVisitor<out T> + BuildActions<T> so evaluators can return typed values directly (IVisitor<int> etc.) instead of always boxing to object. (c) LALR0003 Roslyn diagnostics from a generator-side SchemaValidator — unknown symbol refs, missing root state, duplicate symbols, mutually-exclusive lexer instructions surface at build time instead of runtime. |
| LaTeX rich-render example | ✅ | examples/Latex.Grammar/ (shared Latex partial class — generator runs once) feeds examples/Latex/ (Unicode-string visitor; PublishAot=true). The box-layout / sixel renderer that previously lived as examples/LatexConsole/ moved to sharpastro/Console.Lib/examples/LatexConsole/ so Console.Lib can take a build-time dep on LALR.CC without forming a cycle. |
lalr-tui debugger | ✅ | Tui/LALR.CC.Tui.csproj (alias lalr-tui). Loads *.lalr.yaml live, runs SchemaCompiler + builds the Parser, displays grammar / lexer rules / token stream / parse-table cells in a Console.Lib dock layout. AOT-off because YamlDotNet runtime deserializer needs reflection — Phase 5 doesn't unblock this (Tui edits arbitrary YAML at runtime, so YamlDotNet stays). |
| Phase 5 / slice 1 (compiler-compiler) | ✅ | Parser.cs table-construction extracted into ParserTableBuilder.cs — pure C#, no LexicalGrammar dependency, identical public API on Parser (delegates via passthrough). Sets up the netstandard2.0 link path for slice 2. Also tightened all introspection-property types from IList<> / ICollection<> / ISet<> / HashSet<int>[] to IReadOnly* (or concrete HashSet<int> for the IReadOnlySet-needing ones, since the latter is .NET 5+ and the builder will be linked into netstandard2.0). |
| Phase 5 / slice 2 (compiler-compiler) | ✅ | ParserTableBuilder + dependencies (Grammar, ParseTable, LRItems, GrammarConflict, SymbolName) now <Compile Link>-shared into the netstandard2.0 source generator. Required: extracting Reduction to its own file, splitting Production into a partial readonly struct (linkable partial owns Left/Right/HasRewriter + Delegate? storage; runtime partial in Production.Rewriter.cs adds the strongly-typed Func<int, Item[], object> ctor + Rewrite()), and replacing HashCode.Combine (netstandard 2.1+) with a manual fold. Generator can now run table-build at compile time. |
| Phase 5 / slice 3 (compiler-compiler) | ✅ | New TablesEmitter runs ParserTableBuilder at build time and emits <Name>.Tables.g.cs with Definition (Grammar literal), ParseTable (Action[,] literal), and BuildParser() factory. New Parser(Grammar, ParseTable) ctor skips table-build (introspection getters throw NotSupportedException on this path; Productions/NonTerminals derived directly from Grammar). New LALR0004 Roslyn diagnostic surfaces unresolved S/R + R/R conflicts at build time with YAML locator (replaces GrammarConflictException for pre-baked consumers). 306/306 tests, stage parity holds. Action-free BuildParser() only — visitor-aware overload is slice 4. |