Mercurial Hosting > luan
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() { |