@@ -199,20 +199,38 @@ private ForeachMapStatement foreachMapStatement() {
199
199
}
200
200
201
201
private FunctionDefineStatement functionDefine () {
202
- // def name(arg1, arg2) { ... } || def name(args) = expr
202
+ // def name(arg1, arg2 = value ) { ... } || def name(args) = expr
203
203
final String name = consume (TokenType .WORD ).getText ();
204
+ final Arguments arguments = arguments ();
205
+ final Statement body = statementBody ();
206
+ return new FunctionDefineStatement (name , arguments , body );
207
+ }
208
+
209
+ private Arguments arguments () {
210
+ // (arg1, arg2, arg3 = expr1, arg4 = expr2)
211
+ final Arguments arguments = new Arguments ();
212
+ boolean startsOptionalArgs = false ;
204
213
consume (TokenType .LPAREN );
205
- final List <String > argNames = new ArrayList <>();
206
214
while (!match (TokenType .RPAREN )) {
207
- argNames .add (consume (TokenType .WORD ).getText ());
215
+ final String name = consume (TokenType .WORD ).getText ();
216
+ if (match (TokenType .EQ )) {
217
+ startsOptionalArgs = true ;
218
+ arguments .addOptional (name , variable ());
219
+ } else if (!startsOptionalArgs ) {
220
+ arguments .addRequired (name );
221
+ } else {
222
+ throw new ParseException ("Required argument cannot be after optional" );
223
+ }
208
224
match (TokenType .COMMA );
209
225
}
210
- if (lookMatch (0 , TokenType .EQ )) {
211
- match (TokenType .EQ );
212
- return new FunctionDefineStatement (name , argNames , new ReturnStatement (expression ()));
226
+ return arguments ;
227
+ }
228
+
229
+ private Statement statementBody () {
230
+ if (match (TokenType .EQ )) {
231
+ return new ReturnStatement (expression ());
213
232
}
214
- final Statement body = statementOrBlock ();
215
- return new FunctionDefineStatement (name , argNames , body );
233
+ return statementOrBlock ();
216
234
}
217
235
218
236
private FunctionalExpression function (Expression qualifiedNameExpr ) {
@@ -534,20 +552,9 @@ private Expression primary() {
534
552
return match ();
535
553
}
536
554
if (match (TokenType .DEF )) {
537
- consume (TokenType .LPAREN );
538
- final List <String > argNames = new ArrayList <>();
539
- while (!match (TokenType .RPAREN )) {
540
- argNames .add (consume (TokenType .WORD ).getText ());
541
- match (TokenType .COMMA );
542
- }
543
- Statement statement ;
544
- if (lookMatch (0 , TokenType .EQ )) {
545
- match (TokenType .EQ );
546
- statement = new ReturnStatement (expression ());
547
- } else {
548
- statement = statementOrBlock ();
549
- }
550
- return new ValueExpression (new UserDefinedFunction (argNames , statement ));
555
+ final Arguments arguments = arguments ();
556
+ final Statement statement = statementBody ();
557
+ return new ValueExpression (new UserDefinedFunction (arguments , statement ));
551
558
}
552
559
return variable ();
553
560
}
0 commit comments