Mercurial Hosting > luan
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 } |