Skip to content

Fix pretty() of patterns so the output recompiles to the same regex - #431

Open
binggao1230 wants to merge 1 commit into
neogeny:mainfrom
binggao1230:fix/pattern-pretty-roundtrip
Open

binggao1230 wants to merge 1 commit into
neogeny:mainfrom
binggao1230:fix/pattern-pretty-roundtrip

Conversation

@binggao1230

Copy link
Copy Markdown
Contributor

pretty() output should recompile to the same grammar; for regexes it does not, mostly without an error.

Pattern._pretty() trimmed the pattern and switched to the ?"..." form whenever it held a /.

The printer reindents line by line, so a regex spanning lines comes back with the new indentation inside it — silently a different grammar:

g = tatsu.compile('start = /line1\n  line2/ $ ;')   # two spaces
tatsu.compile(g.pretty()).parse('line1\n  line2')   # FailedParse: wants four now

?"..." holds neither a line break nor a double quote (DOUBLEQUOTED is /"((?:[^"\n]|\\"|\\\\)*?)"/), so the recompile raises outright on /line1\/\nline2/, and on any pattern with both a / and a ". The pat.replace('"', r'\"') in that branch cannot help — \" does not parse inside ?"..." either.

Auditing the rest of the surface: 19 of the 28 round-trip cases in the new test fail on main. Every character str.splitlines() breaks on (\v \f \r \x1c-\x1e \x85 \u2028 \u2029), whitespace at either end of the pattern and tabs (both eaten by trim()), and the same at every nesting depth. Grammar._pretty() sends @@comments/@@eol_comments/@@whitespace through the same '/' in value branch and escapes nothing, so @@comments :: ?'/[*].*?[*]/|"[^"]*"' prints source that does not parse.

So: escape what the printer would rewrite, keep ?"..." where it is legal, /.../ with escaped slashes otherwise. Patterns under (?x) keep the existing layout normalisation — whitespace is not significant there, and escaping it would be.

This is the case #430's description offered to file separately. Different module, no dependency on it, though both add to tests/grammar/pretty_test.py.

Also ran a pretty → compile → pretty fixed-point sweep over every grammar in the repo, which stays clean. 501 pass, 6 skipped.

Pattern._pretty() ran the pattern through trim() and switched to the
?"..." form whenever it held a slash.  But pretty() reindents its output
line by line, so a regex spanning lines came back with the indentation
inside it, and ?"..." holds neither a line break nor a double quote, so
those grammars did not recompile at all.

Escape the characters str.splitlines() breaks on, keep ?"..." where it
is legal, and use the /.../ form with escaped slashes otherwise.
Patterns under (?x) keep the existing layout normalisation, where
whitespace is not significant.

Grammar._pretty() rendered the regex directives through the same branch,
escaping nothing.
@codspeed

codspeed Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Congrats! CodSpeed is installed 🎉

🆕 5 new benchmarks were detected.

You will start to see performance impacts in the reports once the benchmarks are run from your default branch.

Detected benchmarks


Open in CodSpeed

This branch has not been deployed

No deployments
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