@@ -93,53 +93,56 @@ Expression parseExpression() { auto saved = lex.save; scope(failure) lex = saved; - - // Expr ::= E0 - // E0 ::= (E1 "=")* E1 - // E1 ::= (E2 "+"|"-")* E2 - // E2 ::= (E3 "*"|"/")* E3 - // E3 ::= int | str | id | "(" Expr ")" - - return parseE0(); + return parseE(0); } - Expression parseE0() - { - auto lhs = parseE1(); - if( tryEat("=") ) - lhs = new BinOpExpression(lhs.pos, "=", lhs, parseE0()); - return lhs; - } + // [TODO] multi-char operators are not supported by the lexer... + static immutable string[][] operator_perferences = [ + [","], + ["="], // caution! left associative + ["or"], + ["and"], + ["!="], + ["=="], + ["<","<=",">",">="], + ["|"], + ["^"], + ["&"], + ["<<", ">>"], + ["+","-"], + ["*","/","%"] + ]; - Expression parseE1() + Expression parseE(int level = 0) { - for(auto lhs = parseE2();;) + if( operator_perferences.length <= level ) + return parseBaseExpression(); + else { - if( tryEat("+") ) - lhs = new BinOpExpression(lhs.pos, "+", lhs, parseE2()); - else if( tryEat("-") ) - lhs = new BinOpExpression(lhs.pos, "-", lhs, parseE2()); - else - return lhs; + auto ops = operator_perferences[level]; + auto e = parseE(level+1); + seq: + while( !lex.empty ) + { + auto pos = lex.front.pos; + foreach(op; ops) + if( tryEat(op) ) + { + if( op == "=" ) // right assoc + return new AssignExpression(e.pos, e, parseE(level)); + else + e = new FuncallExpression(e.pos, new VarExpression(pos, op), e, parseE(level+1)); + continue seq; + } + break; + } + return e; } } - Expression parseE2() - { - for(auto lhs = parseE3();;) - { - if( tryEat("*") ) - lhs = new BinOpExpression(lhs.pos, "*", lhs, parseE3()); - else if( tryEat("/") ) - lhs = new BinOpExpression(lhs.pos, "/", lhs, parseE3()); - else - return lhs; - } - } - - Expression parseE3() + Expression parseBaseExpression() { if( lex.empty ) throw new ParserException("EOF during parsing an expression"); auto pos = lex.front.pos; @@ -155,9 +158,9 @@ return new StrLiteralExpression(pos, lex.front.str); } if( tryEat("(") ) { - auto e = parseE0(); + auto e = parseE(); eat(")", "after parenthesized expression"); return e; } scope(exit) lex.popFront; @@ -210,13 +213,13 @@ 42; `); auto s0 = new DeclStatement(null, "zzz", new IntLiteralExpression(null, BigInt(100))); - auto s1 = new ExprStatement(null, new BinOpExpression(null, "=", + auto s1 = new ExprStatement(null, new AssignExpression(null, new VarExpression(null, "zzz"), - new BinOpExpression(null, "+", + new FuncallExpression(null, new VarExpression(null,"+"), new VarExpression(null, "zzz"), - new BinOpExpression(null, "*", + new FuncallExpression(null, new VarExpression(null,"*"), new VarExpression(null, "zzz"), new StrLiteralExpression(null, "fo\\no") )))); auto s2 = new ExprStatement(null, new IntLiteralExpression(null, BigInt(42)));