Mercurial Hosting > luan
comparison src/luan/interp/LuanParser.java @ 107:dbf459397217
change OutputStatement to JspExpressions;
fix multiple results handling;
git-svn-id: https://luan-java.googlecode.com/svn/trunk@108 21e917c8-12df-6dd8-5cb6-c86387c605b9
author | fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9> |
---|---|
date | Mon, 19 May 2014 09:17:57 +0000 |
parents | 1a29dd3888f6 |
children | 3c404a296995 |
comparison
equal
deleted
inserted
replaced
106:1a29dd3888f6 | 107:dbf459397217 |
---|---|
141 if( t==null ) | 141 if( t==null ) |
142 throw parser.exception(msg); | 142 throw parser.exception(msg); |
143 return t; | 143 return t; |
144 } | 144 } |
145 | 145 |
146 private static Expr expr(Code code) { | |
147 if( code instanceof Expressions ) | |
148 return new ExpressionsExpr((Expressions)code); | |
149 return (Expr)code; | |
150 } | |
151 | |
146 private FnDef newFnDef(int start,Stmt stmt) { | 152 private FnDef newFnDef(int start,Stmt stmt) { |
147 return new FnDef( se(start), stmt, frame.stackSize, symbolsSize(), frame.isVarArg, frame.upValueGetters.toArray(NO_UP_VALUE_GETTERS) ); | 153 return new FnDef( se(start), stmt, frame.stackSize, symbolsSize(), frame.isVarArg, frame.upValueGetters.toArray(NO_UP_VALUE_GETTERS) ); |
148 } | 154 } |
149 | 155 |
150 private FnDef RequiredTarget() throws ParseException { | 156 private FnDef RequiredTarget() throws ParseException { |
184 parser.begin(); | 190 parser.begin(); |
185 if( parser.match( ';' ) ) | 191 if( parser.match( ';' ) ) |
186 return parser.success(); | 192 return parser.success(); |
187 if( parser.match( "--" ) ) { | 193 if( parser.match( "--" ) ) { |
188 while( parser.noneOf("\r\n") ); | 194 while( parser.noneOf("\r\n") ); |
189 EndOfLine(); | 195 } |
190 return parser.success(); | 196 return EndOfLine() ? parser.success() : parser.failure(); |
191 } | |
192 if( EndOfLine() ) | |
193 return parser.success(); | |
194 parser.rollback(); | |
195 Stmt stmt = OutputStmt(); | |
196 if( stmt != null ) { | |
197 stmts.add(stmt); | |
198 return parser.success(); | |
199 } | |
200 return parser.failure(); | |
201 } | 197 } |
202 | 198 |
203 private boolean EndOfLine() { | 199 private boolean EndOfLine() { |
204 return parser.match( "\r\n" ) || parser.match( '\r' ) || parser.match( '\n' ); | 200 return parser.match( "\r\n" ) || parser.match( '\r' ) || parser.match( '\n' ); |
205 } | 201 } |
225 ) { | 221 ) { |
226 stmts.add(stmt); | 222 stmts.add(stmt); |
227 } | 223 } |
228 } | 224 } |
229 | 225 |
230 private Stmt OutputStmt() throws ParseException { | 226 private Expressions JspExpressions() throws ParseException { |
231 int start = parser.begin(); | 227 int start = parser.begin(); |
232 if( !parser.match( "%>" ) ) | 228 if( !parser.match( "%>" ) ) |
233 return parser.failure(null); | 229 return parser.failure(null); |
234 EndOfLine(); | 230 EndOfLine(); |
235 ExpList.Builder builder = new ExpList.Builder(); | 231 ExpList.Builder builder = new ExpList.Builder(); |
238 Spaces(); | 234 Spaces(); |
239 builder.add( RequiredExpr() ); | 235 builder.add( RequiredExpr() ); |
240 RequiredMatch( "%>" ); | 236 RequiredMatch( "%>" ); |
241 } else if( parser.match( "<%" ) ) { | 237 } else if( parser.match( "<%" ) ) { |
242 Spaces(); | 238 Spaces(); |
243 return parser.success(new OutputStmt( se(start), builder.build() )); | 239 return parser.success(builder.build()); |
244 } else { | 240 } else { |
245 int i = parser.currentIndex(); | 241 int i = parser.currentIndex(); |
246 do { | 242 do { |
247 if( parser.match( "%>" ) ) | 243 if( parser.match( "%>" ) ) |
248 throw parser.exception("'%>' unexpected"); | 244 throw parser.exception("'%>' unexpected"); |
249 if( !parser.anyChar() ) | 245 if( !parser.anyChar() ) |
250 throw parser.exception("Unclosed output statement"); | 246 throw parser.exception("Unclosed JSP expressions"); |
251 } while( !parser.test( "<%" ) ); | 247 } while( !parser.test( "<%" ) ); |
252 String match = parser.textFrom(i); | 248 String match = parser.textFrom(i); |
253 builder.add( new ConstExpr(match) ); | 249 builder.add( new ConstExpr(match) ); |
254 } | 250 } |
255 } | 251 } |
272 | 268 |
273 int start = parser.currentIndex(); | 269 int start = parser.currentIndex(); |
274 Var var = nameVar(start,RequiredName()); | 270 Var var = nameVar(start,RequiredName()); |
275 while( parser.match( '.' ) ) { | 271 while( parser.match( '.' ) ) { |
276 Spaces(); | 272 Spaces(); |
277 var = indexVar( start, var.expr(), NameExpr(false) ); | 273 var = indexVar( start, expr(var.expr()), NameExpr(false) ); |
278 } | 274 } |
279 Settable fnName = var.settable(); | 275 Settable fnName = var.settable(); |
280 | 276 |
281 FnDef fnDef = RequiredFunction(false); | 277 FnDef fnDef = RequiredFunction(false); |
282 return parser.success( new SetStmt(fnName,fnDef) ); | 278 return parser.success( new SetStmt(fnName,fnDef) ); |
307 if( !Keyword("for") ) | 303 if( !Keyword("for") ) |
308 return parser.failure(null); | 304 return parser.failure(null); |
309 List<String> names = RequiredNameList(false); | 305 List<String> names = RequiredNameList(false); |
310 if( !Keyword("in") ) | 306 if( !Keyword("in") ) |
311 return parser.failure(null); | 307 return parser.failure(null); |
312 Expr expr = RequiredExpr(); | 308 Expr expr = expr(RequiredExpr()); |
313 RequiredKeyword("do"); | 309 RequiredKeyword("do"); |
314 addSymbols(names); | 310 addSymbols(names); |
315 Stmt loop = RequiredLoopBlock(); | 311 Stmt loop = RequiredLoopBlock(); |
316 RequiredKeyword("end"); | 312 RequiredKeyword("end"); |
317 Stmt stmt = new GenericForStmt( se(start), stackStart, symbolsSize() - stackStart, expr, loop ); | 313 Stmt stmt = new GenericForStmt( se(start), stackStart, symbolsSize() - stackStart, expr, loop ); |
324 if( !Keyword("for") ) | 320 if( !Keyword("for") ) |
325 return parser.failure(null); | 321 return parser.failure(null); |
326 String name = RequiredName(); | 322 String name = RequiredName(); |
327 RequiredMatch( "=" ); | 323 RequiredMatch( "=" ); |
328 Spaces(); | 324 Spaces(); |
329 Expr from = RequiredExpr(); | 325 Expr from = expr(RequiredExpr()); |
330 Expr to; | 326 Expr to; |
331 Expr step; | 327 Expr step; |
332 if( parser.match(',') ) { | 328 if( parser.match(',') ) { |
333 Spaces(); | 329 Spaces(); |
334 to = RequiredExpr(); | 330 to = expr(RequiredExpr()); |
335 if( parser.match(',') ) { | 331 if( parser.match(',') ) { |
336 Spaces(); | 332 Spaces(); |
337 step = RequiredExpr(); | 333 step = expr(RequiredExpr()); |
338 } else { | 334 } else { |
339 step = new ConstExpr(1); | 335 step = new ConstExpr(1); |
340 } | 336 } |
341 } else { | 337 } else { |
342 RequiredKeyword("to"); | 338 RequiredKeyword("to"); |
343 to = RequiredExpr(); | 339 to = expr(RequiredExpr()); |
344 step = Keyword("step") ? RequiredExpr() : new ConstExpr(1); | 340 step = Keyword("step") ? expr(RequiredExpr()) : new ConstExpr(1); |
345 } | 341 } |
346 addSymbol(name); // add "for" var to symbols | 342 addSymbol(name); // add "for" var to symbols |
347 RequiredKeyword("do"); | 343 RequiredKeyword("do"); |
348 Stmt loop = RequiredLoopBlock(); | 344 Stmt loop = RequiredLoopBlock(); |
349 RequiredKeyword("end"); | 345 RequiredKeyword("end"); |
423 | 419 |
424 private Stmt WhileStmt() throws ParseException { | 420 private Stmt WhileStmt() throws ParseException { |
425 parser.begin(); | 421 parser.begin(); |
426 if( !Keyword("while") ) | 422 if( !Keyword("while") ) |
427 return parser.failure(null); | 423 return parser.failure(null); |
428 Expr cnd = RequiredExpr(); | 424 Expr cnd = expr(RequiredExpr()); |
429 RequiredKeyword("do"); | 425 RequiredKeyword("do"); |
430 Stmt loop = RequiredLoopBlock(); | 426 Stmt loop = RequiredLoopBlock(); |
431 RequiredKeyword("end"); | 427 RequiredKeyword("end"); |
432 return parser.success( new WhileStmt(cnd,loop) ); | 428 return parser.success( new WhileStmt(cnd,loop) ); |
433 } | 429 } |
436 parser.begin(); | 432 parser.begin(); |
437 if( !Keyword("repeat") ) | 433 if( !Keyword("repeat") ) |
438 return parser.failure(null); | 434 return parser.failure(null); |
439 Stmt loop = RequiredLoopBlock(); | 435 Stmt loop = RequiredLoopBlock(); |
440 RequiredKeyword("until"); | 436 RequiredKeyword("until"); |
441 Expr cnd = RequiredExpr(); | 437 Expr cnd = expr(RequiredExpr()); |
442 return parser.success( new RepeatStmt(loop,cnd) ); | 438 return parser.success( new RepeatStmt(loop,cnd) ); |
443 } | 439 } |
444 | 440 |
445 private Stmt RequiredLoopBlock() throws ParseException { | 441 private Stmt RequiredLoopBlock() throws ParseException { |
446 incLoops(); | 442 incLoops(); |
455 return parser.failure(null); | 451 return parser.failure(null); |
456 return parser.success( IfStmt2() ); | 452 return parser.success( IfStmt2() ); |
457 } | 453 } |
458 | 454 |
459 private Stmt IfStmt2() throws ParseException { | 455 private Stmt IfStmt2() throws ParseException { |
460 Expr cnd = RequiredExpr(); | 456 Expr cnd = expr(RequiredExpr()); |
461 RequiredKeyword("then"); | 457 RequiredKeyword("then"); |
462 Stmt thenBlock = RequiredBlock(); | 458 Stmt thenBlock = RequiredBlock(); |
463 Stmt elseBlock; | 459 Stmt elseBlock; |
464 if( Keyword("elseif") ) { | 460 if( Keyword("elseif") ) { |
465 elseBlock = IfStmt2(); | 461 elseBlock = IfStmt2(); |
507 if( var==null ) | 503 if( var==null ) |
508 return null; | 504 return null; |
509 return var.settable(); | 505 return var.settable(); |
510 } | 506 } |
511 | 507 |
512 private Expr RequiredExpr() throws ParseException { | 508 private Code RequiredExpr() throws ParseException { |
513 return RequiredExpr(false); | 509 return RequiredExpr(false); |
514 } | 510 } |
515 | 511 |
516 private Expr Expr() throws ParseException { | 512 private Code Expr() throws ParseException { |
517 return Expr(false); | 513 return Expr(false); |
518 } | 514 } |
519 | 515 |
520 private Expr RequiredExpr(boolean inParens) throws ParseException { | 516 private Code RequiredExpr(boolean inParens) throws ParseException { |
521 parser.begin(); | 517 parser.begin(); |
522 return parser.success(required(Expr(inParens),"Bad expression")); | 518 return parser.success(required(Expr(inParens),"Bad expression")); |
523 } | 519 } |
524 | 520 |
525 private Expr Expr(boolean inParens) throws ParseException { | 521 private Code Expr(boolean inParens) throws ParseException { |
526 parser.begin(); | 522 parser.begin(); |
527 Expressions exps = VarArgs(inParens); | 523 Code exp; |
528 if( exps != null ) | 524 return (exp = VarArgs(inParens)) != null |
529 return parser.success( new ExpressionsExpr(exps) ); | 525 || (exp = JspExpressions()) != null |
530 Expr exp = OrExpr(inParens); | 526 || (exp = OrExpr(inParens)) != null |
527 ? parser.success(exp) | |
528 : parser.failure((Code)null) | |
529 ; | |
530 } | |
531 | |
532 private Code OrExpr(boolean inParens) throws ParseException { | |
533 int start = parser.begin(); | |
534 Code exp = AndExpr(inParens); | |
531 if( exp==null ) | 535 if( exp==null ) |
532 return parser.failure(null); | 536 return parser.failure(null); |
537 while( Keyword("or",inParens) ) { | |
538 exp = new OrExpr( se(start), expr(exp), required(expr(AndExpr(inParens))) ); | |
539 } | |
533 return parser.success(exp); | 540 return parser.success(exp); |
534 } | 541 } |
535 | 542 |
536 private Expr OrExpr(boolean inParens) throws ParseException { | 543 private Code AndExpr(boolean inParens) throws ParseException { |
537 int start = parser.begin(); | 544 int start = parser.begin(); |
538 Expr exp = AndExpr(inParens); | 545 Code exp = RelExpr(inParens); |
539 if( exp==null ) | 546 if( exp==null ) |
540 return parser.failure(null); | 547 return parser.failure(null); |
541 while( Keyword("or",inParens) ) { | 548 while( Keyword("and",inParens) ) { |
542 exp = new OrExpr( se(start), exp, required(AndExpr(inParens)) ); | 549 exp = new AndExpr( se(start), expr(exp), required(expr(RelExpr(inParens))) ); |
543 } | 550 } |
544 return parser.success(exp); | 551 return parser.success(exp); |
545 } | 552 } |
546 | 553 |
547 private Expr AndExpr(boolean inParens) throws ParseException { | 554 private Code RelExpr(boolean inParens) throws ParseException { |
548 int start = parser.begin(); | 555 int start = parser.begin(); |
549 Expr exp = RelExpr(inParens); | 556 Code exp = ConcatExpr(inParens); |
550 if( exp==null ) | |
551 return parser.failure(null); | |
552 while( Keyword("and",inParens) ) { | |
553 exp = new AndExpr( se(start), exp, required(RelExpr(inParens)) ); | |
554 } | |
555 return parser.success(exp); | |
556 } | |
557 | |
558 private Expr RelExpr(boolean inParens) throws ParseException { | |
559 int start = parser.begin(); | |
560 Expr exp = ConcatExpr(inParens); | |
561 if( exp==null ) | 557 if( exp==null ) |
562 return parser.failure(null); | 558 return parser.failure(null); |
563 while(true) { | 559 while(true) { |
564 if( parser.match("==") ) { | 560 if( parser.match("==") ) { |
565 Spaces(inParens); | 561 Spaces(inParens); |
566 exp = new EqExpr( se(start), exp, required(ConcatExpr(inParens)) ); | 562 exp = new EqExpr( se(start), expr(exp), required(expr(ConcatExpr(inParens))) ); |
567 } else if( parser.match("~=") ) { | 563 } else if( parser.match("~=") ) { |
568 Spaces(inParens); | 564 Spaces(inParens); |
569 exp = new NotExpr( se(start), new EqExpr( se(start), exp, required(ConcatExpr(inParens)) ) ); | 565 exp = new NotExpr( se(start), new EqExpr( se(start), expr(exp), required(expr(ConcatExpr(inParens))) ) ); |
570 } else if( parser.match("<=") ) { | 566 } else if( parser.match("<=") ) { |
571 Spaces(inParens); | 567 Spaces(inParens); |
572 exp = new LeExpr( se(start), exp, required(ConcatExpr(inParens)) ); | 568 exp = new LeExpr( se(start), expr(exp), required(expr(ConcatExpr(inParens))) ); |
573 } else if( parser.match(">=") ) { | 569 } else if( parser.match(">=") ) { |
574 Spaces(inParens); | 570 Spaces(inParens); |
575 exp = new LeExpr( se(start), required(ConcatExpr(inParens)), exp ); | 571 exp = new LeExpr( se(start), required(expr(ConcatExpr(inParens))), expr(exp) ); |
576 } else if( parser.match("<") ) { | 572 } else if( parser.match("<") ) { |
577 Spaces(inParens); | 573 Spaces(inParens); |
578 exp = new LtExpr( se(start), exp, required(ConcatExpr(inParens)) ); | 574 exp = new LtExpr( se(start), expr(exp), required(expr(ConcatExpr(inParens))) ); |
579 } else if( parser.match(">") ) { | 575 } else if( parser.match(">") ) { |
580 Spaces(inParens); | 576 Spaces(inParens); |
581 exp = new LtExpr( se(start), required(ConcatExpr(inParens)), exp ); | 577 exp = new LtExpr( se(start), required(expr(ConcatExpr(inParens))), expr(exp) ); |
582 } else | 578 } else |
583 break; | 579 break; |
584 } | 580 } |
585 return parser.success(exp); | 581 return parser.success(exp); |
586 } | 582 } |
587 | 583 |
588 private Expr ConcatExpr(boolean inParens) throws ParseException { | 584 private Code ConcatExpr(boolean inParens) throws ParseException { |
589 int start = parser.begin(); | 585 int start = parser.begin(); |
590 Expr exp = SumExpr(inParens); | 586 Code exp = SumExpr(inParens); |
591 if( exp==null ) | 587 if( exp==null ) |
592 return parser.failure(null); | 588 return parser.failure(null); |
593 if( parser.match("..") ) { | 589 if( parser.match("..") ) { |
594 Spaces(inParens); | 590 Spaces(inParens); |
595 exp = new ConcatExpr( se(start), exp, required(ConcatExpr(inParens)) ); | 591 exp = new ConcatExpr( se(start), expr(exp), required(expr(ConcatExpr(inParens))) ); |
596 } | 592 } |
597 return parser.success(exp); | 593 return parser.success(exp); |
598 } | 594 } |
599 | 595 |
600 private Expr SumExpr(boolean inParens) throws ParseException { | 596 private Code SumExpr(boolean inParens) throws ParseException { |
601 int start = parser.begin(); | 597 int start = parser.begin(); |
602 Expr exp = TermExpr(inParens); | 598 Code exp = TermExpr(inParens); |
603 if( exp==null ) | 599 if( exp==null ) |
604 return parser.failure(null); | 600 return parser.failure(null); |
605 while(true) { | 601 while(true) { |
606 if( parser.match('+') ) { | 602 if( parser.match('+') ) { |
607 Spaces(inParens); | 603 Spaces(inParens); |
608 exp = new AddExpr( se(start), exp, required(TermExpr(inParens)) ); | 604 exp = new AddExpr( se(start), expr(exp), required(expr(TermExpr(inParens))) ); |
609 } else if( Minus() ) { | 605 } else if( Minus() ) { |
610 Spaces(inParens); | 606 Spaces(inParens); |
611 exp = new SubExpr( se(start), exp, required(TermExpr(inParens)) ); | 607 exp = new SubExpr( se(start), expr(exp), required(expr(TermExpr(inParens))) ); |
612 } else | 608 } else |
613 break; | 609 break; |
614 } | 610 } |
615 return parser.success(exp); | 611 return parser.success(exp); |
616 } | 612 } |
618 private boolean Minus() { | 614 private boolean Minus() { |
619 parser.begin(); | 615 parser.begin(); |
620 return parser.match('-') && !parser.match('-') ? parser.success() : parser.failure(); | 616 return parser.match('-') && !parser.match('-') ? parser.success() : parser.failure(); |
621 } | 617 } |
622 | 618 |
623 private Expr TermExpr(boolean inParens) throws ParseException { | 619 private Code TermExpr(boolean inParens) throws ParseException { |
624 int start = parser.begin(); | 620 int start = parser.begin(); |
625 Expr exp = UnaryExpr(inParens); | 621 Code exp = UnaryExpr(inParens); |
626 if( exp==null ) | 622 if( exp==null ) |
627 return parser.failure(null); | 623 return parser.failure(null); |
628 while(true) { | 624 while(true) { |
629 if( parser.match('*') ) { | 625 if( parser.match('*') ) { |
630 Spaces(inParens); | 626 Spaces(inParens); |
631 exp = new MulExpr( se(start), exp, required(UnaryExpr(inParens)) ); | 627 exp = new MulExpr( se(start), expr(exp), required(expr(UnaryExpr(inParens))) ); |
632 } else if( parser.match('/') ) { | 628 } else if( parser.match('/') ) { |
633 Spaces(inParens); | 629 Spaces(inParens); |
634 exp = new DivExpr( se(start), exp, required(UnaryExpr(inParens)) ); | 630 exp = new DivExpr( se(start), expr(exp), required(expr(UnaryExpr(inParens))) ); |
635 } else if( parser.match('%') ) { | 631 } else if( Mod() ) { |
636 Spaces(inParens); | 632 Spaces(inParens); |
637 exp = new ModExpr( se(start), exp, required(UnaryExpr(inParens)) ); | 633 exp = new ModExpr( se(start), expr(exp), required(expr(UnaryExpr(inParens))) ); |
638 } else | 634 } else |
639 break; | 635 break; |
640 } | 636 } |
641 return parser.success(exp); | 637 return parser.success(exp); |
642 } | 638 } |
643 | 639 |
644 private Expr UnaryExpr(boolean inParens) throws ParseException { | 640 private boolean Mod() { |
641 parser.begin(); | |
642 return parser.match('%') && !parser.match('>') ? parser.success() : parser.failure(); | |
643 } | |
644 | |
645 private Code UnaryExpr(boolean inParens) throws ParseException { | |
645 int start = parser.begin(); | 646 int start = parser.begin(); |
646 if( parser.match('#') ) { | 647 if( parser.match('#') ) { |
647 Spaces(inParens); | 648 Spaces(inParens); |
648 return parser.success( new LenExpr( se(start), required(UnaryExpr(inParens)) ) ); | 649 return parser.success( new LenExpr( se(start), required(expr(UnaryExpr(inParens))) ) ); |
649 } | 650 } |
650 if( Minus() ) { | 651 if( Minus() ) { |
651 Spaces(inParens); | 652 Spaces(inParens); |
652 return parser.success( new UnmExpr( se(start), required(UnaryExpr(inParens)) ) ); | 653 return parser.success( new UnmExpr( se(start), required(expr(UnaryExpr(inParens))) ) ); |
653 } | 654 } |
654 if( Keyword("not",inParens) ) { | 655 if( Keyword("not",inParens) ) { |
655 Spaces(inParens); | 656 Spaces(inParens); |
656 return parser.success( new NotExpr( se(start), required(UnaryExpr(inParens)) ) ); | 657 return parser.success( new NotExpr( se(start), required(expr(UnaryExpr(inParens))) ) ); |
657 } | 658 } |
658 Expr exp = PowExpr(inParens); | 659 Code exp = PowExpr(inParens); |
659 if( exp==null ) | 660 if( exp==null ) |
660 return parser.failure(null); | 661 return parser.failure(null); |
661 return parser.success(exp); | 662 return parser.success(exp); |
662 } | 663 } |
663 | 664 |
664 private Expr PowExpr(boolean inParens) throws ParseException { | 665 private Code PowExpr(boolean inParens) throws ParseException { |
665 int start = parser.begin(); | 666 int start = parser.begin(); |
666 Expr exp = SingleExpr(inParens); | 667 Code exp = SingleExpr(inParens); |
667 if( exp==null ) | 668 if( exp==null ) |
668 return parser.failure(null); | 669 return parser.failure(null); |
669 if( parser.match('^') ) { | 670 if( parser.match('^') ) { |
670 Spaces(inParens); | 671 Spaces(inParens); |
671 exp = new ConcatExpr( se(start), exp, required(PowExpr(inParens)) ); | 672 exp = new ConcatExpr( se(start), expr(exp), required(expr(PowExpr(inParens))) ); |
672 } | 673 } |
673 return parser.success(exp); | 674 return parser.success(exp); |
674 } | 675 } |
675 | 676 |
676 private Expr SingleExpr(boolean inParens) throws ParseException { | 677 private Code SingleExpr(boolean inParens) throws ParseException { |
677 parser.begin(); | 678 parser.begin(); |
678 Expr exp; | 679 Code exp; |
679 exp = FunctionExpr(inParens); | 680 exp = FunctionExpr(inParens); |
680 if( exp != null ) | 681 if( exp != null ) |
681 return parser.success(exp); | 682 return parser.success(exp); |
682 exp = TableExpr(inParens); | 683 exp = TableExpr(inParens); |
683 if( exp != null ) | 684 if( exp != null ) |
738 return parser.failure(null); | 739 return parser.failure(null); |
739 Spaces(true); | 740 Spaces(true); |
740 List<TableExpr.Field> fields = new ArrayList<TableExpr.Field>(); | 741 List<TableExpr.Field> fields = new ArrayList<TableExpr.Field>(); |
741 ExpList.Builder builder = new ExpList.Builder(); | 742 ExpList.Builder builder = new ExpList.Builder(); |
742 while( Field(fields,builder) && FieldSep() ); | 743 while( Field(fields,builder) && FieldSep() ); |
743 RequiredMatch('}'); | 744 if( !parser.match('}') ) |
745 throw parser.exception("Expected table element or '}'"); | |
744 return parser.success( new TableExpr( se(start), fields.toArray(new TableExpr.Field[0]), builder.build() ) ); | 746 return parser.success( new TableExpr( se(start), fields.toArray(new TableExpr.Field[0]), builder.build() ) ); |
745 } | 747 } |
746 | 748 |
747 private boolean FieldSep() throws ParseException { | 749 private boolean FieldSep() throws ParseException { |
748 if( !parser.anyOf(",;") ) | 750 if( !parser.anyOf(",;") ) |
755 parser.begin(); | 757 parser.begin(); |
756 Expr exp = SubExpr(true); | 758 Expr exp = SubExpr(true); |
757 if( exp==null ) | 759 if( exp==null ) |
758 exp = NameExpr(true); | 760 exp = NameExpr(true); |
759 if( exp!=null && parser.match('=') ) { | 761 if( exp!=null && parser.match('=') ) { |
760 fields.add( new TableExpr.Field( exp, required(Expr(true)) ) ); | 762 fields.add( new TableExpr.Field( exp, required(expr(Expr(true))) ) ); |
761 return parser.success(); | 763 return parser.success(); |
762 } | 764 } |
763 parser.rollback(); | 765 parser.rollback(); |
764 exp = Expr(true); | 766 Code code = Expr(true); |
765 if( exp != null ) { | 767 if( code != null ) { |
766 builder.add(exp); | 768 builder.add(code); |
767 return parser.success(); | 769 return parser.success(); |
768 } | 770 } |
769 return parser.failure(); | 771 return parser.failure(); |
770 } | 772 } |
771 | 773 |
772 private Expr VarExp(boolean inParens) throws ParseException { | 774 private Code VarExp(boolean inParens) throws ParseException { |
773 Var var = VarZ(inParens); | 775 Var var = VarZ(inParens); |
774 return var==null ? null : var.expr(); | 776 return var==null ? null : var.expr(); |
775 } | 777 } |
776 | 778 |
777 private Var VarZ(boolean inParens) throws ParseException { | 779 private Var VarZ(boolean inParens) throws ParseException { |
784 var = var2; | 786 var = var2; |
785 } | 787 } |
786 return parser.success(var); | 788 return parser.success(var); |
787 } | 789 } |
788 | 790 |
789 private Var Var2(boolean inParens,int start,Expr exp1) throws ParseException { | 791 private Var Var2(boolean inParens,int start,Code exp1) throws ParseException { |
790 Var var = VarExt(inParens,start,exp1); | 792 Var var = VarExt(inParens,start,exp1); |
791 if( var != null ) | 793 if( var != null ) |
792 return var; | 794 return var; |
793 if( parser.match("->") ) { | 795 if( parser.match("->") ) { |
794 Spaces(inParens); | 796 Spaces(inParens); |
795 ExpList.Builder builder = new ExpList.Builder(); | 797 ExpList.Builder builder = new ExpList.Builder(); |
796 builder.add(exp1); | 798 builder.add(exp1); |
797 Expr exp2 = RequiredVarExpB(inParens); | 799 Expr exp2 = expr(RequiredVarExpB(inParens)); |
798 FnCall fnCall = required(Args( inParens, start, exp2, builder )); | 800 FnCall fnCall = required(Args( inParens, start, exp2, builder )); |
799 return exprVar( new ExpressionsExpr(fnCall) ); | 801 return exprVar(fnCall); |
800 } | 802 } |
801 FnCall fnCall = Args( inParens, start, exp1, new ExpList.Builder() ); | 803 FnCall fnCall = Args( inParens, start, expr(exp1), new ExpList.Builder() ); |
802 if( fnCall != null ) | 804 if( fnCall != null ) |
803 return exprVar( new ExpressionsExpr(fnCall) ); | 805 return exprVar(fnCall); |
804 return null; | 806 return null; |
805 } | 807 } |
806 | 808 |
807 private Expr RequiredVarExpB(boolean inParens) throws ParseException { | 809 private Code RequiredVarExpB(boolean inParens) throws ParseException { |
808 int start = parser.begin(); | 810 int start = parser.begin(); |
809 Var var = required(VarStart(inParens)); | 811 Var var = required(VarStart(inParens)); |
810 Var var2; | 812 Var var2; |
811 while( (var2=VarExt(inParens,start,var.expr())) != null ) { | 813 while( (var2=VarExt(inParens,start,var.expr())) != null ) { |
812 var = var2; | 814 var = var2; |
813 } | 815 } |
814 return parser.success(var.expr()); | 816 return parser.success(var.expr()); |
815 } | 817 } |
816 | 818 |
817 private Var VarExt(boolean inParens,int start,Expr exp1) throws ParseException { | 819 private Var VarExt(boolean inParens,int start,Code exp1) throws ParseException { |
818 parser.begin(); | 820 parser.begin(); |
819 Expr exp2 = SubExpr(inParens); | 821 Expr exp2 = SubExpr(inParens); |
820 exp2 = SubExpr(inParens); | 822 exp2 = SubExpr(inParens); |
821 if( exp2 != null ) | 823 if( exp2 != null ) |
822 return parser.success(indexVar(start,exp1,exp2)); | 824 return parser.success(indexVar(start,expr(exp1),exp2)); |
823 if( parser.match('.') ) { | 825 if( parser.match('.') ) { |
824 Spaces(inParens); | 826 Spaces(inParens); |
825 exp2 = NameExpr(inParens); | 827 exp2 = NameExpr(inParens); |
826 if( exp2!=null ) | 828 if( exp2!=null ) |
827 return parser.success(indexVar(start,exp1,exp2)); | 829 return parser.success(indexVar(start,expr(exp1),exp2)); |
828 } | 830 } |
829 return parser.failure(null); | 831 return parser.failure(null); |
830 } | 832 } |
831 | 833 |
832 private Var VarStart(boolean inParens) throws ParseException { | 834 private Var VarStart(boolean inParens) throws ParseException { |
833 int start = parser.begin(); | 835 int start = parser.begin(); |
834 if( parser.match('(') ) { | 836 if( parser.match('(') ) { |
835 Spaces(true); | 837 Spaces(true); |
836 Expr exp = Expr(true); | 838 Expr exp = expr(Expr(true)); |
837 RequiredMatch(')'); | 839 RequiredMatch(')'); |
838 Spaces(inParens); | 840 Spaces(inParens); |
839 return parser.success(exprVar(exp)); | 841 return parser.success(exprVar(exp)); |
840 } | 842 } |
841 String name = Name(inParens); | 843 String name = Name(inParens); |
853 return new GetUpVar(null,index); | 855 return new GetUpVar(null,index); |
854 throw new RuntimeException("_ENV not found"); | 856 throw new RuntimeException("_ENV not found"); |
855 } | 857 } |
856 | 858 |
857 private interface Var { | 859 private interface Var { |
858 public Expr expr(); | 860 public Code expr(); |
859 public Settable settable(); | 861 public Settable settable(); |
860 } | 862 } |
861 | 863 |
862 private Var nameVar(final int start,final String name) { | 864 private Var nameVar(final int start,final String name) { |
863 return new Var() { | 865 return new Var() { |
882 return new SetTableEntry( se(start), env(), new ConstExpr(name) ); | 884 return new SetTableEntry( se(start), env(), new ConstExpr(name) ); |
883 } | 885 } |
884 }; | 886 }; |
885 } | 887 } |
886 | 888 |
887 private Var exprVar(final Expr expr) { | 889 private Var exprVar(final Code expr) { |
888 return new Var() { | 890 return new Var() { |
889 | 891 |
890 public Expr expr() { | 892 public Code expr() { |
891 return expr; | 893 return expr; |
892 } | 894 } |
893 | 895 |
894 public Settable settable() { | 896 public Settable settable() { |
895 return null; | 897 return null; |
910 }; | 912 }; |
911 } | 913 } |
912 | 914 |
913 private FnCall Args(boolean inParens,int start,Expr fn,ExpList.Builder builder) throws ParseException { | 915 private FnCall Args(boolean inParens,int start,Expr fn,ExpList.Builder builder) throws ParseException { |
914 parser.begin(); | 916 parser.begin(); |
917 return args(inParens,builder) | |
918 ? parser.success( new FnCall( se(start), fn, builder.build() ) ) | |
919 : parser.failure((FnCall)null); | |
920 } | |
921 | |
922 private boolean args(boolean inParens,ExpList.Builder builder) throws ParseException { | |
915 if( parser.match('(') ) { | 923 if( parser.match('(') ) { |
916 Spaces(true); | 924 Spaces(true); |
917 ExpList(true,builder); // optional | 925 ExpList(true,builder); // optional |
918 RequiredMatch(')'); | 926 if( !parser.match(')') ) |
927 throw parser.exception("Expression or ')' expected"); | |
919 Spaces(inParens); | 928 Spaces(inParens); |
920 } else { | 929 return true; |
921 Expr exp = TableExpr(inParens); | 930 } |
922 if( exp != null ) { | 931 Expr exp = TableExpr(inParens); |
923 builder.add(exp); | 932 if( exp != null ) { |
924 } else { | 933 builder.add(exp); |
925 String s = StringLiteral(inParens); | 934 return true; |
926 if( s != null ) { | 935 } |
927 builder.add( new ConstExpr(s) ); | 936 String s = StringLiteral(inParens); |
928 } else { | 937 if( s != null ) { |
929 return parser.failure(null); | 938 builder.add( new ConstExpr(s) ); |
930 } | 939 return true; |
931 } | 940 } |
932 } | 941 Expressions exps = JspExpressions(); |
933 return parser.success( new FnCall( se(start), fn, builder.build() ) ); | 942 if( exps != null ) { |
943 builder.add(exps); | |
944 return true; | |
945 } | |
946 return false; | |
934 } | 947 } |
935 | 948 |
936 private Expressions ExpList() throws ParseException { | 949 private Expressions ExpList() throws ParseException { |
937 return ExpList(false); | 950 return ExpList(false); |
938 } | 951 } |
942 return ExpList(inParens,builder) ? builder.build() : null; | 955 return ExpList(inParens,builder) ? builder.build() : null; |
943 } | 956 } |
944 | 957 |
945 private boolean ExpList(boolean inParens,ExpList.Builder builder) throws ParseException { | 958 private boolean ExpList(boolean inParens,ExpList.Builder builder) throws ParseException { |
946 parser.begin(); | 959 parser.begin(); |
947 Expr exp = Expr(inParens); | 960 Code exp = Expr(inParens); |
948 if( exp==null ) | 961 if( exp==null ) |
949 return parser.failure(); | 962 return parser.failure(); |
950 builder.add(exp); | 963 builder.add(exp); |
951 while( parser.match(',') ) { | 964 while( parser.match(',') ) { |
952 Spaces(inParens); | 965 Spaces(inParens); |
958 private Expr SubExpr(boolean inParens) throws ParseException { | 971 private Expr SubExpr(boolean inParens) throws ParseException { |
959 parser.begin(); | 972 parser.begin(); |
960 if( !parser.match('[') ) | 973 if( !parser.match('[') ) |
961 return parser.failure(null); | 974 return parser.failure(null); |
962 Spaces(true); | 975 Spaces(true); |
963 Expr exp = RequiredExpr(true); | 976 Expr exp = expr(RequiredExpr(true)); |
964 RequiredMatch(']'); | 977 RequiredMatch(']'); |
965 Spaces(inParens); | 978 Spaces(inParens); |
966 return parser.success(exp); | 979 return parser.success(exp); |
967 } | 980 } |
968 | 981 |