Diff
Not logged in

Differences From Artifact [a819ba1b27fdc13d]:

To Artifact [4856c979362ef435]:


95 95 auto saved = lex.save; 96 96 scope(failure) lex = saved; 97 97 return parseE(0); 98 98 } 99 99 100 100 // [TODO] multi-char operators are not supported by the lexer... 101 101 static immutable string[][] operator_perferences = [ 102 - [","], 103 - ["="], // caution! left associative 102 + ["="], 104 103 ["or"], 105 104 ["and"], 106 105 ["!="], 107 106 ["=="], 108 107 ["<","<=",">",">="], 109 108 ["|"], 110 109 ["^"], ................................................................................ 142 141 } 143 142 144 143 Expression parseBaseExpression() 145 144 { 146 145 if( lex.empty ) 147 146 throw new ParserException("EOF during parsing an expression"); 148 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,"Unexpected EOF"); 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 expression"); 172 + auto pos = lex.front.pos; 149 173 150 174 if( lex.front.kind == Token.Kind.number ) 151 175 { 152 176 scope(exit) lex.popFront; 153 177 return new IntLiteralExpression(pos, BigInt(cast(string)lex.front.str)); 154 178 } 155 179 if( lex.front.kind == Token.Kind.stringLiteral ) ................................................................................ 159 183 } 160 184 if( tryEat("(") ) 161 185 { 162 186 auto e = parseE(); 163 187 eat(")", "after parenthesized expression"); 164 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,"Unexpected EOF"); 199 + throw e; 200 + } 201 + if( lex.front.kind != Token.Kind.identifier ) { 202 + auto e = ParserException.create(lex,"Identifier Expected for parameters"); 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,"Unexpected EOF"); 217 + throw e; 218 + } 219 + funbody ~= parseStatement(); 220 + } 221 + return new FunLiteralExpression(pos, params, funbody); 222 + } 166 223 scope(exit) lex.popFront; 167 224 return new VarExpression(pos, lex.front.str); 168 225 } 169 226 170 227 private: 171 228 Lexer lex; 172 229 ................................................................................ 226 283 227 284 Program prog = p.parseProgram(); 228 285 assert( prog.length == 3 ); 229 286 assert( prog[0] == s0 ); 230 287 assert( prog[1] == s1 ); 231 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(null, 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 +}