11import {
22 lazy ,
3- literal ,
43 map ,
54 nothing ,
65 oneOf ,
@@ -15,15 +14,21 @@ import {
1514 atomWithAdditionalQuotationRequirements ,
1615 type Atom ,
1716} from './atom.js'
17+ import {
18+ arrow ,
19+ closingBrace ,
20+ closingParenthesis ,
21+ colon ,
22+ comma ,
23+ dot ,
24+ openingBrace ,
25+ openingParenthesis ,
26+ } from './literals.js'
1827import { optionallySurroundedByParentheses } from './parentheses.js'
19- import { trivia } from './trivia.js'
28+ import { optionalTrivia , trivia } from './trivia.js'
2029
2130export type Molecule = { readonly [ key : Atom ] : Molecule | Atom }
2231
23- export const moleculeParser : Parser < Molecule > = lazy (
24- ( ) => potentiallySugaredMolecule ,
25- )
26-
2732// Keyless properties are automatically assigned numeric indexes, which uses some mutable state.
2833type Indexer = ( ) => string
2934const makeIncrementingIndexer = ( ) : Indexer => {
@@ -47,7 +52,7 @@ const propertyValue = oneOf([
4752] )
4853
4954const namedProperty = map (
50- sequence ( [ propertyKey , literal ( ':' ) , optional ( trivia ) , propertyValue ] ) ,
55+ sequence ( [ propertyKey , colon , optionalTrivia , propertyValue ] ) ,
5156 ( [ key , _colon , _trivia , value ] ) => [ key , value ] as const ,
5257)
5358
@@ -60,28 +65,28 @@ const property = (index: Indexer) =>
6065 )
6166
6267const propertyDelimiter = oneOf ( [
63- sequence ( [ optional ( trivia ) , literal ( ',' ) , optional ( trivia ) ] ) ,
68+ sequence ( [ optionalTrivia , comma , optionalTrivia ] ) ,
6469 trivia ,
6570] )
6671
6772const argument = map (
6873 sequence ( [
69- literal ( '(' ) ,
70- optional ( trivia ) ,
74+ openingParenthesis ,
75+ optionalTrivia ,
7176 propertyValue ,
72- optional ( trivia ) ,
73- literal ( ')' ) ,
77+ optionalTrivia ,
78+ closingParenthesis ,
7479 ] ) ,
7580 ( [ _openingParenthesis , _trivia1 , argument , _trivia2 , _closingParenthesis ] ) =>
7681 argument ,
7782)
7883
7984const dottedKeyPathComponent = map (
8085 sequence ( [
81- optional ( trivia ) ,
82- literal ( '.' ) ,
83- optional ( trivia ) ,
84- atomWithAdditionalQuotationRequirements ( literal ( '.' ) ) ,
86+ optionalTrivia ,
87+ dot ,
88+ optionalTrivia ,
89+ atomWithAdditionalQuotationRequirements ( dot ) ,
8590 ] ) ,
8691 ( [ _trivia1 , _dot , _trivia2 , key ] ) => key ,
8792)
@@ -91,7 +96,7 @@ const moleculeAsEntries = (
9196) : Parser < readonly ( readonly [ string , string | Molecule ] ) [ ] > =>
9297 map (
9398 sequence ( [
94- literal ( '{' ) ,
99+ openingBrace ,
95100 // Allow initial property not preceded by a delimiter (e.g. `{a b}`).
96101 optional ( property ( index ) ) ,
97102 zeroOrMore (
@@ -101,7 +106,7 @@ const moleculeAsEntries = (
101106 ) ,
102107 ) ,
103108 optional ( propertyDelimiter ) ,
104- literal ( '}' ) ,
109+ closingBrace ,
105110 ] ) ,
106111 ( [
107112 _openingBrace ,
@@ -125,17 +130,17 @@ const sugarFreeMolecule: Parser<Molecule> = optionallySurroundedByParentheses(
125130const sugaredLookup : Parser < Molecule > = optionallySurroundedByParentheses (
126131 map (
127132 sequence ( [
128- literal ( ':' ) ,
133+ colon ,
129134 // Reserve `.` so that `:a.b` is parsed as a lookup followed by an index.
130- atomWithAdditionalQuotationRequirements ( literal ( '.' ) ) ,
135+ atomWithAdditionalQuotationRequirements ( dot ) ,
131136 ] ) ,
132137 ( [ _colon , key ] ) => ( { 0 : '@lookup' , key } ) ,
133138 ) ,
134139)
135140
136141const sugaredFunction : Parser < Molecule > = optionallySurroundedByParentheses (
137142 map (
138- sequence ( [ atomParser , trivia , literal ( '=>' ) , trivia , propertyValue ] ) ,
143+ sequence ( [ atomParser , trivia , arrow , trivia , propertyValue ] ) ,
139144 ( [ parameter , _trivia1 , _arrow , _trivia2 , body ] ) => ( {
140145 0 : '@function' ,
141146 parameter,
@@ -210,3 +215,5 @@ const potentiallySugaredMolecule: Parser<Molecule> = (() => {
210215 potentiallySugaredNonApply ,
211216 ] )
212217} ) ( )
218+
219+ export const moleculeParser : Parser < Molecule > = potentiallySugaredMolecule
0 commit comments