Repository navigation
Simplify the syntax so every line reads left to right - #46
Merged
Merged
Conversation
Every ARIA role that Playwright accepts, except generic, none, and presentation, is its own locator prefix: `button:"Sign in"`, `button:~Sign` for a substring match, and `dialog:*` for any name. `role:` is gone. Prefixes are strict: a bare colon in a locator always marks a prefix, and `>>` is never a segment. Browser tabs are windows: `WINDOW name` and `window:name closed`. A bare value cannot start with `@`, `name: value` lines need a space after the colon, and a quoted string joins a token only after `:` or `:~`. The removed `[Asserts]` and `[Captures]` sections are gone. With these rules the parser reads each line left to right, so the grammar in SPEC section 17 drops its per-context locator rules and lookaheads. Sample flows, SPEC examples, eval caches, and tests use the new syntax. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A `#` in the middle of a bare token started a comment, so `VISIT /docs#install` visited `/docs`, and `ASSERT url == https://shop.example.com/#/cart` compared against the URL without its fragment. `whirl check` passed both files. A `#` now starts a comment only at the start of a line or after white space, as in the shell. Inside a token it is text, so URL fragments and `css:#submit` work without quotes. A value that starts with `#` still needs quotes, and `whirl fmt` keeps them there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A json: or xpath: argument had its own rule: one bare run or one quoted string. So json:a:"b" was an error while css:a:"b" worked. The argument now follows the token rule for every prefix value, and the grammar drops its `single` rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 5, 2026
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 #45.
The grammar in #45 needed a locator rule for each kind of line and many lookaheads. The cause was the syntax: one line could split in more than one way, and the parser had to look ahead to choose. This PR changes the syntax so that the parser reads each line left to right, one token at a time.
PRESSis the only line that still looks one token ahead.This changes existing flows. Whirl has no users to migrate yet, so there is no compatibility mode. The sample flows, SPEC examples, eval caches, and tests use the new syntax.
Locators
CLICK role:button "Sign in"CLICK button:"Sign in"CLICK role~:button SignCLICK button:~SignASSERT role:dialog visibleASSERT dialog:* visibleASSERT text~:Added visibleASSERT text:~Added visiblegeneric,none, andpresentation: 79 roles.role:is gone.*matches any name. A quoted"*"is the literal name.~of a substring match follows the colon, for roles and the five text prefixes alike.>>is never a segment; quote it to match it as text.Role options such as
levelare not in this PR. A later form could beheading[level=2]:"Welcome back".Windows
Browser tabs are windows, so
tabis free for the ARIA role:TAB paymentWINDOW paymentASSERT tab:payment closedASSERT window:payment closedThe lint codes are
duplicate-windowandunknown-window. The shim protocol does not change; its wire command is still namedtab.Tokens
@. A bare@token is always the step timeout and must end its line. Quote a value such as"@60s".name: valueline needs a space after the colon: in options,CAPTURElines, headers, and snapshot settings.label:"First name"orbutton:~"Sign in". This is also true forjson:andxpath:, which had a rule of their own.#starts a comment only at the start of a line or after white space. Before, a#inside a token started a comment. SoVISIT /docs#installvisited/docs, andASSERT url == https://shop.example.com/#/cartcompared against the URL without its fragment, andwhirl checkpassed both. Nowcss:#submitand URL fragments work without quotes.ACT,EXTRACT, orJUDGE, a first token with a prefix starts the scope.DRAGneeds no quotes on atothat is text. AfterSCROLL, a bare direction ortois always the motion.Removed
The
[Asserts]and[Captures]sections are gone. They are unknown sections,whirl fmtno longer rewrites them, and thesections-removedandmixed-check-syntaxerrors are gone.Result
The grammar in SPEC section 17 went from 107 rules and 46 lookaheads to 91 rules and 31 lookaheads, and that includes the new list of 79 roles. Its locator rules no longer depend on the kind of line.
parse.rsis about 100 lines shorter.Commits
#after white space.json:andxpath:join a quoted string like other prefixes.Validation
mise run check.whirl checkon 185 sample files and SPEC examples: the old build on the original files, and the new build on the converted files. 182 gave the same result, down to each diagnostic's code and line. The other 3 were tests of the removed sections, which this PR deletes.🤖 Generated with Claude Code