Index: polemy/parse.d ================================================================== --- polemy/parse.d +++ polemy/parse.d @@ -195,24 +195,52 @@ AST Funcall() { /// Funcall ::= BaseExpression ["(" Expression%"," ")"]* auto e = BaseExpression(); - while( tryEat("(") ) - { - auto pos = currentPosition(); - AST[] args; - while( !tryEat(")") ) { - if( lex.empty ) - throw genex!UnexpectedEOF(pos, "closing ')' for arguments not found"); - args ~= E(0); - if( !tryEat(",") ) { - eat(")", "after function parameters"); - break; + for(;;) + if( tryEat("(") ) + { + auto pos = currentPosition(); + AST[] args; + while( !tryEat(")") ) { + if( lex.empty ) + throw genex!UnexpectedEOF(pos, "closing ')' for arguments not found"); + args ~= E(0); + if( !tryEat(",") ) { + eat(")", "after function parameters"); + break; + } } + e = new FuncallExpression(e.pos, e, args); + } + else if( tryEat("{") ) + { + e = parseTableSetAfterBrace(e); } - e = new FuncallExpression(e.pos, e, args); + else + break; + return e; + } + + AST parseTableSetAfterBrace(AST e) + { + if( tryEat("}") ) + return e; + auto pos = currentPosition(); + for(;;) + { + string key = eatId("for table key", AllowQuoted); + eat(":", "after table key"); + AST val = E(0); + e = new FuncallExpression(pos, new VarExpression(pos,".="), + e, new StrLiteral(pos,key), val); + if( !tryEat(",") ) + { + eat("}", "for the end of table literal"); + break; + } } return e; } AST BaseExpression() @@ -246,26 +274,11 @@ return e; } if( tryEat("{") ) { AST e = new FuncallExpression(pos, new VarExpression(pos,"{}")); - if( tryEat("}") ) - return e; - for(;;) - { - string key = eatId("for table key", AllowQuoted); - eat(":", "after table key"); - AST val = E(0); - e = new FuncallExpression(pos, new VarExpression(pos,".="), - e, new StrLiteral(pos,key), val); - if( !tryEat(",") ) - { - eat("}", "for the end of table literal"); - break; - } - } - return e; + return parseTableSetAfterBrace(e); } if( tryEat("if") ) { eat("(", "after if"); auto cond = E(0); @@ -467,6 +480,7 @@ assert_eq(parseString(`{}`), call(var("{}"))); assert_eq(parseString(`{foo:1,"bar":2}`), call(var(".="), call(var(".="), call(var("{}")), strl("foo"), intl(1)), strl("bar"), intl(2))); assert_eq(parseString(`{}.foo`), call(var("."),call(var("{}")),strl("foo"))); assert_eq(parseString(`{}.?foo`), call(var(".?"),call(var("{}")),strl("foo"))); + assert_eq(parseString(`x{y:1}`), call(var(".="),var("x"),strl("y"),intl(1))); } Index: tricks/test.d ================================================================== --- tricks/test.d +++ tricks/test.d @@ -102,17 +102,18 @@ assert_throw!AssertError( assert_throw!AssertError(error()) ); } template assertOp(string op) { - void assertOp(A, B, string fn=__FILE__, size_t ln=__LINE__)(A a, B b, string msg="") - { + void assertOp(A, B, string fn=__FILE__, size_t ln=__LINE__)(lazy A a_, lazy B b_, string msg="") + { try - { if( mixin("a"~op~"b") ) return; } + { A a=a_(); B b=b_(); if( mixin("a"~op~"b") ) return; + onAssertErrorMsg(fn, ln, msg.length ? msg : text(a, " !", op, " ", b)); } catch(Throwable e) { onAssertErrorMsg(fn, ln, msg.length ? msg : "bad exception \n >> "~e.toString()); } - onAssertErrorMsg(fn, ln, msg.length ? msg : text(a, " !", op, " ", b)); + assert(false); } } alias assertOp!(`==`) assert_eq; /// asserts two operands are == alias assertOp!(`!=`) assert_ne; /// asserts two operands are !=