Repository navigation
Replace the SPEC grammar with a PEG that tests check against the parser - #45
Merged
Merged
Conversation
SPEC section 17 now defines the whole syntax of a .whirl file as a
parsing expression grammar in pest notation. Section 17.1 lists the
value rules that the grammar leaves out. grammar_tests.rs reads the
grammar from SPEC.md and requires the grammar and the parser to accept
the same files, with the same entries and steps, on the repository's
samples, edge cases, and changed copies of the samples.
The comparison found three places where the parser differed from the
SPEC, now fixed: JSON array bodies after HTTP and MOCK were a parse
error; MOCK lines with no VISIT after them parsed; and a JSON string's
\\{{name}} lost its reference in the parsed value.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #44.
The EBNF in SPEC section 17 left out tokens, white space, escapes, step timeouts, and where each kind of locator ends, and nothing checked it against the parser. This PR replaces it with a complete grammar and a test that keeps the two in step.
The grammar
Section 17 is now a parsing expression grammar (PEG) in pest notation, with a short table that explains the notation. A PEG fits Whirl better than EBNF: its ordered choice and lookahead express the rules that decide how a line splits, such as "a final bare
@durationis the timeout" and "a baretoseparates the two locators ofDRAG". Each kind of line ends its locator in a different place, so each has its own locator rule; one shared rule checks thatnth:is never first,ai:is last, and aframe:is followed by an element segment.Section 17.1 lists 11 value rules that the grammar leaves out, such as valid regexes, JSONPath queries, option value forms, and unique header names.
The test
crates/whirl/src/lang/grammar_tests.rsreads the grammar from SPEC.md withpest_vm. For each input, the grammar and the parser must both accept it or both reject it, and when both accept, they must find the same entries and steps. The parser may reject a file that the grammar accepts only with an error from a section 17.1 rule..whirlfile and Markdownwhirlblock in the repository, about 360 edge cases, and about 60,000 copies of the samples with one line changed.#[ignore], about 8 min): about 480,000 copies with a tricky token or character put in or swapped in.The sweeps found one error in my first draft of the grammar (a final
>>before a comment), now fixed. One gap stays unchecked: a step timeout whose number overflows 64 bits is a value to the parser but a timeout to the grammar; rule 10 of section 17.1 states it.New dev dependencies:
pest,pest_meta, andpest_vm2.9.2, pinned.Parser fixes
The comparison found three places where the parser differed from the SPEC:
HTTPorMOCKthat starts with[was read as a section header, so every array body was a parse error. Section 7.3 allows arrays.MOCKlines with noVISIT. A file of onlyMOCKlines, orMOCKlines followed byHTTP,PAGE, or a check line before the firstVISIT, parsed. Section 4 requires the first browser entry to start withVISITafter anyMOCKlines. These are now parse errors, with a new case incheck_mock_invalid.\\{{name}}in a JSON string. The parse check and the run read it as an escaped backslash before a reference, but the parsed value kept the literal text\{{name}}. Sowhirl checkdid not see the reference, and a JSON literal in a text comparison compared the wrong text. The value now matches.Two SPEC sentences were also inaccurate against the parser, and now say what it does: section 3.1 on final
@durationtokens, and section 7.3 on where a JSON body starts.Validation:
mise run check; the nightly grammar sweep passed locally; CI below.🤖 Generated with Claude Code