@@ -66,15 +66,25 @@ } } immutable LexPosition varpos = (lex.empty ? null : lex.front.pos); string var = eatId("after "~kwd,true); - eat("=", "after "~kwd); - kwd = (kwd[0]=='@' ? kwd : ""); // "let, var, def ==> neutral layer" - auto e = E(0); - if( tryEat(";") && !lex.empty && (lex.front.quoted || !["}",")","]"].canFind(lex.front.str)) ) - return new LetExpression(pos, var, kwd, e, Body()); - else - return new LetExpression(pos, var, kwd, e, new VarExpression(varpos, var)); + // [TODO] refactor. only auto e = ... differ + if(tryEat("(")) { + kwd = (kwd[0]=='@' ? kwd : ""); // "let, var, def ==> neutral layer" + auto e = parseLambdaAfterOpenParen(varpos); + if( tryEat(";") && !lex.empty && (lex.front.quoted || !["}",")","]"].canFind(lex.front.str)) ) + return new LetExpression(pos, var, kwd, e, Body()); + else + return new LetExpression(pos, var, kwd, e, new VarExpression(varpos, var)); + } else { + eat("=", "after "~kwd); + kwd = (kwd[0]=='@' ? kwd : ""); // "let, var, def ==> neutral layer" + auto e = E(0); + if( tryEat(";") && !lex.empty && (lex.front.quoted || !["}",")","]"].canFind(lex.front.str)) ) + return new LetExpression(pos, var, kwd, e, Body()); + else + return new LetExpression(pos, var, kwd, e, new VarExpression(varpos, var)); + } } else { asExpression: @@ -203,24 +213,29 @@ } if( tryEat("fun") || tryEat("\u03BB") ) { eat("(", "after fun"); - string[] params; - while( !tryEat(")") ) - { - params ~= eatId("for function parameter"); - if( !tryEat(",") ) { - eat(")", "after function parameters"); - break; - } - } - eat("{", "after function parameters"); - auto funbody = Body(); - eat("}", "after function body"); - return new FunLiteral(pos, params, funbody); + return parseLambdaAfterOpenParen(pos); } scope(exit) lex.popFront; return new VarExpression(pos, lex.front.str); + } + + AST parseLambdaAfterOpenParen(immutable LexPosition pos) + { + string[] params; + while( !tryEat(")") ) + { + params ~= eatId("for function parameter"); + if( !tryEat(",") ) { + eat(")", "after function parameters"); + break; + } + } + eat("{", "after function parameters"); + auto funbody = Body(); + eat("}", "after function body"); + return new FunLiteral(pos, params, funbody); } private: Lexer lex; @@ -331,4 +346,14 @@ assert_throw!ParseException(parseString(`@val x ==`)); assert_throw!ParseException(parseString(`if(){1}`)); assert_throw!UnexpectedEOF(parseString(`f(`)); } + +unittest +{ + mixin EasyAST; + assert_eq(parseString(`def foo(x) { x+1 }; foo`), + let("foo", "", + fun(["x"], call(var("+"), var("x"), intl(1))), + var("foo")) + ); +}