Diff
Not logged in

Differences From Artifact [a819ba1b27fdc13d]:

To Artifact [4856c979362ef435]:


95 auto saved = lex.save; 95 auto saved = lex.save; 96 scope(failure) lex = saved; 96 scope(failure) lex = saved; 97 return parseE(0); 97 return parseE(0); 98 } 98 } 99 99 100 // [TODO] multi-char operators are not supported by the lexer... 100 // [TODO] multi-char operators are not supported by the lexer... 101 static immutable string[][] operator_perferences = [ 101 static immutable string[][] operator_perferences = [ 102 [","], | 102 ["="], 103 ["="], // caution! left associative < 104 ["or"], 103 ["or"], 105 ["and"], 104 ["and"], 106 ["!="], 105 ["!="], 107 ["=="], 106 ["=="], 108 ["<","<=",">",">="], 107 ["<","<=",">",">="], 109 ["|"], 108 ["|"], 110 ["^"], 109 ["^"], ................................................................................................................................................................................ 142 } 141 } 143 142 144 Expression parseBaseExpression() 143 Expression parseBaseExpression() 145 { 144 { 146 if( lex.empty ) 145 if( lex.empty ) 147 throw new ParserException("EOF during parsing an express 146 throw new ParserException("EOF during parsing an express 148 auto pos = lex.front.pos; 147 auto pos = lex.front.pos; > 148 Expression e = parseBaseBaseExpression(); > 149 while( tryEat("(") ) // funcall > 150 { > 151 Expression[] args; > 152 while( !tryEat(")") ) { > 153 if( lex.empty ) { > 154 auto ex = ParserException.create(lex,"Un > 155 throw ex; > 156 } > 157 args ~= parseE(); > 158 if( !tryEat(",") ) { > 159 eat(")", "after function parameters"); > 160 break; > 161 } > 162 } > 163 e = new FuncallExpression(pos, e, args); > 164 } > 165 return e; > 166 } > 167 > 168 Expression parseBaseBaseExpression() > 169 { > 170 if( lex.empty ) > 171 throw new ParserException("EOF during parsing an express > 172 auto pos = lex.front.pos; 149 173 150 if( lex.front.kind == Token.Kind.number ) 174 if( lex.front.kind == Token.Kind.number ) 151 { 175 { 152 scope(exit) lex.popFront; 176 scope(exit) lex.popFront; 153 return new IntLiteralExpression(pos, BigInt(cast(string) 177 return new IntLiteralExpression(pos, BigInt(cast(string) 154 } 178 } 155 if( lex.front.kind == Token.Kind.stringLiteral ) 179 if( lex.front.kind == Token.Kind.stringLiteral ) ................................................................................................................................................................................ 159 } 183 } 160 if( tryEat("(") ) 184 if( tryEat("(") ) 161 { 185 { 162 auto e = parseE(); 186 auto e = parseE(); 163 eat(")", "after parenthesized expression"); 187 eat(")", "after parenthesized expression"); 164 return e; 188 return e; 165 } 189 } > 190 > 191 if( tryEat("fun") ) > 192 { > 193 eat("(", "after fun"); > 194 string[] params; > 195 for(;;) > 196 { > 197 if( lex.empty ) { > 198 auto e = ParserException.create(lex,"Une > 199 throw e; > 200 } > 201 if( lex.front.kind != Token.Kind.identifier ) { > 202 auto e = ParserException.create(lex,"Ide > 203 throw e; > 204 } > 205 params ~= lex.front.str; > 206 lex.popFront; > 207 if( !tryEat(",") ) { > 208 eat(")", "after function parameters"); > 209 break; > 210 } > 211 } > 212 eat("{", "after function parameters"); > 213 Statement[] funbody; > 214 while(!tryEat("}")) { > 215 if( lex.empty ) { > 216 auto e = ParserException.create(lex,"Une > 217 throw e; > 218 } > 219 funbody ~= parseStatement(); > 220 } > 221 return new FunLiteralExpression(pos, params, funbody); > 222 } 166 scope(exit) lex.popFront; 223 scope(exit) lex.popFront; 167 return new VarExpression(pos, lex.front.str); 224 return new VarExpression(pos, lex.front.str); 168 } 225 } 169 226 170 private: 227 private: 171 Lexer lex; 228 Lexer lex; 172 229 ................................................................................................................................................................................ 226 283 227 Program prog = p.parseProgram(); 284 Program prog = p.parseProgram(); 228 assert( prog.length == 3 ); 285 assert( prog.length == 3 ); 229 assert( prog[0] == s0 ); 286 assert( prog[0] == s0 ); 230 assert( prog[1] == s1 ); 287 assert( prog[1] == s1 ); 231 assert( prog[2] == s2 ); 288 assert( prog[2] == s2 ); 232 } 289 } > 290 > 291 unittest > 292 { > 293 auto p = parserFromString(` > 294 var f = fun(x,y){x+y;}; > 295 f(1,fun(abc){}(4)); > 296 `); > 297 Program prog = p.parseProgram(); > 298 assert( prog.length == 2 ); > 299 assert( prog[0] == new DeclStatement(null, "f", new FunLiteralExpression > 300 ["x","y"], [new ExprStatement(null, > 301 new FuncallExpression(null, new VarExpression(null, "+") > 302 new VarExpression(null, "x"), new VarExpression(null, "y > 303 ))); > 304 assert( prog[1] == new ExprStatement(null, new FuncallExpression(null, > 305 new VarExpression(null, "f"), > 306 new IntLiteralExpression(null, BigInt(1)), > 307 new FuncallExpression(null, > 308 new FunLiteralExpression(null, ["abc"], [ > 309 ]), > 310 new IntLiteralExpression(null, BigInt(4)) > 311 )))); > 312 }