|
1 | 1 | import { |
2 | | - as, |
3 | 2 | lazy, |
4 | 3 | literal, |
5 | 4 | map, |
@@ -29,18 +28,9 @@ export const moleculeParser: Parser<Molecule> = oneOf([ |
29 | 28 | lazy(() => sugaredFunction), |
30 | 29 | ]) |
31 | 30 |
|
32 | | -// During parsing molecules and properties are represented as nested arrays (of key/value pairs). |
33 | | -// The following utilities make it easier to work with such a structure. |
34 | | - |
35 | | -const omit = (theParser: Parser<unknown>) => as(theParser, []) |
36 | | - |
37 | 31 | const optional = <Output>( |
38 | | - theParser: Parser<readonly Output[]>, |
39 | | -): Parser<readonly Output[]> => oneOf([theParser, omit(nothing)]) |
40 | | - |
41 | | -const withoutOmittedOutputs = <Output>( |
42 | | - theParser: Parser<readonly (readonly Output[])[]>, |
43 | | -) => map(theParser, output => output.filter(output => output.length > 0)) |
| 32 | + parser: Parser<NonNullable<Output>>, |
| 33 | +): Parser<Output | undefined> => oneOf([parser, nothing]) |
44 | 34 |
|
45 | 35 | // Keyless properties are automatically assigned numeric indexes, which uses some mutable state. |
46 | 36 | type Indexer = () => string |
@@ -130,28 +120,31 @@ const property = (index: Indexer) => |
130 | 120 | oneOf([namedProperty, numberedProperty(index)]), |
131 | 121 | ) |
132 | 122 |
|
133 | | -const moleculeAsEntries = (index: Indexer) => |
134 | | - withoutOmittedOutputs( |
135 | | - map( |
136 | | - sequence([ |
137 | | - literal('{'), |
138 | | - // Allow initial property not preceded by a delimiter (e.g. `{a b}`). |
139 | | - map(optional(property(index)), property => [property]), |
140 | | - zeroOrMore( |
141 | | - map( |
142 | | - sequence([propertyDelimiter, property(index)]), |
143 | | - ([_delimiter, property]) => property, |
144 | | - ), |
| 123 | +const moleculeAsEntries = ( |
| 124 | + index: Indexer, |
| 125 | +): Parser<readonly (readonly [string, string | Molecule])[]> => |
| 126 | + map( |
| 127 | + sequence([ |
| 128 | + literal('{'), |
| 129 | + // Allow initial property not preceded by a delimiter (e.g. `{a b}`). |
| 130 | + optional(property(index)), |
| 131 | + zeroOrMore( |
| 132 | + map( |
| 133 | + sequence([propertyDelimiter, property(index)]), |
| 134 | + ([_delimiter, property]) => property, |
145 | 135 | ), |
146 | | - optional(omit(propertyDelimiter)), |
147 | | - literal('}'), |
148 | | - ]), |
149 | | - ([ |
150 | | - _openingBrace, |
151 | | - optionalInitialProperty, |
152 | | - remainingProperties, |
153 | | - _delimiter, |
154 | | - _closingBrace, |
155 | | - ]) => [...optionalInitialProperty, ...remainingProperties], |
156 | | - ), |
| 136 | + ), |
| 137 | + optional(propertyDelimiter), |
| 138 | + literal('}'), |
| 139 | + ]), |
| 140 | + ([ |
| 141 | + _openingBrace, |
| 142 | + optionalInitialProperty, |
| 143 | + remainingProperties, |
| 144 | + _delimiter, |
| 145 | + _closingBrace, |
| 146 | + ]) => |
| 147 | + optionalInitialProperty === undefined |
| 148 | + ? remainingProperties |
| 149 | + : [optionalInitialProperty, ...remainingProperties], |
157 | 150 | ) |
0 commit comments