Skip to content

Commit dbd02ad

Browse files
committed
Add DSL example
1 parent 4bb25b3 commit dbd02ad

File tree

1 file changed

+35
-14
lines changed

1 file changed

+35
-14
lines changed

Documentation/Evolution/DelimiterSyntax.md

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,21 @@ let re = /[0-9]+/
1414

1515
This proposal helps complete the story told in [Regex Type and Overview][regex-type] and [elsewhere][pitch-status]. Literals are compiled directly, allowing errors to be found at compile time, rather than at run time. Using a literal also allows editors to support features such as syntax coloring inside the literal, highlighting sub-structure of the regex, and conversion of the literal to an equivalent result builder DSL (see [Regex builder DSL][regex-dsl]). It would be difficult to support all of this if regexes could only be defined inside a string.
1616

17+
A regex literal also allows for seamless composition with the Regex DSL, enabling the intermixing of a regex syntax with other elements of the builder:
18+
19+
```swift
20+
// A regex literal for parsing an amount of currency in dollars or pounds.
21+
let regex = Regex {
22+
/([$£])/
23+
TryCapture {
24+
OneOrMore(.digit)
25+
"."
26+
Repeat(.digit, count: 2)
27+
} transform: { Amount(twoDecimalPlaces: $0) }
28+
}
29+
```
30+
31+
This flexibility allows for terse matching syntax to be used when it's suitable, and more explicit syntax where clarity and strong types are required.
1732

1833
## Proposed solution
1934

@@ -94,35 +109,41 @@ In order to help avoid further parsing ambiguities, a `/.../` regex literal will
94109

95110
#### Rationale
96111

97-
This is due to 2 main ambiguities. The first of which arises when a `/.../` regex literal starts a new line. This is particularly problematic for result builders, where we expect it to be frequently used, for example:
112+
This is due to 2 main parsing ambiguities. The first of which arises when a `/.../` regex literal starts a new line. This is particularly problematic for result builders, where we expect it to be frequently used, in particular within a `Regex` builder:
98113

99114
```swift
100-
Builder {
101-
1
102-
/ 2 /
103-
3
115+
let digit = Regex {
116+
TryCapture(OneOrMore(.digit)) { Int($0) }
117+
}
118+
// Matches against <digit>+ (' + ' | ' - ') <digit>+
119+
let regex Regex {
120+
digit
121+
/ [+-] /
122+
digit
104123
}
105124
```
106125

107-
This is parsed as a single operator chain, however it is likely the user is expecting a regex literal. To resolve this ambiguity, a regex literal may not start with a space or tab character. The above therefore remains an operator chain. This takes advantage of the fact that infix operators require consistent spacing on either side.
126+
Instead of being parsed as 3 result builder elements, the second of which being a regex literal, this is instead parsed as a single operator chain with the operands `digit`, `[+-]`, and `digit`. This will therefore be diagnosed as semantically invalid.
127+
128+
To avoid this issue, a regex literal may not start with a space or tab character. This takes advantage of the fact that infix operators require consistent spacing on either side.
108129

109130
If a space or tab is needed as the first character, it must be either escaped, e.g:
110131

111132
```swift
112-
Builder {
113-
1
114-
/\ 2 /
115-
3
133+
Regex {
134+
digit
135+
/\ [+-] /
136+
digit
116137
}
117138
```
118139

119140
or extended syntax must be used, e.g:
120141

121142
```swift
122-
Builder {
123-
1
124-
#/ 2 /#
125-
3
143+
Regex {
144+
digit
145+
#/ [+-] /#
146+
digit
126147
}
127148
```
128149

0 commit comments

Comments
 (0)