Diff
Not logged in

Differences From Artifact [fe545db0fb7a2428]:

To Artifact [a819ba1b27fdc13d]:


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