Skip to content

Add a grammar health checker for two HermitCrab admissibility preconditions - #475

Open
johnml1135 wants to merge 1 commit into
masterfrom
feature/grammar-health-checker
Open

Add a grammar health checker for two HermitCrab admissibility preconditions#475
johnml1135 wants to merge 1 commit into
masterfrom
feature/grammar-health-checker

Conversation

@johnml1135

@johnml1135 johnml1135 commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

HermitCrab imposes two requirements on a grammar that nothing currently reports. A grammar author only discovers a violation as a parse that silently returns nothing, which is a hard failure to diagnose from the outside.

Every segment used must be declared in a CharacterDefinitionTable. An undeclared segment makes the parser refuse every word containing it — total, and silent-looking.

Each segment needs a distinct phonological feature bundle within its table. When two segments share one, the parser cannot reliably determine which morphemes are involved.

GrammarHealthChecker.Check(Language) reports both as findings carrying a severity, a stable code, and the offending declarations named so a host can navigate to them.

Design notes

Diagnostic only. It never throws and never changes parse behaviour — a grammar the engine would load still loads. It reports; the host decides what to do.

In the netstandard2.0 engine library, not a tool. So it ships in the SIL.Machine.Morphology.HermitCrab NuGet package and any host — FieldWorks, or anyone testing their own grammar — can call it directly on a loaded Language. Verified by packing: lib/netstandard2.0/SIL.Machine.Morphology.HermitCrab.dll.

The duplicate-bundle check is skipped when a grammar declares no PhonologicalFeatureSystem at all. Such a grammar distinguishes segments by their representation alone, so every bundle is the same empty struct by construction. Reporting that would be a false positive on a correct grammar, and grammars of exactly this shape exist.

Tests

Five tests covering both checks, the clean case, and the feature-less-grammar case. They build the object model directly rather than loading XML, so they have no external fixture dependency. Full HermitCrab suite passes (73/73).

🤖 Generated with Claude Code


This change is Reviewable

…itions

HermitCrab imposes two requirements on a grammar that nothing reports today, so
a grammar author only learns of a violation as a parse that silently returns
nothing.

Every segment used must be declared in a CharacterDefinitionTable: an undeclared
segment makes the parser refuse every word containing it. And each segment needs
a distinct phonological feature bundle within its table: when two share one, the
parser cannot reliably determine which morphemes are involved.

GrammarHealthChecker.Check(Language) reports both as findings with a severity, a
stable code and the offending declarations named. It is diagnostic only -- a
grammar the engine would load still loads, and nothing throws.

Lives in the netstandard2.0 engine library rather than a tool, so FieldWorks and
any other host can call it directly on a loaded Language.

The duplicate-bundle check is skipped for a grammar that declares no
PhonologicalFeatureSystem at all. Such a grammar distinguishes segments by their
representation alone, so every bundle is the same empty struct by construction
and reporting it would be a false positive on a correct grammar.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant