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        &[ParityCapability::ObjectRoundTrip, ParityCapability::SelfDescription],
328        "Executable fixture covers projectional model serialization as source data.",
329    ),
330    parity_target(
331        "Coccinelle",
332        "https://github.com/coccinelle/coccinelle",
333        QUERY_TRANSFORM_RECONSTRUCT,
334        "Executable fixture covers input/semantic-patch/result triple transform behavior.",
335    ),
336    parity_target(
337        "GF",
338        "https://github.com/GrammaticalFramework/gf-rgl",
339        FORMALIZATION_CROSS_LANGUAGE,
340        "Executable fixture covers grammar parse/linearization-style formalization.",
341    ),
342    parity_target(
343        "Universal Dependencies",
344        "https://universaldependencies.org",
345        &[ParityCapability::LosslessParsing],
346        "Executable fixture covers UD morphosyntax vocabulary links over natural-language text.",
347    ),
348    parity_target(
349        "LanguageTool",
350        "https://github.com/languagetool-org/languagetool",
351        &[ParityCapability::ErrorRecovery],
352        "Executable fixture covers negative grammar-rule example recovery.",
353    ),
354    parity_target(
355        "doublets-rs",
356        "https://github.com/linksplatform/doublets-rs",
357        &[ParityCapability::ObjectRoundTrip, ParityCapability::SnapshotVersioning],
358        "Executable fixture covers binary doublets storage round-trip gates.",
359    ),
360];
361
362/// Expected verification result for an executable parity fixture.
363#[derive(Clone, Copy, Debug, PartialEq, Eq)]
364pub enum ParityVerificationExpectation {
365    /// Fixture should parse without recovery diagnostics.
366    Clean,
367    /// Fixture should round-trip while exposing recovery diagnostics.
368    Recoverable,
369}
370
371/// Text transform expectation attached to a query/transform parity fixture.
372#[derive(Clone, Copy, Debug, PartialEq, Eq)]
373pub struct ParityTransformExpectation {
374    pub(crate) query: &'static str,
375    pub(crate) capture_name: &'static str,
376    pub(crate) replacement: &'static str,
377    pub(crate) expected_output: &'static str,
378}
379
380impl ParityTransformExpectation {
381    /// Query used to select the links to replace.
382    #[must_use]
383    pub const fn query(&self) -> &'static str {
384        self.query
385    }
386
387    /// Capture name whose source text should be replaced.
388    #[must_use]
389    pub const fn capture_name(&self) -> &'static str {
390        self.capture_name
391    }
392
393    /// Replacement source text.
394    #[must_use]
395    pub const fn replacement(&self) -> &'static str {
396        self.replacement
397    }
398
399    /// Expected reconstructed source after applying the transform.
400    #[must_use]
401    pub const fn expected_output(&self) -> &'static str {
402        self.expected_output
403    }
404}
405
406/// Executable source fixture tied to a parity target.
407#[derive(Clone, Copy, Debug, PartialEq, Eq)]
408pub struct ParityFixture {
409    pub(crate) target_name: &'static str,
410    pub(crate) name: &'static str,
411    pub(crate) language: &'static str,
412    pub(crate) source: &'static str,
413    pub(crate) expected_reconstruction: &'static str,
414    pub(crate) provenance: &'static str,
415    pub(crate) verification_expectation: ParityVerificationExpectation,
416    pub(crate) transform_expectation: Option<ParityTransformExpectation>,
417    pub(crate) capabilities: &'static [ParityCapability],
418}
419
420impl ParityFixture {
421    /// Target project name.
422    #[must_use]
423    pub const fn target_name(&self) -> &'static str {
424        self.target_name
425    }
426
427    /// Fixture name.
428    #[must_use]
429    pub const fn name(&self) -> &'static str {
430        self.name
431    }
432
433    /// Source language label used by the parser.
434    #[must_use]
435    pub const fn language(&self) -> &'static str {
436        self.language
437    }
438
439    /// Source text exercised by the fixture.
440    #[must_use]
441    pub const fn source(&self) -> &'static str {
442        self.source
443    }
444
445    /// Expected lossless reconstruction.
446    #[must_use]
447    pub const fn expected_reconstruction(&self) -> &'static str {
448        self.expected_reconstruction
449    }
450
451    /// Upstream source path and license for this ported fixture.
452    #[must_use]
453    pub const fn provenance(&self) -> &'static str {
454        self.provenance
455    }
456
457    /// Expected verification result after parsing this fixture.
458    #[must_use]
459    pub const fn verification_expectation(&self) -> ParityVerificationExpectation {
460        self.verification_expectation
461    }
462
463    /// Optional query/transform assertion for this fixture.
464    #[must_use]
465    pub const fn transform_expectation(&self) -> Option<ParityTransformExpectation> {
466        self.transform_expectation
467    }
468
469    /// Capabilities exercised by this fixture.
470    #[must_use]
471    pub const fn capabilities(&self) -> &'static [ParityCapability] {
472        self.capabilities
473    }
474
475    /// Parity target for this fixture.
476    #[must_use]
477    pub fn target(&self) -> &'static ParityTarget {
478        PARITY_TARGETS
479            .iter()
480            .find(|target| target.name() == self.target_name)
481            .expect("parity fixture target must exist")
482    }
483}
484
485pub use crate::parity_fixtures::PARITY_FIXTURES;
486
487/// Family of language coverage targets.
488#[derive(Clone, Copy, Debug, PartialEq, Eq)]
489pub enum LanguageFamily {
490    /// Markup or document container languages.
491    Markup,
492    /// Programming languages.
493    Programming,
494    /// Natural languages.
495    Natural,
496    /// Data-exchange / interchange formats.
497    DataFormat,
498}
499
500/// Language whose grammar or natural-language parser should be supported.
501#[derive(Clone, Copy, Debug, PartialEq, Eq)]
502pub struct LanguageTarget {
503    name: &'static str,
504    family: LanguageFamily,
505    basis: &'static str,
506}
507
508impl LanguageTarget {
509    /// Language name.
510    #[must_use]
511    pub const fn name(&self) -> &'static str {
512        self.name
513    }
514
515    /// Language family.
516    #[must_use]
517    pub const fn family(&self) -> LanguageFamily {
518        self.family
519    }
520
521    /// Basis for including this target.
522    #[must_use]
523    pub const fn basis(&self) -> &'static str {
524        self.basis
525    }
526}
527
528const DATA_FORMAT_BASIS: &str = "Issue #47 R-3 data-exchange format target";
529const SCHEMA_BASIS: &str = "Issue #47 R-4 schema/interface-definition target";
530
531const fn language_target(
532    name: &'static str,
533    family: LanguageFamily,
534    basis: &'static str,
535) -> LanguageTarget {
536    LanguageTarget {
537        name,
538        family,
539        basis,
540    }
541}
542
543/// Executable lossless parse fixture for a required language target.
544#[derive(Clone, Copy, Debug, PartialEq, Eq)]
545pub struct LanguageFixture {
546    pub(crate) language: &'static str,
547    pub(crate) source: &'static str,
548    pub(crate) description: &'static str,
549}
550
551impl LanguageFixture {
552    /// Language label used by the parser.
553    #[must_use]
554    pub const fn language(&self) -> &'static str {
555        self.language
556    }
557
558    /// Source text that must parse and reconstruct losslessly.
559    #[must_use]
560    pub const fn source(&self) -> &'static str {
561        self.source
562    }
563
564    /// Behavior represented by this fixture.
565    #[must_use]
566    pub const fn description(&self) -> &'static str {
567        self.description
568    }
569}
570
571/// Required document-container languages.
572pub const MARKUP_LANGUAGE_TARGETS: &[LanguageTarget] = &[
573    language_target(
574        "txt",
575        LanguageFamily::Markup,
576        "Issue #5 degenerate plain-text container target",
577    ),
578    language_target(
579        "Markdown",
580        LanguageFamily::Markup,
581        "Founding issue full-document target",
582    ),
583    language_target(
584        "HTML",
585        LanguageFamily::Markup,
586        "Founding issue full-document target",
587    ),
588    language_target(
589        "PDF",
590        LanguageFamily::Markup,
591        "Issue #84 binary document container target (text PDF profile)",
592    ),
593    language_target(
594        "DOCX",
595        LanguageFamily::Markup,
596        "Issue #85 OOXML document container target (DOCX OPC profile)",
597    ),
598];
599
600/// Required data-exchange / interchange format targets.
601///
602/// Each entry has a wired parser and a round-trip [`LANGUAGE_FIXTURES`] entry.
603/// JSON, YAML, TOML, XML, INI, protobuf, and GraphQL use tree-sitter grammars;
604/// CSV and JSON5 use small lossless parsers because their published
605/// tree-sitter bindings still target the incompatible `tree-sitter ~0.20` ABI.
606pub const DATA_FORMAT_TARGETS: &[LanguageTarget] = &[
607    language_target("JSON", LanguageFamily::DataFormat, DATA_FORMAT_BASIS),
608    language_target("YAML", LanguageFamily::DataFormat, DATA_FORMAT_BASIS),
609    language_target("TOML", LanguageFamily::DataFormat, DATA_FORMAT_BASIS),
610    language_target("XML", LanguageFamily::DataFormat, DATA_FORMAT_BASIS),
611    language_target("INI", LanguageFamily::DataFormat, DATA_FORMAT_BASIS),
612    language_target("protobuf", LanguageFamily::DataFormat, DATA_FORMAT_BASIS),
613    language_target("GraphQL", LanguageFamily::DataFormat, SCHEMA_BASIS),
614    language_target("CSV", LanguageFamily::DataFormat, DATA_FORMAT_BASIS),
615    language_target("JSON5", LanguageFamily::DataFormat, DATA_FORMAT_BASIS),
616];
617
618/// Initial top-ten programming-language parser targets.
619pub const PROGRAMMING_LANGUAGE_TARGETS: &[LanguageTarget] = &[
620    LanguageTarget {
621        name: "Python",
622        family: LanguageFamily::Programming,
623        basis: "TIOBE May 2026 top 10",
624    },
625    LanguageTarget {
626        name: "C",
627        family: LanguageFamily::Programming,
628        basis: "TIOBE May 2026 top 10",
629    },
630    LanguageTarget {
631        name: "Java",
632        family: LanguageFamily::Programming,
633        basis: "TIOBE May 2026 top 10",
634    },
635    LanguageTarget {
636        name: "C++",
637        family: LanguageFamily::Programming,
638        basis: "TIOBE May 2026 top 10",
639    },
640    LanguageTarget {
641        name: "C#",
642        family: LanguageFamily::Programming,
643        basis: "TIOBE May 2026 top 10",
644    },
645    LanguageTarget {
646        name: "JavaScript",
647        family: LanguageFamily::Programming,
648        basis: "TIOBE May 2026 top 10",
649    },
650    LanguageTarget {
651        name: "Visual Basic",
652        family: LanguageFamily::Programming,
653        basis: "TIOBE May 2026 top 10",
654    },
655    LanguageTarget {
656        name: "R",
657        family: LanguageFamily::Programming,
658        basis: "TIOBE May 2026 top 10",
659    },
660    LanguageTarget {
661        name: "sql-ansi",
662        family: LanguageFamily::Programming,
663        basis: "TIOBE May 2026 top 10 SQL family baseline dialect",
664    },
665    LanguageTarget {
666        name: "Delphi/Object Pascal",
667        family: LanguageFamily::Programming,
668        basis: "TIOBE May 2026 top 10",
669    },
670];
671
672/// Second-tier programming-language parser targets immediately below the TIOBE
673/// top ten.
674///
675/// Each entry has a wired tree-sitter grammar in `src/tree_sitter_adapter.rs`
676/// and a round-trip [`LANGUAGE_FIXTURES`] entry.
677pub const SECOND_TIER_PROGRAMMING_LANGUAGE_TARGETS: &[LanguageTarget] = &[
678    LanguageTarget {
679        name: "PHP",
680        family: LanguageFamily::Programming,
681        basis: "Issue #47 R-2 popular language immediately below the TIOBE top 10",
682    },
683    LanguageTarget {
684        name: "Swift",
685        family: LanguageFamily::Programming,
686        basis: "Issue #47 R-2 popular language immediately below the TIOBE top 10",
687    },
688    LanguageTarget {
689        name: "Kotlin",
690        family: LanguageFamily::Programming,
691        basis: "Issue #47 R-2 popular language immediately below the TIOBE top 10",
692    },
693    LanguageTarget {
694        name: "Scala",
695        family: LanguageFamily::Programming,
696        basis: "Issue #47 R-2 popular language immediately below the TIOBE top 10",
697    },
698    LanguageTarget {
699        name: "Lua",
700        family: LanguageFamily::Programming,
701        basis: "Issue #47 R-2 popular language immediately below the TIOBE top 10",
702    },
703    LanguageTarget {
704        name: "Perl",
705        family: LanguageFamily::Programming,
706        basis: "Issue #47 R-2 popular language immediately below the TIOBE top 10; issue #70 Perl grammar follow-up resolved via ts-parser-perl",
707    },
708];
709
710/// Initial top-ten natural-language parser targets in Ethnologue 2025 total-speaker order.
711pub const NATURAL_LANGUAGE_TARGETS: &[LanguageTarget] = &[
712    LanguageTarget {
713        name: "English",
714        family: LanguageFamily::Natural,
715        basis: "Ethnologue/Britannica total-speaker top 10",
716    },
717    LanguageTarget {
718        name: "Mandarin Chinese",
719        family: LanguageFamily::Natural,
720        basis: "Ethnologue/Britannica total-speaker top 10",
721    },
722    LanguageTarget {
723        name: "Hindi",
724        family: LanguageFamily::Natural,
725        basis: "Ethnologue/Britannica total-speaker top 10",
726    },
727    LanguageTarget {
728        name: "Spanish",
729        family: LanguageFamily::Natural,
730        basis: "Ethnologue/Britannica total-speaker top 10",
731    },
732    LanguageTarget {
733        name: "Modern Standard Arabic",
734        family: LanguageFamily::Natural,
735        basis: "Ethnologue/Britannica total-speaker top 10",
736    },
737    LanguageTarget {
738        name: "French",
739        family: LanguageFamily::Natural,
740        basis: "Ethnologue/Britannica total-speaker top 10",
741    },
742    LanguageTarget {
743        name: "Bengali",
744        family: LanguageFamily::Natural,
745        basis: "Ethnologue/Britannica total-speaker top 10",
746    },
747    LanguageTarget {
748        name: "Portuguese",
749        family: LanguageFamily::Natural,
750        basis: "Ethnologue/Britannica total-speaker top 10",
751    },
752    LanguageTarget {
753        name: "Russian",
754        family: LanguageFamily::Natural,
755        basis: "Ethnologue/Britannica total-speaker top 10",
756    },
757    LanguageTarget {
758        name: "Urdu",
759        family: LanguageFamily::Natural,
760        basis: "Ethnologue/Britannica total-speaker top 10",
761    },
762];
763
764pub use crate::language_fixtures::LANGUAGE_FIXTURES;
765
766/// Mixed-grammar embedding case that must become one unified links network.
767#[derive(Clone, Copy, Debug, PartialEq, Eq)]
768pub struct GrammarEmbeddingTarget {
769    host_language: &'static str,
770    embedded_language: &'static str,
771    trigger: &'static str,
772}
773
774impl GrammarEmbeddingTarget {
775    /// Host language containing the embedded region.
776    #[must_use]
777    pub const fn host_language(&self) -> &'static str {
778        self.host_language
779    }
780
781    /// Embedded region language or language family.
782    #[must_use]
783    pub const fn embedded_language(&self) -> &'static str {
784        self.embedded_language
785    }
786
787    /// Detection trigger or boundary.
788    #[must_use]
789    pub const fn trigger(&self) -> &'static str {
790        self.trigger
791    }
792}
793
794/// Initial mixed-grammar coverage targets.
795pub const GRAMMAR_EMBEDDING_TARGETS: &[GrammarEmbeddingTarget] = &[
796    GrammarEmbeddingTarget {
797        host_language: "Markdown",
798        embedded_language: "Programming language region",
799        trigger: "fenced code language tag",
800    },
801    GrammarEmbeddingTarget {
802        host_language: "Markdown",
803        embedded_language: "HTML",
804        trigger: "inline or block HTML",
805    },
806    GrammarEmbeddingTarget {
807        host_language: "HTML",
808        embedded_language: "JavaScript",
809        trigger: "script element",
810    },
811    GrammarEmbeddingTarget {
812        host_language: "HTML",
813        embedded_language: "CSS",
814        trigger: "style element or style attribute",
815    },
816];