Repository navigation
fix(swift): scan expression identifiers by UAX 31 XID_Continue - #3547
Open
karolkulesza wants to merge 12 commits into
Open
karolkulesza wants to merge 12 commits into
karolkulesza wants to merge 12 commits into
Conversation
The Swift expression parser decided which characters belong to a path,
function name, argument name or keyword with Character.isLetter and
isNumber. isNumber also accepts characters such as ½ and ², so Swift
parsed ${a½} as a path and ${add(½: 1)} as a call, while web_core, Dart
and Python reject both.
Scan by UAX 31 XID_Continue instead, like the other engines: a
character counts when all of its scalars are XID_Continue. Paths still
allow /, . and -.
Add shared cases to conformance/core/expressions.yaml for non-ASCII
paths, function names, argument names and keyword boundaries, and for
rejecting ½. They pass in the Swift, web_core, Dart and Python runners.
Part of a2ui-project#2838
Contributor
There was a problem hiding this comment.
Code Review
This pull request updates the Swift expression parser to support non-ASCII characters in paths, identifiers, and function/argument names using the UAX #31 XID_Continue standard, and adds corresponding conformance tests. Feedback on the changes suggests optimizing the isIdentifierCharacter method with a fast-path check for ASCII characters to prevent potential performance overhead from Unicode scalar property lookups.
pinieb
reviewed
Oct 29, 2026
…ombining marks A Swift Character is a grapheme cluster, so a '/', '.' or '-' followed by a combining mark such as U+0301 arrives as one Character and was rejected, while web_core, Dart and Python accept it. Check path characters scalar by scalar, fold the scan predicates into the while-let conditions, and flatten matchesKeyword with a guard. Add shared conformance cases for combining marks (including right after a slash or dot), a supplementary-plane XID_Continue character, and a supplementary-plane character outside XID_Continue.
This branch has not been deployed
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.
Description
The Swift expression parser used
Character.isLetter || isNumberto scan paths, function names, argument names and the character aftertrue/false/null.isNumberalso accepts characters such as½and², so Swift parsed${a½}as a path and${add(½: 1)}as a call. web_core, Dart and Python scan by UAX 31XID_Continueand reject both.This PR makes Swift scan by
XID_Continuetoo: aCharactercounts when all of its scalars areXID_Continue. Paths still allow/,.and-, and are also checked per scalar, because a SwiftCharacteris a grapheme cluster and a separator followed by a combining mark such as U+0301 arrives as oneCharacter. Like the other parsers, it does not requireXID_Startfor the first character.It also adds eight shared cases to
conformance/core/expressions.yaml: non-ASCII path, function and argument names, a keyword followed byß, combining marks (including right after/and.) and the supplementary-plane𠮷are accepted, and½in a path, after a keyword and in an argument name, and🚀in a path are rejected.Testing:
swift testpasses (685 tests; the only issues are the 4 existing known issues inAdapterConformanceTests). Without the parser change, the three½cases and the combining-mark path case fail.expression_parser.conformance.test.js), Dart (expressions_conformance_test.dart) and Python (test_conformance.py) pass the new cases without changes.swift-format lint --strictis clean.Part of #2838
Pre-launch Checklist
One time:
For this PR:
If you need help, consider asking for advice on the discussion board.