comparison src/luan/interp/LuanParser.java @ 65:1ff53a88579a

multi-line statements git-svn-id: https://luan-java.googlecode.com/svn/trunk@66 21e917c8-12df-6dd8-5cb6-c86387c605b9
author fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
date Thu, 17 Jan 2013 23:09:50 +0000
parents a68ccb7aaa9c
children 8ea2e94f3318
comparison
equal deleted inserted replaced
64:177cfdc2bdb3 65:1ff53a88579a
14 import org.parboiled.support.Var; 14 import org.parboiled.support.Var;
15 import org.parboiled.support.StringVar; 15 import org.parboiled.support.StringVar;
16 import org.parboiled.support.StringBuilderVar; 16 import org.parboiled.support.StringBuilderVar;
17 import org.parboiled.support.ValueStack; 17 import org.parboiled.support.ValueStack;
18 import org.parboiled.errors.ErrorUtils; 18 import org.parboiled.errors.ErrorUtils;
19 import org.parboiled.annotations.Cached;
19 import luan.Luan; 20 import luan.Luan;
20 import luan.LuanState; 21 import luan.LuanState;
21 import luan.LuanSource; 22 import luan.LuanSource;
22 23
23 24
82 } 83 }
83 84
84 static final UpValue.Getter[] NO_UP_VALUE_GETTERS = new UpValue.Getter[0]; 85 static final UpValue.Getter[] NO_UP_VALUE_GETTERS = new UpValue.Getter[0];
85 86
86 int nEquals; 87 int nEquals;
87 int parens = 0;
88 Frame frame = new Frame(); 88 Frame frame = new Frame();
89 89
90 boolean nEquals(int n) { 90 boolean nEquals(int n) {
91 nEquals = n; 91 nEquals = n;
92 return true;
93 }
94
95 boolean incParens() {
96 parens++;
97 return true;
98 }
99
100 boolean decParens() {
101 parens--;
102 return true; 92 return true;
103 } 93 }
104 94
105 List<String> symbols() { 95 List<String> symbols() {
106 return frame.symbols; 96 return frame.symbols;
155 } 145 }
156 146
157 Rule Target() { 147 Rule Target() {
158 Var<Integer> start = new Var<Integer>(); 148 Var<Integer> start = new Var<Integer>();
159 return Sequence( 149 return Sequence(
160 Spaces(), 150 Spaces(false),
161 start.set(currentIndex()), 151 start.set(currentIndex()),
162 FirstOf( 152 FirstOf(
163 Sequence( 153 Sequence(
164 ExpList(), 154 ExpList(false),
165 push( new ReturnStmt( se(start.get()), (Expressions)pop() ) ), 155 push( new ReturnStmt( se(start.get()), (Expressions)pop() ) ),
166 push( newChunk(start.get()) ), 156 push( newChunk(start.get()) ),
167 EOI 157 EOI
168 ), 158 ),
169 Sequence( 159 Sequence(
206 Sequence( 196 Sequence(
207 Optional( "--", ZeroOrMore(NoneOf("\r\n")) ), 197 Optional( "--", ZeroOrMore(NoneOf("\r\n")) ),
208 EndOfLine() 198 EndOfLine()
209 ) 199 )
210 ), 200 ),
211 Spaces() 201 Spaces(false)
212 ); 202 );
213 } 203 }
214 204
215 Rule EndOfLine() { 205 Rule EndOfLine() {
216 return FirstOf("\r\n", '\r', '\n'); 206 return FirstOf("\r\n", '\r', '\n');
255 ANY 245 ANY
256 ), 246 ),
257 addToExpList(builder.get(),new ConstExpr(match())) 247 addToExpList(builder.get(),new ConstExpr(match()))
258 ), 248 ),
259 Sequence( 249 Sequence(
260 "<%=", Spaces(), 250 "<%=", Spaces(false),
261 Expr(), 251 Expr(false),
262 addToExpList(builder.get()), 252 addToExpList(builder.get()),
263 "%>" 253 "%>"
264 ) 254 )
265 ) 255 )
266 ), 256 ),
267 "<%", Spaces(), 257 "<%", Spaces(false),
268 push( new OutputStmt( se(start.get()), builder.get().build() ) ) 258 push( new OutputStmt( se(start.get()), builder.get().build() ) )
269 ); 259 );
270 } 260 }
271 261
272 Rule ReturnStmt() { 262 Rule ReturnStmt() {
273 Var<Integer> start = new Var<Integer>(); 263 Var<Integer> start = new Var<Integer>();
274 return Sequence( 264 return Sequence(
275 start.set(currentIndex()), 265 start.set(currentIndex()),
276 Keyword("return"), Expressions(), 266 Keyword("return",false), Expressions(false),
277 push( new ReturnStmt( se(start.get()), (Expressions)pop() ) ) 267 push( new ReturnStmt( se(start.get()), (Expressions)pop() ) )
278 ); 268 );
279 } 269 }
280 270
281 Rule FunctionStmt() { 271 Rule FunctionStmt() {
282 return Sequence( 272 return Sequence(
283 Keyword("function"), FnName(), Function(), 273 Keyword("function",false), FnName(), Function(false),
284 push( new SetStmt( (Settable)pop(1), expr(pop()) ) ) 274 push( new SetStmt( (Settable)pop(1), expr(pop()) ) )
285 ); 275 );
286 } 276 }
287 277
288 Rule FnName() { 278 Rule FnName() {
289 Var<Integer> start = new Var<Integer>(); 279 Var<Integer> start = new Var<Integer>();
290 return Sequence( 280 return Sequence(
291 start.set(currentIndex()), 281 start.set(currentIndex()),
292 push(null), // marker 282 push(null), // marker
293 Name(), 283 Name(false),
294 ZeroOrMore( 284 ZeroOrMore(
295 '.', Spaces(), 285 '.', Spaces(false),
296 makeVarExp(start.get()), 286 makeVarExp(start.get()),
297 NameExpr() 287 NameExpr(false)
298 ), 288 ),
299 makeSettableVar(start.get()) 289 makeSettableVar(start.get())
300 ); 290 );
301 } 291 }
302 292
303 Rule LocalFunctionStmt() { 293 Rule LocalFunctionStmt() {
304 return Sequence( 294 return Sequence(
305 Keyword("local"), Keyword("function"), 295 Keyword("local",false), Keyword("function",false),
306 Name(), 296 Name(false),
307 addSymbol( (String)pop() ), 297 addSymbol( (String)pop() ),
308 Function(), 298 Function(false),
309 push( new SetStmt( new SetLocalVar(symbolsSize()-1), expr(pop()) ) ) 299 push( new SetStmt( new SetLocalVar(symbolsSize()-1), expr(pop()) ) )
310 ); 300 );
311 } 301 }
312 302
313 Rule BreakStmt() { 303 Rule BreakStmt() {
314 return Sequence( 304 return Sequence(
315 Keyword("break"), 305 Keyword("break",false),
316 frame.loops > 0, 306 frame.loops > 0,
317 push( new BreakStmt() ) 307 push( new BreakStmt() )
318 ); 308 );
319 } 309 }
320 310
322 Var<Integer> start = new Var<Integer>(); 312 Var<Integer> start = new Var<Integer>();
323 Var<Integer> stackStart = new Var<Integer>(symbolsSize()); 313 Var<Integer> stackStart = new Var<Integer>(symbolsSize());
324 Var<List<String>> names = new Var<List<String>>(new ArrayList<String>()); 314 Var<List<String>> names = new Var<List<String>>(new ArrayList<String>());
325 return Sequence( 315 return Sequence(
326 start.set(currentIndex()), 316 start.set(currentIndex()),
327 Keyword("for"), NameList(names), Keyword("in"), Expr(), Keyword("do"), 317 Keyword("for",false), NameList(false,names), Keyword("in",false), Expr(false), Keyword("do",false),
328 addSymbols(names.get()), 318 addSymbols(names.get()),
329 LoopBlock(), Keyword("end"), 319 LoopBlock(), Keyword("end",false),
330 push( new GenericForStmt( se(start.get()), stackStart.get(), symbolsSize() - stackStart.get(), expr(pop(1)), (Stmt)pop() ) ), 320 push( new GenericForStmt( se(start.get()), stackStart.get(), symbolsSize() - stackStart.get(), expr(pop(1)), (Stmt)pop() ) ),
331 popSymbols( symbolsSize() - stackStart.get() ) 321 popSymbols( symbolsSize() - stackStart.get() )
332 ); 322 );
333 } 323 }
334 324
335 Rule NumericForStmt() { 325 Rule NumericForStmt() {
336 Var<Integer> start = new Var<Integer>(); 326 Var<Integer> start = new Var<Integer>();
337 return Sequence( 327 return Sequence(
338 start.set(currentIndex()), 328 start.set(currentIndex()),
339 Keyword("for"), Name(), '=', Spaces(), Expr(), Keyword("to"), Expr(), 329 Keyword("for",false), Name(false), '=', Spaces(false), Expr(false), Keyword("to",false), Expr(false),
340 push( new ConstExpr(1) ), // default step 330 push( new ConstExpr(1) ), // default step
341 Optional( 331 Optional(
342 Keyword("step"), 332 Keyword("step",false),
343 drop(), 333 drop(),
344 Expr() 334 Expr(false)
345 ), 335 ),
346 addSymbol( (String)pop(3) ), // add "for" var to symbols 336 addSymbol( (String)pop(3) ), // add "for" var to symbols
347 Keyword("do"), LoopBlock(), Keyword("end"), 337 Keyword("do",false), LoopBlock(), Keyword("end",false),
348 push( new NumericForStmt( se(start.get()), symbolsSize()-1, expr(pop(3)), expr(pop(2)), expr(pop(1)), (Stmt)pop() ) ), 338 push( new NumericForStmt( se(start.get()), symbolsSize()-1, expr(pop(3)), expr(pop(2)), expr(pop(1)), (Stmt)pop() ) ),
349 popSymbols(1) 339 popSymbols(1)
350 ); 340 );
351 } 341 }
352 342
353 Rule TryStmt() { 343 Rule TryStmt() {
354 return Sequence( 344 return Sequence(
355 Keyword("try"), Block(), 345 Keyword("try",false), Block(),
356 Keyword("catch"), Name(), addSymbol( (String)pop() ), 346 Keyword("catch",false), Name(false), addSymbol( (String)pop() ),
357 Keyword("do"), Block(), Keyword("end"), 347 Keyword("do",false), Block(), Keyword("end",false),
358 push( new TryStmt( (Stmt)pop(1), symbolsSize()-1, (Stmt)pop() ) ), 348 push( new TryStmt( (Stmt)pop(1), symbolsSize()-1, (Stmt)pop() ) ),
359 popSymbols(1) 349 popSymbols(1)
360 ); 350 );
361 } 351 }
362 352
363 Rule DoStmt() { 353 Rule DoStmt() {
364 return Sequence( 354 return Sequence(
365 Keyword("do"), Block(), Keyword("end") 355 Keyword("do",false), Block(), Keyword("end",false)
366 ); 356 );
367 } 357 }
368 358
369 Rule LocalStmt(Var<List<Stmt>> stmts) { 359 Rule LocalStmt(Var<List<Stmt>> stmts) {
370 Var<List<String>> names = new Var<List<String>>(new ArrayList<String>()); 360 Var<List<String>> names = new Var<List<String>>(new ArrayList<String>());
371 return Sequence( 361 return Sequence(
372 Keyword("local"), NameList(names), 362 Keyword("local",false), NameList(false,names),
373 Optional( 363 Optional(
374 '=', Spaces(), ExpList(), 364 '=', Spaces(false), ExpList(false),
375 stmts.get().add( newSetLocalStmt(names.get().size()) ) 365 stmts.get().add( newSetLocalStmt(names.get().size()) )
376 ), 366 ),
377 addSymbols(names.get()) 367 addSymbols(names.get())
378 ); 368 );
379 } 369 }
380 370
381 Rule NameList(Var<List<String>> names) { 371 Rule NameList(boolean inParens,Var<List<String>> names) {
382 return Sequence( 372 return Sequence(
383 Name(), 373 Name(inParens),
384 names.get().add( (String)pop() ), 374 names.get().add( (String)pop() ),
385 ZeroOrMore( 375 ZeroOrMore(
386 ',', Spaces(), Name(), 376 ',', Spaces(inParens), Name(inParens),
387 names.get().add( (String)pop() ) 377 names.get().add( (String)pop() )
388 ) 378 )
389 ); 379 );
390 } 380 }
391 381
399 return new SetStmt( vars, values ); 389 return new SetStmt( vars, values );
400 } 390 }
401 391
402 Rule WhileStmt() { 392 Rule WhileStmt() {
403 return Sequence( 393 return Sequence(
404 Keyword("while"), Expr(), Keyword("do"), LoopBlock(), Keyword("end"), 394 Keyword("while",false), Expr(false), Keyword("do",false), LoopBlock(), Keyword("end",false),
405 push( new WhileStmt( expr(pop(1)), (Stmt)pop() ) ) 395 push( new WhileStmt( expr(pop(1)), (Stmt)pop() ) )
406 ); 396 );
407 } 397 }
408 398
409 Rule RepeatStmt() { 399 Rule RepeatStmt() {
410 return Sequence( 400 return Sequence(
411 Keyword("repeat"), LoopBlock(), Keyword("until"), Expr(), 401 Keyword("repeat",false), LoopBlock(), Keyword("until",false), Expr(false),
412 push( new RepeatStmt( (Stmt)pop(1), expr(pop()) ) ) 402 push( new RepeatStmt( (Stmt)pop(1), expr(pop()) ) )
413 ); 403 );
414 } 404 }
415 405
416 Rule LoopBlock() { 406 Rule LoopBlock() {
418 } 408 }
419 409
420 Rule IfStmt() { 410 Rule IfStmt() {
421 Var<Integer> n = new Var<Integer>(1); 411 Var<Integer> n = new Var<Integer>(1);
422 return Sequence( 412 return Sequence(
423 Keyword("if"), Expr(), Keyword("then"), Block(), 413 Keyword("if",false), Expr(false), Keyword("then",false), Block(),
424 push(Stmt.EMPTY), 414 push(Stmt.EMPTY),
425 ZeroOrMore( 415 ZeroOrMore(
426 Keyword("elseif"), drop(), Expr(), Keyword("then"), Block(), 416 Keyword("elseif",false), drop(), Expr(false), Keyword("then",false), Block(),
427 push(Stmt.EMPTY), 417 push(Stmt.EMPTY),
428 n.set(n.get()+1) 418 n.set(n.get()+1)
429 ), 419 ),
430 Optional( 420 Optional(
431 Keyword("else"), drop(), Block() 421 Keyword("else",false), drop(), Block()
432 ), 422 ),
433 Keyword("end"), 423 Keyword("end",false),
434 buildIfStmt(n.get()) 424 buildIfStmt(n.get())
435 ); 425 );
436 } 426 }
437 427
438 boolean buildIfStmt(int n) { 428 boolean buildIfStmt(int n) {
446 } 436 }
447 437
448 Rule SetStmt() { 438 Rule SetStmt() {
449 return Sequence( 439 return Sequence(
450 VarList(), 440 VarList(),
451 '=', Spaces(), 441 '=', Spaces(false),
452 ExpList(), 442 ExpList(false),
453 push( newSetStmt() ) 443 push( newSetStmt() )
454 ); 444 );
455 } 445 }
456 446
457 Rule ExpressionsStmt() { 447 Rule ExpressionsStmt() {
458 return Sequence( 448 return Sequence(
459 ExpList(), 449 ExpList(false),
460 push( new ExpressionsStmt((Expressions)pop()) ) 450 push( new ExpressionsStmt((Expressions)pop()) )
461 ); 451 );
462 } 452 }
463 453
464 SetStmt newSetStmt() { 454 SetStmt newSetStmt() {
472 Var<List<Settable>> vars = new Var<List<Settable>>(new ArrayList<Settable>()); 462 Var<List<Settable>> vars = new Var<List<Settable>>(new ArrayList<Settable>());
473 return Sequence( 463 return Sequence(
474 SettableVar(), 464 SettableVar(),
475 vars.get().add( (Settable)pop() ), 465 vars.get().add( (Settable)pop() ),
476 ZeroOrMore( 466 ZeroOrMore(
477 ',', Spaces(), SettableVar(), 467 ',', Spaces(false), SettableVar(),
478 vars.get().add( (Settable)pop() ) 468 vars.get().add( (Settable)pop() )
479 ), 469 ),
480 push(vars.get()) 470 push(vars.get())
481 ); 471 );
482 } 472 }
483 473
484 Rule SettableVar() { 474 Rule SettableVar() {
485 Var<Integer> start = new Var<Integer>(); 475 Var<Integer> start = new Var<Integer>();
486 return Sequence( 476 return Sequence(
487 start.set(currentIndex()), 477 start.set(currentIndex()),
488 Var(), 478 Var(false),
489 makeSettableVar(start.get()) 479 makeSettableVar(start.get())
490 ); 480 );
491 } 481 }
492 482
493 boolean makeSettableVar(int start) { 483 boolean makeSettableVar(int start) {
508 if( index != -1 ) 498 if( index != -1 )
509 return push( new SetUpVar(index) ); 499 return push( new SetUpVar(index) );
510 return push( new SetTableEntry( se(start), env(), new ConstExpr(name) ) ); 500 return push( new SetTableEntry( se(start), env(), new ConstExpr(name) ) );
511 } 501 }
512 502
513 Rule Expr() { 503 @Cached
504 Rule Expr(boolean inParens) {
514 return FirstOf( 505 return FirstOf(
515 VarArgs(), 506 VarArgs(inParens),
516 OrExpr() 507 OrExpr(inParens)
517 ); 508 );
518 } 509 }
519 510
520 Rule OrExpr() { 511 @Cached
521 Var<Integer> start = new Var<Integer>(); 512 Rule OrExpr(boolean inParens) {
522 return Sequence( 513 Var<Integer> start = new Var<Integer>();
523 start.set(currentIndex()), 514 return Sequence(
524 AndExpr(), 515 start.set(currentIndex()),
525 ZeroOrMore( "or", Spaces(), AndExpr(), push( new OrExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ) 516 AndExpr(inParens),
526 ); 517 ZeroOrMore( Keyword("or",inParens), AndExpr(inParens), push( new OrExpr(se(start.get()),expr(pop(1)),expr(pop())) ) )
527 } 518 );
528 519 }
529 Rule AndExpr() { 520
530 Var<Integer> start = new Var<Integer>(); 521 @Cached
531 return Sequence( 522 Rule AndExpr(boolean inParens) {
532 start.set(currentIndex()), 523 Var<Integer> start = new Var<Integer>();
533 RelExpr(), 524 return Sequence(
534 ZeroOrMore( "and", Spaces(), RelExpr(), push( new AndExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ) 525 start.set(currentIndex()),
535 ); 526 RelExpr(inParens),
536 } 527 ZeroOrMore( Keyword("and",inParens), RelExpr(inParens), push( new AndExpr(se(start.get()),expr(pop(1)),expr(pop())) ) )
537 528 );
538 Rule RelExpr() { 529 }
539 Var<Integer> start = new Var<Integer>(); 530
540 return Sequence( 531 @Cached
541 start.set(currentIndex()), 532 Rule RelExpr(boolean inParens) {
542 ConcatExpr(), 533 Var<Integer> start = new Var<Integer>();
534 return Sequence(
535 start.set(currentIndex()),
536 ConcatExpr(inParens),
543 ZeroOrMore( 537 ZeroOrMore(
544 FirstOf( 538 FirstOf(
545 Sequence( "==", Spaces(), ConcatExpr(), push( new EqExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ), 539 Sequence( "==", Spaces(inParens), ConcatExpr(inParens), push( new EqExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ),
546 Sequence( "~=", Spaces(), ConcatExpr(), push( new NotExpr(se(start.get()),new EqExpr(se(start.get()),expr(pop(1)),expr(pop()))) ) ), 540 Sequence( "~=", Spaces(inParens), ConcatExpr(inParens), push( new NotExpr(se(start.get()),new EqExpr(se(start.get()),expr(pop(1)),expr(pop()))) ) ),
547 Sequence( "<=", Spaces(), ConcatExpr(), push( new LeExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ), 541 Sequence( "<=", Spaces(inParens), ConcatExpr(inParens), push( new LeExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ),
548 Sequence( ">=", Spaces(), ConcatExpr(), push( new LeExpr(se(start.get()),expr(pop()),expr(pop())) ) ), 542 Sequence( ">=", Spaces(inParens), ConcatExpr(inParens), push( new LeExpr(se(start.get()),expr(pop()),expr(pop())) ) ),
549 Sequence( "<", Spaces(), ConcatExpr(), push( new LtExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ), 543 Sequence( "<", Spaces(inParens), ConcatExpr(inParens), push( new LtExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ),
550 Sequence( ">", Spaces(), ConcatExpr(), push( new LtExpr(se(start.get()),expr(pop()),expr(pop())) ) ) 544 Sequence( ">", Spaces(inParens), ConcatExpr(inParens), push( new LtExpr(se(start.get()),expr(pop()),expr(pop())) ) )
551 ) 545 )
552 ) 546 )
553 ); 547 );
554 } 548 }
555 549
556 Rule ConcatExpr() { 550 @Cached
557 Var<Integer> start = new Var<Integer>(); 551 Rule ConcatExpr(boolean inParens) {
558 return Sequence( 552 Var<Integer> start = new Var<Integer>();
559 start.set(currentIndex()), 553 return Sequence(
560 SumExpr(), 554 start.set(currentIndex()),
561 Optional( "..", Spaces(), ConcatExpr(), push( new ConcatExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ) 555 SumExpr(inParens),
562 ); 556 Optional( "..", Spaces(inParens), ConcatExpr(inParens), push( new ConcatExpr(se(start.get()),expr(pop(1)),expr(pop())) ) )
563 } 557 );
564 558 }
565 Rule SumExpr() { 559
566 Var<Integer> start = new Var<Integer>(); 560 @Cached
567 return Sequence( 561 Rule SumExpr(boolean inParens) {
568 start.set(currentIndex()), 562 Var<Integer> start = new Var<Integer>();
569 TermExpr(), 563 return Sequence(
564 start.set(currentIndex()),
565 TermExpr(inParens),
570 ZeroOrMore( 566 ZeroOrMore(
571 FirstOf( 567 FirstOf(
572 Sequence( '+', Spaces(), TermExpr(), push( new AddExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ), 568 Sequence( '+', Spaces(inParens), TermExpr(inParens), push( new AddExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ),
573 Sequence( '-', TestNot('-'), Spaces(), TermExpr(), push( new SubExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ) 569 Sequence( '-', TestNot('-'), Spaces(inParens), TermExpr(inParens), push( new SubExpr(se(start.get()),expr(pop(1)),expr(pop())) ) )
574 ) 570 )
575 ) 571 )
576 ); 572 );
577 } 573 }
578 574
579 Rule TermExpr() { 575 @Cached
580 Var<Integer> start = new Var<Integer>(); 576 Rule TermExpr(boolean inParens) {
581 return Sequence( 577 Var<Integer> start = new Var<Integer>();
582 start.set(currentIndex()), 578 return Sequence(
583 UnaryExpr(), 579 start.set(currentIndex()),
580 UnaryExpr(inParens),
584 ZeroOrMore( 581 ZeroOrMore(
585 FirstOf( 582 FirstOf(
586 Sequence( '*', Spaces(), UnaryExpr(), push( new MulExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ), 583 Sequence( '*', Spaces(inParens), UnaryExpr(inParens), push( new MulExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ),
587 Sequence( '/', Spaces(), UnaryExpr(), push( new DivExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ), 584 Sequence( '/', Spaces(inParens), UnaryExpr(inParens), push( new DivExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ),
588 Sequence( '%', Spaces(), UnaryExpr(), push( new ModExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ) 585 Sequence( '%', Spaces(inParens), UnaryExpr(inParens), push( new ModExpr(se(start.get()),expr(pop(1)),expr(pop())) ) )
589 ) 586 )
590 ) 587 )
591 ); 588 );
592 } 589 }
593 590
594 Rule UnaryExpr() { 591 @Cached
592 Rule UnaryExpr(boolean inParens) {
595 Var<Integer> start = new Var<Integer>(); 593 Var<Integer> start = new Var<Integer>();
596 return Sequence( 594 return Sequence(
597 start.set(currentIndex()), 595 start.set(currentIndex()),
598 FirstOf( 596 FirstOf(
599 Sequence( '#', Spaces(), PowExpr(), push( new LenExpr(se(start.get()),expr(pop())) ) ), 597 Sequence( '#', Spaces(inParens), PowExpr(inParens), push( new LenExpr(se(start.get()),expr(pop())) ) ),
600 Sequence( '-', TestNot('-'), Spaces(), PowExpr(), push( new UnmExpr(se(start.get()),expr(pop())) ) ), 598 Sequence( '-', TestNot('-'), Spaces(inParens), PowExpr(inParens), push( new UnmExpr(se(start.get()),expr(pop())) ) ),
601 Sequence( "not", Spaces(), PowExpr(), push( new NotExpr(se(start.get()),expr(pop())) ) ), 599 Sequence( Keyword("not",inParens), PowExpr(inParens), push( new NotExpr(se(start.get()),expr(pop())) ) ),
602 PowExpr() 600 PowExpr(inParens)
603 ) 601 )
604 ); 602 );
605 } 603 }
606 604
607 Rule PowExpr() { 605 @Cached
608 Var<Integer> start = new Var<Integer>(); 606 Rule PowExpr(boolean inParens) {
609 return Sequence( 607 Var<Integer> start = new Var<Integer>();
610 start.set(currentIndex()), 608 return Sequence(
611 SingleExpr(), 609 start.set(currentIndex()),
612 Optional( '^', Spaces(), PowExpr(), push( new PowExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ) 610 SingleExpr(inParens),
613 ); 611 Optional( '^', Spaces(inParens), PowExpr(inParens), push( new PowExpr(se(start.get()),expr(pop(1)),expr(pop())) ) )
614 } 612 );
615 613 }
616 Rule SingleExpr() { 614
615 @Cached
616 Rule SingleExpr(boolean inParens) {
617 return FirstOf( 617 return FirstOf(
618 FunctionExpr(), 618 FunctionExpr(inParens),
619 TableExpr(), 619 TableExpr(inParens),
620 VarExp(), 620 VarExp(inParens),
621 LiteralExpr() 621 Literal(inParens)
622 ); 622 );
623 } 623 }
624 624
625 Rule FunctionExpr() { 625 @Cached
626 return Sequence( "function", Spaces(), Function() ); 626 Rule FunctionExpr(boolean inParens) {
627 } 627 return Sequence( "function", Spaces(inParens), Function(inParens) );
628 628 }
629 Rule Function() { 629
630 @Cached
631 Rule Function(boolean inParens) {
630 Var<Integer> start = new Var<Integer>(); 632 Var<Integer> start = new Var<Integer>();
631 Var<List<String>> names = new Var<List<String>>(new ArrayList<String>()); 633 Var<List<String>> names = new Var<List<String>>(new ArrayList<String>());
632 return Sequence( 634 return Sequence(
633 start.set(currentIndex()), 635 start.set(currentIndex()),
634 '(', incParens(), Spaces(), 636 '(', Spaces(true),
635 action( frame = new Frame(frame) ), 637 action( frame = new Frame(frame) ),
636 Optional( 638 Optional(
637 FirstOf( 639 FirstOf(
638 Sequence( 640 Sequence(
639 NameList(names), addSymbols(names.get()), 641 NameList(true,names), addSymbols(names.get()),
640 Optional( ',', Spaces(), VarArgName() ) 642 Optional( ',', Spaces(true), VarArgName() )
641 ), 643 ),
642 VarArgName() 644 VarArgName()
643 ) 645 )
644 ), 646 ),
645 ')', decParens(), Spaces(), Block(), Keyword("end"), 647 ')', Spaces(inParens), Block(), Keyword("end",inParens),
646 push( newChunk(start.get()) ), 648 push( newChunk(start.get()) ),
647 action( frame = frame.parent ) 649 action( frame = frame.parent )
648 ); 650 );
649 } 651 }
650 652
651 Rule VarArgName() { 653 Rule VarArgName() {
652 return Sequence( 654 return Sequence(
653 "...", Spaces(), 655 "...", Spaces(true),
654 action( frame.isVarArg = true ) 656 action( frame.isVarArg = true )
655 ); 657 );
656 } 658 }
657 659
658 Rule VarArgs() { 660 @Cached
659 Var<Integer> start = new Var<Integer>(); 661 Rule VarArgs(boolean inParens) {
660 return Sequence( 662 Var<Integer> start = new Var<Integer>();
661 start.set(currentIndex()), 663 return Sequence(
662 "...", Spaces(), 664 start.set(currentIndex()),
665 "...", Spaces(inParens),
663 frame.isVarArg, 666 frame.isVarArg,
664 push( new VarArgs(se(start.get())) ) 667 push( new VarArgs(se(start.get())) )
665 ); 668 );
666 } 669 }
667 670
668 Rule TableExpr() { 671 @Cached
672 Rule TableExpr(boolean inParens) {
669 Var<Integer> start = new Var<Integer>(); 673 Var<Integer> start = new Var<Integer>();
670 Var<List<TableExpr.Field>> fields = new Var<List<TableExpr.Field>>(new ArrayList<TableExpr.Field>()); 674 Var<List<TableExpr.Field>> fields = new Var<List<TableExpr.Field>>(new ArrayList<TableExpr.Field>());
671 Var<ExpList.Builder> builder = new Var<ExpList.Builder>(new ExpList.Builder()); 675 Var<ExpList.Builder> builder = new Var<ExpList.Builder>(new ExpList.Builder());
672 return Sequence( 676 return Sequence(
673 start.set(currentIndex()), 677 start.set(currentIndex()),
674 '{', incParens(), Spaces(), 678 '{', Spaces(true),
675 Optional( 679 Optional(
676 Field(fields,builder), 680 Field(fields,builder),
677 ZeroOrMore( 681 ZeroOrMore(
678 FieldSep(), 682 FieldSep(),
679 Field(fields,builder) 683 Field(fields,builder)
680 ), 684 ),
681 Optional( FieldSep() ) 685 Optional( FieldSep() )
682 ), 686 ),
683 '}', decParens(), 687 '}',
684 Spaces(), 688 Spaces(inParens),
685 push( new TableExpr( se(start.get()), fields.get().toArray(new TableExpr.Field[0]), builder.get().build() ) ) 689 push( new TableExpr( se(start.get()), fields.get().toArray(new TableExpr.Field[0]), builder.get().build() ) )
686 ); 690 );
687 } 691 }
688 692
689 Rule FieldSep() { 693 Rule FieldSep() {
690 return Sequence( AnyOf(",;"), Spaces() ); 694 return Sequence( AnyOf(",;"), Spaces(true) );
691 } 695 }
692 696
693 Rule Field(Var<List<TableExpr.Field>> fields,Var<ExpList.Builder> builder) { 697 Rule Field(Var<List<TableExpr.Field>> fields,Var<ExpList.Builder> builder) {
694 return FirstOf( 698 return FirstOf(
695 Sequence( 699 Sequence(
696 FirstOf( SubExpr(), NameExpr() ), 700 FirstOf( SubExpr(true), NameExpr(true) ),
697 '=', Spaces(), Expr(), 701 '=', Spaces(true), Expr(true),
698 fields.get().add( new TableExpr.Field( expr(pop(1)), expr(pop()) ) ) 702 fields.get().add( new TableExpr.Field( expr(pop(1)), expr(pop()) ) )
699 ), 703 ),
700 Sequence( 704 Sequence(
701 Expr(), 705 Expr(true),
702 addToExpList(builder.get()) 706 addToExpList(builder.get())
703 ) 707 )
704 ); 708 );
705 } 709 }
706 710
708 if( obj instanceof Expressions ) 712 if( obj instanceof Expressions )
709 return new ExpressionsExpr((Expressions)obj); 713 return new ExpressionsExpr((Expressions)obj);
710 return (Expr)obj; 714 return (Expr)obj;
711 } 715 }
712 716
713 Rule VarExp() { 717 @Cached
714 Var<Integer> start = new Var<Integer>(); 718 Rule VarExp(boolean inParens) {
715 return Sequence( 719 Var<Integer> start = new Var<Integer>();
716 start.set(currentIndex()), 720 return Sequence(
717 Var(), 721 start.set(currentIndex()),
722 Var(inParens),
718 makeVarExp(start.get()) 723 makeVarExp(start.get())
719 ); 724 );
720 } 725 }
721 726
722 Rule Var() { 727 @Cached
728 Rule Var(boolean inParens) {
723 Var<Integer> start = new Var<Integer>(); 729 Var<Integer> start = new Var<Integer>();
724 return Sequence( 730 return Sequence(
725 start.set(currentIndex()), 731 start.set(currentIndex()),
726 FirstOf( 732 FirstOf(
727 Sequence( 733 Sequence(
728 '(', incParens(), Spaces(), Expr(), ')', decParens(), Spaces(), 734 '(', Spaces(true), Expr(true), ')', Spaces(inParens),
729 push(expr(pop())), 735 push(expr(pop())),
730 push(null) // marker 736 push(null) // marker
731 ), 737 ),
732 Sequence( 738 Sequence(
733 push(null), // marker 739 push(null), // marker
734 Name() 740 Name(inParens)
735 ) 741 )
736 ), 742 ),
737 ZeroOrMore( 743 ZeroOrMore(
738 makeVarExp(start.get()), 744 makeVarExp(start.get()),
739 FirstOf( 745 FirstOf(
740 SubExpr(), 746 SubExpr(inParens),
741 Sequence( '.', Spaces(), NameExpr() ), 747 Sequence( '.', Spaces(inParens), NameExpr(inParens) ),
742 Sequence( 748 Sequence(
743 Args(start), 749 Args(inParens,start),
744 push(null) // marker 750 push(null) // marker
745 ) 751 )
746 ) 752 )
747 ) 753 )
748 ); 754 );
774 return push( new GetUpVar(se(start),index) ); 780 return push( new GetUpVar(se(start),index) );
775 return push( new IndexExpr( se(start), env(), new ConstExpr(name) ) ); 781 return push( new IndexExpr( se(start), env(), new ConstExpr(name) ) );
776 } 782 }
777 783
778 // function should be on top of the stack 784 // function should be on top of the stack
779 Rule Args(Var<Integer> start) { 785 Rule Args(boolean inParens,Var<Integer> start) {
780 return Sequence( 786 return Sequence(
781 FirstOf( 787 FirstOf(
782 Sequence( 788 Sequence(
783 '(', incParens(), Spaces(), Expressions(), ')', decParens(), Spaces() 789 '(', Spaces(true), Expressions(true), ')', Spaces(inParens)
784 ), 790 ),
785 Sequence( 791 Sequence(
786 TableExpr(), 792 TableExpr(inParens),
787 push( new ExpList.SingleExpList(expr(pop())) ) 793 push( new ExpList.SingleExpList(expr(pop())) )
788 ), 794 ),
789 Sequence( 795 Sequence(
790 StringLiteral(), Spaces(), 796 StringLiteral(inParens),
791 push( new ExpList.SingleExpList(new ConstExpr(pop())) ) 797 push( new ExpList.SingleExpList(new ConstExpr(pop())) )
792 ) 798 )
793 ), 799 ),
794 push( new FnCall( se(start.get()), expr(pop(1)), (Expressions)pop() ) ) 800 push( new FnCall( se(start.get()), expr(pop(1)), (Expressions)pop() ) )
795 ); 801 );
796 } 802 }
797 803
798 Rule Expressions() { 804 @Cached
805 Rule Expressions(boolean inParens) {
799 return FirstOf( 806 return FirstOf(
800 ExpList(), 807 ExpList(inParens),
801 push( ExpList.emptyExpList ) 808 push( ExpList.emptyExpList )
802 ); 809 );
803 } 810 }
804 811
805 Rule ExpList() { 812 @Cached
813 Rule ExpList(boolean inParens) {
806 Var<ExpList.Builder> builder = new Var<ExpList.Builder>(new ExpList.Builder()); 814 Var<ExpList.Builder> builder = new Var<ExpList.Builder>(new ExpList.Builder());
807 return Sequence( 815 return Sequence(
808 Expr(), 816 Expr(inParens),
809 addToExpList(builder.get()), 817 addToExpList(builder.get()),
810 ZeroOrMore( 818 ZeroOrMore(
811 ',', Spaces(), Expr(), 819 ',', Spaces(inParens), Expr(inParens),
812 addToExpList(builder.get()) 820 addToExpList(builder.get())
813 ), 821 ),
814 push( builder.get().build() ) 822 push( builder.get().build() )
815 ); 823 );
816 } 824 }
828 boolean addToExpList(ExpList.Builder bld, Expr expr) { 836 boolean addToExpList(ExpList.Builder bld, Expr expr) {
829 bld.add(expr); 837 bld.add(expr);
830 return true; 838 return true;
831 } 839 }
832 840
833 Rule SubExpr() { 841 @Cached
834 return Sequence( '[', incParens(), Spaces(), Expr(), ']', decParens(), Spaces() ); 842 Rule SubExpr(boolean inParens) {
835 } 843 return Sequence( '[', Spaces(true), Expr(true), ']', Spaces(inParens) );
836 844 }
837 Rule NameExpr() { 845
838 return Sequence( 846 @Cached
839 Name(), 847 Rule NameExpr(boolean inParens) {
848 return Sequence(
849 Name(inParens),
840 push( new ConstExpr((String)pop()) ) 850 push( new ConstExpr((String)pop()) )
841 ); 851 );
842 } 852 }
843 853
844 Rule Name() { 854 @Cached
855 Rule Name(boolean inParens) {
845 return Sequence( 856 return Sequence(
846 Sequence( 857 Sequence(
847 NameFirstChar(), 858 NameFirstChar(),
848 ZeroOrMore( NameChar() ) 859 ZeroOrMore( NameChar() )
849 ), 860 ),
850 !keywords.contains(match()), 861 !keywords.contains(match()),
851 push(match()), 862 push(match()),
852 Spaces() 863 Spaces(inParens)
853 ); 864 );
854 } 865 }
855 866
856 Rule NameChar() { 867 Rule NameChar() {
857 return FirstOf( NameFirstChar(), Digit() ); 868 return FirstOf( NameFirstChar(), Digit() );
863 CharRange('A', 'Z'), 874 CharRange('A', 'Z'),
864 '_' 875 '_'
865 ); 876 );
866 } 877 }
867 878
868 Rule Keyword(String keyword) { 879 Rule Keyword(String keyword,boolean inParens) {
869 return Sequence( 880 return Sequence(
870 keyword, 881 keyword,
871 TestNot( NameChar() ), 882 TestNot( NameChar() ),
872 Spaces() 883 Spaces(inParens)
873 ); 884 );
874 } 885 }
875 886
876 static final Set<String> keywords = new HashSet<String>(Arrays.asList( 887 static final Set<String> keywords = new HashSet<String>(Arrays.asList(
877 "and", 888 "and",
900 "try", 911 "try",
901 "until", 912 "until",
902 "while" 913 "while"
903 )); 914 ));
904 915
905 Rule LiteralExpr() { 916 @Cached
906 return Sequence( 917 Rule Literal(boolean inParens) {
907 Literal(), Spaces(), 918 return Sequence(
919 FirstOf(
920 NilLiteral(inParens),
921 BooleanLiteral(inParens),
922 NumberLiteral(inParens),
923 StringLiteral(inParens)
924 ),
908 push(new ConstExpr(pop())) 925 push(new ConstExpr(pop()))
909 ); 926 );
910 } 927 }
911 928
912 Rule Literal() { 929 @Cached
930 Rule NilLiteral(boolean inParens) {
931 return Sequence( Keyword("nil",inParens), push(null) );
932 }
933
934 @Cached
935 Rule BooleanLiteral(boolean inParens) {
913 return FirstOf( 936 return FirstOf(
914 NilLiteral(), 937 Sequence( Keyword("true",inParens), push(true) ),
915 BooleanLiteral(), 938 Sequence( Keyword("false",inParens), push(false) )
916 NumberLiteral(), 939 );
917 StringLiteral() 940 }
918 ); 941
919 } 942 @Cached
920 943 Rule NumberLiteral(boolean inParens) {
921 Rule NilLiteral() { 944 return Sequence(
922 return Sequence( "nil", push(null) ); 945 FirstOf(
923 } 946 Sequence(
924 947 IgnoreCase("0x"),
925 Rule BooleanLiteral() { 948 HexNumber()
926 return FirstOf( 949 ),
927 Sequence( "true", push(true) ), 950 Sequence(
928 Sequence( "false", push(false) ) 951 DecNumber(),
929 ); 952 push(Double.valueOf(match()))
930 } 953 )
931 954 ),
932 Rule NumberLiteral() { 955 TestNot( NameChar() ),
933 return FirstOf( 956 Spaces(inParens)
934 Sequence(
935 IgnoreCase("0x"),
936 HexNumber()
937 ),
938 Sequence(
939 DecNumber(),
940 push(Double.valueOf(match()))
941 )
942 ); 957 );
943 } 958 }
944 959
945 Rule DecNumber() { 960 Rule DecNumber() {
946 return FirstOf( 961 return FirstOf(
1009 Digit(), 1024 Digit(),
1010 AnyOf("abcdefABCDEF") 1025 AnyOf("abcdefABCDEF")
1011 ); 1026 );
1012 } 1027 }
1013 1028
1014 Rule StringLiteral() { 1029 @Cached
1015 return FirstOf( 1030 Rule StringLiteral(boolean inParens) {
1016 QuotedString('"'), 1031 return Sequence(
1017 QuotedString('\''), 1032 FirstOf(
1018 LongString() 1033 QuotedString('"'),
1034 QuotedString('\''),
1035 LongString()
1036 ),
1037 Spaces(inParens)
1019 ); 1038 );
1020 } 1039 }
1021 1040
1022 Rule LongString() { 1041 Rule LongString() {
1023 return Sequence( 1042 return Sequence(
1085 ) 1104 )
1086 ) 1105 )
1087 ); 1106 );
1088 } 1107 }
1089 1108
1090 Rule Spaces() { 1109 @Cached
1110 Rule Spaces(boolean inParens) {
1091 return ZeroOrMore( 1111 return ZeroOrMore(
1092 FirstOf( 1112 FirstOf(
1093 AnyOf(" \t"), 1113 AnyOf(" \t"),
1094 Comment(), 1114 Comment(),
1095 Sequence( '\\', EndOfLine() )//, 1115 Sequence( '\\', EndOfLine() ),
1096 // Sequence( AnyOf("\r\n"), parens > 0 ) 1116 Sequence( AnyOf("\r\n"), inParens )
1097 ) 1117 )
1098 ); 1118 );
1099 } 1119 }
1100 1120
1101 Rule Comment() { 1121 Rule Comment() {