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