comparison core/src/luan/impl/LuanParser.java @ 674:2994e46f62b7

some optimization
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 12 Apr 2016 19:31:18 -0600
parents d3e5414bdf4c
children d95caff8ba8c
comparison
equal deleted inserted replaced
673:33629d753cf9 674:2994e46f62b7
12 12
13 13
14 final class LuanParser { 14 final class LuanParser {
15 15
16 private interface Sym { 16 private interface Sym {
17 public ExpString exp(); 17 public Expr exp();
18 } 18 }
19 19
20 private int symCounter = 0; 20 private int symCounter = 0;
21 21
22 private class LocalSym implements Sym { 22 private class LocalSym implements Sym {
27 LocalSym(String name) { 27 LocalSym(String name) {
28 this.name = name; 28 this.name = name;
29 this.javaName = name + "_" + (++symCounter); 29 this.javaName = name + "_" + (++symCounter);
30 } 30 }
31 31
32 StmtString declaration(ExpString value) { 32 Stmts declaration(Expr value) {
33 StmtString stmt = new StmtString(); 33 Stmts stmt = new Stmts();
34 if( value==null ) { 34 if( value==null ) {
35 stmt.list.add( new Object() { 35 stmt.list.add( new Object() {
36 @Override public String toString() { 36 @Override public String toString() {
37 if( !isPointer ) 37 if( !isPointer )
38 return "Object " + javaName + ";\n"; 38 return "Object " + javaName + ";\n";
39 else 39 else
40 return "final Pointer " + javaName + " = new Pointer();\n"; 40 return "final Pointer " + javaName + " = new Pointer();\n";
41 } 41 }
42 } ); 42 } );
43 } else { 43 } else {
44 if( value.valType != Val.SINGLE ) throw new RuntimeException();
44 stmt.list.add( new Object() { 45 stmt.list.add( new Object() {
45 @Override public String toString() { 46 @Override public String toString() {
46 if( !isPointer ) 47 if( !isPointer )
47 return "Object " + javaName + " = "; 48 return "Object " + javaName + " = ";
48 else 49 else
60 } ); 61 } );
61 } 62 }
62 return stmt; 63 return stmt;
63 } 64 }
64 65
65 @Override public ExpString exp() { 66 @Override public Expr exp() {
66 ExpString exp = new ExpString(true,false); 67 Expr exp = new Expr(Val.SINGLE,false);
67 exp.list.add( new Object() { 68 exp.list.add( new Object() {
68 @Override public String toString() { 69 @Override public String toString() {
69 if( !isPointer ) 70 if( !isPointer )
70 return javaName; 71 return javaName;
71 else 72 else
89 90
90 String init() { 91 String init() {
91 return "upValues[" + i + "] = " + value + ";\n"; 92 return "upValues[" + i + "] = " + value + ";\n";
92 } 93 }
93 94
94 @Override public ExpString exp() { 95 @Override public Expr exp() {
95 ExpString exp = new ExpString(true,false); 96 Expr exp = new Expr(Val.SINGLE,false);
96 exp.list.add( new Object() { 97 exp.list.add( new Object() {
97 @Override public String toString() { 98 @Override public String toString() {
98 return "upValues[" + i + "].o"; 99 return "upValues[" + i + "].o";
99 } 100 }
100 } ); 101 } );
182 } 183 }
183 184
184 // final LuanSource source; 185 // final LuanSource source;
185 private Frame frame; 186 private Frame frame;
186 private final Parser parser; 187 private final Parser parser;
187 private final StmtString top = new StmtString(); 188 private final Stmts top = new Stmts();
188 189
189 LuanParser(String sourceName,String sourceText) { 190 LuanParser(String sourceName,String sourceText) {
190 // this.source = source; 191 // this.source = source;
191 this.frame = new Frame(); 192 this.frame = new Frame();
192 this.parser = new Parser(sourceName,sourceText); 193 this.parser = new Parser(sourceName,sourceText);
203 204
204 private int symbolsSize() { 205 private int symbolsSize() {
205 return frame.symbols.size(); 206 return frame.symbols.size();
206 } 207 }
207 208
208 private StmtString addSymbol(String name,ExpString value) { 209 private Stmts addSymbol(String name,Expr value) {
209 final LocalSym sym = frame.addLocalSym(name); 210 final LocalSym sym = frame.addLocalSym(name);
210 return sym.declaration(value); 211 return sym.declaration(value);
211 } 212 }
212 213
213 private Sym getSym(String name) { 214 private Sym getSym(String name) {
238 private <T> T required(T t,String msg) throws ParseException { 239 private <T> T required(T t,String msg) throws ParseException {
239 if( t==null ) 240 if( t==null )
240 throw parser.exception(msg); 241 throw parser.exception(msg);
241 return t; 242 return t;
242 } 243 }
243 /* 244
244 private static Expr expr(Expressions exprs) { 245 private Class newFnClass(int start,Stmts stmt) {
245 if( exprs==null )
246 return null;
247 if( exprs instanceof Expr )
248 return (Expr)exprs;
249 return new ExpressionsExpr(exprs);
250 }
251 */
252 private Class newFnClass(int start,StmtString stmt) {
253 if( !stmt.hasReturn ) 246 if( !stmt.hasReturn )
254 stmt.list.add( "return LuanFunction.NOTHING;\n" ); 247 stmt.list.add( "return LuanFunction.NOTHING;\n" );
255 return toFnClass( stmt, frame.upValueSymbols ); 248 return toFnClass( stmt, frame.upValueSymbols );
256 } 249 }
257 250
258 private ExpString newFnExpStr(int start,StmtString stmt) { 251 private Expr newFnExpStr(int start,Stmts stmt) {
259 if( !stmt.hasReturn ) 252 if( !stmt.hasReturn )
260 stmt.list.add( "return LuanFunction.NOTHING;\n" ); 253 stmt.list.add( "return LuanFunction.NOTHING;\n" );
261 return toFnExpStr( stmt, frame.upValueSymbols ); 254 return toFnExpStr( stmt, frame.upValueSymbols );
262 } 255 }
263 256
264 Class Expression() throws ParseException { 257 Class Expression() throws ParseException {
265 Spaces(In.NOTHING); 258 Spaces(In.NOTHING);
266 int start = parser.begin(); 259 int start = parser.begin();
267 ExpString expr = ExprZ(In.NOTHING); 260 Expr expr = ExprZ(In.NOTHING);
268 if( expr != null && parser.endOfInput() ) { 261 if( expr != null && parser.endOfInput() ) {
269 top.list.add( "return " ); 262 top.list.add( "return " );
270 top.list.addAll( expr.list ); 263 top.list.addAll( expr.list );
271 top.list.add( ";\n" ); 264 top.list.add( ";\n" );
272 top.hasReturn = true; 265 top.hasReturn = true;
278 Class RequiredModule() throws ParseException { 271 Class RequiredModule() throws ParseException {
279 Spaces(In.NOTHING); 272 Spaces(In.NOTHING);
280 int start = parser.begin(); 273 int start = parser.begin();
281 frame.isVarArg = true; 274 frame.isVarArg = true;
282 top.list.add( "final Object[] varArgs = LuanImpl.varArgs(args,0);\n" ); 275 top.list.add( "final Object[] varArgs = LuanImpl.varArgs(args,0);\n" );
283 StmtString block = RequiredBlock(); 276 Stmts block = RequiredBlock();
284 top.list.addAll( block.list ); 277 top.list.addAll( block.list );
285 top.hasReturn = block.hasReturn; 278 top.hasReturn = block.hasReturn;
286 if( parser.endOfInput() ) 279 if( parser.endOfInput() )
287 return parser.success(newFnClass(start,top)); 280 return parser.success(newFnClass(start,top));
288 throw parser.exception(); 281 throw parser.exception();
289 } 282 }
290 283
291 private StmtString RequiredBlock() throws ParseException { 284 private Stmts RequiredBlock() throws ParseException {
292 StmtString stmts = new StmtString(); 285 Stmts stmts = new Stmts();
293 int stackStart = symbolsSize(); 286 int stackStart = symbolsSize();
294 boolean isReturn = Stmt(stmts); 287 boolean isReturn = Stmt(stmts);
295 while( !isReturn && StmtSep(stmts) ) { 288 while( !isReturn && StmtSep(stmts) ) {
296 Spaces(In.NOTHING); 289 Spaces(In.NOTHING);
297 isReturn = Stmt(stmts); 290 isReturn = Stmt(stmts);
302 popSymbols( stackEnd - stackStart ); 295 popSymbols( stackEnd - stackStart );
303 stmts.hasReturn = isReturn; 296 stmts.hasReturn = isReturn;
304 return stmts; 297 return stmts;
305 } 298 }
306 299
307 private boolean StmtSep(StmtString stmts) throws ParseException { 300 private boolean StmtSep(Stmts stmts) throws ParseException {
308 parser.begin(); 301 parser.begin();
309 if( parser.match( ';' ) ) 302 if( parser.match( ';' ) )
310 return parser.success(); 303 return parser.success();
311 if( EndOfLine() ) 304 if( EndOfLine() )
312 return parser.success(); 305 return parser.success();
313 if( stmts != null ) { 306 if( stmts != null ) {
314 // parser.rollback(); 307 // parser.rollback();
315 StmtString stmt = TemplateStmt(); 308 Stmts stmt = TemplateStmt();
316 if( stmt != null ) { 309 if( stmt != null ) {
317 stmts.list.addAll(stmt.list); 310 stmts.list.addAll(stmt.list);
318 return parser.success(); 311 return parser.success();
319 } 312 }
320 } 313 }
323 316
324 private boolean EndOfLine() { 317 private boolean EndOfLine() {
325 return parser.match( "\r\n" ) || parser.match( '\r' ) || parser.match( '\n' ); 318 return parser.match( "\r\n" ) || parser.match( '\r' ) || parser.match( '\n' );
326 } 319 }
327 320
328 private boolean Stmt(StmtString stmts) throws ParseException { 321 private boolean Stmt(Stmts stmts) throws ParseException {
329 StmtString stmt; 322 Stmts stmt;
330 if( (stmt=ReturnStmt()) != null ) { 323 if( (stmt=ReturnStmt()) != null ) {
331 stmts.list.addAll(stmt.list); 324 stmts.list.addAll(stmt.list);
332 return true; 325 return true;
333 } 326 }
334 if( (stmt=FunctionStmt()) != null 327 if( (stmt=FunctionStmt()) != null
346 stmts.list.addAll(stmt.list); 339 stmts.list.addAll(stmt.list);
347 } 340 }
348 return false; 341 return false;
349 } 342 }
350 343
351 private ExpString indexExpStr(ExpString exp1,ExpString exp2) { 344 private Expr indexExpStr(Expr exp1,Expr exp2) {
352 ExpString exp = new ExpString(true,false); 345 Expr exp = new Expr(Val.SINGLE,false);
353 exp.list.add( "luan.index(" ); 346 exp.list.add( "luan.index(" );
354 exp.list.addAll( exp1.expr().list ); 347 exp.list.addAll( exp1.single().list );
355 exp.list.add( "," ); 348 exp.list.add( "," );
356 exp.list.addAll( exp2.expr().list ); 349 exp.list.addAll( exp2.single().list );
357 exp.list.add( ")" ); 350 exp.list.add( ")" );
358 return exp; 351 return exp;
359 } 352 }
360 353
361 private ExpString callExpStr(ExpString fn,ExpString args) { 354 private Expr callExpStr(Expr fn,Expr args) {
362 ExpString exp = new ExpString(false,true); 355 Expr exp = new Expr(null,true);
363 exp.list.add( "Luan.checkFunction(" ); 356 exp.list.add( "Luan.checkFunction(" );
364 exp.list.addAll( fn.expr().list ); 357 exp.list.addAll( fn.single().list );
365 exp.list.add( ").call(luan,Luan.array(" ); 358 exp.list.add( ").call(luan," );
366 exp.list.addAll( args.list ); 359 exp.list.addAll( args.array().list );
367 exp.list.add( "))" ); 360 exp.list.add( ")" );
368 return exp; 361 return exp;
369 } 362 }
370 363
371 private StmtString TemplateStmt() throws ParseException { 364 private Stmts TemplateStmt() throws ParseException {
372 ExpString exprs = TemplateExpressions(In.NOTHING); 365 Expr exprs = TemplateExpressions(In.NOTHING);
373 if( exprs == null ) 366 if( exprs == null )
374 return null; 367 return null;
375 ExpString requireCall = new ExpString(true,false); 368 Expr requireCall = new Expr(Val.SINGLE,false);
376 requireCall.list.add( "PackageLuan.require(luan,\"luan:Io\")" ); 369 requireCall.list.add( "PackageLuan.require(luan,\"luan:Io\")" );
377 ExpString stdoutExp = indexExpStr( requireCall.expr(), constExpStr("stdout") ); 370 Expr stdoutExp = indexExpStr( requireCall.single(), constExpStr("stdout") );
378 ExpString writeExp = indexExpStr( stdoutExp, constExpStr("write") ); 371 Expr writeExp = indexExpStr( stdoutExp, constExpStr("write") );
379 ExpString writeCall = callExpStr( writeExp, exprs ); 372 Expr writeCall = callExpStr( writeExp, exprs );
380 StmtString stmt = new StmtString(); 373 Stmts stmt = new Stmts();
381 stmt.list.addAll( writeCall.list ); 374 stmt.list.addAll( writeCall.list );
382 stmt.list.add( ";\n" ); 375 stmt.list.add( ";\n" );
383 return stmt; 376 return stmt;
384 } 377 }
385 378
386 private ExpString TemplateExpressions(In in) throws ParseException { 379 private Expr TemplateExpressions(In in) throws ParseException {
387 if( in.template ) 380 if( in.template )
388 return null; 381 return null;
389 int start = parser.begin(); 382 int start = parser.begin();
390 if( !parser.match( "%>" ) ) 383 if( !parser.match( "%>" ) )
391 return parser.failure(null); 384 return parser.failure(null);
392 EndOfLine(); 385 EndOfLine();
393 In inTemplate = in.template(); 386 In inTemplate = in.template();
394 List<ExpString> builder = new ArrayList<ExpString>(); 387 List<Expr> builder = new ArrayList<Expr>();
395 while(true) { 388 while(true) {
396 if( parser.match( "<%=" ) ) { 389 if( parser.match( "<%=" ) ) {
397 Spaces(inTemplate); 390 Spaces(inTemplate);
398 builder.add( RequiredExpr(inTemplate) ); 391 builder.add( RequiredExpr(inTemplate) );
399 RequiredMatch( "%>" ); 392 RequiredMatch( "%>" );
412 builder.add( constExpStr(match) ); 405 builder.add( constExpStr(match) );
413 } 406 }
414 } 407 }
415 } 408 }
416 409
417 private StmtString ReturnStmt() throws ParseException { 410 private Stmts ReturnStmt() throws ParseException {
418 parser.begin(); 411 parser.begin();
419 if( !Keyword("return",In.NOTHING) ) 412 if( !Keyword("return",In.NOTHING) )
420 return parser.failure(null); 413 return parser.failure(null);
421 ExpString exprs = ExpStringList(In.NOTHING); 414 Expr exprs = ExpStringList(In.NOTHING);
422 StmtString stmt = new StmtString(); 415 Stmts stmt = new Stmts();
423 stmt.list.add( "return " ); 416 stmt.list.add( "return " );
424 if( exprs != null ) 417 if( exprs != null )
425 stmt.list.addAll( exprs.list ); 418 stmt.list.addAll( exprs.list );
426 else 419 else
427 stmt.list.add( "LuanFunction.NOTHING" ); 420 stmt.list.add( "LuanFunction.NOTHING" );
428 stmt.list.add( ";\n" ); 421 stmt.list.add( ";\n" );
429 return parser.success( stmt ); 422 return parser.success( stmt );
430 } 423 }
431 424
432 private StmtString FunctionStmt() throws ParseException { 425 private Stmts FunctionStmt() throws ParseException {
433 parser.begin(); 426 parser.begin();
434 if( !Keyword("function",In.NOTHING) ) 427 if( !Keyword("function",In.NOTHING) )
435 return parser.failure(null); 428 return parser.failure(null);
436 429
437 parser.currentIndex(); 430 parser.currentIndex();
438 Var var = nameVar(RequiredName(In.NOTHING)); 431 Var var = nameVar(RequiredName(In.NOTHING));
439 while( parser.match( '.' ) ) { 432 while( parser.match( '.' ) ) {
440 Spaces(In.NOTHING); 433 Spaces(In.NOTHING);
441 ExpString exp = NameExpr(In.NOTHING); 434 Expr exp = NameExpr(In.NOTHING);
442 if( exp==null ) 435 if( exp==null )
443 return parser.failure(null); 436 return parser.failure(null);
444 var = indexVar( var.exp(), exp ); 437 var = indexVar( var.exp(), exp );
445 } 438 }
446 439
447 ExpString fnDef = RequiredFunction(In.NOTHING); 440 Expr fnDef = RequiredFunction(In.NOTHING);
448 return parser.success( var.set(fnDef) ); 441 return parser.success( var.set(fnDef) );
449 } 442 }
450 443
451 private StmtString LocalFunctionStmt() throws ParseException { 444 private Stmts LocalFunctionStmt() throws ParseException {
452 parser.begin(); 445 parser.begin();
453 if( !(Keyword("local",In.NOTHING) && Keyword("function",In.NOTHING)) ) 446 if( !(Keyword("local",In.NOTHING) && Keyword("function",In.NOTHING)) )
454 return parser.failure(null); 447 return parser.failure(null);
455 StmtString stmt = new StmtString(); 448 Stmts stmt = new Stmts();
456 String name = RequiredName(In.NOTHING); 449 String name = RequiredName(In.NOTHING);
457 stmt.list.addAll( addSymbol(name,null).list ); 450 stmt.list.addAll( addSymbol(name,null).list );
458 ExpString fnDef = RequiredFunction(In.NOTHING); 451 Expr fnDef = RequiredFunction(In.NOTHING);
459 stmt.list.addAll( nameVar(name).set(fnDef).list ); 452 stmt.list.addAll( nameVar(name).set(fnDef).list );
460 /* 453 /*
461 Settable s = new SetLocalVar(symbolsSize()-1); 454 Settable s = new SetLocalVar(symbolsSize()-1);
462 StmtString stmt = new StmtString(); 455 Stmts stmt = new Stmts();
463 stmt.list.add( settableToString(s) ); 456 stmt.list.add( settableToString(s) );
464 stmt.list.add( ".set(luan," ); 457 stmt.list.add( ".set(luan," );
465 stmt.list.addAll( fnDef.list ); 458 stmt.list.addAll( fnDef.list );
466 stmt.list.add( ");\n" ); 459 stmt.list.add( ");\n" );
467 */ 460 */
468 return parser.success( stmt ); 461 return parser.success( stmt );
469 } 462 }
470 463
471 private StmtString BreakStmt() throws ParseException { 464 private Stmts BreakStmt() throws ParseException {
472 parser.begin(); 465 parser.begin();
473 if( !Keyword("break",In.NOTHING) ) 466 if( !Keyword("break",In.NOTHING) )
474 return parser.failure(null); 467 return parser.failure(null);
475 if( frame.loops <= 0 ) 468 if( frame.loops <= 0 )
476 throw parser.exception("'break' outside of loop"); 469 throw parser.exception("'break' outside of loop");
477 StmtString stmt = new StmtString(); 470 Stmts stmt = new Stmts();
478 stmt.list.add( "break;\n" ); 471 stmt.list.add( "break;\n" );
479 return parser.success( stmt ); 472 return parser.success( stmt );
480 } 473 }
481 474
482 int forCounter = 0; 475 int forCounter = 0;
483 476
484 private StmtString ForStmt() throws ParseException { 477 private Stmts ForStmt() throws ParseException {
485 parser.begin(); 478 parser.begin();
486 int stackStart = symbolsSize(); 479 int stackStart = symbolsSize();
487 if( !Keyword("for",In.NOTHING) ) 480 if( !Keyword("for",In.NOTHING) )
488 return parser.failure(null); 481 return parser.failure(null);
489 List<String> names = RequiredNameList(In.NOTHING); 482 List<String> names = RequiredNameList(In.NOTHING);
490 if( !Keyword("in",In.NOTHING) ) 483 if( !Keyword("in",In.NOTHING) )
491 return parser.failure(null); 484 return parser.failure(null);
492 ExpString expr = RequiredExpr(In.NOTHING).expr(); 485 Expr expr = RequiredExpr(In.NOTHING).single();
493 RequiredKeyword("do",In.NOTHING); 486 RequiredKeyword("do",In.NOTHING);
494 487
495 String fnVar = "fn"+ ++forCounter; 488 String fnVar = "fn"+ ++forCounter;
496 ExpString fnExp = new ExpString(false,false); 489 Expr fnExp = new Expr(null,false);
497 fnExp.list.add( fnVar + ".call(luan)" ); 490 fnExp.list.add( fnVar + ".call(luan)" );
498 StmtString stmt = new StmtString(); 491 Stmts stmt = new Stmts();
499 stmt.list.add( "" 492 stmt.list.add( ""
500 +"LuanFunction "+fnVar+" = Luan.checkFunction(" 493 +"LuanFunction "+fnVar+" = Luan.checkFunction("
501 ); 494 );
502 stmt.list.addAll( expr.list ); 495 stmt.list.addAll( expr.list );
503 stmt.list.add( ");\n" ); 496 stmt.list.add( ");\n" );
504 stmt.list.add( "while(true) {\n" ); 497 stmt.list.add( "while(true) {\n" );
505 stmt.list.addAll( makeLocalSetStmt(names,fnExp).list ); 498 stmt.list.addAll( makeLocalSetStmt(names,fnExp).list );
506 stmt.list.add( "if( " ); 499 stmt.list.add( "if( " );
507 stmt.list.addAll( nameVar(names.get(0)).exp().list ); 500 stmt.list.addAll( nameVar(names.get(0)).exp().list );
508 stmt.list.add( "==null ) break;\n" ); 501 stmt.list.add( "==null ) break;\n" );
509 StmtString loop = RequiredLoopBlock(); 502 Stmts loop = RequiredLoopBlock();
510 RequiredKeyword("end",In.NOTHING); 503 RequiredKeyword("end",In.NOTHING);
511 stmt.list.addAll( loop.list ); 504 stmt.list.addAll( loop.list );
512 stmt.list.add( "}\n" ); 505 stmt.list.add( "}\n" );
513 popSymbols( symbolsSize() - stackStart ); 506 popSymbols( symbolsSize() - stackStart );
514 return parser.success(stmt); 507 return parser.success(stmt);
515 } 508 }
516 509
517 private StmtString DoStmt() throws ParseException { 510 private Stmts DoStmt() throws ParseException {
518 parser.begin(); 511 parser.begin();
519 if( !Keyword("do",In.NOTHING) ) 512 if( !Keyword("do",In.NOTHING) )
520 return parser.failure(null); 513 return parser.failure(null);
521 StmtString stmt = RequiredBlock(); 514 Stmts stmt = RequiredBlock();
522 RequiredKeyword("end",In.NOTHING); 515 RequiredKeyword("end",In.NOTHING);
523 return parser.success(stmt); 516 return parser.success(stmt);
524 } 517 }
525 518
526 private StmtString LocalStmt() throws ParseException { 519 private Stmts LocalStmt() throws ParseException {
527 parser.begin(); 520 parser.begin();
528 if( !Keyword("local",In.NOTHING) ) 521 if( !Keyword("local",In.NOTHING) )
529 return parser.failure(null); 522 return parser.failure(null);
530 List<String> names = NameList(In.NOTHING); 523 List<String> names = NameList(In.NOTHING);
531 if( names==null ) { 524 if( names==null ) {
532 if( Keyword("function",In.NOTHING) ) 525 if( Keyword("function",In.NOTHING) )
533 return parser.failure(null); // handled later 526 return parser.failure(null); // handled later
534 throw parser.exception("Invalid local statement"); 527 throw parser.exception("Invalid local statement");
535 } 528 }
536 StmtString stmt = new StmtString(); 529 Stmts stmt = new Stmts();
537 if( parser.match( '=' ) ) { 530 if( parser.match( '=' ) ) {
538 Spaces(In.NOTHING); 531 Spaces(In.NOTHING);
539 ExpString values = ExpStringList(In.NOTHING); 532 Expr values = ExpStringList(In.NOTHING);
540 if( values==null ) 533 if( values==null )
541 throw parser.exception("Expressions expected"); 534 throw parser.exception("Expressions expected");
542 stmt.list.addAll( makeLocalSetStmt(names,values).list ); 535 stmt.list.addAll( makeLocalSetStmt(names,values).list );
543 } else { 536 } else {
544 ExpString value = new ExpString(true,false); 537 Expr value = new Expr(Val.SINGLE,false);
545 value.list.add( "null" ); 538 value.list.add( "null" );
546 for( String name : names ) { 539 for( String name : names ) {
547 stmt.list.addAll( addSymbol(name,value).list ); 540 stmt.list.addAll( addSymbol(name,value).list );
548 } 541 }
549 } 542 }
579 if( name==null ) 572 if( name==null )
580 return parser.failure(null); 573 return parser.failure(null);
581 return parser.success(name); 574 return parser.success(name);
582 } 575 }
583 576
584 private StmtString WhileStmt() throws ParseException { 577 private Stmts WhileStmt() throws ParseException {
585 parser.begin(); 578 parser.begin();
586 if( !Keyword("while",In.NOTHING) ) 579 if( !Keyword("while",In.NOTHING) )
587 return parser.failure(null); 580 return parser.failure(null);
588 ExpString cnd = RequiredExpr(In.NOTHING).expr(); 581 Expr cnd = RequiredExpr(In.NOTHING).single();
589 RequiredKeyword("do",In.NOTHING); 582 RequiredKeyword("do",In.NOTHING);
590 StmtString loop = RequiredLoopBlock(); 583 Stmts loop = RequiredLoopBlock();
591 RequiredKeyword("end",In.NOTHING); 584 RequiredKeyword("end",In.NOTHING);
592 StmtString stmt = new StmtString(); 585 Stmts stmt = new Stmts();
593 stmt.list.add( "while( Luan.checkBoolean(" ); 586 stmt.list.add( "while( Luan.checkBoolean(" );
594 stmt.list.addAll( cnd.list ); 587 stmt.list.addAll( cnd.list );
595 stmt.list.add( ") ) {\n" ); 588 stmt.list.add( ") ) {\n" );
596 stmt.list.addAll( loop.list ); 589 stmt.list.addAll( loop.list );
597 stmt.list.add( "}\n" ); 590 stmt.list.add( "}\n" );
598 return parser.success( stmt ); 591 return parser.success( stmt );
599 } 592 }
600 593
601 private StmtString RepeatStmt() throws ParseException { 594 private Stmts RepeatStmt() throws ParseException {
602 parser.begin(); 595 parser.begin();
603 if( !Keyword("repeat",In.NOTHING) ) 596 if( !Keyword("repeat",In.NOTHING) )
604 return parser.failure(null); 597 return parser.failure(null);
605 StmtString loop =RequiredLoopBlock(); 598 Stmts loop =RequiredLoopBlock();
606 RequiredKeyword("until",In.NOTHING); 599 RequiredKeyword("until",In.NOTHING);
607 ExpString cnd = RequiredExpr(In.NOTHING).expr(); 600 Expr cnd = RequiredExpr(In.NOTHING).single();
608 StmtString stmt = new StmtString(); 601 Stmts stmt = new Stmts();
609 stmt.list.add( "do {\n" ); 602 stmt.list.add( "do {\n" );
610 stmt.list.addAll( loop.list ); 603 stmt.list.addAll( loop.list );
611 stmt.list.add( "} while( !Luan.checkBoolean(" ); 604 stmt.list.add( "} while( !Luan.checkBoolean(" );
612 stmt.list.addAll( cnd.list ); 605 stmt.list.addAll( cnd.list );
613 stmt.list.add( ") );\n" ); 606 stmt.list.add( ") );\n" );
614 return parser.success( stmt ); 607 return parser.success( stmt );
615 } 608 }
616 609
617 private StmtString RequiredLoopBlock() throws ParseException { 610 private Stmts RequiredLoopBlock() throws ParseException {
618 incLoops(); 611 incLoops();
619 StmtString stmt = RequiredBlock(); 612 Stmts stmt = RequiredBlock();
620 decLoops(); 613 decLoops();
621 return stmt; 614 return stmt;
622 } 615 }
623 616
624 private StmtString IfStmt() throws ParseException { 617 private Stmts IfStmt() throws ParseException {
625 parser.begin(); 618 parser.begin();
626 if( !Keyword("if",In.NOTHING) ) 619 if( !Keyword("if",In.NOTHING) )
627 return parser.failure(null); 620 return parser.failure(null);
628 StmtString stmt = new StmtString(); 621 Stmts stmt = new Stmts();
629 ExpString cnd; 622 Expr cnd;
630 StmtString block; 623 Stmts block;
631 cnd = RequiredExpr(In.NOTHING).expr(); 624 cnd = RequiredExpr(In.NOTHING).single();
632 RequiredKeyword("then",In.NOTHING); 625 RequiredKeyword("then",In.NOTHING);
633 block = RequiredBlock(); 626 block = RequiredBlock();
634 stmt.list.add( "if( Luan.checkBoolean(" ); 627 stmt.list.add( "if( Luan.checkBoolean(" );
635 stmt.list.addAll( cnd.list ); 628 stmt.list.addAll( cnd.list );
636 stmt.list.add( ") ) {\n" ); 629 stmt.list.add( ") ) {\n" );
637 stmt.list.addAll( block.list ); 630 stmt.list.addAll( block.list );
638 while( Keyword("elseif",In.NOTHING) ) { 631 while( Keyword("elseif",In.NOTHING) ) {
639 cnd = RequiredExpr(In.NOTHING).expr(); 632 cnd = RequiredExpr(In.NOTHING).single();
640 RequiredKeyword("then",In.NOTHING); 633 RequiredKeyword("then",In.NOTHING);
641 block = RequiredBlock(); 634 block = RequiredBlock();
642 stmt.list.add( "} else if( Luan.checkBoolean(" ); 635 stmt.list.add( "} else if( Luan.checkBoolean(" );
643 stmt.list.addAll( cnd.list ); 636 stmt.list.addAll( cnd.list );
644 stmt.list.add( ") ) {\n" ); 637 stmt.list.add( ") ) {\n" );
652 RequiredKeyword("end",In.NOTHING); 645 RequiredKeyword("end",In.NOTHING);
653 stmt.list.add( "}\n" ); 646 stmt.list.add( "}\n" );
654 return parser.success( stmt ); 647 return parser.success( stmt );
655 } 648 }
656 649
657 private StmtString SetStmt() throws ParseException { 650 private Stmts SetStmt() throws ParseException {
658 parser.begin(); 651 parser.begin();
659 List<Var> vars = new ArrayList<Var>(); 652 List<Var> vars = new ArrayList<Var>();
660 Var v = SettableVar(); 653 Var v = SettableVar();
661 if( v == null ) 654 if( v == null )
662 return parser.failure(null); 655 return parser.failure(null);
669 vars.add(v); 662 vars.add(v);
670 } 663 }
671 if( !parser.match( '=' ) ) 664 if( !parser.match( '=' ) )
672 return parser.failure(null); 665 return parser.failure(null);
673 Spaces(In.NOTHING); 666 Spaces(In.NOTHING);
674 ExpString values = ExpStringList(In.NOTHING); 667 Expr values = ExpStringList(In.NOTHING);
675 if( values==null ) 668 if( values==null )
676 // throw parser.exception("Expressions expected"); 669 // throw parser.exception("Expressions expected");
677 return parser.failure(null); 670 return parser.failure(null);
678 return parser.success( makeSetStmt(vars,values) ); 671 return parser.success( makeSetStmt(vars,values) );
679 } 672 }
680 673
681 private StmtString makeSetStmt(List<Var> vars,ExpString values) throws ParseException { 674 private Stmts makeSetStmt(List<Var> vars,Expr values) throws ParseException {
682 int n = vars.size(); 675 int n = vars.size();
683 if( n == 1 ) 676 if( n == 1 )
684 return vars.get(0).set(values); 677 return vars.get(0).set(values);
685 StmtString stmt = new StmtString(); 678 Stmts stmt = new Stmts();
686 stmt.list.add( "t = " ); 679 String varName = values.valType==Val.ARRAY ? "a" : "t";
680 stmt.list.add( varName + " = " );
687 stmt.list.addAll( values.list ); 681 stmt.list.addAll( values.list );
688 stmt.list.add( ";\n" ); 682 stmt.list.add( ";\n" );
689 ExpString t = new ExpString(values.isExpr,false); 683 Expr t = new Expr(values.valType,false);
690 t.list.add( "t" ); 684 t.list.add( varName );
685 t = t.single();
691 stmt.list.addAll( vars.get(0).set(t).list ); 686 stmt.list.addAll( vars.get(0).set(t).list );
692 for( int i=1; i<n; i++ ) { 687 for( int i=1; i<n; i++ ) {
693 t.list.clear(); 688 t.list.clear();
694 t.list.add( "LuanImpl.pick(t,"+i+")" ); 689 t.list.add( "LuanImpl.pick(" + varName + ","+i+")" );
695 stmt.list.addAll( vars.get(i).set(t).list ); 690 stmt.list.addAll( vars.get(i).set(t).list );
696 } 691 }
697 return stmt; 692 return stmt;
698 } 693 }
699 694
700 private StmtString makeLocalSetStmt(List<String> names,ExpString values) throws ParseException { 695 private Stmts makeLocalSetStmt(List<String> names,Expr values) throws ParseException {
701 int n = names.size(); 696 int n = names.size();
702 if( n == 1 ) 697 if( n == 1 )
703 return addSymbol(names.get(0),values.expr()); 698 return addSymbol(names.get(0),values.single());
704 StmtString stmt = new StmtString(); 699 Stmts stmt = new Stmts();
705 stmt.list.add( "t = " ); 700 String varName = values.valType==Val.ARRAY ? "a" : "t";
701 stmt.list.add( varName + " = " );
706 stmt.list.addAll( values.list ); 702 stmt.list.addAll( values.list );
707 stmt.list.add( ";\n" ); 703 stmt.list.add( ";\n" );
708 ExpString t = new ExpString(values.isExpr,false); 704 Expr t = new Expr(values.valType,false);
709 t.list.add( "t" ); 705 t.list.add( varName );
710 stmt.list.addAll( addSymbol(names.get(0),t.expr()).list ); 706 t = t.single();
707 stmt.list.addAll( addSymbol(names.get(0),t).list );
711 for( int i=1; i<n; i++ ) { 708 for( int i=1; i<n; i++ ) {
712 t.list.clear(); 709 t.list.clear();
713 t.list.add( "LuanImpl.pick(t,"+i+")" ); 710 t.list.add( "LuanImpl.pick(" + varName + ","+i+")" );
714 stmt.list.addAll( addSymbol(names.get(i),t).list ); 711 stmt.list.addAll( addSymbol(names.get(i),t).list );
715 } 712 }
716 return stmt; 713 return stmt;
717 } 714 }
718 715
719 private StmtString ExpressionsStmt() throws ParseException { 716 private Stmts ExpressionsStmt() throws ParseException {
720 parser.begin(); 717 parser.begin();
721 ExpString exp = ExprZ(In.NOTHING); 718 Expr exp = ExprZ(In.NOTHING);
722 if( exp != null && exp.isStmt ) { 719 if( exp != null && exp.isStmt ) {
723 StmtString stmt = new StmtString(); 720 Stmts stmt = new Stmts();
724 if( exp.isExpr ) { 721 if( exp.valType==Val.SINGLE ) {
725 stmt.list.add( "LuanImpl.nop(" ); 722 stmt.list.add( "LuanImpl.nop(" );
726 stmt.list.addAll( exp.list ); 723 stmt.list.addAll( exp.list );
727 stmt.list.add( ")" ); 724 stmt.list.add( ")" );
728 } else { 725 } else {
729 stmt.list.addAll( exp.list ); 726 stmt.list.addAll( exp.list );
740 if( var==null || !var.isSettable() ) 737 if( var==null || !var.isSettable() )
741 return parser.failure(null); 738 return parser.failure(null);
742 return parser.success( var ); 739 return parser.success( var );
743 } 740 }
744 741
745 private ExpString RequiredExpr(In in) throws ParseException { 742 private Expr RequiredExpr(In in) throws ParseException {
746 parser.begin(); 743 parser.begin();
747 return parser.success(required(ExprZ(in),"Bad expression")); 744 return parser.success(required(ExprZ(in),"Bad expression"));
748 } 745 }
749 746
750 private ExpString ExprZ(In in) throws ParseException { 747 private Expr ExprZ(In in) throws ParseException {
751 return OrExpr(in); 748 return OrExpr(in);
752 } 749 }
753 750
754 private ExpString OrExpr(In in) throws ParseException { 751 private Expr OrExpr(In in) throws ParseException {
755 parser.begin(); 752 parser.begin();
756 ExpString exp = AndExpr(in); 753 Expr exp = AndExpr(in);
757 if( exp==null ) 754 if( exp==null )
758 return parser.failure(null); 755 return parser.failure(null);
759 while( Keyword("or",in) ) { 756 while( Keyword("or",in) ) {
760 exp = exp.expr(); 757 exp = exp.single();
761 ExpString exp2 = required(RelExpr(in)).expr(); 758 Expr exp2 = required(RelExpr(in)).single();
762 ExpString newExp = new ExpString(true,true); 759 Expr newExp = new Expr(Val.SINGLE,true);
763 newExp.list.add( "(LuanImpl.cnd(t = " ); 760 newExp.list.add( "(LuanImpl.cnd(t = " );
764 newExp.list.addAll( exp.list ); 761 newExp.list.addAll( exp.list );
765 newExp.list.add( ") ? t : (" ); 762 newExp.list.add( ") ? t : (" );
766 newExp.list.addAll( exp2.list ); 763 newExp.list.addAll( exp2.list );
767 newExp.list.add( "))" ); 764 newExp.list.add( "))" );
768 exp = newExp; 765 exp = newExp;
769 } 766 }
770 return parser.success(exp); 767 return parser.success(exp);
771 } 768 }
772 769
773 private ExpString AndExpr(In in) throws ParseException { 770 private Expr AndExpr(In in) throws ParseException {
774 parser.begin(); 771 parser.begin();
775 ExpString exp = RelExpr(in); 772 Expr exp = RelExpr(in);
776 if( exp==null ) 773 if( exp==null )
777 return parser.failure(null); 774 return parser.failure(null);
778 while( Keyword("and",in) ) { 775 while( Keyword("and",in) ) {
779 exp = exp.expr(); 776 exp = exp.single();
780 ExpString exp2 = required(RelExpr(in)).expr(); 777 Expr exp2 = required(RelExpr(in)).single();
781 ExpString newExp = new ExpString(true,true); 778 Expr newExp = new Expr(Val.SINGLE,true);
782 newExp.list.add( "(LuanImpl.cnd(t = " ); 779 newExp.list.add( "(LuanImpl.cnd(t = " );
783 newExp.list.addAll( exp.list ); 780 newExp.list.addAll( exp.list );
784 newExp.list.add( ") ? (" ); 781 newExp.list.add( ") ? (" );
785 newExp.list.addAll( exp2.list ); 782 newExp.list.addAll( exp2.list );
786 newExp.list.add( ") : t)" ); 783 newExp.list.add( ") : t)" );
787 exp = newExp; 784 exp = newExp;
788 } 785 }
789 return parser.success(exp); 786 return parser.success(exp);
790 } 787 }
791 788
792 private ExpString RelExpr(In in) throws ParseException { 789 private Expr RelExpr(In in) throws ParseException {
793 parser.begin(); 790 parser.begin();
794 ExpString exp = ConcatExpr(in); 791 Expr exp = ConcatExpr(in);
795 if( exp==null ) 792 if( exp==null )
796 return parser.failure(null); 793 return parser.failure(null);
797 while(true) { 794 while(true) {
798 if( parser.match("==") ) { 795 if( parser.match("==") ) {
799 Spaces(in); 796 Spaces(in);
800 exp = exp.expr(); 797 exp = exp.single();
801 ExpString exp2 = required(ConcatExpr(in)).expr(); 798 Expr exp2 = required(ConcatExpr(in)).single();
802 ExpString newExp = new ExpString(true,false); 799 Expr newExp = new Expr(Val.SINGLE,false);
803 newExp.list.add( "LuanImpl.eq(luan," ); 800 newExp.list.add( "LuanImpl.eq(luan," );
804 newExp.list.addAll( exp.list ); 801 newExp.list.addAll( exp.list );
805 newExp.list.add( "," ); 802 newExp.list.add( "," );
806 newExp.list.addAll( exp2.list ); 803 newExp.list.addAll( exp2.list );
807 newExp.list.add( ")" ); 804 newExp.list.add( ")" );
808 exp = newExp; 805 exp = newExp;
809 } else if( parser.match("~=") ) { 806 } else if( parser.match("~=") ) {
810 Spaces(in); 807 Spaces(in);
811 exp = exp.expr(); 808 exp = exp.single();
812 ExpString exp2 = required(ConcatExpr(in)).expr(); 809 Expr exp2 = required(ConcatExpr(in)).single();
813 ExpString newExp = new ExpString(true,false); 810 Expr newExp = new Expr(Val.SINGLE,false);
814 newExp.list.add( "!LuanImpl.eq(luan," ); 811 newExp.list.add( "!LuanImpl.eq(luan," );
815 newExp.list.addAll( exp.list ); 812 newExp.list.addAll( exp.list );
816 newExp.list.add( "," ); 813 newExp.list.add( "," );
817 newExp.list.addAll( exp2.list ); 814 newExp.list.addAll( exp2.list );
818 newExp.list.add( ")" ); 815 newExp.list.add( ")" );
819 exp = newExp; 816 exp = newExp;
820 } else if( parser.match("<=") ) { 817 } else if( parser.match("<=") ) {
821 Spaces(in); 818 Spaces(in);
822 exp = exp.expr(); 819 exp = exp.single();
823 ExpString exp2 = required(ConcatExpr(in)).expr(); 820 Expr exp2 = required(ConcatExpr(in)).single();
824 ExpString newExp = new ExpString(true,false); 821 Expr newExp = new Expr(Val.SINGLE,false);
825 newExp.list.add( "LuanImpl.le(luan," ); 822 newExp.list.add( "LuanImpl.le(luan," );
826 newExp.list.addAll( exp.list ); 823 newExp.list.addAll( exp.list );
827 newExp.list.add( "," ); 824 newExp.list.add( "," );
828 newExp.list.addAll( exp2.list ); 825 newExp.list.addAll( exp2.list );
829 newExp.list.add( ")" ); 826 newExp.list.add( ")" );
830 exp = newExp; 827 exp = newExp;
831 } else if( parser.match(">=") ) { 828 } else if( parser.match(">=") ) {
832 Spaces(in); 829 Spaces(in);
833 exp = exp.expr(); 830 exp = exp.single();
834 ExpString exp2 = required(ConcatExpr(in)).expr(); 831 Expr exp2 = required(ConcatExpr(in)).single();
835 ExpString newExp = new ExpString(true,false); 832 Expr newExp = new Expr(Val.SINGLE,false);
836 newExp.list.add( "LuanImpl.le(luan," ); 833 newExp.list.add( "LuanImpl.le(luan," );
837 newExp.list.addAll( exp2.list ); 834 newExp.list.addAll( exp2.list );
838 newExp.list.add( "," ); 835 newExp.list.add( "," );
839 newExp.list.addAll( exp.list ); 836 newExp.list.addAll( exp.list );
840 newExp.list.add( ")" ); 837 newExp.list.add( ")" );
841 exp = newExp; 838 exp = newExp;
842 } else if( parser.match("<") ) { 839 } else if( parser.match("<") ) {
843 Spaces(in); 840 Spaces(in);
844 exp = exp.expr(); 841 exp = exp.single();
845 ExpString exp2 = required(ConcatExpr(in)).expr(); 842 Expr exp2 = required(ConcatExpr(in)).single();
846 ExpString newExp = new ExpString(true,false); 843 Expr newExp = new Expr(Val.SINGLE,false);
847 newExp.list.add( "LuanImpl.lt(luan," ); 844 newExp.list.add( "LuanImpl.lt(luan," );
848 newExp.list.addAll( exp.list ); 845 newExp.list.addAll( exp.list );
849 newExp.list.add( "," ); 846 newExp.list.add( "," );
850 newExp.list.addAll( exp2.list ); 847 newExp.list.addAll( exp2.list );
851 newExp.list.add( ")" ); 848 newExp.list.add( ")" );
852 exp = newExp; 849 exp = newExp;
853 } else if( parser.match(">") ) { 850 } else if( parser.match(">") ) {
854 Spaces(in); 851 Spaces(in);
855 exp = exp.expr(); 852 exp = exp.single();
856 ExpString exp2 = required(ConcatExpr(in)).expr(); 853 Expr exp2 = required(ConcatExpr(in)).single();
857 ExpString newExp = new ExpString(true,false); 854 Expr newExp = new Expr(Val.SINGLE,false);
858 newExp.list.add( "LuanImpl.lt(luan," ); 855 newExp.list.add( "LuanImpl.lt(luan," );
859 newExp.list.addAll( exp2.list ); 856 newExp.list.addAll( exp2.list );
860 newExp.list.add( "," ); 857 newExp.list.add( "," );
861 newExp.list.addAll( exp.list ); 858 newExp.list.addAll( exp.list );
862 newExp.list.add( ")" ); 859 newExp.list.add( ")" );
865 break; 862 break;
866 } 863 }
867 return parser.success(exp); 864 return parser.success(exp);
868 } 865 }
869 866
870 private ExpString ConcatExpr(In in) throws ParseException { 867 private Expr ConcatExpr(In in) throws ParseException {
871 parser.begin(); 868 parser.begin();
872 ExpString exp = SumExpr(in); 869 Expr exp = SumExpr(in);
873 if( exp==null ) 870 if( exp==null )
874 return parser.failure(null); 871 return parser.failure(null);
875 if( parser.match("..") ) { 872 if( parser.match("..") ) {
876 Spaces(in); 873 Spaces(in);
877 exp = exp.expr(); 874 exp = exp.single();
878 ExpString exp2 = required(ConcatExpr(in)).expr(); 875 Expr exp2 = required(ConcatExpr(in)).single();
879 ExpString newExp = new ExpString(true,false); 876 Expr newExp = new Expr(Val.SINGLE,false);
880 newExp.list.add( "LuanImpl.concat(luan," ); 877 newExp.list.add( "LuanImpl.concat(luan," );
881 newExp.list.addAll( exp.list ); 878 newExp.list.addAll( exp.list );
882 newExp.list.add( "," ); 879 newExp.list.add( "," );
883 newExp.list.addAll( exp2.list ); 880 newExp.list.addAll( exp2.list );
884 newExp.list.add( ")" ); 881 newExp.list.add( ")" );
885 exp = newExp; 882 exp = newExp;
886 } 883 }
887 return parser.success(exp); 884 return parser.success(exp);
888 } 885 }
889 886
890 private ExpString SumExpr(In in) throws ParseException { 887 private Expr SumExpr(In in) throws ParseException {
891 parser.begin(); 888 parser.begin();
892 ExpString exp = TermExpr(in); 889 Expr exp = TermExpr(in);
893 if( exp==null ) 890 if( exp==null )
894 return parser.failure(null); 891 return parser.failure(null);
895 while(true) { 892 while(true) {
896 if( parser.match('+') ) { 893 if( parser.match('+') ) {
897 Spaces(in); 894 Spaces(in);
898 exp = exp.expr(); 895 exp = exp.single();
899 ExpString exp2 = required(TermExpr(in)).expr(); 896 Expr exp2 = required(TermExpr(in)).single();
900 ExpString newExp = new ExpString(true,false); 897 Expr newExp = new Expr(Val.SINGLE,false);
901 newExp.list.add( "LuanImpl.add(luan," ); 898 newExp.list.add( "LuanImpl.add(luan," );
902 newExp.list.addAll( exp.list ); 899 newExp.list.addAll( exp.list );
903 newExp.list.add( "," ); 900 newExp.list.add( "," );
904 newExp.list.addAll( exp2.list ); 901 newExp.list.addAll( exp2.list );
905 newExp.list.add( ")" ); 902 newExp.list.add( ")" );
906 exp = newExp; 903 exp = newExp;
907 } else if( Minus() ) { 904 } else if( Minus() ) {
908 Spaces(in); 905 Spaces(in);
909 exp = exp.expr(); 906 exp = exp.single();
910 ExpString exp2 = required(TermExpr(in)).expr(); 907 Expr exp2 = required(TermExpr(in)).single();
911 ExpString newExp = new ExpString(true,false); 908 Expr newExp = new Expr(Val.SINGLE,false);
912 newExp.list.add( "LuanImpl.sub(luan," ); 909 newExp.list.add( "LuanImpl.sub(luan," );
913 newExp.list.addAll( exp.list ); 910 newExp.list.addAll( exp.list );
914 newExp.list.add( "," ); 911 newExp.list.add( "," );
915 newExp.list.addAll( exp2.list ); 912 newExp.list.addAll( exp2.list );
916 newExp.list.add( ")" ); 913 newExp.list.add( ")" );
924 private boolean Minus() { 921 private boolean Minus() {
925 parser.begin(); 922 parser.begin();
926 return parser.match('-') && !parser.match('-') ? parser.success() : parser.failure(); 923 return parser.match('-') && !parser.match('-') ? parser.success() : parser.failure();
927 } 924 }
928 925
929 private ExpString TermExpr(In in) throws ParseException { 926 private Expr TermExpr(In in) throws ParseException {
930 parser.begin(); 927 parser.begin();
931 ExpString exp = UnaryExpr(in); 928 Expr exp = UnaryExpr(in);
932 if( exp==null ) 929 if( exp==null )
933 return parser.failure(null); 930 return parser.failure(null);
934 while(true) { 931 while(true) {
935 if( parser.match('*') ) { 932 if( parser.match('*') ) {
936 Spaces(in); 933 Spaces(in);
937 exp = exp.expr(); 934 exp = exp.single();
938 ExpString exp2 = required(UnaryExpr(in)).expr(); 935 Expr exp2 = required(UnaryExpr(in)).single();
939 ExpString newExp = new ExpString(true,false); 936 Expr newExp = new Expr(Val.SINGLE,false);
940 newExp.list.add( "LuanImpl.mul(luan," ); 937 newExp.list.add( "LuanImpl.mul(luan," );
941 newExp.list.addAll( exp.list ); 938 newExp.list.addAll( exp.list );
942 newExp.list.add( "," ); 939 newExp.list.add( "," );
943 newExp.list.addAll( exp2.list ); 940 newExp.list.addAll( exp2.list );
944 newExp.list.add( ")" ); 941 newExp.list.add( ")" );
945 exp = newExp; 942 exp = newExp;
946 } else if( parser.match('/') ) { 943 } else if( parser.match('/') ) {
947 Spaces(in); 944 Spaces(in);
948 exp = exp.expr(); 945 exp = exp.single();
949 ExpString exp2 = required(UnaryExpr(in)).expr(); 946 Expr exp2 = required(UnaryExpr(in)).single();
950 ExpString newExp = new ExpString(true,false); 947 Expr newExp = new Expr(Val.SINGLE,false);
951 newExp.list.add( "LuanImpl.div(luan," ); 948 newExp.list.add( "LuanImpl.div(luan," );
952 newExp.list.addAll( exp.list ); 949 newExp.list.addAll( exp.list );
953 newExp.list.add( "," ); 950 newExp.list.add( "," );
954 newExp.list.addAll( exp2.list ); 951 newExp.list.addAll( exp2.list );
955 newExp.list.add( ")" ); 952 newExp.list.add( ")" );
956 exp = newExp; 953 exp = newExp;
957 } else if( Mod() ) { 954 } else if( Mod() ) {
958 Spaces(in); 955 Spaces(in);
959 exp = exp.expr(); 956 exp = exp.single();
960 ExpString exp2 = required(UnaryExpr(in)).expr(); 957 Expr exp2 = required(UnaryExpr(in)).single();
961 ExpString newExp = new ExpString(true,false); 958 Expr newExp = new Expr(Val.SINGLE,false);
962 newExp.list.add( "LuanImpl.mod(luan," ); 959 newExp.list.add( "LuanImpl.mod(luan," );
963 newExp.list.addAll( exp.list ); 960 newExp.list.addAll( exp.list );
964 newExp.list.add( "," ); 961 newExp.list.add( "," );
965 newExp.list.addAll( exp2.list ); 962 newExp.list.addAll( exp2.list );
966 newExp.list.add( ")" ); 963 newExp.list.add( ")" );
974 private boolean Mod() { 971 private boolean Mod() {
975 parser.begin(); 972 parser.begin();
976 return parser.match('%') && !parser.match('>') ? parser.success() : parser.failure(); 973 return parser.match('%') && !parser.match('>') ? parser.success() : parser.failure();
977 } 974 }
978 975
979 private ExpString UnaryExpr(In in) throws ParseException { 976 private Expr UnaryExpr(In in) throws ParseException {
980 parser.begin(); 977 parser.begin();
981 if( parser.match('#') ) { 978 if( parser.match('#') ) {
982 Spaces(in); 979 Spaces(in);
983 ExpString exp = required(UnaryExpr(in)).expr(); 980 Expr exp = required(UnaryExpr(in)).single();
984 ExpString newExp = new ExpString(true,false); 981 Expr newExp = new Expr(Val.SINGLE,false);
985 newExp.list.add( "LuanImpl.len(luan," ); 982 newExp.list.add( "LuanImpl.len(luan," );
986 newExp.list.addAll( exp.list ); 983 newExp.list.addAll( exp.list );
987 newExp.list.add( ")" ); 984 newExp.list.add( ")" );
988 return parser.success(newExp); 985 return parser.success(newExp);
989 } 986 }
990 if( Minus() ) { 987 if( Minus() ) {
991 Spaces(in); 988 Spaces(in);
992 ExpString exp = required(UnaryExpr(in)).expr(); 989 Expr exp = required(UnaryExpr(in)).single();
993 ExpString newExp = new ExpString(true,false); 990 Expr newExp = new Expr(Val.SINGLE,false);
994 newExp.list.add( "LuanImpl.unm(luan," ); 991 newExp.list.add( "LuanImpl.unm(luan," );
995 newExp.list.addAll( exp.list ); 992 newExp.list.addAll( exp.list );
996 newExp.list.add( ")" ); 993 newExp.list.add( ")" );
997 return parser.success(newExp); 994 return parser.success(newExp);
998 } 995 }
999 if( Keyword("not",in) ) { 996 if( Keyword("not",in) ) {
1000 Spaces(in); 997 Spaces(in);
1001 ExpString exp = required(UnaryExpr(in)).expr(); 998 Expr exp = required(UnaryExpr(in)).single();
1002 ExpString newExp = new ExpString(true,false); 999 Expr newExp = new Expr(Val.SINGLE,false);
1003 newExp.list.add( "!Luan.checkBoolean(" ); 1000 newExp.list.add( "!Luan.checkBoolean(" );
1004 newExp.list.addAll( exp.list ); 1001 newExp.list.addAll( exp.list );
1005 newExp.list.add( ")" ); 1002 newExp.list.add( ")" );
1006 return parser.success(newExp); 1003 return parser.success(newExp);
1007 } 1004 }
1008 ExpString exp = PowExpr(in); 1005 Expr exp = PowExpr(in);
1009 if( exp==null ) 1006 if( exp==null )
1010 return parser.failure(null); 1007 return parser.failure(null);
1011 return parser.success(exp); 1008 return parser.success(exp);
1012 } 1009 }
1013 1010
1014 private ExpString PowExpr(In in) throws ParseException { 1011 private Expr PowExpr(In in) throws ParseException {
1015 parser.begin(); 1012 parser.begin();
1016 ExpString exp1 = SingleExpr(in); 1013 Expr exp1 = SingleExpr(in);
1017 if( exp1==null ) 1014 if( exp1==null )
1018 return parser.failure(null); 1015 return parser.failure(null);
1019 if( parser.match('^') ) { 1016 if( parser.match('^') ) {
1020 Spaces(in); 1017 Spaces(in);
1021 ExpString exp2 = required(PowExpr(in)); 1018 Expr exp2 = required(PowExpr(in));
1022 ExpString newExp = new ExpString(true,false); 1019 Expr newExp = new Expr(Val.SINGLE,false);
1023 newExp.list.add( "LuanImpl.pow(luan," ); 1020 newExp.list.add( "LuanImpl.pow(luan," );
1024 newExp.list.addAll( exp1.expr().list ); 1021 newExp.list.addAll( exp1.single().list );
1025 newExp.list.add( "," ); 1022 newExp.list.add( "," );
1026 newExp.list.addAll( exp2.expr().list ); 1023 newExp.list.addAll( exp2.single().list );
1027 newExp.list.add( ")" ); 1024 newExp.list.add( ")" );
1028 exp1 = newExp; 1025 exp1 = newExp;
1029 } 1026 }
1030 return parser.success(exp1); 1027 return parser.success(exp1);
1031 } 1028 }
1032 1029
1033 private ExpString SingleExpr(In in) throws ParseException { 1030 private Expr SingleExpr(In in) throws ParseException {
1034 parser.begin(); 1031 parser.begin();
1035 ExpString exp = FunctionExpr(in); 1032 Expr exp = FunctionExpr(in);
1036 if( exp != null ) 1033 if( exp != null )
1037 return parser.success(exp); 1034 return parser.success(exp);
1038 exp = VarExp(in); 1035 exp = VarExp(in);
1039 if( exp != null ) 1036 if( exp != null )
1040 return parser.success(exp); 1037 return parser.success(exp);
1042 if( exp != null ) 1039 if( exp != null )
1043 return parser.success(exp); 1040 return parser.success(exp);
1044 return parser.failure(null); 1041 return parser.failure(null);
1045 } 1042 }
1046 1043
1047 private ExpString FunctionExpr(In in) throws ParseException { 1044 private Expr FunctionExpr(In in) throws ParseException {
1048 if( !Keyword("function",in) ) 1045 if( !Keyword("function",in) )
1049 return null; 1046 return null;
1050 return RequiredFunction(in); 1047 return RequiredFunction(in);
1051 } 1048 }
1052 1049
1053 private ExpString RequiredFunction(In in) throws ParseException { 1050 private Expr RequiredFunction(In in) throws ParseException {
1054 int start = parser.begin(); 1051 int start = parser.begin();
1055 RequiredMatch('('); 1052 RequiredMatch('(');
1056 In inParens = in.parens(); 1053 In inParens = in.parens();
1057 Spaces(inParens); 1054 Spaces(inParens);
1058 frame = new Frame(frame); 1055 frame = new Frame(frame);
1059 StmtString stmt = new StmtString(); 1056 Stmts stmt = new Stmts();
1060 List<String> names = NameList(in); 1057 List<String> names = NameList(in);
1061 if( names != null ) { 1058 if( names != null ) {
1062 ExpString args = new ExpString(false,false); 1059 Expr args = new Expr(Val.ARRAY,false);
1063 args.list.add( "args" ); 1060 args.list.add( "args" );
1064 stmt.list.addAll( makeLocalSetStmt(names,args).list ); 1061 stmt.list.addAll( makeLocalSetStmt(names,args).list );
1065 if( parser.match(',') ) { 1062 if( parser.match(',') ) {
1066 Spaces(inParens); 1063 Spaces(inParens);
1067 if( !parser.match("...") ) 1064 if( !parser.match("...") )
1075 frame.isVarArg = true; 1072 frame.isVarArg = true;
1076 stmt.list.add( "final Object[] varArgs = LuanImpl.varArgs(args,0);\n" ); 1073 stmt.list.add( "final Object[] varArgs = LuanImpl.varArgs(args,0);\n" );
1077 } 1074 }
1078 RequiredMatch(')'); 1075 RequiredMatch(')');
1079 Spaces(in); 1076 Spaces(in);
1080 StmtString block = RequiredBlock(); 1077 Stmts block = RequiredBlock();
1081 stmt.list.addAll( block.list ); 1078 stmt.list.addAll( block.list );
1082 stmt.hasReturn = block.hasReturn; 1079 stmt.hasReturn = block.hasReturn;
1083 RequiredKeyword("end",in); 1080 RequiredKeyword("end",in);
1084 ExpString fnDef = newFnExpStr(start,stmt); 1081 Expr fnDef = newFnExpStr(start,stmt);
1085 frame = frame.parent; 1082 frame = frame.parent;
1086 return parser.success(fnDef); 1083 return parser.success(fnDef);
1087 } 1084 }
1088 1085
1089 private ExpString VarArgs(In in) throws ParseException { 1086 private Expr VarArgs(In in) throws ParseException {
1090 parser.begin(); 1087 parser.begin();
1091 if( !frame.isVarArg || !parser.match("...") ) 1088 if( !frame.isVarArg || !parser.match("...") )
1092 return parser.failure(null); 1089 return parser.failure(null);
1093 Spaces(in); 1090 Spaces(in);
1094 ExpString exp = new ExpString(false,false); 1091 Expr exp = new Expr(Val.ARRAY,false);
1095 exp.list.add("varArgs"); 1092 exp.list.add("varArgs");
1096 return parser.success(exp); 1093 return parser.success(exp);
1097 } 1094 }
1098 1095
1099 private ExpString TableExpr(In in) throws ParseException { 1096 private Expr TableExpr(In in) throws ParseException {
1100 parser.begin(); 1097 parser.begin();
1101 if( !parser.match('{') ) 1098 if( !parser.match('{') )
1102 return parser.failure(null); 1099 return parser.failure(null);
1103 Spaces(In.NOTHING); 1100 Spaces(In.NOTHING);
1104 List<ExpString> builder = new ArrayList<ExpString>(); 1101 List<Expr> builder = new ArrayList<Expr>();
1105 Field(builder); 1102 Field(builder);
1106 while( FieldSep() ) { 1103 while( FieldSep() ) {
1107 Spaces(In.NOTHING); 1104 Spaces(In.NOTHING);
1108 Field(builder); 1105 Field(builder);
1109 } 1106 }
1110 ExpString exp = TemplateExpressions(In.NOTHING); 1107 Expr exp = TemplateExpressions(In.NOTHING);
1111 if( exp != null ) 1108 if( exp != null )
1112 builder.add(exp); 1109 builder.add(exp);
1113 if( !parser.match('}') ) 1110 if( !parser.match('}') )
1114 throw parser.exception("Expected table element or '}'"); 1111 throw parser.exception("Expected table element or '}'");
1115 Spaces(in); 1112 Spaces(in);
1116 exp = new ExpString(true,false); 1113 exp = new Expr(Val.SINGLE,false);
1117 exp.list.add( "LuanImpl.table(" ); 1114 exp.list.add( "LuanImpl.table(" );
1118 exp.list.addAll( expString(builder).list ); 1115 exp.list.addAll( expString(builder).array().list );
1119 exp.list.add( ")" ); 1116 exp.list.add( ")" );
1120 return parser.success( exp ); 1117 return parser.success( exp );
1121 } 1118 }
1122 1119
1123 private boolean FieldSep() throws ParseException { 1120 private boolean FieldSep() throws ParseException {
1124 return parser.anyOf(",;") || EndOfLine(); 1121 return parser.anyOf(",;") || EndOfLine();
1125 } 1122 }
1126 1123
1127 private boolean Field(List<ExpString> builder) throws ParseException { 1124 private boolean Field(List<Expr> builder) throws ParseException {
1128 parser.begin(); 1125 parser.begin();
1129 ExpString exp = SubExpr(In.NOTHING); 1126 Expr exp = SubExpr(In.NOTHING);
1130 if( exp==null ) 1127 if( exp==null )
1131 exp = NameExpr(In.NOTHING); 1128 exp = NameExpr(In.NOTHING);
1132 if( exp!=null && parser.match('=') ) { 1129 if( exp!=null && parser.match('=') ) {
1133 Spaces(In.NOTHING); 1130 Spaces(In.NOTHING);
1134 ExpString val = RequiredExpr(In.NOTHING).expr(); 1131 Expr val = RequiredExpr(In.NOTHING).single();
1135 ExpString newExp = new ExpString(true,false); 1132 Expr newExp = new Expr(Val.SINGLE,false);
1136 newExp.list.add( "new TableField(" ); 1133 newExp.list.add( "new TableField(" );
1137 newExp.list.addAll( exp.list ); 1134 newExp.list.addAll( exp.list );
1138 newExp.list.add( "," ); 1135 newExp.list.add( "," );
1139 newExp.list.addAll( val.list ); 1136 newExp.list.addAll( val.list );
1140 newExp.list.add( ")" ); 1137 newExp.list.add( ")" );
1141 builder.add( newExp ); 1138 builder.add( newExp );
1142 return parser.success(); 1139 return parser.success();
1143 } 1140 }
1144 parser.rollback(); 1141 parser.rollback();
1145 ExpString exprs = ExprZ(In.NOTHING); 1142 Expr exprs = ExprZ(In.NOTHING);
1146 if( exprs != null ) { 1143 if( exprs != null ) {
1147 builder.add(exprs); 1144 builder.add(exprs);
1148 return parser.success(); 1145 return parser.success();
1149 } 1146 }
1150 return parser.failure(); 1147 return parser.failure();
1151 } 1148 }
1152 1149
1153 private ExpString VarExp(In in) throws ParseException { 1150 private Expr VarExp(In in) throws ParseException {
1154 Var var = VarZ(in); 1151 Var var = VarZ(in);
1155 return var==null ? null : var.exp(); 1152 return var==null ? null : var.exp();
1156 } 1153 }
1157 1154
1158 private Var VarZ(In in) throws ParseException { 1155 private Var VarZ(In in) throws ParseException {
1169 1166
1170 private Var VarStart(In in) throws ParseException { 1167 private Var VarStart(In in) throws ParseException {
1171 if( parser.match('(') ) { 1168 if( parser.match('(') ) {
1172 In inParens = in.parens(); 1169 In inParens = in.parens();
1173 Spaces(inParens); 1170 Spaces(inParens);
1174 ExpString exp = RequiredExpr(inParens).expr(); 1171 Expr exp = RequiredExpr(inParens).single();
1175 RequiredMatch(')'); 1172 RequiredMatch(')');
1176 Spaces(in); 1173 Spaces(in);
1177 return exprVar(exp); 1174 return exprVar(exp);
1178 } 1175 }
1179 String name = Name(in); 1176 String name = Name(in);
1180 if( name != null ) 1177 if( name != null )
1181 return nameVar(name); 1178 return nameVar(name);
1182 ExpString exp; 1179 Expr exp;
1183 exp = TableExpr(in); 1180 exp = TableExpr(in);
1184 if( exp != null ) 1181 if( exp != null )
1185 return exprVar(exp); 1182 return exprVar(exp);
1186 exp = Literal(in); 1183 exp = Literal(in);
1187 if( exp != null ) 1184 if( exp != null )
1188 return exprVar(exp); 1185 return exprVar(exp);
1189 return null; 1186 return null;
1190 } 1187 }
1191 1188
1192 private Var Var2(In in,ExpString exp1) throws ParseException { 1189 private Var Var2(In in,Expr exp1) throws ParseException {
1193 parser.begin(); 1190 parser.begin();
1194 ExpString exp2 = SubExpr(in); 1191 Expr exp2 = SubExpr(in);
1195 if( exp2 != null ) 1192 if( exp2 != null )
1196 return parser.success(indexVar(exp1,exp2)); 1193 return parser.success(indexVar(exp1,exp2));
1197 if( parser.match('.') ) { 1194 if( parser.match('.') ) {
1198 Spaces(in); 1195 Spaces(in);
1199 exp2 = NameExpr(in); 1196 exp2 = NameExpr(in);
1200 if( exp2!=null ) 1197 if( exp2!=null )
1201 return parser.success(indexVar(exp1,exp2)); 1198 return parser.success(indexVar(exp1,exp2));
1202 return parser.failure(null); 1199 return parser.failure(null);
1203 } 1200 }
1204 ExpString fnCall = Args( in, exp1, new ArrayList<ExpString>() ); 1201 Expr fnCall = Args( in, exp1, new ArrayList<Expr>() );
1205 if( fnCall != null ) 1202 if( fnCall != null )
1206 return parser.success(exprVar(fnCall)); 1203 return parser.success(exprVar(fnCall));
1207 return parser.failure(null); 1204 return parser.failure(null);
1208 } 1205 }
1209 1206
1210 private interface Var { 1207 private interface Var {
1211 public ExpString exp() throws ParseException; 1208 public Expr exp() throws ParseException;
1212 // public Settable settable() throws ParseException; 1209 // public Settable settable() throws ParseException;
1213 public boolean isSettable(); 1210 public boolean isSettable();
1214 public StmtString set(ExpString val) throws ParseException; 1211 public Stmts set(Expr val) throws ParseException;
1215 } 1212 }
1216 1213
1217 private ExpString env() { 1214 private Expr env() {
1218 Sym sym = getSym("_ENV"); 1215 Sym sym = getSym("_ENV");
1219 if( sym != null ) 1216 if( sym != null )
1220 return sym.exp(); 1217 return sym.exp();
1221 return null; 1218 return null;
1222 } 1219 }
1223 1220
1224 private Var nameVar(final String name) { 1221 private Var nameVar(final String name) {
1225 return new Var() { 1222 return new Var() {
1226 1223
1227 public ExpString exp() throws ParseException { 1224 public Expr exp() throws ParseException {
1228 Sym sym = getSym(name); 1225 Sym sym = getSym(name);
1229 if( sym != null ) 1226 if( sym != null )
1230 return sym.exp(); 1227 return sym.exp();
1231 ExpString envExpr = env(); 1228 Expr envExpr = env();
1232 if( envExpr != null ) 1229 if( envExpr != null )
1233 return indexExpStr( envExpr, constExpStr(name) ); 1230 return indexExpStr( envExpr, constExpStr(name) );
1234 parser.failure(null); 1231 parser.failure(null);
1235 throw parser.exception("name '"+name+"' not defined"); 1232 throw parser.exception("name '"+name+"' not defined");
1236 } 1233 }
1237 1234
1238 public boolean isSettable() { 1235 public boolean isSettable() {
1239 return true; 1236 return true;
1240 } 1237 }
1241 /* 1238
1242 private Settable settable() throws ParseException { 1239 public Stmts set(Expr val) throws ParseException {
1243 int index = stackIndex(name);
1244 if( index != -1 )
1245 return new SetLocalVar(index);
1246 index = upValueIndex(name);
1247 if( index != -1 )
1248 return new SetUpVar(index);
1249 Expr envExpr = env();
1250 if( envExpr != null )
1251 return new SetTableEntry( envExpr, new ConstExpr(name) );
1252 parser.failure(null);
1253 throw parser.exception("name '"+name+"' not defined");
1254 }
1255 */
1256 public StmtString set(ExpString val) throws ParseException {
1257 Sym sym = getSym(name); 1240 Sym sym = getSym(name);
1258 if( sym != null ) { 1241 if( sym != null ) {
1259 StmtString stmt = new StmtString(); 1242 Stmts stmt = new Stmts();
1260 stmt.list.addAll( sym.exp().list ); 1243 stmt.list.addAll( sym.exp().list );
1261 stmt.list.add( " = " ); 1244 stmt.list.add( " = " );
1262 stmt.list.addAll( val.expr().list ); 1245 stmt.list.addAll( val.single().list );
1263 stmt.list.add( ";\n" ); 1246 stmt.list.add( ";\n" );
1264 return stmt; 1247 return stmt;
1265 } 1248 }
1266 ExpString envExpr = env(); 1249 Expr envExpr = env();
1267 if( envExpr != null ) 1250 if( envExpr != null )
1268 return indexVar( envExpr, constExpStr(name) ).set(val); 1251 return indexVar( envExpr, constExpStr(name) ).set(val);
1269 throw new RuntimeException(); 1252 throw new RuntimeException();
1270 } 1253 }
1271 }; 1254 };
1272 } 1255 }
1273 1256
1274 private Var exprVar(final ExpString expr) { 1257 private Var exprVar(final Expr expr) {
1275 return new Var() { 1258 return new Var() {
1276 1259
1277 public ExpString exp() { 1260 public Expr exp() {
1278 return expr; 1261 return expr;
1279 } 1262 }
1280 1263
1281 public boolean isSettable() { 1264 public boolean isSettable() {
1282 return false; 1265 return false;
1283 } 1266 }
1284 1267
1285 public StmtString set(ExpString val) { 1268 public Stmts set(Expr val) {
1286 throw new RuntimeException(); 1269 throw new RuntimeException();
1287 } 1270 }
1288 }; 1271 };
1289 } 1272 }
1290 1273
1291 private Var indexVar(final ExpString table,final ExpString key) { 1274 private Var indexVar(final Expr table,final Expr key) {
1292 return new Var() { 1275 return new Var() {
1293 1276
1294 public ExpString exp() { 1277 public Expr exp() {
1295 return indexExpStr( table, key ); 1278 return indexExpStr( table, key );
1296 } 1279 }
1297 1280
1298 public boolean isSettable() { 1281 public boolean isSettable() {
1299 return true; 1282 return true;
1300 } 1283 }
1301 /* 1284
1302 public Settable settable() { 1285 public Stmts set(Expr val) {
1303 return new SetTableEntry(expr(LuanParser.exp(table)),expr(LuanParser.exp(key))); 1286 Stmts stmt = new Stmts();
1304 }
1305 */
1306 public StmtString set(ExpString val) {
1307 StmtString stmt = new StmtString();
1308 stmt.list.add( "LuanImpl.put(luan," ); 1287 stmt.list.add( "LuanImpl.put(luan," );
1309 stmt.list.addAll( table.expr().list ); 1288 stmt.list.addAll( table.single().list );
1310 stmt.list.add( "," ); 1289 stmt.list.add( "," );
1311 stmt.list.addAll( key.expr().list ); 1290 stmt.list.addAll( key.single().list );
1312 stmt.list.add( "," ); 1291 stmt.list.add( "," );
1313 stmt.list.addAll( val.expr().list ); 1292 stmt.list.addAll( val.single().list );
1314 stmt.list.add( ");\n" ); 1293 stmt.list.add( ");\n" );
1315 return stmt; 1294 return stmt;
1316 } 1295 }
1317 }; 1296 };
1318 } 1297 }
1319 1298
1320 private ExpString Args(In in,ExpString fn,List<ExpString> builder) throws ParseException { 1299 private Expr Args(In in,Expr fn,List<Expr> builder) throws ParseException {
1321 parser.begin(); 1300 parser.begin();
1322 return args(in,builder) 1301 return args(in,builder)
1323 ? parser.success( callExpStr( fn, expString(builder) ) ) 1302 ? parser.success( callExpStr( fn, expString(builder) ) )
1324 : parser.failure((ExpString)null); 1303 : parser.failure((Expr)null);
1325 } 1304 }
1326 1305
1327 private boolean args(In in,List<ExpString> builder) throws ParseException { 1306 private boolean args(In in,List<Expr> builder) throws ParseException {
1328 parser.begin(); 1307 parser.begin();
1329 if( parser.match('(') ) { 1308 if( parser.match('(') ) {
1330 In inParens = in.parens(); 1309 In inParens = in.parens();
1331 Spaces(inParens); 1310 Spaces(inParens);
1332 ExpList(inParens,builder); // optional 1311 ExpList(inParens,builder); // optional
1333 if( !parser.match(')') ) 1312 if( !parser.match(')') )
1334 throw parser.exception("Expression or ')' expected"); 1313 throw parser.exception("Expression or ')' expected");
1335 Spaces(in); 1314 Spaces(in);
1336 return parser.success(); 1315 return parser.success();
1337 } 1316 }
1338 ExpString exp = TableExpr(in); 1317 Expr exp = TableExpr(in);
1339 if( exp != null ) { 1318 if( exp != null ) {
1340 builder.add(exp); 1319 builder.add(exp);
1341 return parser.success(); 1320 return parser.success();
1342 } 1321 }
1343 String s = StringLiteral(in); 1322 String s = StringLiteral(in);
1353 } 1332 }
1354 */ 1333 */
1355 return parser.failure(); 1334 return parser.failure();
1356 } 1335 }
1357 1336
1358 private ExpString ExpStringList(In in) throws ParseException { 1337 private Expr ExpStringList(In in) throws ParseException {
1359 List<ExpString> builder = new ArrayList<ExpString>(); 1338 List<Expr> builder = new ArrayList<Expr>();
1360 return ExpList(in,builder) ? expString(builder) : null; 1339 return ExpList(in,builder) ? expString(builder) : null;
1361 } 1340 }
1362 1341
1363 private boolean ExpList(In in,List<ExpString> builder) throws ParseException { 1342 private boolean ExpList(In in,List<Expr> builder) throws ParseException {
1364 parser.begin(); 1343 parser.begin();
1365 ExpString exp = TemplateExpressions(in); 1344 Expr exp = TemplateExpressions(in);
1366 if( exp != null ) { 1345 if( exp != null ) {
1367 builder.add(exp); 1346 builder.add(exp);
1368 return parser.success(); 1347 return parser.success();
1369 } 1348 }
1370 exp = ExprZ(in); 1349 exp = ExprZ(in);
1381 builder.add( RequiredExpr(in) ); 1360 builder.add( RequiredExpr(in) );
1382 } 1361 }
1383 return parser.success(); 1362 return parser.success();
1384 } 1363 }
1385 1364
1386 private ExpString SubExpr(In in) throws ParseException { 1365 private Expr SubExpr(In in) throws ParseException {
1387 parser.begin(); 1366 parser.begin();
1388 if( !parser.match('[') || parser.test("[") || parser.test("=") ) 1367 if( !parser.match('[') || parser.test("[") || parser.test("=") )
1389 return parser.failure(null); 1368 return parser.failure(null);
1390 Spaces(In.NOTHING); 1369 Spaces(In.NOTHING);
1391 ExpString exp = RequiredExpr(In.NOTHING).expr(); 1370 Expr exp = RequiredExpr(In.NOTHING).single();
1392 RequiredMatch(']'); 1371 RequiredMatch(']');
1393 Spaces(in); 1372 Spaces(in);
1394 return parser.success(exp); 1373 return parser.success(exp);
1395 } 1374 }
1396 1375
1397 private ExpString NameExpr(In in) throws ParseException { 1376 private Expr NameExpr(In in) throws ParseException {
1398 parser.begin(); 1377 parser.begin();
1399 String name = Name(in); 1378 String name = Name(in);
1400 if( name==null ) 1379 if( name==null )
1401 return parser.failure(null); 1380 return parser.failure(null);
1402 return parser.success(constExpStr(name)); 1381 return parser.success(constExpStr(name));
1476 "true", 1455 "true",
1477 "until", 1456 "until",
1478 "while" 1457 "while"
1479 )); 1458 ));
1480 1459
1481 private ExpString Literal(In in) throws ParseException { 1460 private Expr Literal(In in) throws ParseException {
1482 parser.begin(); 1461 parser.begin();
1483 if( NilLiteral(in) ) { 1462 if( NilLiteral(in) ) {
1484 ExpString exp = new ExpString(true,false); 1463 Expr exp = new Expr(Val.SINGLE,false);
1485 exp.list.add( "null" ); 1464 exp.list.add( "null" );
1486 return parser.success(exp); 1465 return parser.success(exp);
1487 } 1466 }
1488 Boolean b = BooleanLiteral(in); 1467 Boolean b = BooleanLiteral(in);
1489 if( b != null ) { 1468 if( b != null ) {
1490 ExpString exp = new ExpString(true,false); 1469 Expr exp = new Expr(Val.SINGLE,false);
1491 exp.list.add( b.toString() ); 1470 exp.list.add( b.toString() );
1492 return parser.success(exp); 1471 return parser.success(exp);
1493 } 1472 }
1494 Number n = NumberLiteral(in); 1473 Number n = NumberLiteral(in);
1495 if( n != null ) { 1474 if( n != null ) {
1496 String s = n.toString(); 1475 String s = n.toString();
1497 if( n instanceof Long ) 1476 if( n instanceof Long )
1498 s += "L"; 1477 s += "L";
1499 ExpString exp = new ExpString(true,false); 1478 Expr exp = new Expr(Val.SINGLE,false);
1500 exp.list.add( s ); 1479 exp.list.add( s );
1501 return parser.success(exp); 1480 return parser.success(exp);
1502 } 1481 }
1503 String s = StringLiteral(in); 1482 String s = StringLiteral(in);
1504 if( s != null ) 1483 if( s != null )
1505 return parser.success(constExpStr(s)); 1484 return parser.success(constExpStr(s));
1506 return parser.failure(null); 1485 return parser.failure(null);
1507 } 1486 }
1508 1487
1509 private ExpString constExpStr(String s) { 1488 private Expr constExpStr(String s) {
1510 s = s 1489 s = s
1511 .replace("\\","\\\\") 1490 .replace("\\","\\\\")
1512 .replace("\"","\\\"") 1491 .replace("\"","\\\"")
1513 .replace("\n","\\n") 1492 .replace("\n","\\n")
1514 .replace("\r","\\r") 1493 .replace("\r","\\r")
1515 .replace("\t","\\t") 1494 .replace("\t","\\t")
1516 .replace("\b","\\b") 1495 .replace("\b","\\b")
1517 ; 1496 ;
1518 ExpString exp = new ExpString(true,false); 1497 Expr exp = new Expr(Val.SINGLE,false);
1519 exp.list.add( "\""+s+"\"" ); 1498 exp.list.add( "\""+s+"\"" );
1520 return exp; 1499 return exp;
1521 } 1500 }
1522 1501
1523 private boolean NilLiteral(In in) throws ParseException { 1502 private boolean NilLiteral(In in) throws ParseException {
1767 1746
1768 1747
1769 1748
1770 private static int classCounter = 0; 1749 private static int classCounter = 0;
1771 1750
1772 private class ExpString { 1751 private enum Val { SINGLE, ARRAY }
1752
1753 private class Expr {
1773 final List list = new ArrayList(); 1754 final List list = new ArrayList();
1774 final boolean isExpr; 1755 final Val valType;
1775 final boolean isStmt; 1756 final boolean isStmt;
1776 /* 1757
1777 ExpString(Expressions exp) { 1758 Expr(Val valType,boolean isStmt) {
1778 if( exp==null ) throw new NullPointerException(); 1759 this.valType = valType;
1779 int i = LuanImpl.addObj(exp);
1780 list.add( "((Expressions)LuanImpl.getObj(" + i + ")).eval(luan)" );
1781 isExpr = exp instanceof Expr;
1782 isStmt = exp instanceof StmtExp;
1783 }
1784 */
1785 ExpString(boolean isExpr,boolean isStmt) {
1786 this.isExpr = isExpr;
1787 this.isStmt = isStmt; 1760 this.isStmt = isStmt;
1788 } 1761 }
1789 1762
1790 ExpString expr() { 1763 Expr single() {
1791 if( isExpr ) 1764 if( valType==Val.SINGLE )
1792 return this; 1765 return this;
1793 ExpString exp = new ExpString(true,isStmt); 1766 Expr exp = new Expr(Val.SINGLE,isStmt);
1794 exp.list.add( "Luan.first(" ); 1767 exp.list.add( valType==Val.ARRAY ? "LuanImpl.first(" : "Luan.first(" );
1795 exp.list.addAll( list ); 1768 exp.list.addAll( list );
1796 exp.list.add( ")" ); 1769 exp.list.add( ")" );
1797 return exp; 1770 return exp;
1798 } 1771 }
1799 } 1772
1800 1773 Expr array() {
1801 private ExpString expString(List<ExpString> list) { 1774 if( valType==Val.ARRAY )
1802 ExpString exp = new ExpString(false,false); 1775 return this;
1776 Expr exp = new Expr(Val.ARRAY,isStmt);
1777 if( valType==Val.SINGLE ) {
1778 exp.list.add( "new Object[]{" );
1779 exp.list.addAll( list );
1780 exp.list.add( "}" );
1781 } else {
1782 exp.list.add( "Luan.array(" );
1783 exp.list.addAll( list );
1784 exp.list.add( ")" );
1785 }
1786 return exp;
1787 }
1788
1789 }
1790
1791 private Expr expString(List<Expr> list) {
1792 Expr exp = new Expr(Val.ARRAY,false);
1803 switch(list.size()) { 1793 switch(list.size()) {
1804 case 0: 1794 case 0:
1805 exp.list.add("LuanFunction.NOTHING"); 1795 exp.list.add("LuanFunction.NOTHING");
1806 return exp; 1796 return exp;
1807 case 1: 1797 case 1:
1808 return list.get(0); 1798 return list.get(0);
1809 default: 1799 default:
1810 int lastI = list.size() - 1; 1800 int lastI = list.size() - 1;
1811 exp.list.add( "new Object[]{" ); 1801 exp.list.add( "new Object[]{" );
1812 for( int i=0; i<lastI; i++ ) { 1802 for( int i=0; i<lastI; i++ ) {
1813 exp.list.addAll( list.get(i).expr().list ); 1803 exp.list.addAll( list.get(i).single().list );
1814 exp.list.add( "," ); 1804 exp.list.add( "," );
1815 } 1805 }
1816 ExpString last = list.get(lastI); 1806 Expr last = list.get(lastI);
1817 if( last.isExpr ) { 1807 if( last.valType==Val.SINGLE ) {
1818 exp.list.addAll( last.list ); 1808 exp.list.addAll( last.list );
1819 exp.list.add( "}" ); 1809 exp.list.add( "}" );
1820 } else { 1810 } else {
1821 exp.list.add( "}" ); 1811 exp.list.add( "}" );
1822 exp.list.add( 0, "LuanImpl.concatArgs(" ); 1812 exp.list.add( 0, "LuanImpl.concatArgs(" );
1826 } 1816 }
1827 return exp; 1817 return exp;
1828 } 1818 }
1829 } 1819 }
1830 1820
1831 private static class StmtString { 1821 private static class Stmts {
1832 final List list = new ArrayList(); 1822 final List list = new ArrayList();
1833 boolean hasReturn = false; 1823 boolean hasReturn = false;
1834 } 1824 }
1835 1825
1836 private static String concat(List list) { 1826 private static String concat(List list) {
1837 StringBuilder sb = new StringBuilder(); 1827 StringBuilder sb = new StringBuilder();
1838 for( Object o : list ) { 1828 for( Object o : list ) {
1839 if( o instanceof List ) throw new RuntimeException(); 1829 if( o instanceof List ) throw new RuntimeException();
1840 if( o instanceof ExpString ) throw new RuntimeException(); 1830 if( o instanceof Expr ) throw new RuntimeException();
1841 if( o instanceof StmtString ) throw new RuntimeException(); 1831 if( o instanceof Stmts ) throw new RuntimeException();
1842 sb.append( o.toString() ); 1832 sb.append( o.toString() );
1843 } 1833 }
1844 return sb.toString(); 1834 return sb.toString();
1845 } 1835 }
1846 1836
1847 private Class toFnClass(StmtString stmt,List<UpSym> upValueSymbols) { 1837 private Class toFnClass(Stmts stmt,List<UpSym> upValueSymbols) {
1848 String code = concat(stmt.list); 1838 String code = concat(stmt.list);
1849 //System.out.println("code:\n"+code); 1839 //System.out.println("code:\n"+code);
1850 1840
1851 String className = "EXP" + ++classCounter; 1841 String className = "EXP" + ++classCounter;
1852 String classCode = "" 1842 String classCode = ""
1864 + init(upValueSymbols) 1854 + init(upValueSymbols)
1865 +" }\n" 1855 +" }\n"
1866 +"\n" 1856 +"\n"
1867 +" @Override public Object doCall(LuanState luan,Object[] args) throws LuanException {\n" 1857 +" @Override public Object doCall(LuanState luan,Object[] args) throws LuanException {\n"
1868 +" Object t;\n" 1858 +" Object t;\n"
1859 +" Object[] a;\n"
1869 +" " + code 1860 +" " + code
1870 +" }\n" 1861 +" }\n"
1871 +"}\n" 1862 +"}\n"
1872 ; 1863 ;
1873 try { 1864 try {
1877 } catch(ClassNotFoundException e) { 1868 } catch(ClassNotFoundException e) {
1878 throw new RuntimeException(e); 1869 throw new RuntimeException(e);
1879 } 1870 }
1880 } 1871 }
1881 1872
1882 private ExpString toFnExpStr(StmtString stmt,List<UpSym> upValueSymbols) { 1873 private Expr toFnExpStr(Stmts stmt,List<UpSym> upValueSymbols) {
1883 ExpString exp = new ExpString(true,false); 1874 Expr exp = new Expr(Val.SINGLE,false);
1884 exp.list.add( "" 1875 exp.list.add( ""
1885 +"\n" 1876 +"\n"
1886 +"new Closure("+upValueSymbols.size()+",java) {\n" 1877 +"new Closure("+upValueSymbols.size()+",java) {\n"
1887 +"{\n" 1878 +"{\n"
1888 + init(upValueSymbols) 1879 + init(upValueSymbols)
1889 +"}\n" 1880 +"}\n"
1890 +" @Override public Object doCall(LuanState luan,Object[] args) throws LuanException {\n" 1881 +" @Override public Object doCall(LuanState luan,Object[] args) throws LuanException {\n"
1891 +" Object t;\n" 1882 +" Object t;\n"
1883 +" Object[] a;\n"
1892 +" " 1884 +" "
1893 ); 1885 );
1894 exp.list.addAll( stmt.list ); 1886 exp.list.addAll( stmt.list );
1895 exp.list.add( "" 1887 exp.list.add( ""
1896 +" }\n" 1888 +" }\n"
1905 sb.append( upSym.init() ); 1897 sb.append( upSym.init() );
1906 } 1898 }
1907 return sb.toString(); 1899 return sb.toString();
1908 } 1900 }
1909 1901
1910 /*
1911 private static String settableToString(Settable settable) {
1912 if( settable==null ) throw new NullPointerException();
1913 int i = LuanImpl.addObj(settable);
1914 return"((Settable)LuanImpl.getObj(" + i + "))";
1915 }
1916 */
1917 } 1902 }