Diff
Not logged in

Differences From Artifact [fe545db0fb7a2428]:

To Artifact [a819ba1b27fdc13d]:


90 90 } 91 91 } 92 92 93 93 Expression parseExpression() 94 94 { 95 95 auto saved = lex.save; 96 96 scope(failure) lex = saved; 97 - 98 - // Expr ::= E0 99 - // E0 ::= (E1 "=")* E1 100 - // E1 ::= (E2 "+"|"-")* E2 101 - // E2 ::= (E3 "*"|"/")* E3 102 - // E3 ::= int | str | id | "(" Expr ")" 103 - 104 - return parseE0(); 97 + return parseE(0); 105 98 } 106 99 107 - Expression parseE0() 108 - { 109 - auto lhs = parseE1(); 110 - if( tryEat("=") ) 111 - lhs = new BinOpExpression(lhs.pos, "=", lhs, parseE0()); 112 - return lhs; 113 - } 100 + // [TODO] multi-char operators are not supported by the lexer... 101 + static immutable string[][] operator_perferences = [ 102 + [","], 103 + ["="], // caution! left associative 104 + ["or"], 105 + ["and"], 106 + ["!="], 107 + ["=="], 108 + ["<","<=",">",">="], 109 + ["|"], 110 + ["^"], 111 + ["&"], 112 + ["<<", ">>"], 113 + ["+","-"], 114 + ["*","/","%"] 115 + ]; 114 116 115 - Expression parseE1() 117 + Expression parseE(int level = 0) 116 118 { 117 - for(auto lhs = parseE2();;) 119 + if( operator_perferences.length <= level ) 120 + return parseBaseExpression(); 121 + else 118 122 { 119 - if( tryEat("+") ) 120 - lhs = new BinOpExpression(lhs.pos, "+", lhs, parseE2()); 121 - else if( tryEat("-") ) 122 - lhs = new BinOpExpression(lhs.pos, "-", lhs, parseE2()); 123 - else 124 - return lhs; 123 + auto ops = operator_perferences[level]; 124 + auto e = parseE(level+1); 125 + seq: 126 + while( !lex.empty ) 127 + { 128 + auto pos = lex.front.pos; 129 + foreach(op; ops) 130 + if( tryEat(op) ) 131 + { 132 + if( op == "=" ) // right assoc 133 + return new AssignExpression(e.pos, e, parseE(level)); 134 + else 135 + e = new FuncallExpression(e.pos, new VarExpression(pos, op), e, parseE(level+1)); 136 + continue seq; 137 + } 138 + break; 139 + } 140 + return e; 125 141 } 126 142 } 127 143 128 - Expression parseE2() 129 - { 130 - for(auto lhs = parseE3();;) 131 - { 132 - if( tryEat("*") ) 133 - lhs = new BinOpExpression(lhs.pos, "*", lhs, parseE3()); 134 - else if( tryEat("/") ) 135 - lhs = new BinOpExpression(lhs.pos, "/", lhs, parseE3()); 136 - else 137 - return lhs; 138 - } 139 - } 140 - 141 - Expression parseE3() 144 + Expression parseBaseExpression() 142 145 { 143 146 if( lex.empty ) 144 147 throw new ParserException("EOF during parsing an expression"); 145 148 auto pos = lex.front.pos; 146 149 147 150 if( lex.front.kind == Token.Kind.number ) 148 151 { ................................................................................ 152 155 if( lex.front.kind == Token.Kind.stringLiteral ) 153 156 { 154 157 scope(exit) lex.popFront; 155 158 return new StrLiteralExpression(pos, lex.front.str); 156 159 } 157 160 if( tryEat("(") ) 158 161 { 159 - auto e = parseE0(); 162 + auto e = parseE(); 160 163 eat(")", "after parenthesized expression"); 161 164 return e; 162 165 } 163 166 scope(exit) lex.popFront; 164 167 return new VarExpression(pos, lex.front.str); 165 168 } 166 169 ................................................................................ 207 210 auto p = parserFromString(` 208 211 var zzz = 100; # comment 209 212 zzz = zzz + zzz * "fo\no"; # comment 210 213 42; 211 214 `); 212 215 213 216 auto s0 = new DeclStatement(null, "zzz", new IntLiteralExpression(null, BigInt(100))); 214 - auto s1 = new ExprStatement(null, new BinOpExpression(null, "=", 217 + auto s1 = new ExprStatement(null, new AssignExpression(null, 215 218 new VarExpression(null, "zzz"), 216 - new BinOpExpression(null, "+", 219 + new FuncallExpression(null, new VarExpression(null,"+"), 217 220 new VarExpression(null, "zzz"), 218 - new BinOpExpression(null, "*", 221 + new FuncallExpression(null, new VarExpression(null,"*"), 219 222 new VarExpression(null, "zzz"), 220 223 new StrLiteralExpression(null, "fo\\no") 221 224 )))); 222 225 auto s2 = new ExprStatement(null, new IntLiteralExpression(null, BigInt(42))); 223 226 224 227 Program prog = p.parseProgram(); 225 228 assert( prog.length == 3 ); 226 229 assert( prog[0] == s0 ); 227 230 assert( prog[1] == s1 ); 228 231 assert( prog[2] == s2 ); 229 232 }