Skip to main content

meta_language/
parity.rs

1/// Capability tracked for comparison with existing language tooling.
2#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3pub enum ParityCapability {
4    /// Preserve every byte of source text and source metadata.
5    LosslessParsing,
6    /// Preserve and explicitly attach trivia.
7    TriviaPreservation,
8    /// Produce recoverable error and missing links for invalid input.
9    ErrorRecovery,
10    /// Parse mixed-language documents as one links network.
11    MixedLanguageRegions,
12    /// Match syntax patterns with captures and predicates.
13    QueryMatching,
14    /// Transform the network with match-and-substitute rules.
15    TransformBySubstitution,
16    /// Reconstruct text in the same language without losing unchanged regions.
17    SameLanguageReconstruction,
18    /// Reconstruct text in a different language through shared concepts.
19    CrossLanguageReconstruction,
20    /// Round-trip ordinary host objects through LiNo-compatible links.
21    ObjectRoundTrip,
22    /// Evaluate type, meaning, and truth-value links.
23    SemanticEvaluation,
24    /// Formalize and deformalize text through shared meaning links.
25    FormalizationRoundTrip,
26    /// Describe the meta language with links in the same network.
27    SelfDescription,
28    /// Capture immutable snapshots, edit mutable forks, and commit versions.
29    SnapshotVersioning,
30    /// Serialize the whole network to links-notation text and read it back.
31    LinoSerialization,
32}
33
34/// Upstream project whose feature set and tests should be tracked.
35#[derive(Clone, Copy, Debug, PartialEq, Eq)]
36pub struct ParityTarget {
37    name: &'static str,
38    upstream: &'static str,
39    capabilities: &'static [ParityCapability],
40    test_plan: &'static str,
41}
42
43impl ParityTarget {
44    /// Project name.
45    #[must_use]
46    pub const fn name(&self) -> &'static str {
47        self.name
48    }
49
50    /// Upstream project URL.
51    #[must_use]
52    pub const fn upstream(&self) -> &'static str {
53        self.upstream
54    }
55
56    /// Capabilities tracked for parity.
57    #[must_use]
58    pub const fn capabilities(&self) -> &'static [ParityCapability] {
59        self.capabilities
60    }
61
62    /// Test adoption plan for this project.
63    #[must_use]
64    pub const fn test_plan(&self) -> &'static str {
65        self.test_plan
66    }
67}
68
69const QUERY_TRANSFORM_RECONSTRUCT: &[ParityCapability] = &[
70    ParityCapability::QueryMatching,
71    ParityCapability::TransformBySubstitution,
72    ParityCapability::SameLanguageReconstruction,
73];
74const LOSSLESS_RECONSTRUCT: &[ParityCapability] = &[
75    ParityCapability::LosslessParsing,
76    ParityCapability::SameLanguageReconstruction,
77];
78const LOSSLESS_TRIVIA_RECONSTRUCT: &[ParityCapability] = &[
79    ParityCapability::LosslessParsing,
80    ParityCapability::TriviaPreservation,
81    ParityCapability::SameLanguageReconstruction,
82];
83const LOSSLESS_SNAPSHOT: &[ParityCapability] = &[
84    ParityCapability::LosslessParsing,
85    ParityCapability::SnapshotVersioning,
86];
87const FORMALIZATION_CROSS_LANGUAGE: &[ParityCapability] = &[
88    ParityCapability::FormalizationRoundTrip,
89    ParityCapability::CrossLanguageReconstruction,
90];
91
92const fn parity_target(
93    name: &'static str,
94    upstream: &'static str,
95    capabilities: &'static [ParityCapability],
96    test_plan: &'static str,
97) -> ParityTarget {
98    ParityTarget {
99        name,
100        upstream,
101        capabilities,
102        test_plan,
103    }
104}
105
106/// Competitor and ecosystem projects called out by the founding issue.
107pub const PARITY_TARGETS: &[ParityTarget] = &[
108    ParityTarget {
109        name: "tree-sitter",
110        upstream: "https://github.com/tree-sitter/tree-sitter",
111        capabilities: &[
112            ParityCapability::LosslessParsing,
113            ParityCapability::TriviaPreservation,
114            ParityCapability::ErrorRecovery,
115            ParityCapability::MixedLanguageRegions,
116            ParityCapability::QueryMatching,
117        ],
118        test_plan: "Executable fixture covers concrete syntax, injection, query, and recovery behavior.",
119    },
120    ParityTarget {
121        name: "LibCST",
122        upstream: "https://github.com/Instagram/LibCST",
123        capabilities: &[
124            ParityCapability::LosslessParsing,
125            ParityCapability::TriviaPreservation,
126            ParityCapability::ErrorRecovery,
127            ParityCapability::QueryMatching,
128            ParityCapability::TransformBySubstitution,
129            ParityCapability::SameLanguageReconstruction,
130        ],
131        test_plan: "Executable fixture covers Python parse, metadata, transform, and round-trip behavior.",
132    },
133    ParityTarget {
134        name: "Recast",
135        upstream: "https://github.com/benjamn/recast",
136        capabilities: &[
137            ParityCapability::LosslessParsing,
138            ParityCapability::TriviaPreservation,
139            ParityCapability::SameLanguageReconstruction,
140        ],
141        test_plan: "Executable fixture covers JavaScript/TypeScript parse-print preservation behavior.",
142    },
143    ParityTarget {
144        name: "jscodeshift",
145        upstream: "https://github.com/facebook/jscodeshift",
146        capabilities: &[
147            ParityCapability::QueryMatching,
148            ParityCapability::TransformBySubstitution,
149            ParityCapability::SameLanguageReconstruction,
150        ],
151        test_plan: "Executable fixture covers substitution-rule transform behavior.",
152    },
153    ParityTarget {
154        name: "Rowan",
155        upstream: "https://github.com/rust-analyzer/rowan",
156        capabilities: &[
157            ParityCapability::LosslessParsing,
158            ParityCapability::TriviaPreservation,
159            ParityCapability::SameLanguageReconstruction,
160            ParityCapability::SnapshotVersioning,
161        ],
162        test_plan: "Executable fixture covers persistent syntax and trivia preservation behavior.",
163    },
164    ParityTarget {
165        name: "cstree",
166        upstream: "https://github.com/domenicquirl/cstree",
167        capabilities: &[
168            ParityCapability::LosslessParsing,
169            ParityCapability::TriviaPreservation,
170            ParityCapability::SameLanguageReconstruction,
171            ParityCapability::SnapshotVersioning,
172        ],
173        test_plan: "Executable fixture covers Rust concrete syntax and checkpoint behavior.",
174    },
175    ParityTarget {
176        name: "Roslyn",
177        upstream: "https://github.com/dotnet/roslyn",
178        capabilities: &[
179            ParityCapability::LosslessParsing,
180            ParityCapability::TriviaPreservation,
181            ParityCapability::ErrorRecovery,
182            ParityCapability::QueryMatching,
183            ParityCapability::TransformBySubstitution,
184            ParityCapability::SameLanguageReconstruction,
185        ],
186        test_plan: "Executable fixture covers C# syntax, trivia, diagnostics, and formatting behavior.",
187    },
188    ParityTarget {
189        name: "links-notation",
190        upstream: "https://github.com/link-foundation/links-notation",
191        capabilities: &[
192            ParityCapability::LosslessParsing,
193            ParityCapability::ObjectRoundTrip,
194            ParityCapability::SelfDescription,
195            ParityCapability::LinoSerialization,
196        ],
197        test_plan: "Executable fixtures cover doublet, triplet, N-tuple, indented, nested self-reference, and whole-network serialization LiNo behavior.",
198    },
199    ParityTarget {
200        name: "link-cli",
201        upstream: "https://github.com/link-foundation/link-cli",
202        capabilities: &[ParityCapability::TransformBySubstitution],
203        test_plan: "Executable fixtures cover create, update, delete, and swap substitution behavior.",
204    },
205    ParityTarget {
206        name: "lino-objects-codec",
207        upstream: "https://github.com/link-foundation/lino-objects-codec",
208        capabilities: &[ParityCapability::ObjectRoundTrip],
209        test_plan: "Executable fixture covers encode/decode, identity, shared-reference, and circular-reference behavior.",
210    },
211    ParityTarget {
212        name: "relative-meta-logic",
213        upstream: "https://github.com/link-foundation/relative-meta-logic",
214        capabilities: &[
215            ParityCapability::SemanticEvaluation,
216            ParityCapability::SelfDescription,
217        ],
218        test_plan: "Executable fixture covers dependent-type, many-valued, probabilistic, and paradox behavior.",
219    },
220    ParityTarget {
221        name: "formal-ai",
222        upstream: "https://github.com/link-assistant/formal-ai",
223        capabilities: &[
224            ParityCapability::FormalizationRoundTrip,
225            ParityCapability::SemanticEvaluation,
226            ParityCapability::CrossLanguageReconstruction,
227        ],
228        test_plan: "Executable fixtures cover actual data/seed/*.lino and data/benchmarks/*.lino corpus sources plus cross-language reconstruction behavior.",
229    },
230    ParityTarget {
231        name: "meta-expression",
232        upstream: "https://github.com/link-assistant/meta-expression",
233        capabilities: &[
234            ParityCapability::FormalizationRoundTrip,
235            ParityCapability::TriviaPreservation,
236            ParityCapability::CrossLanguageReconstruction,
237        ],
238        test_plan: "Executable fixtures cover Hawaii naturalization, 1 + 1 formalization, self-reference behavior, and the verified 351-concept lexicon.",
239    },
240    parity_target(
241        "ast-grep",
242        "https://github.com/ast-grep/ast-grep",
243        QUERY_TRANSFORM_RECONSTRUCT,
244        "Executable fixture covers structural rule-test-style matching and replacement.",
245    ),
246    parity_target(
247        "Semgrep",
248        "https://github.com/semgrep/semgrep",
249        QUERY_TRANSFORM_RECONSTRUCT,
250        "Executable fixture covers pattern-corpus-style matching and autofix replacement.",
251    ),
252    parity_target(
253        "Comby",
254        "https://github.com/comby-tools/comby",
255        QUERY_TRANSFORM_RECONSTRUCT,
256        "Executable fixture covers structural search-and-replace over original source bytes.",
257    ),
258    parity_target(
259        "GritQL",
260        "https://github.com/getgrit/gritql",
261        QUERY_TRANSFORM_RECONSTRUCT,
262        "Executable fixture covers snippet-pattern matching and rewrite effects.",
263    ),
264    parity_target(
265        "srcML",
266        "https://github.com/srcML/srcML",
267        LOSSLESS_TRIVIA_RECONSTRUCT,
268        "Executable fixture covers XML source-markup round-trip behavior.",
269    ),
270    parity_target(
271        "difftastic",
272        "https://github.com/Wilfred/difftastic",
273        LOSSLESS_SNAPSHOT,
274        "Executable fixture covers syntax-aware source snapshots used for structural diffing.",
275    ),
276    parity_target(
277        "Babel",
278        "https://github.com/babel/babel",
279        QUERY_TRANSFORM_RECONSTRUCT,
280        "Executable fixture covers parser-fixture-style JavaScript transform behavior.",
281    ),
282    parity_target(
283        "SWC",
284        "https://github.com/swc-project/swc",
285        LOSSLESS_RECONSTRUCT,
286        "Executable fixture covers TypeScript parser corpus round-trip behavior.",
287    ),
288    parity_target(
289        "OpenRewrite",
290        "https://github.com/openrewrite/rewrite",
291        QUERY_TRANSFORM_RECONSTRUCT,
292        "Executable fixture covers before/after recipe-style Java source replacement.",
293    ),
294    parity_target(
295        "Spoon",
296        "https://github.com/INRIA/spoon",
297        QUERY_TRANSFORM_RECONSTRUCT,
298        "Executable fixture covers template-style Java source replacement.",
299    ),
300    parity_target(
301        "JavaParser",
302        "https://github.com/javaparser/javaparser",
303        QUERY_TRANSFORM_RECONSTRUCT,
304        "Executable fixture covers lexical-preserving Java replacement.",
305    ),
306    parity_target(
307        "Rascal",
308        "https://github.com/usethesource/rascal",
309        LOSSLESS_RECONSTRUCT,
310        "Executable fixture covers in-language syntax-test source round-trip behavior.",
311    ),
312    parity_target(
313        "Stratego/Spoofax",
314        "https://github.com/metaborg/spoofax",
315        QUERY_TRANSFORM_RECONSTRUCT,
316        "Executable fixture covers SPT-style embedded-fragment replacement.",
317    ),
318    parity_target(
319        "TXL",
320        "https://www.txl.ca",
321        QUERY_TRANSFORM_RECONSTRUCT,
322        "Executable fixture covers by-example C source transformation.",
323    ),
324    parity_target(
325        "MPS",
326        "https://github.com/JetBrains/MPS",
327        &[
328            ParityCapability::ObjectRoundTrip,
329            ParityCapability::SelfDescription,
330        ],
331        "Executable fixture covers projectional model serialization as source data.",
332    ),
333    parity_target(
334        "Coccinelle",
335        "https://github.com/coccinelle/coccinelle",
336        QUERY_TRANSFORM_RECONSTRUCT,
337        "Executable fixture covers input/semantic-patch/result triple transform behavior.",
338    ),
339    parity_target(
340        "GF",
341        "https://github.com/GrammaticalFramework/gf-rgl",
342        FORMALIZATION_CROSS_LANGUAGE,
343        "Executable fixture covers grammar parse/linearization-style formalization.",
344    ),
345    parity_target(
346        "Universal Dependencies",
347        "https://universaldependencies.org",
348        &[ParityCapability::LosslessParsing],
349        "Executable fixture covers UD morphosyntax vocabulary links over natural-language text.",
350    ),
351    parity_target(
352        "LanguageTool",
353        "https://github.com/languagetool-org/languagetool",
354        &[ParityCapability::ErrorRecovery],
355        "Executable fixture covers negative grammar-rule example recovery.",
356    ),
357    parity_target(
358        "doublets-rs",
359        "https://github.com/linksplatform/doublets-rs",
360        &[
361            ParityCapability::ObjectRoundTrip,
362            ParityCapability::SnapshotVersioning,
363        ],
364        "Executable fixture covers binary doublets storage round-trip gates.",
365    ),
366];
367
368/// Expected verification result for an executable parity fixture.
369#[derive(Clone, Copy, Debug, PartialEq, Eq)]
370pub enum ParityVerificationExpectation {
371    /// Fixture should parse without recovery diagnostics.
372    Clean,
373    /// Fixture should round-trip while exposing recovery diagnostics.
374    Recoverable,
375}
376
377/// Text transform expectation attached to a query/transform parity fixture.
378#[derive(Clone, Copy, Debug, PartialEq, Eq)]
379pub struct ParityTransformExpectation {
380    pub(crate) query: &'static str,
381    pub(crate) capture_name: &'static str,
382    pub(crate) replacement: &'static str,
383    pub(crate) expected_output: &'static str,
384}
385
386impl ParityTransformExpectation {
387    /// Query used to select the links to replace.
388    #[must_use]
389    pub const fn query(&self) -> &'static str {
390        self.query
391    }
392
393    /// Capture name whose source text should be replaced.
394    #[must_use]
395    pub const fn capture_name(&self) -> &'static str {
396        self.capture_name
397    }
398
399    /// Replacement source text.
400    #[must_use]
401    pub const fn replacement(&self) -> &'static str {
402        self.replacement
403    }
404
405    /// Expected reconstructed source after applying the transform.
406    #[must_use]
407    pub const fn expected_output(&self) -> &'static str {
408        self.expected_output
409    }
410}
411
412/// Executable source fixture tied to a parity target.
413#[derive(Clone, Copy, Debug, PartialEq, Eq)]
414pub struct ParityFixture {
415    pub(crate) target_name: &'static str,
416    pub(crate) name: &'static str,
417    pub(crate) language: &'static str,
418    pub(crate) source: &'static str,
419    pub(crate) expected_reconstruction: &'static str,
420    pub(crate) provenance: &'static str,
421    pub(crate) verification_expectation: ParityVerificationExpectation,
422    pub(crate) transform_expectation: Option<ParityTransformExpectation>,
423    pub(crate) capabilities: &'static [ParityCapability],
424}
425
426impl ParityFixture {
427    /// Target project name.
428    #[must_use]
429    pub const fn target_name(&self) -> &'static str {
430        self.target_name
431    }
432
433    /// Fixture name.
434    #[must_use]
435    pub const fn name(&self) -> &'static str {
436        self.name
437    }
438
439    /// Source language label used by the parser.
440    #[must_use]
441    pub const fn language(&self) -> &'static str {
442        self.language
443    }
444
445    /// Source text exercised by the fixture.
446    #[must_use]
447    pub const fn source(&self) -> &'static str {
448        self.source
449    }
450
451    /// Expected lossless reconstruction.
452    #[must_use]
453    pub const fn expected_reconstruction(&self) -> &'static str {
454        self.expected_reconstruction
455    }
456
457    /// Upstream source path and license for this ported fixture.
458    #[must_use]
459    pub const fn provenance(&self) -> &'static str {
460        self.provenance
461    }
462
463    /// Expected verification result after parsing this fixture.
464    #[must_use]
465    pub const fn verification_expectation(&self) -> ParityVerificationExpectation {
466        self.verification_expectation
467    }
468
469    /// Optional query/transform assertion for this fixture.
470    #[must_use]
471    pub const fn transform_expectation(&self) -> Option<ParityTransformExpectation> {
472        self.transform_expectation
473    }
474
475    /// Capabilities exercised by this fixture.
476    #[must_use]
477    pub const fn capabilities(&self) -> &'static [ParityCapability] {
478        self.capabilities
479    }
480
481    /// Parity target for this fixture.
482    #[must_use]
483    pub fn target(&self) -> &'static ParityTarget {
484        PARITY_TARGETS
485            .iter()
486            .find(|target| target.name() == self.target_name)
487            .expect("parity fixture target must exist")
488    }
489}
490
491pub use crate::parity_fixtures::PARITY_FIXTURES;
492
493/// Family of language coverage targets.
494#[derive(Clone, Copy, Debug, PartialEq, Eq)]
495pub enum LanguageFamily {
496    /// Markup or document container languages.
497    Markup,
498    /// Programming languages.
499    Programming,
500    /// Natural languages.
501    Natural,
502    /// Data-exchange / interchange formats.
503    DataFormat,
504}
505
506/// Language whose grammar or natural-language parser should be supported.
507#[derive(Clone, Copy, Debug, PartialEq, Eq)]
508pub struct LanguageTarget {
509    name: &'static str,
510    family: LanguageFamily,
511    basis: &'static str,
512}
513
514impl LanguageTarget {
515    /// Language name.
516    #[must_use]
517    pub const fn name(&self) -> &'static str {
518        self.name
519    }
520
521    /// Language family.
522    #[must_use]
523    pub const fn family(&self) -> LanguageFamily {
524        self.family
525    }
526
527    /// Basis for including this target.
528    #[must_use]
529    pub const fn basis(&self) -> &'static str {
530        self.basis
531    }
532}
533
534const DATA_FORMAT_BASIS: &str = "Issue #47 R-3 data-exchange format target";
535const SCHEMA_BASIS: &str = "Issue #47 R-4 schema/interface-definition target";
536
537const fn language_target(
538    name: &'static str,
539    family: LanguageFamily,
540    basis: &'static str,
541) -> LanguageTarget {
542    LanguageTarget {
543        name,
544        family,
545        basis,
546    }
547}
548
549/// Executable lossless parse fixture for a required language target.
550#[derive(Clone, Copy, Debug, PartialEq, Eq)]
551pub struct LanguageFixture {
552    pub(crate) language: &'static str,
553    pub(crate) source: &'static str,
554    pub(crate) description: &'static str,
555}
556
557impl LanguageFixture {
558    /// Language label used by the parser.
559    #[must_use]
560    pub const fn language(&self) -> &'static str {
561        self.language
562    }
563
564    /// Source text that must parse and reconstruct losslessly.
565    #[must_use]
566    pub const fn source(&self) -> &'static str {
567        self.source
568    }
569
570    /// Behavior represented by this fixture.
571    #[must_use]
572    pub const fn description(&self) -> &'static str {
573        self.description
574    }
575}
576
577/// Required document-container languages.
578pub const MARKUP_LANGUAGE_TARGETS: &[LanguageTarget] = &[
579    language_target(
580        "txt",
581        LanguageFamily::Markup,
582        "Issue #5 degenerate plain-text container target",
583    ),
584    language_target(
585        "Markdown",
586        LanguageFamily::Markup,
587        "Founding issue full-document target",
588    ),
589    language_target(
590        "HTML",
591        LanguageFamily::Markup,
592        "Founding issue full-document target",
593    ),
594    language_target(
595        "PDF",
596        LanguageFamily::Markup,
597        "Issue #84 binary document container target (text PDF profile)",
598    ),
599    language_target(
600        "DOCX",
601        LanguageFamily::Markup,
602        "Issue #85 OOXML document container target (DOCX OPC profile)",
603    ),
604];
605
606/// Required data-exchange / interchange format targets.
607///
608/// Each entry has a wired parser and a round-trip [`LANGUAGE_FIXTURES`] entry.
609/// JSON, YAML, TOML, XML, INI, protobuf, and GraphQL use tree-sitter grammars;
610/// CSV and JSON5 use small lossless parsers because their published
611/// tree-sitter bindings still target the incompatible `tree-sitter ~0.20` ABI.
612pub const DATA_FORMAT_TARGETS: &[LanguageTarget] = &[
613    language_target("JSON", LanguageFamily::DataFormat, DATA_FORMAT_BASIS),
614    language_target("YAML", LanguageFamily::DataFormat, DATA_FORMAT_BASIS),
615    language_target("TOML", LanguageFamily::DataFormat, DATA_FORMAT_BASIS),
616    language_target("XML", LanguageFamily::DataFormat, DATA_FORMAT_BASIS),
617    language_target("INI", LanguageFamily::DataFormat, DATA_FORMAT_BASIS),
618    language_target("protobuf", LanguageFamily::DataFormat, DATA_FORMAT_BASIS),
619    language_target("GraphQL", LanguageFamily::DataFormat, SCHEMA_BASIS),
620    language_target("CSV", LanguageFamily::DataFormat, DATA_FORMAT_BASIS),
621    language_target("JSON5", LanguageFamily::DataFormat, DATA_FORMAT_BASIS),
622];
623
624/// Initial top-ten programming-language parser targets.
625pub const PROGRAMMING_LANGUAGE_TARGETS: &[LanguageTarget] = &[
626    LanguageTarget {
627        name: "Python",
628        family: LanguageFamily::Programming,
629        basis: "TIOBE May 2026 top 10",
630    },
631    LanguageTarget {
632        name: "C",
633        family: LanguageFamily::Programming,
634        basis: "TIOBE May 2026 top 10",
635    },
636    LanguageTarget {
637        name: "Java",
638        family: LanguageFamily::Programming,
639        basis: "TIOBE May 2026 top 10",
640    },
641    LanguageTarget {
642        name: "C++",
643        family: LanguageFamily::Programming,
644        basis: "TIOBE May 2026 top 10",
645    },
646    LanguageTarget {
647        name: "C#",
648        family: LanguageFamily::Programming,
649        basis: "TIOBE May 2026 top 10",
650    },
651    LanguageTarget {
652        name: "JavaScript",
653        family: LanguageFamily::Programming,
654        basis: "TIOBE May 2026 top 10",
655    },
656    LanguageTarget {
657        name: "Visual Basic",
658        family: LanguageFamily::Programming,
659        basis: "TIOBE May 2026 top 10",
660    },
661    LanguageTarget {
662        name: "R",
663        family: LanguageFamily::Programming,
664        basis: "TIOBE May 2026 top 10",
665    },
666    LanguageTarget {
667        name: "sql-ansi",
668        family: LanguageFamily::Programming,
669        basis: "TIOBE May 2026 top 10 SQL family baseline dialect",
670    },
671    LanguageTarget {
672        name: "Delphi/Object Pascal",
673        family: LanguageFamily::Programming,
674        basis: "TIOBE May 2026 top 10",
675    },
676];
677
678/// Second-tier programming-language parser targets immediately below the TIOBE
679/// top ten.
680///
681/// Each entry has a wired tree-sitter grammar in `src/tree_sitter_adapter.rs`
682/// and a round-trip [`LANGUAGE_FIXTURES`] entry.
683pub const SECOND_TIER_PROGRAMMING_LANGUAGE_TARGETS: &[LanguageTarget] = &[
684    LanguageTarget {
685        name: "PHP",
686        family: LanguageFamily::Programming,
687        basis: "Issue #47 R-2 popular language immediately below the TIOBE top 10",
688    },
689    LanguageTarget {
690        name: "Swift",
691        family: LanguageFamily::Programming,
692        basis: "Issue #47 R-2 popular language immediately below the TIOBE top 10",
693    },
694    LanguageTarget {
695        name: "Kotlin",
696        family: LanguageFamily::Programming,
697        basis: "Issue #47 R-2 popular language immediately below the TIOBE top 10",
698    },
699    LanguageTarget {
700        name: "Scala",
701        family: LanguageFamily::Programming,
702        basis: "Issue #47 R-2 popular language immediately below the TIOBE top 10",
703    },
704    LanguageTarget {
705        name: "Lua",
706        family: LanguageFamily::Programming,
707        basis: "Issue #47 R-2 popular language immediately below the TIOBE top 10",
708    },
709    LanguageTarget {
710        name: "Perl",
711        family: LanguageFamily::Programming,
712        basis: "Issue #47 R-2 popular language immediately below the TIOBE top 10; issue #70 Perl grammar follow-up resolved via ts-parser-perl",
713    },
714];
715
716/// Initial top-ten natural-language parser targets in Ethnologue 2025 total-speaker order.
717pub const NATURAL_LANGUAGE_TARGETS: &[LanguageTarget] = &[
718    LanguageTarget {
719        name: "English",
720        family: LanguageFamily::Natural,
721        basis: "Ethnologue/Britannica total-speaker top 10",
722    },
723    LanguageTarget {
724        name: "Mandarin Chinese",
725        family: LanguageFamily::Natural,
726        basis: "Ethnologue/Britannica total-speaker top 10",
727    },
728    LanguageTarget {
729        name: "Hindi",
730        family: LanguageFamily::Natural,
731        basis: "Ethnologue/Britannica total-speaker top 10",
732    },
733    LanguageTarget {
734        name: "Spanish",
735        family: LanguageFamily::Natural,
736        basis: "Ethnologue/Britannica total-speaker top 10",
737    },
738    LanguageTarget {
739        name: "Modern Standard Arabic",
740        family: LanguageFamily::Natural,
741        basis: "Ethnologue/Britannica total-speaker top 10",
742    },
743    LanguageTarget {
744        name: "French",
745        family: LanguageFamily::Natural,
746        basis: "Ethnologue/Britannica total-speaker top 10",
747    },
748    LanguageTarget {
749        name: "Bengali",
750        family: LanguageFamily::Natural,
751        basis: "Ethnologue/Britannica total-speaker top 10",
752    },
753    LanguageTarget {
754        name: "Portuguese",
755        family: LanguageFamily::Natural,
756        basis: "Ethnologue/Britannica total-speaker top 10",
757    },
758    LanguageTarget {
759        name: "Russian",
760        family: LanguageFamily::Natural,
761        basis: "Ethnologue/Britannica total-speaker top 10",
762    },
763    LanguageTarget {
764        name: "Urdu",
765        family: LanguageFamily::Natural,
766        basis: "Ethnologue/Britannica total-speaker top 10",
767    },
768];
769
770pub use crate::language_fixtures::LANGUAGE_FIXTURES;
771
772/// Mixed-grammar embedding case that must become one unified links network.
773#[derive(Clone, Copy, Debug, PartialEq, Eq)]
774pub struct GrammarEmbeddingTarget {
775    host_language: &'static str,
776    embedded_language: &'static str,
777    trigger: &'static str,
778}
779
780impl GrammarEmbeddingTarget {
781    /// Host language containing the embedded region.
782    #[must_use]
783    pub const fn host_language(&self) -> &'static str {
784        self.host_language
785    }
786
787    /// Embedded region language or language family.
788    #[must_use]
789    pub const fn embedded_language(&self) -> &'static str {
790        self.embedded_language
791    }
792
793    /// Detection trigger or boundary.
794    #[must_use]
795    pub const fn trigger(&self) -> &'static str {
796        self.trigger
797    }
798}
799
800/// Initial mixed-grammar coverage targets.
801pub const GRAMMAR_EMBEDDING_TARGETS: &[GrammarEmbeddingTarget] = &[
802    GrammarEmbeddingTarget {
803        host_language: "Markdown",
804        embedded_language: "Programming language region",
805        trigger: "fenced code language tag",
806    },
807    GrammarEmbeddingTarget {
808        host_language: "Markdown",
809        embedded_language: "HTML",
810        trigger: "inline or block HTML",
811    },
812    GrammarEmbeddingTarget {
813        host_language: "HTML",
814        embedded_language: "JavaScript",
815        trigger: "script element",
816    },
817    GrammarEmbeddingTarget {
818        host_language: "HTML",
819        embedded_language: "CSS",
820        trigger: "style element or style attribute",
821    },
822];