Intuitive DSL is designed to reject invalid definitions early and to report runtime syntax failures precisely. This split is deliberate: structural mistakes belong to registration time, while invalid user input belongs to execution time.
Validate grammar authoring upfront. Diagnose runtime input with the furthest, richest failure you can explain.
A compliant engine should reject structurally invalid grammars during registration or compilation, before any command is executed.
[].{}.{ | A }, { A || B }, or { A | }.${} or <>.${task.Definition validation also includes binding metadata. The engine should reject a command definition when a parameter name, a context phrase, or a clause phrase does not exist exactly in the compiled grammar.
When no registered command can fully match the user input, execution fails with a syntax error. A useful diagnostic should explain:
If several parsing paths fail, the engine keeps the failure that occurred furthest into the token stream. If several failures happen at the same furthest position, their expected possibilities should be merged deterministically.
This rule is what makes diagnostics informative instead of noisy.
Most implementations expose both a short message and a richer diagnostic payload. In the current Java implementation, the rich detail is exposed through methods such as getExpectedPossibilities() and getRichMessage().
Tests should assert against the structured or rich diagnostic whenever precision matters.
[]
{}
{ | A }
{ A || B }
${}
${task
... USER name ;
DO { A [ B | C } ;
Input: SET TITLE 'unterminated
Expected detail: closing quote (')
Input: PROCESS FILE ;
Expected detail: a value for file_path
Input: SET DATE 07 03 2026 ;
Expected detail: '.' between date components