@@ -115,54 +115,99 @@ func (p *parser) peek() *token {
115
115
return & p .t [p .currT ]
116
116
}
117
117
118
- func (p * parser ) parseIdentifierList (elementKind string ) (ast.Identifiers , bool , error ) {
119
- _ , exprs , gotComma , err := p .parseCommaList (tokenParenR , elementKind )
120
- if err != nil {
121
- return ast.Identifiers {}, false , err
118
+ func (p * parser ) doublePeek () * token {
119
+ return & p .t [p .currT + 1 ]
120
+ }
121
+
122
+ // in some cases it's convenient to parse something as an expression, and later
123
+ // decide that it should be just an identifer
124
+ func astVarToIdentifier (node ast.Node ) (* ast.Identifier , bool ) {
125
+ v , ok := node .(* ast.Var )
126
+ if ok {
127
+ return & v .Id , true
122
128
}
123
- var ids ast.Identifiers
124
- for _ , n := range exprs {
125
- v , ok := n .(* ast.Var )
126
- if ! ok {
127
- return ast.Identifiers {}, false , MakeStaticError (fmt .Sprintf ("Expected simple identifier but got a complex expression." ), * n .Loc ())
128
- }
129
- ids = append (ids , v .Id )
129
+ return nil , false
130
+ }
131
+
132
+ func (p * parser ) parseArgument () (* ast.Identifier , ast.Node , error ) {
133
+ var id * ast.Identifier
134
+ if p .peek ().kind == tokenIdentifier && p .doublePeek ().kind == tokenOperator && p .doublePeek ().data == "=" {
135
+ ident := p .pop ()
136
+ var tmpID = ast .Identifier (ident .data )
137
+ id = & tmpID
138
+ p .pop () // "=" token
139
+ }
140
+ expr , err := p .parse (maxPrecedence )
141
+ if err != nil {
142
+ return nil , nil , err
130
143
}
131
- return ids , gotComma , nil
144
+ return id , expr , nil
132
145
}
133
146
134
- func (p * parser ) parseCommaList (end tokenKind , elementKind string ) (* token , ast.Nodes , bool , error ) {
135
- var exprs ast.Nodes
147
+ // TODO(sbarzowski) - this returned bool is weird
148
+ // TODO(sbarzowski) - name - it's also used for parameters
149
+ func (p * parser ) parseArguments (elementKind string ) (* token , * ast.Arguments , bool , error ) {
150
+ args := & ast.Arguments {}
136
151
gotComma := false
152
+ namedArgumentAdded := false
137
153
first := true
138
154
for {
139
155
next := p .peek ()
140
- if ! first && ! gotComma {
141
- if next .kind == tokenComma {
142
- p .pop ()
143
- next = p .peek ()
144
- gotComma = true
145
- }
146
- }
147
- if next .kind == end {
156
+
157
+ if next .kind == tokenParenR {
148
158
// gotComma can be true or false here.
149
- return p .pop (), exprs , gotComma , nil
159
+ return p .pop (), args , gotComma , nil
150
160
}
151
161
152
162
if ! first && ! gotComma {
153
- return nil , nil , false , MakeStaticError (fmt .Sprintf ("Expected a comma before next %s." , elementKind ), next .loc )
163
+ return nil , nil , false , MakeStaticError (fmt .Sprintf ("Expected a comma before next %s, got %s ." , elementKind , next ), next .loc )
154
164
}
155
165
156
- expr , err := p .parse ( maxPrecedence )
166
+ id , expr , err := p .parseArgument ( )
157
167
if err != nil {
158
168
return nil , nil , false , err
159
169
}
160
- exprs = append (exprs , expr )
161
- gotComma = false
170
+ if id == nil {
171
+ if namedArgumentAdded {
172
+ return nil , nil , false , MakeStaticError ("Positional argument after a named argument is not allowed" , next .loc )
173
+ }
174
+ args .Positional = append (args .Positional , expr )
175
+ } else {
176
+ namedArgumentAdded = true
177
+ args .Named = append (args .Named , ast.NamedArgument {Name : * id , Arg : expr })
178
+ }
179
+
180
+ if p .peek ().kind == tokenComma {
181
+ p .pop ()
182
+ gotComma = true
183
+ } else {
184
+ gotComma = false
185
+ }
186
+
162
187
first = false
163
188
}
164
189
}
165
190
191
+ // TODO(sbarzowski) - this returned bool is weird
192
+ func (p * parser ) parseParameters (elementKind string ) (* ast.Parameters , bool , error ) {
193
+ _ , args , trailingComma , err := p .parseArguments (elementKind )
194
+ if err != nil {
195
+ return nil , false , err
196
+ }
197
+ var params ast.Parameters
198
+ for _ , arg := range args .Positional {
199
+ id , ok := astVarToIdentifier (arg )
200
+ if ! ok {
201
+ return nil , false , MakeStaticError (fmt .Sprintf ("Expected simple identifier but got a complex expression." ), * arg .Loc ())
202
+ }
203
+ params .Positional = append (params .Positional , * id )
204
+ }
205
+ for _ , arg := range args .Named {
206
+ params .Named = append (params .Named , ast.NamedParameter {Name : arg .Name , DefaultArg : arg .Arg })
207
+ }
208
+ return & params , trailingComma , nil
209
+ }
210
+
166
211
func (p * parser ) parseBind (binds * ast.LocalBinds ) error {
167
212
varID , err := p .popExpect (tokenIdentifier )
168
213
if err != nil {
@@ -176,7 +221,7 @@ func (p *parser) parseBind(binds *ast.LocalBinds) error {
176
221
177
222
if p .peek ().kind == tokenParenL {
178
223
p .pop ()
179
- params , gotComma , err := p .parseIdentifierList ("function parameter" )
224
+ params , gotComma , err := p .parseParameters ("function parameter" )
180
225
if err != nil {
181
226
return err
182
227
}
@@ -373,11 +418,11 @@ func (p *parser) parseObjectRemainder(tok *token) (ast.Node, *token, error) {
373
418
374
419
isMethod := false
375
420
methComma := false
376
- var params ast.Identifiers
421
+ var params * ast.Parameters
377
422
if p .peek ().kind == tokenParenL {
378
423
p .pop ()
379
424
var err error
380
- params , methComma , err = p .parseIdentifierList ("method parameter" )
425
+ params , methComma , err = p .parseParameters ("method parameter" )
381
426
if err != nil {
382
427
return nil , nil , err
383
428
}
@@ -413,7 +458,7 @@ func (p *parser) parseObjectRemainder(tok *token) (ast.Node, *token, error) {
413
458
MethodSugar : isMethod ,
414
459
Expr1 : expr1 ,
415
460
Id : id ,
416
- Ids : params ,
461
+ Params : params ,
417
462
TrailingComma : methComma ,
418
463
Expr2 : body ,
419
464
})
@@ -432,11 +477,11 @@ func (p *parser) parseObjectRemainder(tok *token) (ast.Node, *token, error) {
432
477
433
478
isMethod := false
434
479
funcComma := false
435
- var params ast.Identifiers
480
+ var params * ast.Parameters
436
481
if p .peek ().kind == tokenParenL {
437
482
p .pop ()
438
483
isMethod = true
439
- params , funcComma , err = p .parseIdentifierList ("function parameter" )
484
+ params , funcComma , err = p .parseParameters ("function parameter" )
440
485
if err != nil {
441
486
return nil , nil , err
442
487
}
@@ -459,7 +504,7 @@ func (p *parser) parseObjectRemainder(tok *token) (ast.Node, *token, error) {
459
504
SuperSugar : false ,
460
505
MethodSugar : isMethod ,
461
506
Id : & id ,
462
- Ids : params ,
507
+ Params : params ,
463
508
TrailingComma : funcComma ,
464
509
Expr2 : body ,
465
510
})
@@ -830,7 +875,7 @@ func (p *parser) parse(prec precedence) (ast.Node, error) {
830
875
p .pop ()
831
876
next := p .pop ()
832
877
if next .kind == tokenParenL {
833
- params , gotComma , err := p .parseIdentifierList ("function parameter" )
878
+ params , gotComma , err := p .parseParameters ("function parameter" )
834
879
if err != nil {
835
880
return nil , err
836
881
}
@@ -840,7 +885,7 @@ func (p *parser) parse(prec precedence) (ast.Node, error) {
840
885
}
841
886
return & ast.Function {
842
887
NodeBase : ast .NewNodeBaseLoc (locFromTokenAST (begin , body )),
843
- Parameters : params ,
888
+ Parameters : * params ,
844
889
TrailingComma : gotComma ,
845
890
Body : body ,
846
891
}, nil
@@ -1048,7 +1093,7 @@ func (p *parser) parse(prec precedence) (ast.Node, error) {
1048
1093
Id : & id ,
1049
1094
}
1050
1095
case tokenParenL :
1051
- end , args , gotComma , err := p .parseCommaList ( tokenParenR , "function argument" )
1096
+ end , args , gotComma , err := p .parseArguments ( "function argument" )
1052
1097
if err != nil {
1053
1098
return nil , err
1054
1099
}
@@ -1060,7 +1105,7 @@ func (p *parser) parse(prec precedence) (ast.Node, error) {
1060
1105
lhs = & ast.Apply {
1061
1106
NodeBase : ast .NewNodeBaseLoc (locFromTokens (begin , end )),
1062
1107
Target : lhs ,
1063
- Arguments : args ,
1108
+ Arguments : * args ,
1064
1109
TrailingComma : gotComma ,
1065
1110
TailStrict : tailStrict ,
1066
1111
}
0 commit comments