11
2+ const { log } = console ;
23
3- export default function * normalize ( tokens ) {
4- yield * reduce ( unwrap ( trim ( forwardCombine ( multilineJoiner ( multiline ( tokens ) ) ) ) ) ) ;
5- }
64
5+ export default function * normalize ( tokens ) {
76
8- function * unwrap ( tokens ) {
9-
10- let a = false
11-
12- for ( const token of tokens )
13- if ( a )
14- yield token ;
15- else
16- if ( ! [ 'Newline' , 'Space' , 'ObjectStart' ] . includes ( token . type ) ) {
17- yield token ;
18- a = true ;
19- }
7+ yield *
8+ forwardCombine (
9+ prepareQuotedString (
10+ prepareMultiLines (
11+ prepareMultiStrings (
12+ tokens
13+ ) ) ) ) ;
2014}
2115
22- function * multilineJoiner ( tokens ) {
23-
16+
17+ function * select ( tokens , tokenType , callback ) {
2418 for ( const token of tokens )
25- yield ( token . type === 'Multiline' )
26- ? combineMultiline ( token )
19+ yield ( token . type === tokenType )
20+ ? callback ( token . value )
2721 : token ;
2822}
2923
30- function combineMultiline ( multiline ) {
31-
32- const unindent = ( match ) =>
33- match . substring ( multiline . indent ) ;
34-
35- const value = multiline . value
36- . map ( ( { value } ) => value )
37- . join ( '' )
38- . replace ( / ^ [ ^ \S \n ] * \n / , '' )
39- . replace ( / \n [ ^ \S \n ] * $ / , '' )
40- . replace ( / ^ [ ^ \S \n ] + / gm, unindent ) ;
41-
42- return { type : 'Multiline' , value } ;
24+ function * prepareMultiLines ( tokens ) {
25+ yield * select ( tokens , 'MultiLine' , ( value ) => {
26+
27+ const indent = value
28+ . match ( / ^ [ \s ] * / ) [ 0 ]
29+ . length ;
30+
31+ value = value
32+ . trim ( )
33+ . slice ( 3 , - 3 )
34+
35+ return {
36+ type : 'String' ,
37+ value
38+ }
39+ } )
4340}
4441
45- function * multiline ( tokens ) {
46-
47- let before = tokens . next ( ) ;
48-
49- if ( before . done )
50- return ;
51-
52- before = before . value ;
53-
54- let open = false ;
55- let parts = [ ] ;
56- let indent = 0 ;
57-
58- for ( let { type , value } of tokens ) {
59- if ( open ) {
60- if ( type === 'Multiline' ) {
61- open = false
62- yield { type : 'Multiline' , value : parts , indent } ;
63-
64- before = null ;
65- continue ;
66- } else {
67-
68-
69- parts . push ( {
70- type , value
71- } ) ;
72-
73- continue ;
74- }
75- } else {
76- if ( type === 'Multiline' ) {
77- open = true ;
78- parts = [ ] ;
79-
80- indent = 0 ;
81-
82- if ( before ?. type === 'Space' )
83- indent = before . value . length ;
84-
85- continue ;
86- }
87- }
88-
89- if ( before )
90- yield before ;
42+ function * prepareMultiStrings ( tokens ) {
43+ yield * select ( tokens , 'MultiString' , ( value ) => {
9144
92- before = { type , value } ;
93- }
94-
95- if ( before )
96- yield before ;
45+ const indent = value
46+ . match ( / ^ [ \s ] * / ) [ 0 ]
47+ . length ;
48+
49+ const detent = new RegExp ( `^\\s{1,${ indent } }` , 'gm' ) ;
50+
51+ value = value
52+ . trim ( )
53+ . slice ( 3 , - 3 )
54+ . replace ( / ^ [ ^ \S \n ] * \n / , '' )
55+ . replace ( / \n [ ^ \S \n ] * $ / , '' )
56+ . replace ( detent , '' )
57+
58+ return {
59+ type : 'String' ,
60+ value
61+ }
62+ } )
9763}
9864
99- function * trim ( tokens ) {
100-
101- for ( let { type , value } of tokens ) {
102-
103- if ( type === 'Word' )
104- value = value . trim ( ) ;
105-
106- yield { type , value }
107- }
65+ function * prepareQuotedString ( tokens ) {
66+ for ( const token of tokens )
67+ yield ( [ 'SingleString' , 'DoubleString' ] . includes ( token . type ) )
68+ ? { type : 'String' , value : token . value . slice ( 1 , - 1 ) }
69+ : ( token . type === 'Quoteless' )
70+ ? { type : 'String' , value : token . value . trim ( ) }
71+ : token ;
10872}
10973
11074
@@ -114,7 +78,7 @@ function * forwardCombine(tokens){
11478
11579 while ( ! before . done ) {
11680
117- const now = tokens . next ( ) ;
81+ let now = tokens . next ( ) ;
11882
11983 if ( now . done )
12084 break ;
@@ -131,19 +95,16 @@ function * forwardCombine(tokens){
13195 nowType === 'Newline'
13296 ) continue ;
13397
134- break ;
135- case 'Word' :
136-
13798 if (
138- nowType === 'Space' ||
139- nowType === 'Word'
99+ nowType === 'Member'
140100 ) {
141- before . value . value += now . value . value ;
142- continue ;
101+ now = { value : { type : 'String' , value : now . value . value } }
143102 }
144103
145104 break ;
105+
146106 case 'ObjectStart' :
107+ case 'ArrayStart' :
147108
148109 if (
149110 nowType === 'Space' ||
@@ -161,7 +122,7 @@ function * forwardCombine(tokens){
161122 break ;
162123
163124 case 'Newline' :
164-
125+
165126 if (
166127 nowType === 'Newline' ||
167128 nowType === 'Space'
@@ -170,19 +131,45 @@ function * forwardCombine(tokens){
170131 if (
171132 nowType === 'Comma'
172133 ) {
173- before = { type : 'Comma' }
134+ before = { value : { type : 'Comma' } }
174135 continue ;
175136 }
176137
177138 break ;
178139 case 'Space' :
179140
180141 if (
181- nowType === 'Comma'
142+ nowType === 'Space'
143+ ) continue ;
144+
145+ if (
146+ nowType === 'Colon'
182147 ) {
183- before = { type : 'Comma' }
148+ before = { value : { type : 'Colon' } }
184149 continue ;
185150 }
151+
152+ break ;
153+ case 'String' :
154+
155+ if (
156+ nowType === 'Colon'
157+ ) {
158+ before = { value : { type : 'Member' , value : before . value . value } }
159+ }
160+
161+ break ;
162+ case 'Member' :
163+
164+ if (
165+ nowType === 'Space'
166+ ) continue ;
167+
168+ if (
169+ nowType !== 'Colon'
170+ ) {
171+ before = { value : { type : 'String' , value : before . value . value } }
172+ }
186173 }
187174
188175 yield before . value ;
@@ -192,22 +179,3 @@ function * forwardCombine(tokens){
192179 if ( ! before . done )
193180 yield before . value ;
194181}
195-
196-
197- const complex = [ 'Word' , 'Space' , 'Multiline' ] ;
198-
199- const isSimple = ( { type } ) =>
200- ! complex . includes ( type ) ;
201-
202- function * reduce ( tokens ) {
203- for ( const token of tokens )
204- yield removeRedundantValues ( token ) ;
205- }
206-
207- function removeRedundantValues ( token ) {
208-
209- if ( isSimple ( token ) )
210- delete token . value ;
211-
212- return token ;
213- }
0 commit comments