Skip to content

Commit a146f14

Browse files
committed
perf(toString): no bounds when duplication is shorter
E.g. render `a{3}` as `aaa` because it's shorter.
1 parent 5b5a8da commit a146f14

File tree

4 files changed

+17
-11
lines changed

4 files changed

+17
-11
lines changed

README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,17 +116,19 @@ import { RB } from '@gruhn/regex-utils'
116116

117117
const strContainingCommentEnd = RB(/.*-->.*/)
118118

119-
const commentRegex = RB('<!--')
120-
.concat(strContainingEndMarker.not())
121-
.concat('-->')
119+
const commentStart = RB('<!--')
120+
const commentInner = RB(/^.*-->.*$/).not()
121+
const commentEnd = RB('-->')
122+
123+
const comment = commentStart.concat(commentInner).concat(commentEnd)
122124
```
123125

124126
With `.toRegExp()` we can convert back to a native JavaScript regex:
125127
```typescript
126-
commentRegex.toRegExp()
128+
comment.toRegExp()
127129
```
128130
```
129-
/^(<!-{2}(-{2}-*[^->]|-?[^-])*-{2}-*>)$/
131+
/^<!--(---*[^->]|-?[^-])*---*>$/
130132
```
131133

132134
### Password Regex using Intersections 🔐

benchmark/toStdRegex_output_length-result.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ failed instances:
77
- regexSyntaxError : 0
88

99
size multipliers:
10-
- mean : 323.8333568093031
10+
- mean : 321.86932736154387
1111
- median : 1.1923076923076923
1212
- max : 178441.75438596492
1313
- min : 0.0021570319240724763
1414

1515
memory:
16-
- max heap used : 2370.280075073242 MB
17-
- max rss : 2722.53515625 MB
16+
- max heap used : 2491.6993865966797 MB
17+
- max rss : 2909.78515625 MB

src/ast.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,10 @@ export function toString(ast: RegExpAST, options: RenderOptions): string {
614614
const innerStr = maybeWithParens(ast.inner, ast, options)
615615
if (innerStr === '')
616616
return ''
617+
else if (typeof ast.bounds === 'number' && ast.bounds <= 3 && innerStr.length === 1)
618+
// Just duplicate `innerStr` if that makes rendered expression shorter.
619+
// E.g. `aaa` instead of `a{3}`.
620+
return innerStr.repeat(ast.bounds)
617621
else
618622
return innerStr + repeatBoundsToString(ast.bounds)
619623
}

test/regex.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -264,10 +264,10 @@ describe('derivative', () => {
264264

265265
const derivativeCases = [
266266
[/^((aa*)?)$/, 'a', /^a*$/],
267-
[/^(a{2}(a{3})*)$/, 'a', /^a(a{3})*$/],
267+
[/^(a{2}(a{3})*)$/, 'a', /^a(aaa)*$/],
268268
[/^(a{2}(a*)|(aa*))$/, 'a', /^a?a*$/],
269-
[/^(a(a{3})*|(aa*)?)$/, 'a', /^((a{3})*|a*)$/],
270-
[/^(a{2}(a{3})*|(aa*)?)$/, 'a', /^(a(a{3})*|a*)$/],
269+
[/^(a(a{3})*|(aa*)?)$/, 'a', /^((aaa)*|a*)$/],
270+
[/^(a{2}(a{3})*|(aa*)?)$/, 'a', /^(a(aaa)*|a*)$/],
271271
] as const
272272

273273
for (const [input, str, expected] of derivativeCases) {

0 commit comments

Comments
 (0)