@@ -199,20 +199,38 @@ private ForeachMapStatement foreachMapStatement() {
199199 }
200200
201201 private FunctionDefineStatement functionDefine () {
202- // def name(arg1, arg2) { ... } || def name(args) = expr
202+ // def name(arg1, arg2 = value ) { ... } || def name(args) = expr
203203 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 ;
204213 consume (TokenType .LPAREN );
205- final List <String > argNames = new ArrayList <>();
206214 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+ }
208224 match (TokenType .COMMA );
209225 }
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 ());
213232 }
214- final Statement body = statementOrBlock ();
215- return new FunctionDefineStatement (name , argNames , body );
233+ return statementOrBlock ();
216234 }
217235
218236 private FunctionalExpression function (Expression qualifiedNameExpr ) {
@@ -534,20 +552,9 @@ private Expression primary() {
534552 return match ();
535553 }
536554 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 ));
551558 }
552559 return variable ();
553560 }
0 commit comments