Differences From Artifact [789e91a27a62e096]:
- File
polemy/parse.d
- 2010-11-21 14:24:33 - part of checkin [3995a5eb6a] on branch trunk - added iikagen pattern match (user: kinaba) [annotate]
To Artifact [9df8a8a07696ff22]:
- File
polemy/parse.d
- 2010-11-23 07:42:13 - part of checkin [6ac127ddd0] on branch trunk - new evaluator (user: kinaba) [annotate]
98 string kwd = "@" ~ layer; 98 string kwd = "@" ~ layer;
99 string var = layer; 99 string var = layer;
100 100
101 auto e = tryEat("(") 101 auto e = tryEat("(")
102 ? parseLambdaAfterOpenParen(pos) // let var ( . 102 ? parseLambdaAfterOpenParen(pos) // let var ( .
103 : (eat("=", "after "~kwd), E(0)); // let var = . 103 : (eat("=", "after "~kwd), E(0)); // let var = .
104 if( moreDeclarationExists() ) 104 if( moreDeclarationExists() )
105 return new LetExpression(pos, var, SystemLayer, | 105 return new Let(pos, var, SystemLayer, e, Body())
106 else 106 else
107 return new LetExpression(pos, var, SystemLayer, | 107 return new Let(pos, var, SystemLayer, e,
108 new LayExpression(pos, SystemLayer, new | 108 new Lay(pos, SystemLayer, new Var(pos, v
109 ); 109 );
110 } 110 }
111 else 111 else
112 { 112 {
113 string kwd = layer; 113 string kwd = layer;
114 if( layer.empty && !tryEat(kwd="let") && !tryEat(kwd="va 114 if( layer.empty && !tryEat(kwd="let") && !tryEat(kwd="va
115 return null; // none of {@lay, let, var, def} oc 115 return null; // none of {@lay, let, var, def} oc
................................................................................................................................................................................
117 auto varpos = currentPosition(); 117 auto varpos = currentPosition();
118 string var = eatId("after "~kwd, AllowQuoted); // name o 118 string var = eatId("after "~kwd, AllowQuoted); // name o
119 119
120 auto e = tryEat("(") 120 auto e = tryEat("(")
121 ? parseLambdaAfterOpenParen(varpos) // let var 121 ? parseLambdaAfterOpenParen(varpos) // let var
122 : (eat("=", "after "~kwd), E(0)); // let var 122 : (eat("=", "after "~kwd), E(0)); // let var
123 if( moreDeclarationExists() ) 123 if( moreDeclarationExists() )
124 return new LetExpression(pos, var, layer, e, Bod | 124 return new Let(pos, var, layer, e, Body());
125 else 125 else
126 return new LetExpression(pos, var, layer, e, new | 126 return new Let(pos, var, layer, e, new Var(varpo
127 } 127 }
128 } 128 }
129 129
130 AST TopLevelExpression() 130 AST TopLevelExpression()
131 { 131 {
132 /// TopLevelExpression ::= Expression ([";"|"in"] Body?)? 132 /// TopLevelExpression ::= Expression ([";"|"in"] Body?)?
133 133
134 auto pos = currentPosition(); 134 auto pos = currentPosition();
135 auto e = E(0); 135 auto e = E(0);
136 if( moreDeclarationExists() ) 136 if( moreDeclarationExists() )
137 return new LetExpression(pos, "_", "", e, Body()); | 137 return new Let(pos, "_", "", e, Body());
138 else 138 else
139 return e; 139 return e;
140 } 140 }
141 141
142 private bool moreDeclarationExists() 142 private bool moreDeclarationExists()
143 { 143 {
144 return (tryEat(";") || tryEat("in")) && !closingBracket(); 144 return (tryEat(";") || tryEat("in")) && !closingBracket();
................................................................................................................................................................................
177 return lhs; 177 return lhs;
178 178
179 auto pos = currentPosition(); 179 auto pos = currentPosition();
180 foreach(op; operator_perferences[level]) 180 foreach(op; operator_perferences[level])
181 if( tryEat(op) ) 181 if( tryEat(op) )
182 if( op[0]=='.' ) 182 if( op[0]=='.' )
183 return rec( 183 return rec(
184 new FuncallExpression(lh | 184 new App(lhs.pos, new Var
185 else 185 else
186 return rec( | 186 return rec(
187 new FuncallExpression(lhs.pos, n | 187 new App(lhs.pos, new Var
188 return lhs; 188 return lhs;
189 } 189 }
190 190
191 if( operator_perferences.length <= level ) 191 if( operator_perferences.length <= level )
192 return Funcall(); 192 return Funcall();
193 else 193 else
194 return rec(E(level+1)); 194 return rec(E(level+1));
................................................................................................................................................................................
209 throw genex!UnexpectedEOF(pos, " 209 throw genex!UnexpectedEOF(pos, "
210 args ~= E(0); 210 args ~= E(0);
211 if( !tryEat(",") ) { 211 if( !tryEat(",") ) {
212 eat(")", "after function paramet 212 eat(")", "after function paramet
213 break; 213 break;
214 } 214 }
215 } 215 }
216 e = new FuncallExpression(e.pos, e, args); | 216 e = new App(e.pos, e, args);
217 } 217 }
218 else if( tryEat("{") ) 218 else if( tryEat("{") )
219 { 219 {
220 e = parseTableSetAfterBrace(e); 220 e = parseTableSetAfterBrace(e);
221 } 221 }
222 else 222 else
223 break; 223 break;
................................................................................................................................................................................
230 return e; 230 return e;
231 auto pos = currentPosition(); 231 auto pos = currentPosition();
232 for(;;) 232 for(;;)
233 { 233 {
234 string key = eatId("for table key", AllowQuoted); 234 string key = eatId("for table key", AllowQuoted);
235 eat(":", "after table key"); 235 eat(":", "after table key");
236 AST val = E(0); 236 AST val = E(0);
237 e = new FuncallExpression(pos, new VarExpression(pos,".= | 237 e = new App(pos, new Var(pos,".="),
238 e, new StrLiteral(pos,key), val); | 238 e, new Str(pos,key), val);
239 if( !tryEat(",") ) 239 if( !tryEat(",") )
240 { 240 {
241 eat("}", "for the end of table literal"); 241 eat("}", "for the end of table literal");
242 break; 242 break;
243 } 243 }
244 } 244 }
245 return e; 245 return e;
................................................................................................................................................................................
250 if( lex.empty ) 250 if( lex.empty )
251 throw genex!UnexpectedEOF(currentPosition(), "Reached EO 251 throw genex!UnexpectedEOF(currentPosition(), "Reached EO
252 252
253 auto pos = lex.front.pos; 253 auto pos = lex.front.pos;
254 if( lex.front.quoted ) 254 if( lex.front.quoted )
255 { 255 {
256 scope(exit) lex.popFront; 256 scope(exit) lex.popFront;
257 return new StrLiteral(pos, lex.front.str); | 257 return new Str(pos, lex.front.str);
258 } 258 }
259 if( isNumber(lex.front.str) ) 259 if( isNumber(lex.front.str) )
260 { 260 {
261 scope(exit) lex.popFront; 261 scope(exit) lex.popFront;
262 return new IntLiteral(pos, BigInt(cast(string)lex.front. | 262 return new Int(pos, BigInt(cast(string)lex.front.str));
263 } 263 }
264 if( tryEat("@") ) 264 if( tryEat("@") )
265 { 265 {
266 auto lay = "@"~eatId("for layer ID"); 266 auto lay = "@"~eatId("for layer ID");
267 eat("(", "for layered execution"); 267 eat("(", "for layered execution");
268 auto e = Body(); 268 auto e = Body();
269 eat(")", "after "~lay~"(..."); 269 eat(")", "after "~lay~"(...");
270 return new LayExpression(pos, lay, e); | 270 return new Lay(pos, lay, e);
271 } 271 }
272 if( tryEat("(") ) 272 if( tryEat("(") )
273 { 273 {
274 auto e = Body(); 274 auto e = Body();
275 eat(")", "after parenthesized expression"); 275 eat(")", "after parenthesized expression");
276 return e; 276 return e;
277 } 277 }
278 if( tryEat("{") ) 278 if( tryEat("{") )
279 { 279 {
280 AST e = new FuncallExpression(pos, new VarExpression(pos | 280 AST e = new App(pos, new Var(pos,"{}"));
281 return parseTableSetAfterBrace(e); 281 return parseTableSetAfterBrace(e);
282 } 282 }
283 if( tryEat("if") ) 283 if( tryEat("if") )
284 { 284 {
285 eat("(", "after if"); 285 eat("(", "after if");
286 auto cond = E(0); 286 auto cond = E(0);
287 eat(")", "after if condition"); 287 eat(")", "after if condition");
................................................................................................................................................................................
292 auto el = doNothingExpression(); 292 auto el = doNothingExpression();
293 auto elsePos = (lex.empty ? LexPosition.dummy : lex.fron 293 auto elsePos = (lex.empty ? LexPosition.dummy : lex.fron
294 if( tryEat("else") ) { 294 if( tryEat("else") ) {
295 eat("{", "after else"); 295 eat("{", "after else");
296 el = Body(); 296 el = Body();
297 eat("}", "after else body"); 297 eat("}", "after else body");
298 } 298 }
299 return new FuncallExpression(pos, | 299 return new App(pos,
300 new VarExpression(pos, "if"), | 300 new Var(pos, "if"),
301 cond, 301 cond,
302 new FunLiteral(thenPos, [], th), | 302 new Fun(thenPos, [], th),
303 new FunLiteral(elsePos, [], el) | 303 new Fun(elsePos, [], el)
304 ); 304 );
305 } 305 }
306 if( tryEat("case") ) 306 if( tryEat("case") )
307 { 307 {
308 return parsePatternMatch(pos); 308 return parsePatternMatch(pos);
309 } 309 }
310 if( tryEat("fun") || tryEat("\u03BB") ) // lambda!! 310 if( tryEat("fun") || tryEat("\u03BB") ) // lambda!!
311 { 311 {
312 eat("(", "after fun"); 312 eat("(", "after fun");
313 return parseLambdaAfterOpenParen(pos); 313 return parseLambdaAfterOpenParen(pos);
314 } 314 }
315 scope(exit) lex.popFront; 315 scope(exit) lex.popFront;
316 return new VarExpression(pos, lex.front.str); | 316 return new Var(pos, lex.front.str);
317 } 317 }
318 318
319 AST parsePatternMatch(LexPosition pos) 319 AST parsePatternMatch(LexPosition pos)
320 { 320 {
321 // case( pmExpr )cases 321 // case( pmExpr )cases
322 //==> 322 //==>
323 // let pmVar = pmExpr in (... let pmTryFirst = ... in pmTryFir 323 // let pmVar = pmExpr in (... let pmTryFirst = ... in pmTryFir
324 eat("(", "after case"); 324 eat("(", "after case");
325 AST pmExpr = E(0); 325 AST pmExpr = E(0);
326 eat(")", "after case"); 326 eat(")", "after case");
327 string pmVar = freshVarName(); 327 string pmVar = freshVarName();
328 string pmTryFirst = freshVarName(); 328 string pmTryFirst = freshVarName();
329 AST pmBody = parsePatternMatchCases(pmVar, pmTryFirst, 329 AST pmBody = parsePatternMatchCases(pmVar, pmTryFirst,
330 new FuncallExpression(pos, new VarExpression(pos, pmTryF | 330 new App(pos, new Var(pos, pmTryFirst)));
331 return new LetExpression(pos, pmVar, [], pmExpr, pmBody); | 331 return new Let(pos, pmVar, [], pmExpr, pmBody);
332 } 332 }
333 333
334 AST parsePatternMatchCases(string pmVar, string tryThisBranchVar, AST th 334 AST parsePatternMatchCases(string pmVar, string tryThisBranchVar, AST th
335 { 335 {
336 // when( pat ) { cBody } 336 // when( pat ) { cBody }
337 //==> 337 //==>
338 // ... let failBranchVar = ... in 338 // ... let failBranchVar = ... in
................................................................................................................................................................................
343 string failBranchVar = freshVarName(); 343 string failBranchVar = freshVarName();
344 344
345 eat("(", "after when"); 345 eat("(", "after when");
346 auto pr = parsePattern(); 346 auto pr = parsePattern();
347 eat(")", "after when"); 347 eat(")", "after when");
348 eat("{", "after pattern"); 348 eat("{", "after pattern");
349 AST cBody = Body(); 349 AST cBody = Body();
350 AST judgement = new FuncallExpression(pos, new VarExpres | 350 AST judgement = new App(pos, new Var(pos, "if"),
351 ppTest(pmVar, pr), new FunLiteral(pos,[],ppBind( | 351 ppTest(pmVar, pr), new Fun(pos,[],ppBind(pmVar,
352 new VarExpression(pos, failBranchVar)); | 352 new Var(pos, failBranchVar));
353 eat("}", "after pattern clause"); 353 eat("}", "after pattern clause");
354 return parsePatternMatchCases(pmVar, failBranchVar, 354 return parsePatternMatchCases(pmVar, failBranchVar,
355 new LetExpression(pos, tryThisBranchVar, [], | 355 new Let(pos, tryThisBranchVar, [],
356 new FunLiteral(pos,[],judgement), thenDo | 356 new Fun(pos,[],judgement), thenDoThis)
357 ); 357 );
358 } 358 }
359 else 359 else
360 { 360 {
361 auto pos = currentPosition(); 361 auto pos = currentPosition();
362 AST doNothing = new FunLiteral(pos,[], | 362 AST doNothing = new Fun(pos,[],
363 new StrLiteral(pos, sprintf!"(pattern match fail | 363 new Str(pos, sprintf!"(pattern match failure:%s)
364 return new LetExpression(currentPosition(), tryThisBranc | 364 return new Let(currentPosition(), tryThisBranchVar, [],
365 } 365 }
366 } 366 }
367 367
368 // hageshiku tenuki 368 // hageshiku tenuki
369 abstract class SinglePattern 369 abstract class SinglePattern
370 { 370 {
371 string[] path; 371 string[] path;
372 mixin SimpleClass; 372 mixin SimpleClass;
373 private AST access(string pmVar, string[] path) { 373 private AST access(string pmVar, string[] path) {
374 auto pos = currentPosition(); 374 auto pos = currentPosition();
375 AST e = new VarExpression(pos, pmVar); | 375 AST e = new Var(pos, pmVar);
376 foreach(p; path) 376 foreach(p; path)
377 e = new FuncallExpression(pos, new VarExpression | 377 e = new App(pos, new Var(pos, "."), e, new Str(p
378 return e; 378 return e;
379 } 379 }
380 private AST has(AST e, string k) { 380 private AST has(AST e, string k) {
381 auto pos = currentPosition(); 381 auto pos = currentPosition();
382 return opAndAnd( 382 return opAndAnd(
383 new FuncallExpression(pos, new VarExpression(pos | 383 new App(pos, new Var(pos, "_istable"), e),
384 new FuncallExpression(pos, new VarExpression(pos | 384 new App(pos, new Var(pos, ".?"), e, new Str(pos,
385 ); 385 );
386 } 386 }
387 private AST opAndAnd(AST a, AST b) { 387 private AST opAndAnd(AST a, AST b) {
388 if( a is null ) return b; 388 if( a is null ) return b;
389 if( b is null ) return a; 389 if( b is null ) return a;
390 auto pos = currentPosition(); 390 auto pos = currentPosition();
391 return new FuncallExpression(pos, | 391 return new App(pos,
392 new VarExpression(pos, "if"), | 392 new Var(pos, "if"),
393 a, 393 a,
394 new FunLiteral(pos, [], b), | 394 new Fun(pos, [], b),
395 new FunLiteral(pos, [], new IntLiteral(pos, 0)) | 395 new Fun(pos, [], new Int(pos, 0))
396 ); 396 );
397 } 397 }
398 AST ppTest(string pmVar) { 398 AST ppTest(string pmVar) {
399 AST c = null; 399 AST c = null;
400 for(int i=0; i<path.length; ++i) 400 for(int i=0; i<path.length; ++i)
401 c = opAndAnd(c, has(access(pmVar,path[0..i]), pa 401 c = opAndAnd(c, has(access(pmVar,path[0..i]), pa
402 return c; 402 return c;
................................................................................................................................................................................
409 } 409 }
410 class VarPattern : SinglePattern 410 class VarPattern : SinglePattern
411 { 411 {
412 string name; 412 string name;
413 mixin SimpleClass; 413 mixin SimpleClass;
414 AST ppBind(string pmVar, AST thenDoThis) { 414 AST ppBind(string pmVar, AST thenDoThis) {
415 auto pos = currentPosition(); 415 auto pos = currentPosition();
416 return new LetExpression(pos, name, [], access(pmVar,pat | 416 return new Let(pos, name, [], access(pmVar,path), thenDo
417 } 417 }
418 } 418 }
419 class ConstantPattern : SinglePattern 419 class ConstantPattern : SinglePattern
420 { 420 {
421 AST e; 421 AST e;
422 mixin SimpleClass; 422 mixin SimpleClass;
423 AST ppTest(string pmVar) { 423 AST ppTest(string pmVar) {
424 auto pos = currentPosition(); 424 auto pos = currentPosition();
425 return opAndAnd( super.ppTest(pmVar), 425 return opAndAnd( super.ppTest(pmVar),
426 new FuncallExpression(pos, new VarExpression(pos | 426 new App(pos, new Var(pos,"=="), access(pmVar,pat
427 ); 427 );
428 } 428 }
429 } 429 }
430 430
431 SinglePattern[] parsePattern(string[] path = null) 431 SinglePattern[] parsePattern(string[] path = null)
432 { 432 {
433 SinglePattern[] result; 433 SinglePattern[] result;
................................................................................................................................................................................
441 } while( tryEat(",") ); 441 } while( tryEat(",") );
442 eat("}", "at the end of table pattern"); 442 eat("}", "at the end of table pattern");
443 } 443 }
444 } 444 }
445 else 445 else
446 { 446 {
447 AST e = E(0); 447 AST e = E(0);
448 if(auto ev = cast(VarExpression)e) | 448 if(auto ev = cast(Var)e)
449 if(ev.name == "_") 449 if(ev.name == "_")
450 result ~= new WildPattern(path); 450 result ~= new WildPattern(path);
451 else 451 else
452 result ~= new VarPattern(path, ev.name); 452 result ~= new VarPattern(path, ev.name);
453 else 453 else
454 result ~= new ConstantPattern(path, e); 454 result ~= new ConstantPattern(path, e);
455 } 455 }
................................................................................................................................................................................
460 { 460 {
461 auto pos = currentPosition(); 461 auto pos = currentPosition();
462 AST cond = null; 462 AST cond = null;
463 foreach(p; pats) { 463 foreach(p; pats) {
464 AST c2 = p.ppTest(pmVar); 464 AST c2 = p.ppTest(pmVar);
465 if( c2 !is null ) 465 if( c2 !is null )
466 cond = cond is null ? c2 466 cond = cond is null ? c2
467 : new FuncallExpression(pos, new VarExpressi | 467 : new App(pos, new Var(pos,"&&"), cond, c2);
468 } 468 }
469 return cond is null ? new IntLiteral(currentPosition(), 1) : con | 469 return cond is null ? new Int(currentPosition(), 1) : cond;
470 } 470 }
471 471
472 AST ppBind(string pmVar, SinglePattern[] pats, AST thenDoThis) 472 AST ppBind(string pmVar, SinglePattern[] pats, AST thenDoThis)
473 { 473 {
474 foreach(p; pats) 474 foreach(p; pats)
475 thenDoThis = p.ppBind(pmVar, thenDoThis); 475 thenDoThis = p.ppBind(pmVar, thenDoThis);
476 return thenDoThis; 476 return thenDoThis;
477 } 477 }
478 478
479 AST parseId() 479 AST parseId()
480 { 480 {
481 scope(exit) lex.popFront; 481 scope(exit) lex.popFront;
482 return new StrLiteral(currentPosition(), lex.front.str); | 482 return new Str(currentPosition(), lex.front.str);
483 } 483 }
484 484
485 AST parseLambdaAfterOpenParen(immutable LexPosition pos) 485 AST parseLambdaAfterOpenParen(immutable LexPosition pos)
486 { 486 {
487 Parameter[] params; 487 Parameter[] params;
488 while( !tryEat(")") ) 488 while( !tryEat(")") )
489 { 489 {
................................................................................................................................................................................
492 eat(")", "after function parameters"); 492 eat(")", "after function parameters");
493 break; 493 break;
494 } 494 }
495 } 495 }
496 eat("{", "after function parameters"); 496 eat("{", "after function parameters");
497 auto funbody = Body(); 497 auto funbody = Body();
498 eat("}", "after function body"); 498 eat("}", "after function body");
499 return new FunLiteral(pos, params, funbody); | 499 return new Fun(pos, params, funbody);
500 } 500 }
501 501
502 Parameter parseParam() 502 Parameter parseParam()
503 { 503 {
504 string var; 504 string var;
505 string[] lay; 505 string[] lay;
506 while( !closingBracket() && !lex.empty && lex.front.str!="," ) 506 while( !closingBracket() && !lex.empty && lex.front.str!="," )
................................................................................................................................................................................
554 throw genex!ParseException(currentPosition(), "identifie 554 throw genex!ParseException(currentPosition(), "identifie
555 scope(exit) lex.popFront; 555 scope(exit) lex.popFront;
556 return lex.front.str; 556 return lex.front.str;
557 } 557 }
558 558
559 AST doNothingExpression() 559 AST doNothingExpression()
560 { 560 {
561 return new StrLiteral(currentPosition(), "(empty function body)" | 561 return new Str(currentPosition(), "(empty function body)");
562 } 562 }
563 563
564 immutable(LexPosition) currentPosition() 564 immutable(LexPosition) currentPosition()
565 { 565 {
566 return lex.empty ? null : lex.front.pos; 566 return lex.empty ? null : lex.front.pos;
567 } 567 }
568 } 568 }