comparison src/luan/interp/LuanParser.java @ 129:486a0641bca4

add pickle client/server; fix parser bugs; git-svn-id: https://luan-java.googlecode.com/svn/trunk@130 21e917c8-12df-6dd8-5cb6-c86387c605b9
author fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
date Mon, 09 Jun 2014 09:16:16 +0000
parents f0a4abe58593
children 573ce091ae00
comparison
equal deleted inserted replaced
128:f0a4abe58593 129:486a0641bca4
70 upValueSymbols.add(name); 70 upValueSymbols.add(name);
71 upValueGetters.add(upValueGetter); 71 upValueGetters.add(upValueGetter);
72 } 72 }
73 } 73 }
74 74
75 private static class In {
76 static final In NOTHING = new In(false,false);
77
78 final boolean parens;
79 final boolean jsp;
80
81 private In(boolean parens,boolean jsp) {
82 this.parens = parens;
83 this.jsp = jsp;
84 }
85
86 In parens() {
87 return parens ? this : new In(true,jsp);
88 }
89
90 In jsp() {
91 return jsp ? this : new In(parens,true);
92 }
93 }
94
75 private static final String _ENV = "_ENV"; 95 private static final String _ENV = "_ENV";
76 private static final UpValue.Getter[] NO_UP_VALUE_GETTERS = new UpValue.Getter[0]; 96 private static final UpValue.Getter[] NO_UP_VALUE_GETTERS = new UpValue.Getter[0];
77 97
78 final LuanSource source; 98 final LuanSource source;
79 private Frame frame; 99 private Frame frame;
159 private FnDef newFnDef(int start,Stmt stmt) { 179 private FnDef newFnDef(int start,Stmt stmt) {
160 return new FnDef( se(start), stmt, frame.stackSize, symbolsSize(), frame.isVarArg, frame.upValueGetters.toArray(NO_UP_VALUE_GETTERS) ); 180 return new FnDef( se(start), stmt, frame.stackSize, symbolsSize(), frame.isVarArg, frame.upValueGetters.toArray(NO_UP_VALUE_GETTERS) );
161 } 181 }
162 182
163 FnDef Expressions() throws ParseException { 183 FnDef Expressions() throws ParseException {
164 Spaces(); 184 Spaces(In.NOTHING);
165 int start = parser.begin(); 185 int start = parser.begin();
166 Expressions exprs = ExpList(); 186 Expressions exprs = ExpList(In.NOTHING);
167 if( exprs != null && parser.endOfInput() ) { 187 if( exprs != null && parser.endOfInput() ) {
168 Stmt stmt = new ReturnStmt( se(start), exprs ); 188 Stmt stmt = new ReturnStmt( se(start), exprs );
169 return parser.success(newFnDef(start,stmt)); 189 return parser.success(newFnDef(start,stmt));
170 } 190 }
171 return parser.failure(null); 191 return parser.failure(null);
172 } 192 }
173 193
174 FnDef RequiredModule() throws ParseException { 194 FnDef RequiredModule() throws ParseException {
175 Spaces(); 195 Spaces(In.NOTHING);
176 int start = parser.begin(); 196 int start = parser.begin();
177 frame.isVarArg = true; 197 frame.isVarArg = true;
178 Stmt stmt = RequiredBlock(); 198 Stmt stmt = RequiredBlock();
179 if( parser.endOfInput() ) 199 if( parser.endOfInput() )
180 return parser.success(newFnDef(start,stmt)); 200 return parser.success(newFnDef(start,stmt));
184 private Stmt RequiredBlock() throws ParseException { 204 private Stmt RequiredBlock() throws ParseException {
185 List<Stmt> stmts = new ArrayList<Stmt>(); 205 List<Stmt> stmts = new ArrayList<Stmt>();
186 int stackStart = symbolsSize(); 206 int stackStart = symbolsSize();
187 Stmt(stmts); 207 Stmt(stmts);
188 while( StmtSep(stmts) ) { 208 while( StmtSep(stmts) ) {
189 Spaces(); 209 Spaces(In.NOTHING);
190 Stmt(stmts); 210 Stmt(stmts);
191 } 211 }
192 int stackEnd = symbolsSize(); 212 int stackEnd = symbolsSize();
193 popSymbols( stackEnd - stackStart ); 213 popSymbols( stackEnd - stackStart );
194 if( stmts.isEmpty() ) 214 if( stmts.isEmpty() )
233 ) { 253 ) {
234 stmts.add(stmt); 254 stmts.add(stmt);
235 } 255 }
236 } 256 }
237 257
238 private Expressions JspExpressions() throws ParseException { 258 private Expressions JspExpressions(In in) throws ParseException {
259 if( in.jsp )
260 return null;
239 int start = parser.begin(); 261 int start = parser.begin();
240 if( !parser.match( "%>" ) ) 262 if( !parser.match( "%>" ) )
241 return parser.failure(null); 263 return parser.failure(null);
242 EndOfLine(); 264 EndOfLine();
265 In inJsp = in.jsp();
243 ExpList.Builder builder = new ExpList.Builder(); 266 ExpList.Builder builder = new ExpList.Builder();
244 while(true) { 267 while(true) {
245 if( parser.match( "<%=" ) ) { 268 if( parser.match( "<%=" ) ) {
246 Spaces(); 269 Spaces(inJsp);
247 builder.add( RequiredExpr() ); 270 builder.add( RequiredExpr(inJsp) );
248 RequiredMatch( "%>" ); 271 RequiredMatch( "%>" );
249 } else if( parser.match( "<%" ) ) { 272 } else if( parser.match( "<%" ) ) {
250 Spaces(); 273 Spaces(inJsp);
251 return parser.success(builder.build()); 274 return parser.success(builder.build());
252 } else { 275 } else {
253 int i = parser.currentIndex(); 276 int i = parser.currentIndex();
254 do { 277 do {
255 if( parser.match( "%>" ) ) 278 if( parser.match( "%>" ) )
263 } 286 }
264 } 287 }
265 288
266 private Stmt ReturnStmt() throws ParseException { 289 private Stmt ReturnStmt() throws ParseException {
267 int start = parser.begin(); 290 int start = parser.begin();
268 if( !Keyword("return") ) 291 if( !Keyword("return",In.NOTHING) )
269 return parser.failure(null); 292 return parser.failure(null);
270 Expressions exprs = ExpList(); 293 Expressions exprs = ExpList(In.NOTHING);
271 if( exprs==null ) 294 if( exprs==null )
272 exprs = ExpList.emptyExpList; 295 exprs = ExpList.emptyExpList;
273 return parser.success( new ReturnStmt(se(start),exprs) ); 296 return parser.success( new ReturnStmt(se(start),exprs) );
274 } 297 }
275 298
276 private Stmt FunctionStmt() throws ParseException { 299 private Stmt FunctionStmt() throws ParseException {
277 parser.begin(); 300 parser.begin();
278 if( !Keyword("function") ) 301 if( !Keyword("function",In.NOTHING) )
279 return parser.failure(null); 302 return parser.failure(null);
280 303
281 int start = parser.currentIndex(); 304 int start = parser.currentIndex();
282 Var var = nameVar(start,RequiredName()); 305 Var var = nameVar(start,RequiredName(In.NOTHING));
283 while( parser.match( '.' ) ) { 306 while( parser.match( '.' ) ) {
284 Spaces(); 307 Spaces(In.NOTHING);
285 var = indexVar( start, expr(var.expr()), NameExpr(false) ); 308 var = indexVar( start, expr(var.expr()), NameExpr(In.NOTHING) );
286 } 309 }
287 Settable fnName = var.settable(); 310 Settable fnName = var.settable();
288 311
289 FnDef fnDef = RequiredFunction(false); 312 FnDef fnDef = RequiredFunction(In.NOTHING);
290 return parser.success( new SetStmt(fnName,fnDef) ); 313 return parser.success( new SetStmt(fnName,fnDef) );
291 } 314 }
292 315
293 private Stmt LocalFunctionStmt() throws ParseException { 316 private Stmt LocalFunctionStmt() throws ParseException {
294 parser.begin(); 317 parser.begin();
295 if( !(Keyword("local") && Keyword("function")) ) 318 if( !(Keyword("local",In.NOTHING) && Keyword("function",In.NOTHING)) )
296 return parser.failure(null); 319 return parser.failure(null);
297 String name = RequiredName(); 320 String name = RequiredName(In.NOTHING);
298 addSymbol( name ); 321 addSymbol( name );
299 FnDef fnDef = RequiredFunction(false); 322 FnDef fnDef = RequiredFunction(In.NOTHING);
300 return parser.success( new SetStmt( new SetLocalVar(symbolsSize()-1), fnDef ) ); 323 return parser.success( new SetStmt( new SetLocalVar(symbolsSize()-1), fnDef ) );
301 } 324 }
302 325
303 private Stmt ImportStmt() throws ParseException { 326 private Stmt ImportStmt() throws ParseException {
304 int start = parser.begin(); 327 int start = parser.begin();
305 if( !Keyword("import") ) 328 if( !Keyword("import",In.NOTHING) )
306 return parser.failure(null); 329 return parser.failure(null);
307 Expr importExpr = (Expr)nameVar(start,"require").expr(); 330 Expr importExpr = (Expr)nameVar(start,"require").expr();
308 String modName = StringLiteral(false); 331 String modName = StringLiteral(In.NOTHING);
309 if( modName==null ) 332 if( modName==null )
310 return parser.failure(null); 333 return parser.failure(null);
311 String varName = modName.substring(modName.lastIndexOf('.')+1); 334 String varName = modName.substring(modName.lastIndexOf('.')+1);
312 LuanSource.Element se = se(start); 335 LuanSource.Element se = se(start);
313 FnCall require = new FnCall( se, importExpr, new ExpList.SingleExpList(new ConstExpr(modName)) ); 336 FnCall require = new FnCall( se, importExpr, new ExpList.SingleExpList(new ConstExpr(modName)) );
321 return parser.success( new SetStmt( settable, expr(require) ) ); 344 return parser.success( new SetStmt( settable, expr(require) ) );
322 } 345 }
323 346
324 private Stmt BreakStmt() throws ParseException { 347 private Stmt BreakStmt() throws ParseException {
325 parser.begin(); 348 parser.begin();
326 if( !Keyword("break") ) 349 if( !Keyword("break",In.NOTHING) )
327 return parser.failure(null); 350 return parser.failure(null);
328 if( frame.loops <= 0 ) 351 if( frame.loops <= 0 )
329 throw parser.exception("'break' outside of loop"); 352 throw parser.exception("'break' outside of loop");
330 return parser.success( new BreakStmt() ); 353 return parser.success( new BreakStmt() );
331 } 354 }
332 355
333 private Stmt ForStmt() throws ParseException { 356 private Stmt ForStmt() throws ParseException {
334 int start = parser.begin(); 357 int start = parser.begin();
335 int stackStart = symbolsSize(); 358 int stackStart = symbolsSize();
336 if( !Keyword("for") ) 359 if( !Keyword("for",In.NOTHING) )
337 return parser.failure(null); 360 return parser.failure(null);
338 List<String> names = RequiredNameList(false); 361 List<String> names = RequiredNameList(In.NOTHING);
339 if( !Keyword("in") ) 362 if( !Keyword("in",In.NOTHING) )
340 return parser.failure(null); 363 return parser.failure(null);
341 Expr expr = expr(RequiredExpr()); 364 Expr expr = expr(RequiredExpr(In.NOTHING));
342 RequiredKeyword("do"); 365 RequiredKeyword("do",In.NOTHING);
343 addSymbols(names); 366 addSymbols(names);
344 Stmt loop = RequiredLoopBlock(); 367 Stmt loop = RequiredLoopBlock();
345 RequiredKeyword("end"); 368 RequiredKeyword("end",In.NOTHING);
346 Stmt stmt = new ForStmt( se(start), stackStart, symbolsSize() - stackStart, expr, loop ); 369 Stmt stmt = new ForStmt( se(start), stackStart, symbolsSize() - stackStart, expr, loop );
347 popSymbols( symbolsSize() - stackStart ); 370 popSymbols( symbolsSize() - stackStart );
348 return parser.success(stmt); 371 return parser.success(stmt);
349 } 372 }
350 373
351 private Stmt TryStmt() throws ParseException { 374 private Stmt TryStmt() throws ParseException {
352 parser.begin(); 375 parser.begin();
353 if( !Keyword("try") ) 376 if( !Keyword("try",In.NOTHING) )
354 return parser.failure(null); 377 return parser.failure(null);
355 Stmt tryBlock = RequiredBlock(); 378 Stmt tryBlock = RequiredBlock();
356 RequiredKeyword("catch"); 379 RequiredKeyword("catch",In.NOTHING);
357 String name = RequiredName(); 380 String name = RequiredName(In.NOTHING);
358 addSymbol(name); 381 addSymbol(name);
359 RequiredKeyword("do"); 382 RequiredKeyword("do",In.NOTHING);
360 Stmt catchBlock = RequiredBlock(); 383 Stmt catchBlock = RequiredBlock();
361 RequiredKeyword("end"); 384 RequiredKeyword("end",In.NOTHING);
362 Stmt stmt = new TryStmt( tryBlock, symbolsSize()-1, catchBlock ); 385 Stmt stmt = new TryStmt( tryBlock, symbolsSize()-1, catchBlock );
363 popSymbols(1); 386 popSymbols(1);
364 return parser.success(stmt); 387 return parser.success(stmt);
365 } 388 }
366 389
367 private Stmt DoStmt() throws ParseException { 390 private Stmt DoStmt() throws ParseException {
368 parser.begin(); 391 parser.begin();
369 if( !Keyword("do") ) 392 if( !Keyword("do",In.NOTHING) )
370 return parser.failure(null); 393 return parser.failure(null);
371 Stmt stmt = RequiredBlock(); 394 Stmt stmt = RequiredBlock();
372 RequiredKeyword("end"); 395 RequiredKeyword("end",In.NOTHING);
373 return parser.success(stmt); 396 return parser.success(stmt);
374 } 397 }
375 398
376 private boolean LocalStmt(List<Stmt> stmts) throws ParseException { 399 private boolean LocalStmt(List<Stmt> stmts) throws ParseException {
377 parser.begin(); 400 parser.begin();
378 if( !Keyword("local") ) 401 if( !Keyword("local",In.NOTHING) )
379 return parser.failure(); 402 return parser.failure();
380 List<String> names = NameList(false); 403 List<String> names = NameList(In.NOTHING);
381 if( names==null ) 404 if( names==null )
382 return parser.failure(); 405 return parser.failure();
383 if( parser.match( '=' ) ) { 406 if( parser.match( '=' ) ) {
384 Spaces(); 407 Spaces(In.NOTHING);
385 Expressions values = ExpList(); 408 Expressions values = ExpList(In.NOTHING);
386 if( values==null ) 409 if( values==null )
387 throw parser.exception("Expressions expected"); 410 throw parser.exception("Expressions expected");
388 SetLocalVar[] vars = new SetLocalVar[names.size()]; 411 SetLocalVar[] vars = new SetLocalVar[names.size()];
389 int stackStart = symbolsSize(); 412 int stackStart = symbolsSize();
390 for( int i=0; i<vars.length; i++ ) { 413 for( int i=0; i<vars.length; i++ ) {
394 } 417 }
395 addSymbols(names); 418 addSymbols(names);
396 return parser.success(); 419 return parser.success();
397 } 420 }
398 421
399 private List<String> RequiredNameList(boolean inParens) throws ParseException { 422 private List<String> RequiredNameList(In in) throws ParseException {
400 parser.begin(); 423 parser.begin();
401 List<String> names = NameList(inParens); 424 List<String> names = NameList(in);
402 if( names==null ) 425 if( names==null )
403 parser.exception("Name expected"); 426 parser.exception("Name expected");
404 return parser.success(names); 427 return parser.success(names);
405 } 428 }
406 429
407 private List<String> NameList(boolean inParens) throws ParseException { 430 private List<String> NameList(In in) throws ParseException {
408 String name = Name(inParens); 431 String name = Name(in);
409 if( name==null ) 432 if( name==null )
410 return null; 433 return null;
411 List<String> names = new ArrayList<String>(); 434 List<String> names = new ArrayList<String>();
412 names.add(name); 435 names.add(name);
413 while( parser.match( ',' ) ) { 436 while( parser.match( ',' ) ) {
414 Spaces(inParens); 437 Spaces(in);
415 names.add( RequiredName() ); 438 names.add( RequiredName(in) );
416 } 439 }
417 return names; 440 return names;
418 } 441 }
419 442
420 private Stmt WhileStmt() throws ParseException { 443 private Stmt WhileStmt() throws ParseException {
421 parser.begin(); 444 parser.begin();
422 if( !Keyword("while") ) 445 if( !Keyword("while",In.NOTHING) )
423 return parser.failure(null); 446 return parser.failure(null);
424 Expr cnd = expr(RequiredExpr()); 447 Expr cnd = expr(RequiredExpr(In.NOTHING));
425 RequiredKeyword("do"); 448 RequiredKeyword("do",In.NOTHING);
426 Stmt loop = RequiredLoopBlock(); 449 Stmt loop = RequiredLoopBlock();
427 RequiredKeyword("end"); 450 RequiredKeyword("end",In.NOTHING);
428 return parser.success( new WhileStmt(cnd,loop) ); 451 return parser.success( new WhileStmt(cnd,loop) );
429 } 452 }
430 453
431 private Stmt RepeatStmt() throws ParseException { 454 private Stmt RepeatStmt() throws ParseException {
432 parser.begin(); 455 parser.begin();
433 if( !Keyword("repeat") ) 456 if( !Keyword("repeat",In.NOTHING) )
434 return parser.failure(null); 457 return parser.failure(null);
435 Stmt loop = RequiredLoopBlock(); 458 Stmt loop = RequiredLoopBlock();
436 RequiredKeyword("until"); 459 RequiredKeyword("until",In.NOTHING);
437 Expr cnd = expr(RequiredExpr()); 460 Expr cnd = expr(RequiredExpr(In.NOTHING));
438 return parser.success( new RepeatStmt(loop,cnd) ); 461 return parser.success( new RepeatStmt(loop,cnd) );
439 } 462 }
440 463
441 private Stmt RequiredLoopBlock() throws ParseException { 464 private Stmt RequiredLoopBlock() throws ParseException {
442 incLoops(); 465 incLoops();
445 return stmt; 468 return stmt;
446 } 469 }
447 470
448 private Stmt IfStmt() throws ParseException { 471 private Stmt IfStmt() throws ParseException {
449 parser.begin(); 472 parser.begin();
450 if( !Keyword("if") ) 473 if( !Keyword("if",In.NOTHING) )
451 return parser.failure(null); 474 return parser.failure(null);
452 return parser.success( IfStmt2() ); 475 return parser.success( IfStmt2() );
453 } 476 }
454 477
455 private Stmt IfStmt2() throws ParseException { 478 private Stmt IfStmt2() throws ParseException {
456 Expr cnd = expr(RequiredExpr()); 479 Expr cnd = expr(RequiredExpr(In.NOTHING));
457 RequiredKeyword("then"); 480 RequiredKeyword("then",In.NOTHING);
458 Stmt thenBlock = RequiredBlock(); 481 Stmt thenBlock = RequiredBlock();
459 Stmt elseBlock; 482 Stmt elseBlock;
460 if( Keyword("elseif") ) { 483 if( Keyword("elseif",In.NOTHING) ) {
461 elseBlock = IfStmt2(); 484 elseBlock = IfStmt2();
462 } else { 485 } else {
463 elseBlock = Keyword("else") ? RequiredBlock() : Stmt.EMPTY; 486 elseBlock = Keyword("else",In.NOTHING) ? RequiredBlock() : Stmt.EMPTY;
464 RequiredKeyword("end"); 487 RequiredKeyword("end",In.NOTHING);
465 } 488 }
466 return new IfStmt(cnd,thenBlock,elseBlock); 489 return new IfStmt(cnd,thenBlock,elseBlock);
467 } 490 }
468 491
469 private Stmt SetStmt() throws ParseException { 492 private Stmt SetStmt() throws ParseException {
472 Settable s = SettableVar(); 495 Settable s = SettableVar();
473 if( s == null ) 496 if( s == null )
474 return parser.failure(null); 497 return parser.failure(null);
475 vars.add(s); 498 vars.add(s);
476 while( parser.match( ',' ) ) { 499 while( parser.match( ',' ) ) {
477 Spaces(); 500 Spaces(In.NOTHING);
478 s = SettableVar(); 501 s = SettableVar();
479 if( s == null ) 502 if( s == null )
480 return parser.failure(null); 503 return parser.failure(null);
481 vars.add(s); 504 vars.add(s);
482 } 505 }
483 if( !parser.match( '=' ) ) 506 if( !parser.match( '=' ) )
484 return parser.failure(null); 507 return parser.failure(null);
485 Spaces(); 508 Spaces(In.NOTHING);
486 Expressions values = ExpList(); 509 Expressions values = ExpList(In.NOTHING);
487 if( values==null ) 510 if( values==null )
488 throw parser.exception("Expressions expected"); 511 throw parser.exception("Expressions expected");
489 return parser.success( new SetStmt( vars.toArray(new Settable[0]), values ) ); 512 return parser.success( new SetStmt( vars.toArray(new Settable[0]), values ) );
490 } 513 }
491 514
492 private Stmt ExpressionsStmt() throws ParseException { 515 private Stmt ExpressionsStmt() throws ParseException {
493 parser.begin(); 516 parser.begin();
494 Expressions exprs = ExpList(); 517 Expressions exprs = ExpList(In.NOTHING);
495 if( exprs==null ) 518 if( exprs==null )
496 return parser.failure(null); 519 return parser.failure(null);
497 return parser.success( new ExpressionsStmt(exprs) ); 520 return parser.success( new ExpressionsStmt(exprs) );
498 } 521 }
499 522
500 private Settable SettableVar() throws ParseException { 523 private Settable SettableVar() throws ParseException {
501 int start = parser.begin(); 524 int start = parser.begin();
502 Var var = VarZ(false); 525 Var var = VarZ(In.NOTHING);
503 if( var==null ) 526 if( var==null )
504 return null; 527 return null;
505 return var.settable(); 528 return var.settable();
506 } 529 }
507 530
508 private Code RequiredExpr() throws ParseException { 531 private Code RequiredExpr(In in) throws ParseException {
509 return RequiredExpr(false); 532 parser.begin();
510 } 533 return parser.success(required(Expr(in),"Bad expression"));
511 534 }
512 private Code Expr() throws ParseException { 535
513 return Expr(false); 536 private Code Expr(In in) throws ParseException {
514 }
515
516 private Code RequiredExpr(boolean inParens) throws ParseException {
517 parser.begin();
518 return parser.success(required(Expr(inParens),"Bad expression"));
519 }
520
521 private Code Expr(boolean inParens) throws ParseException {
522 parser.begin(); 537 parser.begin();
523 Code exp; 538 Code exp;
524 return (exp = VarArgs(inParens)) != null 539 return (exp = VarArgs(in)) != null
525 || (exp = JspExpressions()) != null 540 || (exp = JspExpressions(in)) != null
526 || (exp = OrExpr(inParens)) != null 541 || (exp = OrExpr(in)) != null
527 ? parser.success(exp) 542 ? parser.success(exp)
528 : parser.failure((Code)null) 543 : parser.failure((Code)null)
529 ; 544 ;
530 } 545 }
531 546
532 private Code OrExpr(boolean inParens) throws ParseException { 547 private Code OrExpr(In in) throws ParseException {
533 int start = parser.begin(); 548 int start = parser.begin();
534 Code exp = AndExpr(inParens); 549 Code exp = AndExpr(in);
535 if( exp==null ) 550 if( exp==null )
536 return parser.failure(null); 551 return parser.failure(null);
537 while( Keyword("or",inParens) ) { 552 while( Keyword("or",in) ) {
538 exp = new OrExpr( se(start), expr(exp), required(expr(AndExpr(inParens))) ); 553 exp = new OrExpr( se(start), expr(exp), required(expr(AndExpr(in))) );
539 } 554 }
540 return parser.success(exp); 555 return parser.success(exp);
541 } 556 }
542 557
543 private Code AndExpr(boolean inParens) throws ParseException { 558 private Code AndExpr(In in) throws ParseException {
544 int start = parser.begin(); 559 int start = parser.begin();
545 Code exp = RelExpr(inParens); 560 Code exp = RelExpr(in);
546 if( exp==null ) 561 if( exp==null )
547 return parser.failure(null); 562 return parser.failure(null);
548 while( Keyword("and",inParens) ) { 563 while( Keyword("and",in) ) {
549 exp = new AndExpr( se(start), expr(exp), required(expr(RelExpr(inParens))) ); 564 exp = new AndExpr( se(start), expr(exp), required(expr(RelExpr(in))) );
550 } 565 }
551 return parser.success(exp); 566 return parser.success(exp);
552 } 567 }
553 568
554 private Code RelExpr(boolean inParens) throws ParseException { 569 private Code RelExpr(In in) throws ParseException {
555 int start = parser.begin(); 570 int start = parser.begin();
556 Code exp = ConcatExpr(inParens); 571 Code exp = ConcatExpr(in);
557 if( exp==null ) 572 if( exp==null )
558 return parser.failure(null); 573 return parser.failure(null);
559 while(true) { 574 while(true) {
560 if( parser.match("==") ) { 575 if( parser.match("==") ) {
561 Spaces(inParens); 576 Spaces(in);
562 exp = new EqExpr( se(start), expr(exp), required(expr(ConcatExpr(inParens))) ); 577 exp = new EqExpr( se(start), expr(exp), required(expr(ConcatExpr(in))) );
563 } else if( parser.match("~=") ) { 578 } else if( parser.match("~=") ) {
564 Spaces(inParens); 579 Spaces(in);
565 exp = new NotExpr( se(start), new EqExpr( se(start), expr(exp), required(expr(ConcatExpr(inParens))) ) ); 580 exp = new NotExpr( se(start), new EqExpr( se(start), expr(exp), required(expr(ConcatExpr(in))) ) );
566 } else if( parser.match("<=") ) { 581 } else if( parser.match("<=") ) {
567 Spaces(inParens); 582 Spaces(in);
568 exp = new LeExpr( se(start), expr(exp), required(expr(ConcatExpr(inParens))) ); 583 exp = new LeExpr( se(start), expr(exp), required(expr(ConcatExpr(in))) );
569 } else if( parser.match(">=") ) { 584 } else if( parser.match(">=") ) {
570 Spaces(inParens); 585 Spaces(in);
571 exp = new LeExpr( se(start), required(expr(ConcatExpr(inParens))), expr(exp) ); 586 exp = new LeExpr( se(start), required(expr(ConcatExpr(in))), expr(exp) );
572 } else if( parser.match("<") ) { 587 } else if( parser.match("<") ) {
573 Spaces(inParens); 588 Spaces(in);
574 exp = new LtExpr( se(start), expr(exp), required(expr(ConcatExpr(inParens))) ); 589 exp = new LtExpr( se(start), expr(exp), required(expr(ConcatExpr(in))) );
575 } else if( parser.match(">") ) { 590 } else if( parser.match(">") ) {
576 Spaces(inParens); 591 Spaces(in);
577 exp = new LtExpr( se(start), required(expr(ConcatExpr(inParens))), expr(exp) ); 592 exp = new LtExpr( se(start), required(expr(ConcatExpr(in))), expr(exp) );
578 } else 593 } else
579 break; 594 break;
580 } 595 }
581 return parser.success(exp); 596 return parser.success(exp);
582 } 597 }
583 598
584 private Code ConcatExpr(boolean inParens) throws ParseException { 599 private Code ConcatExpr(In in) throws ParseException {
585 int start = parser.begin(); 600 int start = parser.begin();
586 Code exp = SumExpr(inParens); 601 Code exp = SumExpr(in);
587 if( exp==null ) 602 if( exp==null )
588 return parser.failure(null); 603 return parser.failure(null);
589 if( parser.match("..") ) { 604 if( parser.match("..") ) {
590 Spaces(inParens); 605 Spaces(in);
591 exp = new ConcatExpr( se(start), expr(exp), required(expr(ConcatExpr(inParens))) ); 606 exp = new ConcatExpr( se(start), expr(exp), required(expr(ConcatExpr(in))) );
592 } 607 }
593 return parser.success(exp); 608 return parser.success(exp);
594 } 609 }
595 610
596 private Code SumExpr(boolean inParens) throws ParseException { 611 private Code SumExpr(In in) throws ParseException {
597 int start = parser.begin(); 612 int start = parser.begin();
598 Code exp = TermExpr(inParens); 613 Code exp = TermExpr(in);
599 if( exp==null ) 614 if( exp==null )
600 return parser.failure(null); 615 return parser.failure(null);
601 while(true) { 616 while(true) {
602 if( parser.match('+') ) { 617 if( parser.match('+') ) {
603 Spaces(inParens); 618 Spaces(in);
604 exp = new AddExpr( se(start), expr(exp), required(expr(TermExpr(inParens))) ); 619 exp = new AddExpr( se(start), expr(exp), required(expr(TermExpr(in))) );
605 } else if( Minus() ) { 620 } else if( Minus() ) {
606 Spaces(inParens); 621 Spaces(in);
607 exp = new SubExpr( se(start), expr(exp), required(expr(TermExpr(inParens))) ); 622 exp = new SubExpr( se(start), expr(exp), required(expr(TermExpr(in))) );
608 } else 623 } else
609 break; 624 break;
610 } 625 }
611 return parser.success(exp); 626 return parser.success(exp);
612 } 627 }
614 private boolean Minus() { 629 private boolean Minus() {
615 parser.begin(); 630 parser.begin();
616 return parser.match('-') && !parser.match('-') ? parser.success() : parser.failure(); 631 return parser.match('-') && !parser.match('-') ? parser.success() : parser.failure();
617 } 632 }
618 633
619 private Code TermExpr(boolean inParens) throws ParseException { 634 private Code TermExpr(In in) throws ParseException {
620 int start = parser.begin(); 635 int start = parser.begin();
621 Code exp = UnaryExpr(inParens); 636 Code exp = UnaryExpr(in);
622 if( exp==null ) 637 if( exp==null )
623 return parser.failure(null); 638 return parser.failure(null);
624 while(true) { 639 while(true) {
625 if( parser.match('*') ) { 640 if( parser.match('*') ) {
626 Spaces(inParens); 641 Spaces(in);
627 exp = new MulExpr( se(start), expr(exp), required(expr(UnaryExpr(inParens))) ); 642 exp = new MulExpr( se(start), expr(exp), required(expr(UnaryExpr(in))) );
628 } else if( parser.match('/') ) { 643 } else if( parser.match('/') ) {
629 Spaces(inParens); 644 Spaces(in);
630 exp = new DivExpr( se(start), expr(exp), required(expr(UnaryExpr(inParens))) ); 645 exp = new DivExpr( se(start), expr(exp), required(expr(UnaryExpr(in))) );
631 } else if( Mod() ) { 646 } else if( Mod() ) {
632 Spaces(inParens); 647 Spaces(in);
633 exp = new ModExpr( se(start), expr(exp), required(expr(UnaryExpr(inParens))) ); 648 exp = new ModExpr( se(start), expr(exp), required(expr(UnaryExpr(in))) );
634 } else 649 } else
635 break; 650 break;
636 } 651 }
637 return parser.success(exp); 652 return parser.success(exp);
638 } 653 }
640 private boolean Mod() { 655 private boolean Mod() {
641 parser.begin(); 656 parser.begin();
642 return parser.match('%') && !parser.match('>') ? parser.success() : parser.failure(); 657 return parser.match('%') && !parser.match('>') ? parser.success() : parser.failure();
643 } 658 }
644 659
645 private Code UnaryExpr(boolean inParens) throws ParseException { 660 private Code UnaryExpr(In in) throws ParseException {
646 int start = parser.begin(); 661 int start = parser.begin();
647 if( parser.match('#') ) { 662 if( parser.match('#') ) {
648 Spaces(inParens); 663 Spaces(in);
649 return parser.success( new LenExpr( se(start), required(expr(UnaryExpr(inParens))) ) ); 664 return parser.success( new LenExpr( se(start), required(expr(UnaryExpr(in))) ) );
650 } 665 }
651 if( Minus() ) { 666 if( Minus() ) {
652 Spaces(inParens); 667 Spaces(in);
653 return parser.success( new UnmExpr( se(start), required(expr(UnaryExpr(inParens))) ) ); 668 return parser.success( new UnmExpr( se(start), required(expr(UnaryExpr(in))) ) );
654 } 669 }
655 if( Keyword("not",inParens) ) { 670 if( Keyword("not",in) ) {
656 Spaces(inParens); 671 Spaces(in);
657 return parser.success( new NotExpr( se(start), required(expr(UnaryExpr(inParens))) ) ); 672 return parser.success( new NotExpr( se(start), required(expr(UnaryExpr(in))) ) );
658 } 673 }
659 Code exp = PowExpr(inParens); 674 Code exp = PowExpr(in);
660 if( exp==null ) 675 if( exp==null )
661 return parser.failure(null); 676 return parser.failure(null);
662 return parser.success(exp); 677 return parser.success(exp);
663 } 678 }
664 679
665 private Code PowExpr(boolean inParens) throws ParseException { 680 private Code PowExpr(In in) throws ParseException {
666 int start = parser.begin(); 681 int start = parser.begin();
667 Code exp = SingleExpr(inParens); 682 Code exp = SingleExpr(in);
668 if( exp==null ) 683 if( exp==null )
669 return parser.failure(null); 684 return parser.failure(null);
670 if( parser.match('^') ) { 685 if( parser.match('^') ) {
671 Spaces(inParens); 686 Spaces(in);
672 exp = new ConcatExpr( se(start), expr(exp), required(expr(PowExpr(inParens))) ); 687 exp = new ConcatExpr( se(start), expr(exp), required(expr(PowExpr(in))) );
673 } 688 }
674 return parser.success(exp); 689 return parser.success(exp);
675 } 690 }
676 691
677 private Code SingleExpr(boolean inParens) throws ParseException { 692 private Code SingleExpr(In in) throws ParseException {
678 parser.begin(); 693 parser.begin();
679 Code exp; 694 Code exp;
680 exp = FunctionExpr(inParens); 695 exp = FunctionExpr(in);
681 if( exp != null ) 696 if( exp != null )
682 return parser.success(exp); 697 return parser.success(exp);
683 exp = TableExpr(inParens); 698 exp = TableExpr(in);
684 if( exp != null ) 699 if( exp != null )
685 return parser.success(exp); 700 return parser.success(exp);
686 exp = VarExp(inParens); 701 exp = VarExp(in);
687 if( exp != null ) 702 if( exp != null )
688 return parser.success(exp); 703 return parser.success(exp);
689 exp = Literal(inParens); 704 exp = Literal(in);
690 if( exp != null ) 705 if( exp != null )
691 return parser.success(exp); 706 return parser.success(exp);
692 return parser.failure(null); 707 return parser.failure(null);
693 } 708 }
694 709
695 private Expr FunctionExpr(boolean inParens) throws ParseException { 710 private Expr FunctionExpr(In in) throws ParseException {
696 if( !Keyword("function",inParens) ) 711 if( !Keyword("function",in) )
697 return null; 712 return null;
698 return RequiredFunction(inParens); 713 return RequiredFunction(in);
699 } 714 }
700 715
701 private FnDef RequiredFunction(boolean inParens) throws ParseException { 716 private FnDef RequiredFunction(In in) throws ParseException {
702 int start = parser.begin(); 717 int start = parser.begin();
703 RequiredMatch('('); 718 RequiredMatch('(');
704 Spaces(true); 719 In inParens = in.parens();
720 Spaces(inParens);
705 frame = new Frame(frame); 721 frame = new Frame(frame);
706 List<String> names = NameList(false); 722 List<String> names = NameList(in);
707 if( names != null ) { 723 if( names != null ) {
708 addSymbols(names); 724 addSymbols(names);
709 if( parser.match(',') ) { 725 if( parser.match(',') ) {
710 Spaces(true); 726 Spaces(inParens);
711 if( !parser.match("...") ) 727 if( !parser.match("...") )
712 throw parser.exception(); 728 throw parser.exception();
713 frame.isVarArg = true; 729 frame.isVarArg = true;
714 } 730 }
715 } else if( parser.match("...") ) { 731 } else if( parser.match("...") ) {
716 Spaces(true); 732 Spaces(inParens);
717 frame.isVarArg = true; 733 frame.isVarArg = true;
718 } 734 }
719 RequiredMatch(')'); 735 RequiredMatch(')');
720 Spaces(inParens); 736 Spaces(in);
721 Stmt block = RequiredBlock(); 737 Stmt block = RequiredBlock();
722 RequiredKeyword("end",inParens); 738 RequiredKeyword("end",in);
723 FnDef fnDef = newFnDef(start,block); 739 FnDef fnDef = newFnDef(start,block);
724 frame = frame.parent; 740 frame = frame.parent;
725 return parser.success(fnDef); 741 return parser.success(fnDef);
726 } 742 }
727 743
728 private VarArgs VarArgs(boolean inParens) throws ParseException { 744 private VarArgs VarArgs(In in) throws ParseException {
729 int start = parser.begin(); 745 int start = parser.begin();
730 if( !frame.isVarArg || !parser.match("...") ) 746 if( !frame.isVarArg || !parser.match("...") )
731 return parser.failure(null); 747 return parser.failure(null);
748 Spaces(in);
749 return parser.success( new VarArgs(se(start)) );
750 }
751
752 private Expr TableExpr(In in) throws ParseException {
753 int start = parser.begin();
754 if( !parser.match('{') )
755 return parser.failure(null);
756 In inParens = in.parens();
732 Spaces(inParens); 757 Spaces(inParens);
733 return parser.success( new VarArgs(se(start)) );
734 }
735
736 private Expr TableExpr(boolean inParens) throws ParseException {
737 int start = parser.begin();
738 if( !parser.match('{') )
739 return parser.failure(null);
740 Spaces(true);
741 List<TableExpr.Field> fields = new ArrayList<TableExpr.Field>(); 758 List<TableExpr.Field> fields = new ArrayList<TableExpr.Field>();
742 ExpList.Builder builder = new ExpList.Builder(); 759 ExpList.Builder builder = new ExpList.Builder();
743 while( Field(fields,builder) && FieldSep() ); 760 while( Field(fields,builder,in) && FieldSep(inParens) );
744 if( !parser.match('}') ) 761 if( !parser.match('}') )
745 throw parser.exception("Expected table element or '}'"); 762 throw parser.exception("Expected table element or '}'");
746 return parser.success( new TableExpr( se(start), fields.toArray(new TableExpr.Field[0]), builder.build() ) ); 763 return parser.success( new TableExpr( se(start), fields.toArray(new TableExpr.Field[0]), builder.build() ) );
747 } 764 }
748 765
749 private boolean FieldSep() throws ParseException { 766 private boolean FieldSep(In in) throws ParseException {
750 if( !parser.anyOf(",;") ) 767 if( !parser.anyOf(",;") )
751 return false; 768 return false;
752 Spaces(true); 769 Spaces(in);
753 return true; 770 return true;
754 } 771 }
755 772
756 private boolean Field(List<TableExpr.Field> fields,ExpList.Builder builder) throws ParseException { 773 private boolean Field(List<TableExpr.Field> fields,ExpList.Builder builder,In in) throws ParseException {
757 parser.begin(); 774 parser.begin();
758 Expr exp = SubExpr(true); 775 Expr exp = SubExpr(in);
759 if( exp==null ) 776 if( exp==null )
760 exp = NameExpr(true); 777 exp = NameExpr(in);
761 if( exp!=null && parser.match('=') ) { 778 if( exp!=null && parser.match('=') ) {
762 fields.add( new TableExpr.Field( exp, required(expr(Expr(true))) ) ); 779 fields.add( new TableExpr.Field( exp, required(expr(Expr(in))) ) );
763 return parser.success(); 780 return parser.success();
764 } 781 }
765 parser.rollback(); 782 parser.rollback();
766 Code code = Expr(true); 783 Code code = Expr(in);
767 if( code != null ) { 784 if( code != null ) {
768 builder.add(code); 785 builder.add(code);
769 return parser.success(); 786 return parser.success();
770 } 787 }
771 return parser.failure(); 788 return parser.failure();
772 } 789 }
773 790
774 private Code VarExp(boolean inParens) throws ParseException { 791 private Code VarExp(In in) throws ParseException {
775 Var var = VarZ(inParens); 792 Var var = VarZ(in);
776 return var==null ? null : var.expr(); 793 return var==null ? null : var.expr();
777 } 794 }
778 795
779 private Var VarZ(boolean inParens) throws ParseException { 796 private Var VarZ(In in) throws ParseException {
780 int start = parser.begin(); 797 int start = parser.begin();
781 Var var = VarStart(inParens); 798 Var var = VarStart(in);
782 if( var==null ) 799 if( var==null )
783 return parser.failure(null); 800 return parser.failure(null);
784 Var var2; 801 Var var2;
785 while( (var2=Var2(inParens,start,var.expr())) != null ) { 802 while( (var2=Var2(in,start,var.expr())) != null ) {
786 var = var2; 803 var = var2;
787 } 804 }
788 return parser.success(var); 805 return parser.success(var);
789 } 806 }
790 807
791 private Var Var2(boolean inParens,int start,Code exp1) throws ParseException { 808 private Var Var2(In in,int start,Code exp1) throws ParseException {
792 Var var = VarExt(inParens,start,exp1); 809 Var var = VarExt(in,start,exp1);
793 if( var != null ) 810 if( var != null )
794 return var; 811 return var;
795 if( parser.match("->") ) { 812 if( parser.match("->") ) {
796 Spaces(inParens); 813 Spaces(in);
797 ExpList.Builder builder = new ExpList.Builder(); 814 ExpList.Builder builder = new ExpList.Builder();
798 builder.add(exp1); 815 builder.add(exp1);
799 Expr exp2 = expr(RequiredVarExpB(inParens)); 816 Expr exp2 = expr(RequiredVarExpB(in));
800 FnCall fnCall = required(Args( inParens, start, exp2, builder )); 817 FnCall fnCall = required(Args( in, start, exp2, builder ));
801 return exprVar(fnCall); 818 return exprVar(fnCall);
802 } 819 }
803 FnCall fnCall = Args( inParens, start, expr(exp1), new ExpList.Builder() ); 820 FnCall fnCall = Args( in, start, expr(exp1), new ExpList.Builder() );
804 if( fnCall != null ) 821 if( fnCall != null )
805 return exprVar(fnCall); 822 return exprVar(fnCall);
806 return null; 823 return null;
807 } 824 }
808 825
809 private Code RequiredVarExpB(boolean inParens) throws ParseException { 826 private Code RequiredVarExpB(In in) throws ParseException {
810 int start = parser.begin(); 827 int start = parser.begin();
811 Var var = required(VarStart(inParens)); 828 Var var = required(VarStart(in));
812 Var var2; 829 Var var2;
813 while( (var2=VarExt(inParens,start,var.expr())) != null ) { 830 while( (var2=VarExt(in,start,var.expr())) != null ) {
814 var = var2; 831 var = var2;
815 } 832 }
816 return parser.success(var.expr()); 833 return parser.success(var.expr());
817 } 834 }
818 835
819 private Var VarExt(boolean inParens,int start,Code exp1) throws ParseException { 836 private Var VarExt(In in,int start,Code exp1) throws ParseException {
820 parser.begin(); 837 parser.begin();
821 Expr exp2 = SubExpr(inParens); 838 Expr exp2 = SubExpr(in);
822 if( exp2 != null ) 839 if( exp2 != null )
823 return parser.success(indexVar(start,expr(exp1),exp2)); 840 return parser.success(indexVar(start,expr(exp1),exp2));
824 if( parser.match('.') ) { 841 if( parser.match('.') ) {
825 Spaces(inParens); 842 Spaces(in);
826 exp2 = NameExpr(inParens); 843 exp2 = NameExpr(in);
827 if( exp2!=null ) 844 if( exp2!=null )
828 return parser.success(indexVar(start,expr(exp1),exp2)); 845 return parser.success(indexVar(start,expr(exp1),exp2));
829 } 846 }
830 return parser.failure(null); 847 return parser.failure(null);
831 } 848 }
832 849
833 private Var VarStart(boolean inParens) throws ParseException { 850 private Var VarStart(In in) throws ParseException {
834 int start = parser.begin(); 851 int start = parser.begin();
835 if( parser.match('(') ) { 852 if( parser.match('(') ) {
836 Spaces(true); 853 In inParens = in.parens();
837 Expr exp = expr(Expr(true)); 854 Spaces(inParens);
855 Expr exp = expr(Expr(inParens));
838 RequiredMatch(')'); 856 RequiredMatch(')');
839 Spaces(inParens); 857 Spaces(in);
840 return parser.success(exprVar(exp)); 858 return parser.success(exprVar(exp));
841 } 859 }
842 String name = Name(inParens); 860 String name = Name(in);
843 if( name != null ) 861 if( name != null )
844 return parser.success(nameVar(start,name)); 862 return parser.success(nameVar(start,name));
845 return parser.failure(null); 863 return parser.failure(null);
846 } 864 }
847 865
909 return new SetTableEntry(se(start),table,key); 927 return new SetTableEntry(se(start),table,key);
910 } 928 }
911 }; 929 };
912 } 930 }
913 931
914 private FnCall Args(boolean inParens,int start,Expr fn,ExpList.Builder builder) throws ParseException { 932 private FnCall Args(In in,int start,Expr fn,ExpList.Builder builder) throws ParseException {
915 parser.begin(); 933 parser.begin();
916 return args(inParens,builder) 934 return args(in,builder)
917 ? parser.success( new FnCall( se(start), fn, builder.build() ) ) 935 ? parser.success( new FnCall( se(start), fn, builder.build() ) )
918 : parser.failure((FnCall)null); 936 : parser.failure((FnCall)null);
919 } 937 }
920 938
921 private boolean args(boolean inParens,ExpList.Builder builder) throws ParseException { 939 private boolean args(In in,ExpList.Builder builder) throws ParseException {
922 if( parser.match('(') ) { 940 if( parser.match('(') ) {
923 Spaces(true); 941 In inParens = in.parens();
924 ExpList(true,builder); // optional 942 Spaces(inParens);
943 ExpList(inParens,builder); // optional
925 if( !parser.match(')') ) 944 if( !parser.match(')') )
926 throw parser.exception("Expression or ')' expected"); 945 throw parser.exception("Expression or ')' expected");
927 Spaces(inParens); 946 Spaces(in);
928 return true; 947 return true;
929 } 948 }
930 Expr exp = TableExpr(inParens); 949 Expr exp = TableExpr(in);
931 if( exp != null ) { 950 if( exp != null ) {
932 builder.add(exp); 951 builder.add(exp);
933 return true; 952 return true;
934 } 953 }
935 String s = StringLiteral(inParens); 954 String s = StringLiteral(in);
936 if( s != null ) { 955 if( s != null ) {
937 builder.add( new ConstExpr(s) ); 956 builder.add( new ConstExpr(s) );
938 return true; 957 return true;
939 } 958 }
940 Expressions exps = JspExpressions(); 959 Expressions exps = JspExpressions(in);
941 if( exps != null ) { 960 if( exps != null ) {
942 builder.add(exps); 961 builder.add(exps);
943 return true; 962 return true;
944 } 963 }
945 return false; 964 return false;
946 } 965 }
947 966
948 private Expressions ExpList() throws ParseException { 967 private Expressions ExpList(In in) throws ParseException {
949 return ExpList(false);
950 }
951
952 private Expressions ExpList(boolean inParens) throws ParseException {
953 ExpList.Builder builder = new ExpList.Builder(); 968 ExpList.Builder builder = new ExpList.Builder();
954 return ExpList(inParens,builder) ? builder.build() : null; 969 return ExpList(in,builder) ? builder.build() : null;
955 } 970 }
956 971
957 private boolean ExpList(boolean inParens,ExpList.Builder builder) throws ParseException { 972 private boolean ExpList(In in,ExpList.Builder builder) throws ParseException {
958 parser.begin(); 973 parser.begin();
959 Code exp = Expr(inParens); 974 Code exp = Expr(in);
960 if( exp==null ) 975 if( exp==null )
961 return parser.failure(); 976 return parser.failure();
962 builder.add(exp); 977 builder.add(exp);
963 while( parser.match(',') ) { 978 while( parser.match(',') ) {
964 Spaces(inParens); 979 Spaces(in);
965 builder.add( RequiredExpr(inParens) ); 980 builder.add( RequiredExpr(in) );
966 } 981 }
967 return parser.success(); 982 return parser.success();
968 } 983 }
969 984
970 private Expr SubExpr(boolean inParens) throws ParseException { 985 private Expr SubExpr(In in) throws ParseException {
971 parser.begin(); 986 parser.begin();
972 if( !parser.match('[') ) 987 if( !parser.match('[') )
973 return parser.failure(null); 988 return parser.failure(null);
974 Spaces(true); 989 In inParens = in.parens();
975 Expr exp = expr(RequiredExpr(true)); 990 Spaces(inParens);
991 Expr exp = expr(RequiredExpr(inParens));
976 RequiredMatch(']'); 992 RequiredMatch(']');
977 Spaces(inParens); 993 Spaces(in);
978 return parser.success(exp); 994 return parser.success(exp);
979 } 995 }
980 996
981 private Expr NameExpr(boolean inParens) throws ParseException { 997 private Expr NameExpr(In in) throws ParseException {
982 String name = Name(inParens); 998 String name = Name(in);
983 return name==null ? null : new ConstExpr(name); 999 return name==null ? null : new ConstExpr(name);
984 } 1000 }
985 1001
986 private String RequiredName() throws ParseException { 1002 private String RequiredName(In in) throws ParseException {
987 parser.begin(); 1003 parser.begin();
988 String name = Name(); 1004 String name = Name(in);
989 if( name==null ) 1005 if( name==null )
990 parser.exception("Name expected"); 1006 parser.exception("Name expected");
991 return parser.success(name); 1007 return parser.success(name);
992 } 1008 }
993 1009
994 private String Name() throws ParseException { 1010 private String Name(In in) throws ParseException {
995 return Name(false);
996 }
997
998 private String Name(boolean inParens) throws ParseException {
999 int start = parser.begin(); 1011 int start = parser.begin();
1000 if( !NameFirstChar() ) 1012 if( !NameFirstChar() )
1001 return parser.failure(null); 1013 return parser.failure(null);
1002 while( NameChar() ); 1014 while( NameChar() );
1003 String match = parser.textFrom(start); 1015 String match = parser.textFrom(start);
1004 if( keywords.contains(match) ) 1016 if( keywords.contains(match) )
1005 return parser.failure(null); 1017 return parser.failure(null);
1006 Spaces(inParens); 1018 Spaces(in);
1007 return parser.success(match); 1019 return parser.success(match);
1008 } 1020 }
1009 1021
1010 private boolean NameChar() { 1022 private boolean NameChar() {
1011 return NameFirstChar() || Digit(); 1023 return NameFirstChar() || Digit();
1023 private void RequiredMatch(String s) throws ParseException { 1035 private void RequiredMatch(String s) throws ParseException {
1024 if( !parser.match(s) ) 1036 if( !parser.match(s) )
1025 throw parser.exception("'"+s+"' expected"); 1037 throw parser.exception("'"+s+"' expected");
1026 } 1038 }
1027 1039
1028 private void RequiredKeyword(String keyword) throws ParseException { 1040 private void RequiredKeyword(String keyword,In in) throws ParseException {
1029 RequiredKeyword(keyword,false); 1041 if( !Keyword(keyword,in) )
1030 }
1031
1032 private boolean Keyword(String keyword) throws ParseException {
1033 return Keyword(keyword,false);
1034 }
1035
1036 private void RequiredKeyword(String keyword,boolean inParens) throws ParseException {
1037 if( !Keyword(keyword,inParens) )
1038 throw parser.exception("'"+keyword+"' expected"); 1042 throw parser.exception("'"+keyword+"' expected");
1039 } 1043 }
1040 1044
1041 private boolean Keyword(String keyword,boolean inParens) throws ParseException { 1045 private boolean Keyword(String keyword,In in) throws ParseException {
1042 parser.begin(); 1046 parser.begin();
1043 if( !parser.match(keyword) || NameChar() ) 1047 if( !parser.match(keyword) || NameChar() )
1044 return parser.failure(); 1048 return parser.failure();
1045 Spaces(inParens); 1049 Spaces(in);
1046 return parser.success(); 1050 return parser.success();
1047 } 1051 }
1048 1052
1049 private static final Set<String> keywords = new HashSet<String>(Arrays.asList( 1053 private static final Set<String> keywords = new HashSet<String>(Arrays.asList(
1050 "and", 1054 "and",
1072 "try", 1076 "try",
1073 "until", 1077 "until",
1074 "while" 1078 "while"
1075 )); 1079 ));
1076 1080
1077 private Expr Literal(boolean inParens) throws ParseException { 1081 private Expr Literal(In in) throws ParseException {
1078 if( NilLiteral(inParens) ) 1082 if( NilLiteral(in) )
1079 return new ConstExpr(null); 1083 return new ConstExpr(null);
1080 Boolean b = BooleanLiteral(inParens); 1084 Boolean b = BooleanLiteral(in);
1081 if( b != null ) 1085 if( b != null )
1082 return new ConstExpr(b); 1086 return new ConstExpr(b);
1083 Number n = NumberLiteral(inParens); 1087 Number n = NumberLiteral(in);
1084 if( n != null ) 1088 if( n != null )
1085 return new ConstExpr(n); 1089 return new ConstExpr(n);
1086 String s = StringLiteral(inParens); 1090 String s = StringLiteral(in);
1087 if( s != null ) 1091 if( s != null )
1088 return new ConstExpr(s); 1092 return new ConstExpr(s);
1089 return null; 1093 return null;
1090 } 1094 }
1091 1095
1092 private boolean NilLiteral(boolean inParens) throws ParseException { 1096 private boolean NilLiteral(In in) throws ParseException {
1093 return Keyword("nil",inParens); 1097 return Keyword("nil",in);
1094 } 1098 }
1095 1099
1096 private Boolean BooleanLiteral(boolean inParens) throws ParseException { 1100 private Boolean BooleanLiteral(In in) throws ParseException {
1097 if( Keyword("true",inParens) ) 1101 if( Keyword("true",in) )
1098 return true; 1102 return true;
1099 if( Keyword("false",inParens) ) 1103 if( Keyword("false",in) )
1100 return false; 1104 return false;
1101 return null; 1105 return null;
1102 } 1106 }
1103 1107
1104 private Number NumberLiteral(boolean inParens) throws ParseException { 1108 private Number NumberLiteral(In in) throws ParseException {
1105 parser.begin(); 1109 parser.begin();
1106 Number n; 1110 Number n;
1107 if( parser.matchIgnoreCase("0x") ) { 1111 if( parser.matchIgnoreCase("0x") ) {
1108 n = HexNumber(); 1112 n = HexNumber();
1109 } else { 1113 } else {
1110 n = DecNumber(); 1114 n = DecNumber();
1111 } 1115 }
1112 if( n==null || NameChar() ) 1116 if( n==null || NameChar() )
1113 return parser.failure(null); 1117 return parser.failure(null);
1114 Spaces(inParens); 1118 Spaces(in);
1115 return parser.success(n); 1119 return parser.success(n);
1116 } 1120 }
1117 1121
1118 private Number DecNumber() { 1122 private Number DecNumber() {
1119 int start = parser.begin(); 1123 int start = parser.begin();
1187 1191
1188 private boolean HexDigit() { 1192 private boolean HexDigit() {
1189 return Digit() || parser.anyOf("abcdefABCDEF"); 1193 return Digit() || parser.anyOf("abcdefABCDEF");
1190 } 1194 }
1191 1195
1192 private String StringLiteral(boolean inParens) throws ParseException { 1196 private String StringLiteral(In in) throws ParseException {
1193 String s; 1197 String s;
1194 if( (s=QuotedString('"'))==null 1198 if( (s=QuotedString('"'))==null
1195 && (s=QuotedString('\''))==null 1199 && (s=QuotedString('\''))==null
1196 && (s=LongString())==null 1200 && (s=LongString())==null
1197 ) 1201 )
1198 return null; 1202 return null;
1199 Spaces(inParens); 1203 Spaces(in);
1200 return s; 1204 return s;
1201 } 1205 }
1202 1206
1203 private String LongString() throws ParseException { 1207 private String LongString() throws ParseException {
1204 parser.begin(); 1208 parser.begin();
1259 return (char)Integer.parseInt(parser.textFrom(start)); 1263 return (char)Integer.parseInt(parser.textFrom(start));
1260 } 1264 }
1261 return parser.failure(null); 1265 return parser.failure(null);
1262 } 1266 }
1263 1267
1264 private void Spaces() throws ParseException { 1268 private void Spaces(In in) throws ParseException {
1265 Spaces(false); 1269 while( parser.anyOf(" \t") || Comment() || ContinueOnNextLine() || in.parens && NewLine() );
1266 }
1267
1268 private void Spaces(boolean inParens) throws ParseException {
1269 while( parser.anyOf(" \t") || Comment() || ContinueOnNextLine() || inParens && NewLine() );
1270 } 1270 }
1271 1271
1272 private boolean ContinueOnNextLine() { 1272 private boolean ContinueOnNextLine() {
1273 parser.begin(); 1273 parser.begin();
1274 return parser.match('\\') && EndOfLine() ? parser.success() : parser.failure(); 1274 return parser.match('\\') && EndOfLine() ? parser.success() : parser.failure();