Mercurial Hosting > luan
comparison core/src/luan/impl/LuanParser.java @ 679:43522473599d
make java line numbers match
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Thu, 14 Apr 2016 15:19:25 -0600 |
parents | 49f3d290bebd |
children | ecd436959855 |
comparison
equal
deleted
inserted
replaced
678:49f3d290bebd | 679:43522473599d |
---|---|
1 package luan.impl; | 1 package luan.impl; |
2 | 2 |
3 //import java.io.StringWriter; | |
4 //import java.io.PrintWriter; | |
3 import java.util.Set; | 5 import java.util.Set; |
4 import java.util.HashSet; | 6 import java.util.HashSet; |
5 import java.util.Arrays; | 7 import java.util.Arrays; |
6 import java.util.List; | 8 import java.util.List; |
7 import java.util.ArrayList; | 9 import java.util.ArrayList; |
34 Stmts stmt = new Stmts(); | 36 Stmts stmt = new Stmts(); |
35 if( value==null ) { | 37 if( value==null ) { |
36 stmt.add( new Object() { | 38 stmt.add( new Object() { |
37 @Override public String toString() { | 39 @Override public String toString() { |
38 if( !isPointer ) | 40 if( !isPointer ) |
39 return "Object " + javaName + ";\n"; | 41 return "Object " + javaName + "; "; |
40 else | 42 else |
41 return "final Pointer " + javaName + " = new Pointer();\n"; | 43 return "final Pointer " + javaName + " = new Pointer(); "; |
42 } | 44 } |
43 } ); | 45 } ); |
44 } else { | 46 } else { |
45 if( value.valType != Val.SINGLE ) throw new RuntimeException(); | 47 if( value.valType != Val.SINGLE ) throw new RuntimeException(); |
46 stmt.add( new Object() { | 48 stmt.add( new Object() { |
53 } ); | 55 } ); |
54 stmt.addAll(value); | 56 stmt.addAll(value); |
55 stmt.add( new Object() { | 57 stmt.add( new Object() { |
56 @Override public String toString() { | 58 @Override public String toString() { |
57 if( !isPointer ) | 59 if( !isPointer ) |
58 return ";\n"; | 60 return "; "; |
59 else | 61 else |
60 return ");\n"; | 62 return "); "; |
61 } | 63 } |
62 } ); | 64 } ); |
63 } | 65 } |
64 return stmt; | 66 return stmt; |
65 } | 67 } |
88 this.i = i; | 90 this.i = i; |
89 this.value = value; | 91 this.value = value; |
90 } | 92 } |
91 | 93 |
92 String init() { | 94 String init() { |
93 return "upValues[" + i + "] = " + value + ";\n"; | 95 return "upValues[" + i + "] = " + value + "; "; |
94 } | 96 } |
95 | 97 |
96 @Override public Expr exp() { | 98 @Override public Expr exp() { |
97 Expr exp = new Expr(Val.SINGLE,false); | 99 Expr exp = new Expr(Val.SINGLE,false); |
98 exp.add( new Object() { | 100 exp.add( new Object() { |
162 } | 164 } |
163 | 165 |
164 } | 166 } |
165 | 167 |
166 private static class In { | 168 private static class In { |
167 static final In NOTHING = new In(false,false); | 169 static final In NOTHING = new In(false); |
168 | 170 |
169 final boolean parens; | |
170 final boolean template; | 171 final boolean template; |
171 | 172 |
172 private In(boolean parens,boolean template) { | 173 private In(boolean template) { |
173 this.parens = parens; | |
174 this.template = template; | 174 this.template = template; |
175 } | 175 } |
176 | 176 |
177 In parens() { | |
178 return parens ? this : new In(true,false); | |
179 } | |
180 | |
181 In template() { | 177 In template() { |
182 return template ? this : new In(false,true); | 178 return template ? this : new In(true); |
183 } | 179 } |
184 } | 180 } |
185 | 181 |
186 // final LuanSource source; | 182 // final LuanSource source; |
187 private Frame frame; | 183 private Frame frame; |
188 private final Parser parser; | 184 private final Parser parser; |
189 private final Stmts top = new Stmts(); | 185 private final Stmts top; |
190 | 186 |
191 LuanParser(String sourceName,String sourceText) { | 187 LuanParser(String sourceName,String sourceText) { |
192 // this.source = source; | 188 // this.source = source; |
193 this.frame = new Frame(); | 189 this.frame = new Frame(); |
194 this.parser = new Parser(sourceName,sourceText); | 190 this.parser = new Parser(sourceName,sourceText); |
191 this.top = new Stmts(); | |
195 } | 192 } |
196 | 193 |
197 void addVar(String name) { | 194 void addVar(String name) { |
198 UpSym upSym = frame.addUpSym( "-ADDED-" ,"new Pointer()"); | 195 UpSym upSym = frame.addUpSym( "-ADDED-" ,"new Pointer()"); |
199 if( name != null ) { | 196 if( name != null ) { |
200 LocalSym sym = frame.addLocalSym( name ); | 197 LocalSym sym = frame.addLocalSym( name ); |
201 sym.isPointer = true; | 198 sym.isPointer = true; |
202 top.add( "final Pointer " + sym.javaName + " = upValues[" + upSym.i + "];\n" ); | 199 top.add( "final Pointer " + sym.javaName + " = upValues[" + upSym.i + "]; " ); |
203 } | 200 } |
204 } | 201 } |
205 | 202 |
206 private int symbolsSize() { | 203 private int symbolsSize() { |
207 return frame.symbols.size(); | 204 return frame.symbols.size(); |
250 private Expr newFnExpStr(Stmts stmt) { | 247 private Expr newFnExpStr(Stmts stmt) { |
251 return toFnExpStr( stmt, frame.upValueSymbols ); | 248 return toFnExpStr( stmt, frame.upValueSymbols ); |
252 } | 249 } |
253 | 250 |
254 Class Expression() throws ParseException { | 251 Class Expression() throws ParseException { |
255 Spaces(In.NOTHING); | 252 Spaces(); |
256 parser.begin(); | 253 parser.begin(); |
257 Expr expr = ExprZ(In.NOTHING); | 254 Expr expr = ExprZ(In.NOTHING); |
258 if( expr != null && parser.endOfInput() ) { | 255 if( expr != null && parser.endOfInput() ) { |
259 top.add( "return " ); | 256 top.add( "return " ); |
260 top.addAll( expr ); | 257 top.addAll( expr ); |
261 top.add( ";\n" ); | 258 top.add( "; " ); |
262 top.hasReturn = true; | 259 top.hasReturn = true; |
263 return parser.success(newFnClass(top)); | 260 return parser.success(newFnClass(top)); |
264 } | 261 } |
265 return parser.failure(null); | 262 return parser.failure(null); |
266 } | 263 } |
274 GetRequiredModule(); | 271 GetRequiredModule(); |
275 return toFnString( top, frame.upValueSymbols ); | 272 return toFnString( top, frame.upValueSymbols ); |
276 } | 273 } |
277 | 274 |
278 void GetRequiredModule() throws ParseException { | 275 void GetRequiredModule() throws ParseException { |
279 Spaces(In.NOTHING); | 276 Spaces(); |
280 parser.begin(); | 277 parser.begin(); |
281 frame.isVarArg = true; | 278 frame.isVarArg = true; |
282 top.add( "final Object[] varArgs = LuanImpl.varArgs(args,0);\n" ); | 279 top.add( "final Object[] varArgs = LuanImpl.varArgs(args,0); " ); |
283 Stmts block = RequiredBlock(); | 280 Stmts block = RequiredBlock(); |
284 top.addAll( block ); | 281 top.addAll( block ); |
285 top.hasReturn = block.hasReturn; | 282 top.hasReturn = block.hasReturn; |
286 if( !parser.endOfInput() ) | 283 if( !parser.endOfInput() ) |
287 throw parser.exception(); | 284 throw parser.exception(); |
290 | 287 |
291 private Stmts RequiredBlock() throws ParseException { | 288 private Stmts RequiredBlock() throws ParseException { |
292 Stmts stmts = new Stmts(); | 289 Stmts stmts = new Stmts(); |
293 int stackStart = symbolsSize(); | 290 int stackStart = symbolsSize(); |
294 boolean isReturn = Stmt(stmts); | 291 boolean isReturn = Stmt(stmts); |
295 while( !isReturn && StmtSep(stmts) ) { | 292 while( !isReturn && (StmtSep() || TemplateSep(stmts)) ) { |
296 Spaces(In.NOTHING); | 293 Spaces(); |
294 stmts.addNewLines(); | |
297 isReturn = Stmt(stmts); | 295 isReturn = Stmt(stmts); |
298 } | 296 } |
299 while( StmtSep(null) ) | 297 while( StmtSep() ) |
300 Spaces(In.NOTHING); | 298 Spaces(); |
299 stmts.addNewLines(); | |
301 int stackEnd = symbolsSize(); | 300 int stackEnd = symbolsSize(); |
302 popSymbols( stackEnd - stackStart ); | 301 popSymbols( stackEnd - stackStart ); |
303 stmts.hasReturn = isReturn; | 302 stmts.hasReturn = isReturn; |
304 return stmts; | 303 return stmts; |
305 } | 304 } |
306 | 305 |
307 private boolean StmtSep(Stmts stmts) throws ParseException { | 306 private boolean StmtSep() throws ParseException { |
308 parser.begin(); | 307 return parser.match( ';' ) || EndOfLine(); |
309 if( parser.match( ';' ) ) | 308 } |
310 return parser.success(); | 309 |
311 if( EndOfLine() ) | 310 private boolean TemplateSep(Stmts stmts) throws ParseException { |
312 return parser.success(); | 311 Stmts stmt = TemplateStmt(); |
313 if( stmts != null ) { | 312 if( stmt != null ) { |
314 // parser.rollback(); | 313 stmts.addAll(stmt); |
315 Stmts stmt = TemplateStmt(); | 314 return true; |
316 if( stmt != null ) { | 315 } |
317 stmts.addAll(stmt); | 316 return false; |
318 return parser.success(); | |
319 } | |
320 } | |
321 return parser.failure(); | |
322 } | 317 } |
323 | 318 |
324 private boolean EndOfLine() { | 319 private boolean EndOfLine() { |
325 return parser.match( "\r\n" ) || parser.match( '\r' ) || parser.match( '\n' ); | 320 if( parser.match( "\r\n" ) || parser.match( '\r' ) || parser.match( '\n' ) ) { |
321 parser.sb().append('\n'); | |
322 return true; | |
323 } else { | |
324 return false; | |
325 } | |
326 } | 326 } |
327 | 327 |
328 private boolean Stmt(Stmts stmts) throws ParseException { | 328 private boolean Stmt(Stmts stmts) throws ParseException { |
329 Stmts stmt; | 329 Stmts stmt; |
330 if( (stmt=ReturnStmt()) != null ) { | 330 if( (stmt=ReturnStmt()) != null ) { |
377 Expr stdoutExp = indexExpStr( requireCall.single(), constExpStr("stdout") ); | 377 Expr stdoutExp = indexExpStr( requireCall.single(), constExpStr("stdout") ); |
378 Expr writeExp = indexExpStr( stdoutExp, constExpStr("write") ); | 378 Expr writeExp = indexExpStr( stdoutExp, constExpStr("write") ); |
379 Expr writeCall = callExpStr( writeExp, exprs ); | 379 Expr writeCall = callExpStr( writeExp, exprs ); |
380 Stmts stmt = new Stmts(); | 380 Stmts stmt = new Stmts(); |
381 stmt.addAll( writeCall ); | 381 stmt.addAll( writeCall ); |
382 stmt.add( ";\n" ); | 382 stmt.add( "; " ); |
383 return stmt; | 383 return stmt; |
384 } | 384 } |
385 | 385 |
386 private Expr TemplateExpressions(In in) throws ParseException { | 386 private Expr TemplateExpressions(In in) throws ParseException { |
387 if( in.template ) | 387 if( in.template ) |
392 EndOfLine(); | 392 EndOfLine(); |
393 In inTemplate = in.template(); | 393 In inTemplate = in.template(); |
394 List<Expr> builder = new ArrayList<Expr>(); | 394 List<Expr> builder = new ArrayList<Expr>(); |
395 while(true) { | 395 while(true) { |
396 if( parser.match( "<%=" ) ) { | 396 if( parser.match( "<%=" ) ) { |
397 Spaces(inTemplate); | 397 Spaces(); |
398 builder.add( RequiredExpr(inTemplate) ); | 398 builder.add( RequiredExpr(inTemplate) ); |
399 RequiredMatch( "%>" ); | 399 RequiredMatch( "%>" ); |
400 } else if( parser.match( "<%" ) ) { | 400 } else if( parser.match( "<%" ) ) { |
401 Spaces(inTemplate); | 401 Spaces(); |
402 return parser.success(expString(builder)); | 402 return parser.success(expString(builder)); |
403 } else { | 403 } else { |
404 int i = parser.currentIndex(); | 404 int i = parser.currentIndex(); |
405 do { | 405 do { |
406 if( parser.match( "%>" ) ) | 406 if( parser.match( "%>" ) ) |
414 } | 414 } |
415 } | 415 } |
416 | 416 |
417 private Stmts ReturnStmt() throws ParseException { | 417 private Stmts ReturnStmt() throws ParseException { |
418 parser.begin(); | 418 parser.begin(); |
419 if( !Keyword("return",In.NOTHING) ) | 419 if( !Keyword("return") ) |
420 return parser.failure(null); | 420 return parser.failure(null); |
421 Expr exprs = ExpStringList(In.NOTHING); | 421 Expr exprs = ExpStringList(In.NOTHING); |
422 Stmts stmt = new Stmts(); | 422 Stmts stmt = new Stmts(); |
423 stmt.add( "return " ); | 423 stmt.add( "return " ); |
424 if( exprs != null ) | 424 if( exprs != null ) |
425 stmt.addAll( exprs ); | 425 stmt.addAll( exprs ); |
426 else | 426 else |
427 stmt.add( "LuanFunction.NOTHING" ); | 427 stmt.add( "LuanFunction.NOTHING" ); |
428 stmt.add( ";\n" ); | 428 stmt.add( "; " ); |
429 return parser.success( stmt ); | 429 return parser.success( stmt ); |
430 } | 430 } |
431 | 431 |
432 private Stmts FunctionStmt() throws ParseException { | 432 private Stmts FunctionStmt() throws ParseException { |
433 parser.begin(); | 433 parser.begin(); |
434 if( !Keyword("function",In.NOTHING) ) | 434 if( !Keyword("function") ) |
435 return parser.failure(null); | 435 return parser.failure(null); |
436 | 436 |
437 parser.currentIndex(); | 437 parser.currentIndex(); |
438 Var var = nameVar(RequiredName(In.NOTHING)); | 438 Var var = nameVar(RequiredName()); |
439 while( parser.match( '.' ) ) { | 439 while( parser.match( '.' ) ) { |
440 Spaces(In.NOTHING); | 440 Spaces(); |
441 Expr exp = NameExpr(In.NOTHING); | 441 Expr exp = NameExpr(); |
442 if( exp==null ) | 442 if( exp==null ) |
443 return parser.failure(null); | 443 return parser.failure(null); |
444 var = indexVar( var.exp(), exp ); | 444 var = indexVar( var.exp(), exp ); |
445 } | 445 } |
446 | 446 |
448 return parser.success( var.set(fnDef) ); | 448 return parser.success( var.set(fnDef) ); |
449 } | 449 } |
450 | 450 |
451 private Stmts LocalFunctionStmt() throws ParseException { | 451 private Stmts LocalFunctionStmt() throws ParseException { |
452 parser.begin(); | 452 parser.begin(); |
453 if( !(Keyword("local",In.NOTHING) && Keyword("function",In.NOTHING)) ) | 453 if( !(Keyword("local") && Keyword("function")) ) |
454 return parser.failure(null); | 454 return parser.failure(null); |
455 Stmts stmt = new Stmts(); | 455 Stmts stmt = new Stmts(); |
456 String name = RequiredName(In.NOTHING); | 456 String name = RequiredName(); |
457 stmt.addAll( addSymbol(name,null) ); | 457 stmt.addAll( addSymbol(name,null) ); |
458 Expr fnDef = RequiredFunction(In.NOTHING); | 458 Expr fnDef = RequiredFunction(In.NOTHING); |
459 stmt.addAll( nameVar(name).set(fnDef) ); | 459 stmt.addAll( nameVar(name).set(fnDef) ); |
460 return parser.success( stmt ); | 460 return parser.success( stmt ); |
461 } | 461 } |
462 | 462 |
463 private Stmts BreakStmt() throws ParseException { | 463 private Stmts BreakStmt() throws ParseException { |
464 parser.begin(); | 464 parser.begin(); |
465 if( !Keyword("break",In.NOTHING) ) | 465 if( !Keyword("break") ) |
466 return parser.failure(null); | 466 return parser.failure(null); |
467 if( frame.loops <= 0 ) | 467 if( frame.loops <= 0 ) |
468 throw parser.exception("'break' outside of loop"); | 468 throw parser.exception("'break' outside of loop"); |
469 Stmts stmt = new Stmts(); | 469 Stmts stmt = new Stmts(); |
470 stmt.add( "break;\n" ); | 470 stmt.add( "break; " ); |
471 return parser.success( stmt ); | 471 return parser.success( stmt ); |
472 } | 472 } |
473 | 473 |
474 int forCounter = 0; | 474 int forCounter = 0; |
475 | 475 |
476 private Stmts ForStmt() throws ParseException { | 476 private Stmts ForStmt() throws ParseException { |
477 parser.begin(); | 477 parser.begin(); |
478 int stackStart = symbolsSize(); | 478 int stackStart = symbolsSize(); |
479 if( !Keyword("for",In.NOTHING) ) | 479 if( !Keyword("for") ) |
480 return parser.failure(null); | 480 return parser.failure(null); |
481 List<String> names = RequiredNameList(In.NOTHING); | 481 List<String> names = RequiredNameList(); |
482 if( !Keyword("in",In.NOTHING) ) | 482 if( !Keyword("in") ) |
483 return parser.failure(null); | 483 return parser.failure(null); |
484 Expr expr = RequiredExpr(In.NOTHING).single(); | 484 Expr expr = RequiredExpr(In.NOTHING).single(); |
485 RequiredKeyword("do",In.NOTHING); | 485 RequiredKeyword("do",In.NOTHING); |
486 | 486 |
487 String fnVar = "fn"+ ++forCounter; | 487 String fnVar = "fn"+ ++forCounter; |
490 Stmts stmt = new Stmts(); | 490 Stmts stmt = new Stmts(); |
491 stmt.add( "" | 491 stmt.add( "" |
492 +"LuanFunction "+fnVar+" = Luan.checkFunction(" | 492 +"LuanFunction "+fnVar+" = Luan.checkFunction(" |
493 ); | 493 ); |
494 stmt.addAll( expr ); | 494 stmt.addAll( expr ); |
495 stmt.add( ");\n" ); | 495 stmt.add( "); " ); |
496 stmt.add( "while(true) {\n" ); | 496 stmt.add( "while(true) { " ); |
497 stmt.addAll( makeLocalSetStmt(names,fnExp) ); | 497 stmt.addAll( makeLocalSetStmt(names,fnExp) ); |
498 stmt.add( "if( " ); | 498 stmt.add( "if( " ); |
499 stmt.addAll( nameVar(names.get(0)).exp() ); | 499 stmt.addAll( nameVar(names.get(0)).exp() ); |
500 stmt.add( "==null ) break;\n" ); | 500 stmt.add( "==null ) break; " ); |
501 Stmts loop = RequiredLoopBlock(); | 501 Stmts loop = RequiredLoopBlock(); |
502 RequiredKeyword("end",In.NOTHING); | 502 RequiredKeyword("end",In.NOTHING); |
503 stmt.addAll( loop ); | 503 stmt.addAll( loop ); |
504 stmt.add( "}\n" ); | 504 stmt.add( "} " ); |
505 popSymbols( symbolsSize() - stackStart ); | 505 popSymbols( symbolsSize() - stackStart ); |
506 return parser.success(stmt); | 506 return parser.success(stmt); |
507 } | 507 } |
508 | 508 |
509 private Stmts DoStmt() throws ParseException { | 509 private Stmts DoStmt() throws ParseException { |
510 parser.begin(); | 510 parser.begin(); |
511 if( !Keyword("do",In.NOTHING) ) | 511 if( !Keyword("do") ) |
512 return parser.failure(null); | 512 return parser.failure(null); |
513 Stmts stmt = RequiredBlock(); | 513 Stmts stmt = RequiredBlock(); |
514 RequiredKeyword("end",In.NOTHING); | 514 RequiredKeyword("end",In.NOTHING); |
515 return parser.success(stmt); | 515 return parser.success(stmt); |
516 } | 516 } |
517 | 517 |
518 private Stmts LocalStmt() throws ParseException { | 518 private Stmts LocalStmt() throws ParseException { |
519 parser.begin(); | 519 parser.begin(); |
520 if( !Keyword("local",In.NOTHING) ) | 520 if( !Keyword("local") ) |
521 return parser.failure(null); | 521 return parser.failure(null); |
522 List<String> names = NameList(In.NOTHING); | 522 List<String> names = NameList(); |
523 if( names==null ) { | 523 if( names==null ) { |
524 if( Keyword("function",In.NOTHING) ) | 524 if( Keyword("function") ) |
525 return parser.failure(null); // handled later | 525 return parser.failure(null); // handled later |
526 throw parser.exception("Invalid local statement"); | 526 throw parser.exception("Invalid local statement"); |
527 } | 527 } |
528 Stmts stmt = new Stmts(); | 528 Stmts stmt = new Stmts(); |
529 if( parser.match( '=' ) ) { | 529 if( parser.match( '=' ) ) { |
530 Spaces(In.NOTHING); | 530 Spaces(); |
531 Expr values = ExpStringList(In.NOTHING); | 531 Expr values = ExpStringList(In.NOTHING); |
532 if( values==null ) | 532 if( values==null ) |
533 throw parser.exception("Expressions expected"); | 533 throw parser.exception("Expressions expected"); |
534 stmt.addAll( makeLocalSetStmt(names,values) ); | 534 stmt.addAll( makeLocalSetStmt(names,values) ); |
535 } else { | 535 } else { |
540 } | 540 } |
541 } | 541 } |
542 return parser.success(stmt); | 542 return parser.success(stmt); |
543 } | 543 } |
544 | 544 |
545 private List<String> RequiredNameList(In in) throws ParseException { | 545 private List<String> RequiredNameList() throws ParseException { |
546 parser.begin(); | 546 parser.begin(); |
547 List<String> names = NameList(in); | 547 List<String> names = NameList(); |
548 if( names==null ) | 548 if( names==null ) |
549 throw parser.exception("Name expected"); | 549 throw parser.exception("Name expected"); |
550 return parser.success(names); | 550 return parser.success(names); |
551 } | 551 } |
552 | 552 |
553 private List<String> NameList(In in) throws ParseException { | 553 private List<String> NameList() throws ParseException { |
554 String name = Name(in); | 554 String name = Name(); |
555 if( name==null ) | 555 if( name==null ) |
556 return null; | 556 return null; |
557 List<String> names = new ArrayList<String>(); | 557 List<String> names = new ArrayList<String>(); |
558 names.add(name); | 558 names.add(name); |
559 while( (name=anotherName(in)) != null ) { | 559 while( (name=anotherName()) != null ) { |
560 names.add(name); | 560 names.add(name); |
561 } | 561 } |
562 return names; | 562 return names; |
563 } | 563 } |
564 | 564 |
565 private String anotherName(In in) throws ParseException { | 565 private String anotherName() throws ParseException { |
566 parser.begin(); | 566 parser.begin(); |
567 if( !parser.match( ',' ) ) | 567 if( !parser.match( ',' ) ) |
568 return parser.failure(null); | 568 return parser.failure(null); |
569 Spaces(in); | 569 Spaces(); |
570 String name = Name(in); | 570 String name = Name(); |
571 if( name==null ) | 571 if( name==null ) |
572 return parser.failure(null); | 572 return parser.failure(null); |
573 return parser.success(name); | 573 return parser.success(name); |
574 } | 574 } |
575 | 575 |
576 private Stmts WhileStmt() throws ParseException { | 576 private Stmts WhileStmt() throws ParseException { |
577 parser.begin(); | 577 parser.begin(); |
578 if( !Keyword("while",In.NOTHING) ) | 578 if( !Keyword("while") ) |
579 return parser.failure(null); | 579 return parser.failure(null); |
580 Expr cnd = RequiredExpr(In.NOTHING).single(); | 580 Expr cnd = RequiredExpr(In.NOTHING).single(); |
581 RequiredKeyword("do",In.NOTHING); | 581 RequiredKeyword("do",In.NOTHING); |
582 Stmts loop = RequiredLoopBlock(); | 582 Stmts loop = RequiredLoopBlock(); |
583 RequiredKeyword("end",In.NOTHING); | 583 RequiredKeyword("end",In.NOTHING); |
584 Stmts stmt = new Stmts(); | 584 Stmts stmt = new Stmts(); |
585 stmt.add( "while( Luan.checkBoolean(" ); | 585 stmt.add( "while( Luan.checkBoolean(" ); |
586 stmt.addAll( cnd ); | 586 stmt.addAll( cnd ); |
587 stmt.add( ") ) {\n" ); | 587 stmt.add( ") ) { " ); |
588 stmt.addAll( loop ); | 588 stmt.addAll( loop ); |
589 stmt.add( "}\n" ); | 589 stmt.add( "} " ); |
590 return parser.success( stmt ); | 590 return parser.success( stmt ); |
591 } | 591 } |
592 | 592 |
593 private Stmts RepeatStmt() throws ParseException { | 593 private Stmts RepeatStmt() throws ParseException { |
594 parser.begin(); | 594 parser.begin(); |
595 if( !Keyword("repeat",In.NOTHING) ) | 595 if( !Keyword("repeat") ) |
596 return parser.failure(null); | 596 return parser.failure(null); |
597 Stmts loop =RequiredLoopBlock(); | 597 Stmts loop =RequiredLoopBlock(); |
598 RequiredKeyword("until",In.NOTHING); | 598 RequiredKeyword("until",In.NOTHING); |
599 Expr cnd = RequiredExpr(In.NOTHING).single(); | 599 Expr cnd = RequiredExpr(In.NOTHING).single(); |
600 Stmts stmt = new Stmts(); | 600 Stmts stmt = new Stmts(); |
601 stmt.add( "do {\n" ); | 601 stmt.add( "do { " ); |
602 stmt.addAll( loop ); | 602 stmt.addAll( loop ); |
603 stmt.add( "} while( !Luan.checkBoolean(" ); | 603 stmt.add( "} while( !Luan.checkBoolean(" ); |
604 stmt.addAll( cnd ); | 604 stmt.addAll( cnd ); |
605 stmt.add( ") );\n" ); | 605 stmt.add( ") ); " ); |
606 return parser.success( stmt ); | 606 return parser.success( stmt ); |
607 } | 607 } |
608 | 608 |
609 private Stmts RequiredLoopBlock() throws ParseException { | 609 private Stmts RequiredLoopBlock() throws ParseException { |
610 incLoops(); | 610 incLoops(); |
613 return stmt; | 613 return stmt; |
614 } | 614 } |
615 | 615 |
616 private Stmts IfStmt() throws ParseException { | 616 private Stmts IfStmt() throws ParseException { |
617 parser.begin(); | 617 parser.begin(); |
618 if( !Keyword("if",In.NOTHING) ) | 618 if( !Keyword("if") ) |
619 return parser.failure(null); | 619 return parser.failure(null); |
620 Stmts stmt = new Stmts(); | 620 Stmts stmt = new Stmts(); |
621 Expr cnd; | 621 Expr cnd; |
622 Stmts block; | 622 Stmts block; |
623 cnd = RequiredExpr(In.NOTHING).single(); | 623 cnd = RequiredExpr(In.NOTHING).single(); |
624 RequiredKeyword("then",In.NOTHING); | 624 RequiredKeyword("then",In.NOTHING); |
625 block = RequiredBlock(); | 625 block = RequiredBlock(); |
626 stmt.add( "if( Luan.checkBoolean(" ); | 626 stmt.add( "if( Luan.checkBoolean(" ); |
627 stmt.addAll( cnd ); | 627 stmt.addAll( cnd ); |
628 stmt.add( ") ) {\n" ); | 628 stmt.add( ") ) { " ); |
629 stmt.addAll( block ); | 629 stmt.addAll( block ); |
630 while( Keyword("elseif",In.NOTHING) ) { | 630 while( Keyword("elseif") ) { |
631 cnd = RequiredExpr(In.NOTHING).single(); | 631 cnd = RequiredExpr(In.NOTHING).single(); |
632 RequiredKeyword("then",In.NOTHING); | 632 RequiredKeyword("then",In.NOTHING); |
633 block = RequiredBlock(); | 633 block = RequiredBlock(); |
634 stmt.add( "} else if( Luan.checkBoolean(" ); | 634 stmt.add( "} else if( Luan.checkBoolean(" ); |
635 stmt.addAll( cnd ); | 635 stmt.addAll( cnd ); |
636 stmt.add( ") ) {\n" ); | 636 stmt.add( ") ) { " ); |
637 stmt.addAll( block ); | 637 stmt.addAll( block ); |
638 } | 638 } |
639 if( Keyword("else",In.NOTHING) ) { | 639 if( Keyword("else") ) { |
640 block = RequiredBlock(); | 640 block = RequiredBlock(); |
641 stmt.add( "} else {\n" ); | 641 stmt.add( "} else { " ); |
642 stmt.addAll( block ); | 642 stmt.addAll( block ); |
643 } | 643 } |
644 RequiredKeyword("end",In.NOTHING); | 644 RequiredKeyword("end",In.NOTHING); |
645 stmt.add( "}\n" ); | 645 stmt.add( "} " ); |
646 return parser.success( stmt ); | 646 return parser.success( stmt ); |
647 } | 647 } |
648 | 648 |
649 private Stmts SetStmt() throws ParseException { | 649 private Stmts SetStmt() throws ParseException { |
650 parser.begin(); | 650 parser.begin(); |
652 Var v = SettableVar(); | 652 Var v = SettableVar(); |
653 if( v == null ) | 653 if( v == null ) |
654 return parser.failure(null); | 654 return parser.failure(null); |
655 vars.add(v); | 655 vars.add(v); |
656 while( parser.match( ',' ) ) { | 656 while( parser.match( ',' ) ) { |
657 Spaces(In.NOTHING); | 657 Spaces(); |
658 v = SettableVar(); | 658 v = SettableVar(); |
659 if( v == null ) | 659 if( v == null ) |
660 return parser.failure(null); | 660 return parser.failure(null); |
661 vars.add(v); | 661 vars.add(v); |
662 } | 662 } |
663 if( !parser.match( '=' ) ) | 663 if( !parser.match( '=' ) ) |
664 return parser.failure(null); | 664 return parser.failure(null); |
665 Spaces(In.NOTHING); | 665 Spaces(); |
666 Expr values = ExpStringList(In.NOTHING); | 666 Expr values = ExpStringList(In.NOTHING); |
667 if( values==null ) | 667 if( values==null ) |
668 // throw parser.exception("Expressions expected"); | 668 // throw parser.exception("Expressions expected"); |
669 return parser.failure(null); | 669 return parser.failure(null); |
670 return parser.success( makeSetStmt(vars,values) ); | 670 return parser.success( makeSetStmt(vars,values) ); |
676 return vars.get(0).set(values); | 676 return vars.get(0).set(values); |
677 Stmts stmt = new Stmts(); | 677 Stmts stmt = new Stmts(); |
678 String varName = values.valType==Val.ARRAY ? "a" : "t"; | 678 String varName = values.valType==Val.ARRAY ? "a" : "t"; |
679 stmt.add( varName + " = " ); | 679 stmt.add( varName + " = " ); |
680 stmt.addAll( values ); | 680 stmt.addAll( values ); |
681 stmt.add( ";\n" ); | 681 stmt.add( "; " ); |
682 Expr t = new Expr(values.valType,false); | 682 Expr t = new Expr(values.valType,false); |
683 t.add( varName ); | 683 t.add( varName ); |
684 t = t.single(); | 684 t = t.single(); |
685 stmt.addAll( vars.get(0).set(t) ); | 685 stmt.addAll( vars.get(0).set(t) ); |
686 for( int i=1; i<n; i++ ) { | 686 for( int i=1; i<n; i++ ) { |
697 return addSymbol(names.get(0),values.single()); | 697 return addSymbol(names.get(0),values.single()); |
698 Stmts stmt = new Stmts(); | 698 Stmts stmt = new Stmts(); |
699 String varName = values.valType==Val.ARRAY ? "a" : "t"; | 699 String varName = values.valType==Val.ARRAY ? "a" : "t"; |
700 stmt.add( varName + " = " ); | 700 stmt.add( varName + " = " ); |
701 stmt.addAll( values ); | 701 stmt.addAll( values ); |
702 stmt.add( ";\n" ); | 702 stmt.add( "; " ); |
703 Expr t = new Expr(values.valType,false); | 703 Expr t = new Expr(values.valType,false); |
704 t.add( varName ); | 704 t.add( varName ); |
705 t = t.single(); | 705 t = t.single(); |
706 stmt.addAll( addSymbol(names.get(0),t) ); | 706 stmt.addAll( addSymbol(names.get(0),t) ); |
707 for( int i=1; i<n; i++ ) { | 707 for( int i=1; i<n; i++ ) { |
722 stmt.addAll( exp ); | 722 stmt.addAll( exp ); |
723 stmt.add( ")" ); | 723 stmt.add( ")" ); |
724 } else { | 724 } else { |
725 stmt.addAll( exp ); | 725 stmt.addAll( exp ); |
726 } | 726 } |
727 stmt.add( ";\n" ); | 727 stmt.add( "; " ); |
728 return parser.success( stmt ); | 728 return parser.success( stmt ); |
729 } | 729 } |
730 return parser.failure(null); | 730 return parser.failure(null); |
731 } | 731 } |
732 | 732 |
750 private Expr OrExpr(In in) throws ParseException { | 750 private Expr OrExpr(In in) throws ParseException { |
751 parser.begin(); | 751 parser.begin(); |
752 Expr exp = AndExpr(in); | 752 Expr exp = AndExpr(in); |
753 if( exp==null ) | 753 if( exp==null ) |
754 return parser.failure(null); | 754 return parser.failure(null); |
755 while( Keyword("or",in) ) { | 755 while( Keyword("or") ) { |
756 exp = exp.single(); | 756 exp = exp.single(); |
757 Expr exp2 = required(RelExpr(in)).single(); | 757 Expr exp2 = required(RelExpr(in)).single(); |
758 Expr newExp = new Expr(Val.SINGLE,true); | 758 Expr newExp = new Expr(Val.SINGLE,true); |
759 newExp.add( "(LuanImpl.cnd(t = " ); | 759 newExp.add( "(LuanImpl.cnd(t = " ); |
760 newExp.addAll( exp ); | 760 newExp.addAll( exp ); |
769 private Expr AndExpr(In in) throws ParseException { | 769 private Expr AndExpr(In in) throws ParseException { |
770 parser.begin(); | 770 parser.begin(); |
771 Expr exp = RelExpr(in); | 771 Expr exp = RelExpr(in); |
772 if( exp==null ) | 772 if( exp==null ) |
773 return parser.failure(null); | 773 return parser.failure(null); |
774 while( Keyword("and",in) ) { | 774 while( Keyword("and") ) { |
775 exp = exp.single(); | 775 exp = exp.single(); |
776 Expr exp2 = required(RelExpr(in)).single(); | 776 Expr exp2 = required(RelExpr(in)).single(); |
777 Expr newExp = new Expr(Val.SINGLE,true); | 777 Expr newExp = new Expr(Val.SINGLE,true); |
778 newExp.add( "(LuanImpl.cnd(t = " ); | 778 newExp.add( "(LuanImpl.cnd(t = " ); |
779 newExp.addAll( exp ); | 779 newExp.addAll( exp ); |
790 Expr exp = ConcatExpr(in); | 790 Expr exp = ConcatExpr(in); |
791 if( exp==null ) | 791 if( exp==null ) |
792 return parser.failure(null); | 792 return parser.failure(null); |
793 while(true) { | 793 while(true) { |
794 if( parser.match("==") ) { | 794 if( parser.match("==") ) { |
795 Spaces(in); | 795 Spaces(); |
796 exp = exp.single(); | 796 exp = exp.single(); |
797 Expr exp2 = required(ConcatExpr(in)).single(); | 797 Expr exp2 = required(ConcatExpr(in)).single(); |
798 Expr newExp = new Expr(Val.SINGLE,false); | 798 Expr newExp = new Expr(Val.SINGLE,false); |
799 newExp.add( "LuanImpl.eq(luan," ); | 799 newExp.add( "LuanImpl.eq(luan," ); |
800 newExp.addAll( exp ); | 800 newExp.addAll( exp ); |
801 newExp.add( "," ); | 801 newExp.add( "," ); |
802 newExp.addAll( exp2 ); | 802 newExp.addAll( exp2 ); |
803 newExp.add( ")" ); | 803 newExp.add( ")" ); |
804 exp = newExp; | 804 exp = newExp; |
805 } else if( parser.match("~=") ) { | 805 } else if( parser.match("~=") ) { |
806 Spaces(in); | 806 Spaces(); |
807 exp = exp.single(); | 807 exp = exp.single(); |
808 Expr exp2 = required(ConcatExpr(in)).single(); | 808 Expr exp2 = required(ConcatExpr(in)).single(); |
809 Expr newExp = new Expr(Val.SINGLE,false); | 809 Expr newExp = new Expr(Val.SINGLE,false); |
810 newExp.add( "!LuanImpl.eq(luan," ); | 810 newExp.add( "!LuanImpl.eq(luan," ); |
811 newExp.addAll( exp ); | 811 newExp.addAll( exp ); |
812 newExp.add( "," ); | 812 newExp.add( "," ); |
813 newExp.addAll( exp2 ); | 813 newExp.addAll( exp2 ); |
814 newExp.add( ")" ); | 814 newExp.add( ")" ); |
815 exp = newExp; | 815 exp = newExp; |
816 } else if( parser.match("<=") ) { | 816 } else if( parser.match("<=") ) { |
817 Spaces(in); | 817 Spaces(); |
818 exp = exp.single(); | 818 exp = exp.single(); |
819 Expr exp2 = required(ConcatExpr(in)).single(); | 819 Expr exp2 = required(ConcatExpr(in)).single(); |
820 Expr newExp = new Expr(Val.SINGLE,false); | 820 Expr newExp = new Expr(Val.SINGLE,false); |
821 newExp.add( "LuanImpl.le(luan," ); | 821 newExp.add( "LuanImpl.le(luan," ); |
822 newExp.addAll( exp ); | 822 newExp.addAll( exp ); |
823 newExp.add( "," ); | 823 newExp.add( "," ); |
824 newExp.addAll( exp2 ); | 824 newExp.addAll( exp2 ); |
825 newExp.add( ")" ); | 825 newExp.add( ")" ); |
826 exp = newExp; | 826 exp = newExp; |
827 } else if( parser.match(">=") ) { | 827 } else if( parser.match(">=") ) { |
828 Spaces(in); | 828 Spaces(); |
829 exp = exp.single(); | 829 exp = exp.single(); |
830 Expr exp2 = required(ConcatExpr(in)).single(); | 830 Expr exp2 = required(ConcatExpr(in)).single(); |
831 Expr newExp = new Expr(Val.SINGLE,false); | 831 Expr newExp = new Expr(Val.SINGLE,false); |
832 newExp.add( "LuanImpl.le(luan," ); | 832 newExp.add( "LuanImpl.le(luan," ); |
833 newExp.addAll( exp2 ); | 833 newExp.addAll( exp2 ); |
834 newExp.add( "," ); | 834 newExp.add( "," ); |
835 newExp.addAll( exp ); | 835 newExp.addAll( exp ); |
836 newExp.add( ")" ); | 836 newExp.add( ")" ); |
837 exp = newExp; | 837 exp = newExp; |
838 } else if( parser.match("<") ) { | 838 } else if( parser.match("<") ) { |
839 Spaces(in); | 839 Spaces(); |
840 exp = exp.single(); | 840 exp = exp.single(); |
841 Expr exp2 = required(ConcatExpr(in)).single(); | 841 Expr exp2 = required(ConcatExpr(in)).single(); |
842 Expr newExp = new Expr(Val.SINGLE,false); | 842 Expr newExp = new Expr(Val.SINGLE,false); |
843 newExp.add( "LuanImpl.lt(luan," ); | 843 newExp.add( "LuanImpl.lt(luan," ); |
844 newExp.addAll( exp ); | 844 newExp.addAll( exp ); |
845 newExp.add( "," ); | 845 newExp.add( "," ); |
846 newExp.addAll( exp2 ); | 846 newExp.addAll( exp2 ); |
847 newExp.add( ")" ); | 847 newExp.add( ")" ); |
848 exp = newExp; | 848 exp = newExp; |
849 } else if( parser.match(">") ) { | 849 } else if( parser.match(">") ) { |
850 Spaces(in); | 850 Spaces(); |
851 exp = exp.single(); | 851 exp = exp.single(); |
852 Expr exp2 = required(ConcatExpr(in)).single(); | 852 Expr exp2 = required(ConcatExpr(in)).single(); |
853 Expr newExp = new Expr(Val.SINGLE,false); | 853 Expr newExp = new Expr(Val.SINGLE,false); |
854 newExp.add( "LuanImpl.lt(luan," ); | 854 newExp.add( "LuanImpl.lt(luan," ); |
855 newExp.addAll( exp2 ); | 855 newExp.addAll( exp2 ); |
867 parser.begin(); | 867 parser.begin(); |
868 Expr exp = SumExpr(in); | 868 Expr exp = SumExpr(in); |
869 if( exp==null ) | 869 if( exp==null ) |
870 return parser.failure(null); | 870 return parser.failure(null); |
871 if( parser.match("..") ) { | 871 if( parser.match("..") ) { |
872 Spaces(in); | 872 Spaces(); |
873 exp = exp.single(); | 873 exp = exp.single(); |
874 Expr exp2 = required(ConcatExpr(in)).single(); | 874 Expr exp2 = required(ConcatExpr(in)).single(); |
875 Expr newExp = new Expr(Val.SINGLE,false); | 875 Expr newExp = new Expr(Val.SINGLE,false); |
876 newExp.add( "LuanImpl.concat(luan," ); | 876 newExp.add( "LuanImpl.concat(luan," ); |
877 newExp.addAll( exp ); | 877 newExp.addAll( exp ); |
888 Expr exp = TermExpr(in); | 888 Expr exp = TermExpr(in); |
889 if( exp==null ) | 889 if( exp==null ) |
890 return parser.failure(null); | 890 return parser.failure(null); |
891 while(true) { | 891 while(true) { |
892 if( parser.match('+') ) { | 892 if( parser.match('+') ) { |
893 Spaces(in); | 893 Spaces(); |
894 exp = exp.single(); | 894 exp = exp.single(); |
895 Expr exp2 = required(TermExpr(in)).single(); | 895 Expr exp2 = required(TermExpr(in)).single(); |
896 Expr newExp = new Expr(Val.SINGLE,false); | 896 Expr newExp = new Expr(Val.SINGLE,false); |
897 newExp.add( "LuanImpl.add(luan," ); | 897 newExp.add( "LuanImpl.add(luan," ); |
898 newExp.addAll( exp ); | 898 newExp.addAll( exp ); |
899 newExp.add( "," ); | 899 newExp.add( "," ); |
900 newExp.addAll( exp2 ); | 900 newExp.addAll( exp2 ); |
901 newExp.add( ")" ); | 901 newExp.add( ")" ); |
902 exp = newExp; | 902 exp = newExp; |
903 } else if( Minus() ) { | 903 } else if( Minus() ) { |
904 Spaces(in); | 904 Spaces(); |
905 exp = exp.single(); | 905 exp = exp.single(); |
906 Expr exp2 = required(TermExpr(in)).single(); | 906 Expr exp2 = required(TermExpr(in)).single(); |
907 Expr newExp = new Expr(Val.SINGLE,false); | 907 Expr newExp = new Expr(Val.SINGLE,false); |
908 newExp.add( "LuanImpl.sub(luan," ); | 908 newExp.add( "LuanImpl.sub(luan," ); |
909 newExp.addAll( exp ); | 909 newExp.addAll( exp ); |
927 Expr exp = UnaryExpr(in); | 927 Expr exp = UnaryExpr(in); |
928 if( exp==null ) | 928 if( exp==null ) |
929 return parser.failure(null); | 929 return parser.failure(null); |
930 while(true) { | 930 while(true) { |
931 if( parser.match('*') ) { | 931 if( parser.match('*') ) { |
932 Spaces(in); | 932 Spaces(); |
933 exp = exp.single(); | 933 exp = exp.single(); |
934 Expr exp2 = required(UnaryExpr(in)).single(); | 934 Expr exp2 = required(UnaryExpr(in)).single(); |
935 Expr newExp = new Expr(Val.SINGLE,false); | 935 Expr newExp = new Expr(Val.SINGLE,false); |
936 newExp.add( "LuanImpl.mul(luan," ); | 936 newExp.add( "LuanImpl.mul(luan," ); |
937 newExp.addAll( exp ); | 937 newExp.addAll( exp ); |
938 newExp.add( "," ); | 938 newExp.add( "," ); |
939 newExp.addAll( exp2 ); | 939 newExp.addAll( exp2 ); |
940 newExp.add( ")" ); | 940 newExp.add( ")" ); |
941 exp = newExp; | 941 exp = newExp; |
942 } else if( parser.match('/') ) { | 942 } else if( parser.match('/') ) { |
943 Spaces(in); | 943 Spaces(); |
944 exp = exp.single(); | 944 exp = exp.single(); |
945 Expr exp2 = required(UnaryExpr(in)).single(); | 945 Expr exp2 = required(UnaryExpr(in)).single(); |
946 Expr newExp = new Expr(Val.SINGLE,false); | 946 Expr newExp = new Expr(Val.SINGLE,false); |
947 newExp.add( "LuanImpl.div(luan," ); | 947 newExp.add( "LuanImpl.div(luan," ); |
948 newExp.addAll( exp ); | 948 newExp.addAll( exp ); |
949 newExp.add( "," ); | 949 newExp.add( "," ); |
950 newExp.addAll( exp2 ); | 950 newExp.addAll( exp2 ); |
951 newExp.add( ")" ); | 951 newExp.add( ")" ); |
952 exp = newExp; | 952 exp = newExp; |
953 } else if( Mod() ) { | 953 } else if( Mod() ) { |
954 Spaces(in); | 954 Spaces(); |
955 exp = exp.single(); | 955 exp = exp.single(); |
956 Expr exp2 = required(UnaryExpr(in)).single(); | 956 Expr exp2 = required(UnaryExpr(in)).single(); |
957 Expr newExp = new Expr(Val.SINGLE,false); | 957 Expr newExp = new Expr(Val.SINGLE,false); |
958 newExp.add( "LuanImpl.mod(luan," ); | 958 newExp.add( "LuanImpl.mod(luan," ); |
959 newExp.addAll( exp ); | 959 newExp.addAll( exp ); |
973 } | 973 } |
974 | 974 |
975 private Expr UnaryExpr(In in) throws ParseException { | 975 private Expr UnaryExpr(In in) throws ParseException { |
976 parser.begin(); | 976 parser.begin(); |
977 if( parser.match('#') ) { | 977 if( parser.match('#') ) { |
978 Spaces(in); | 978 Spaces(); |
979 Expr exp = required(UnaryExpr(in)).single(); | 979 Expr exp = required(UnaryExpr(in)).single(); |
980 Expr newExp = new Expr(Val.SINGLE,false); | 980 Expr newExp = new Expr(Val.SINGLE,false); |
981 newExp.add( "LuanImpl.len(luan," ); | 981 newExp.add( "LuanImpl.len(luan," ); |
982 newExp.addAll( exp ); | 982 newExp.addAll( exp ); |
983 newExp.add( ")" ); | 983 newExp.add( ")" ); |
984 return parser.success(newExp); | 984 return parser.success(newExp); |
985 } | 985 } |
986 if( Minus() ) { | 986 if( Minus() ) { |
987 Spaces(in); | 987 Spaces(); |
988 Expr exp = required(UnaryExpr(in)).single(); | 988 Expr exp = required(UnaryExpr(in)).single(); |
989 Expr newExp = new Expr(Val.SINGLE,false); | 989 Expr newExp = new Expr(Val.SINGLE,false); |
990 newExp.add( "LuanImpl.unm(luan," ); | 990 newExp.add( "LuanImpl.unm(luan," ); |
991 newExp.addAll( exp ); | 991 newExp.addAll( exp ); |
992 newExp.add( ")" ); | 992 newExp.add( ")" ); |
993 return parser.success(newExp); | 993 return parser.success(newExp); |
994 } | 994 } |
995 if( Keyword("not",in) ) { | 995 if( Keyword("not") ) { |
996 Spaces(in); | 996 Spaces(); |
997 Expr exp = required(UnaryExpr(in)).single(); | 997 Expr exp = required(UnaryExpr(in)).single(); |
998 Expr newExp = new Expr(Val.SINGLE,false); | 998 Expr newExp = new Expr(Val.SINGLE,false); |
999 newExp.add( "!Luan.checkBoolean(" ); | 999 newExp.add( "!Luan.checkBoolean(" ); |
1000 newExp.addAll( exp ); | 1000 newExp.addAll( exp ); |
1001 newExp.add( ")" ); | 1001 newExp.add( ")" ); |
1011 parser.begin(); | 1011 parser.begin(); |
1012 Expr exp1 = SingleExpr(in); | 1012 Expr exp1 = SingleExpr(in); |
1013 if( exp1==null ) | 1013 if( exp1==null ) |
1014 return parser.failure(null); | 1014 return parser.failure(null); |
1015 if( parser.match('^') ) { | 1015 if( parser.match('^') ) { |
1016 Spaces(in); | 1016 Spaces(); |
1017 Expr exp2 = required(PowExpr(in)); | 1017 Expr exp2 = required(PowExpr(in)); |
1018 Expr newExp = new Expr(Val.SINGLE,false); | 1018 Expr newExp = new Expr(Val.SINGLE,false); |
1019 newExp.add( "LuanImpl.pow(luan," ); | 1019 newExp.add( "LuanImpl.pow(luan," ); |
1020 newExp.addAll( exp1.single() ); | 1020 newExp.addAll( exp1.single() ); |
1021 newExp.add( "," ); | 1021 newExp.add( "," ); |
1032 if( exp != null ) | 1032 if( exp != null ) |
1033 return parser.success(exp); | 1033 return parser.success(exp); |
1034 exp = VarExp(in); | 1034 exp = VarExp(in); |
1035 if( exp != null ) | 1035 if( exp != null ) |
1036 return parser.success(exp); | 1036 return parser.success(exp); |
1037 exp = VarArgs(in); | 1037 exp = VarArgs(); |
1038 if( exp != null ) | 1038 if( exp != null ) |
1039 return parser.success(exp); | 1039 return parser.success(exp); |
1040 return parser.failure(null); | 1040 return parser.failure(null); |
1041 } | 1041 } |
1042 | 1042 |
1043 private Expr FunctionExpr(In in) throws ParseException { | 1043 private Expr FunctionExpr(In in) throws ParseException { |
1044 if( !Keyword("function",in) ) | 1044 if( !Keyword("function") ) |
1045 return null; | 1045 return null; |
1046 return RequiredFunction(in); | 1046 return RequiredFunction(in); |
1047 } | 1047 } |
1048 | 1048 |
1049 private Expr RequiredFunction(In in) throws ParseException { | 1049 private Expr RequiredFunction(In in) throws ParseException { |
1050 parser.begin(); | 1050 parser.begin(); |
1051 RequiredMatch('('); | 1051 RequiredMatch('('); |
1052 In inParens = in.parens(); | 1052 Spaces(); |
1053 Spaces(inParens); | |
1054 frame = new Frame(frame); | 1053 frame = new Frame(frame); |
1055 Stmts stmt = new Stmts(); | 1054 Stmts stmt = new Stmts(); |
1056 List<String> names = NameList(in); | 1055 List<String> names = NameList(); |
1057 if( names != null ) { | 1056 if( names != null ) { |
1058 Expr args = new Expr(Val.ARRAY,false); | 1057 Expr args = new Expr(Val.ARRAY,false); |
1059 args.add( "args" ); | 1058 args.add( "args" ); |
1060 stmt.addAll( makeLocalSetStmt(names,args) ); | 1059 stmt.addAll( makeLocalSetStmt(names,args) ); |
1061 if( parser.match(',') ) { | 1060 if( parser.match(',') ) { |
1062 Spaces(inParens); | 1061 Spaces(); |
1063 if( !parser.match("...") ) | 1062 if( !parser.match("...") ) |
1064 throw parser.exception(); | 1063 throw parser.exception(); |
1065 Spaces(inParens); | 1064 Spaces(); |
1066 frame.isVarArg = true; | 1065 frame.isVarArg = true; |
1067 stmt.add( "final Object[] varArgs = LuanImpl.varArgs(args," + names.size() + ");\n" ); | 1066 stmt.add( "final Object[] varArgs = LuanImpl.varArgs(args," + names.size() + "); " ); |
1068 } | 1067 } |
1069 } else if( parser.match("...") ) { | 1068 } else if( parser.match("...") ) { |
1070 Spaces(inParens); | 1069 Spaces(); |
1071 frame.isVarArg = true; | 1070 frame.isVarArg = true; |
1072 stmt.add( "final Object[] varArgs = LuanImpl.varArgs(args,0);\n" ); | 1071 stmt.add( "final Object[] varArgs = LuanImpl.varArgs(args,0); " ); |
1073 } | 1072 } |
1074 RequiredMatch(')'); | 1073 RequiredMatch(')'); |
1075 Spaces(in); | 1074 Spaces(); |
1076 Stmts block = RequiredBlock(); | 1075 Stmts block = RequiredBlock(); |
1077 stmt.addAll( block ); | 1076 stmt.addAll( block ); |
1078 stmt.hasReturn = block.hasReturn; | 1077 stmt.hasReturn = block.hasReturn; |
1078 Expr fnDef = newFnExpStr(stmt); | |
1079 RequiredKeyword("end",in); | 1079 RequiredKeyword("end",in); |
1080 Expr fnDef = newFnExpStr(stmt); | |
1081 frame = frame.parent; | 1080 frame = frame.parent; |
1082 return parser.success(fnDef); | 1081 return parser.success(fnDef); |
1083 } | 1082 } |
1084 | 1083 |
1085 private Expr VarArgs(In in) throws ParseException { | 1084 private Expr VarArgs() throws ParseException { |
1086 parser.begin(); | 1085 parser.begin(); |
1087 if( !frame.isVarArg || !parser.match("...") ) | 1086 if( !frame.isVarArg || !parser.match("...") ) |
1088 return parser.failure(null); | 1087 return parser.failure(null); |
1089 Spaces(in); | 1088 Spaces(); |
1090 Expr exp = new Expr(Val.ARRAY,false); | 1089 Expr exp = new Expr(Val.ARRAY,false); |
1091 exp.add("varArgs"); | 1090 exp.add("varArgs"); |
1092 return parser.success(exp); | 1091 return parser.success(exp); |
1093 } | 1092 } |
1094 | 1093 |
1095 private Expr TableExpr(In in) throws ParseException { | 1094 private Expr TableExpr() throws ParseException { |
1096 parser.begin(); | 1095 parser.begin(); |
1097 if( !parser.match('{') ) | 1096 if( !parser.match('{') ) |
1098 return parser.failure(null); | 1097 return parser.failure(null); |
1099 Spaces(In.NOTHING); | 1098 Spaces(); |
1100 List<Expr> builder = new ArrayList<Expr>(); | 1099 List<Expr> builder = new ArrayList<Expr>(); |
1101 Field(builder); | 1100 Field(builder); |
1102 while( FieldSep() ) { | 1101 while( FieldSep() ) { |
1103 Spaces(In.NOTHING); | 1102 Spaces(); |
1104 Field(builder); | 1103 Field(builder); |
1105 } | 1104 } |
1106 Expr exp = TemplateExpressions(In.NOTHING); | 1105 Expr exp = TemplateExpressions(In.NOTHING); |
1107 if( exp != null ) | 1106 if( exp != null ) |
1108 builder.add(exp); | 1107 builder.add(exp); |
1109 if( !parser.match('}') ) | 1108 if( !parser.match('}') ) |
1110 throw parser.exception("Expected table element or '}'"); | 1109 throw parser.exception("Expected table element or '}'"); |
1111 Spaces(in); | 1110 Spaces(); |
1112 exp = new Expr(Val.SINGLE,false); | 1111 exp = new Expr(Val.SINGLE,false); |
1113 exp.add( "LuanImpl.table(" ); | 1112 exp.add( "LuanImpl.table(" ); |
1114 exp.addAll( expString(builder).array() ); | 1113 exp.addAll( expString(builder).array() ); |
1115 exp.add( ")" ); | 1114 exp.add( ")" ); |
1116 return parser.success( exp ); | 1115 return parser.success( exp ); |
1122 | 1121 |
1123 private boolean Field(List<Expr> builder) throws ParseException { | 1122 private boolean Field(List<Expr> builder) throws ParseException { |
1124 parser.begin(); | 1123 parser.begin(); |
1125 Expr exp = SubExpr(In.NOTHING); | 1124 Expr exp = SubExpr(In.NOTHING); |
1126 if( exp==null ) | 1125 if( exp==null ) |
1127 exp = NameExpr(In.NOTHING); | 1126 exp = NameExpr(); |
1128 if( exp!=null && parser.match('=') ) { | 1127 if( exp!=null && parser.match('=') ) { |
1129 Spaces(In.NOTHING); | 1128 Spaces(); |
1130 Expr val = RequiredExpr(In.NOTHING).single(); | 1129 Expr val = RequiredExpr(In.NOTHING).single(); |
1131 Expr newExp = new Expr(Val.SINGLE,false); | 1130 Expr newExp = new Expr(Val.SINGLE,false); |
1132 newExp.add( "new TableField(" ); | 1131 newExp.add( "new TableField(" ); |
1133 newExp.addAll( exp ); | 1132 newExp.addAll( exp ); |
1134 newExp.add( "," ); | 1133 newExp.add( "," ); |
1163 return parser.success(var); | 1162 return parser.success(var); |
1164 } | 1163 } |
1165 | 1164 |
1166 private Var VarStart(In in) throws ParseException { | 1165 private Var VarStart(In in) throws ParseException { |
1167 if( parser.match('(') ) { | 1166 if( parser.match('(') ) { |
1168 In inParens = in.parens(); | 1167 Spaces(); |
1169 Spaces(inParens); | 1168 Expr exp = RequiredExpr(in).single(); |
1170 Expr exp = RequiredExpr(inParens).single(); | |
1171 RequiredMatch(')'); | 1169 RequiredMatch(')'); |
1172 Spaces(in); | 1170 Spaces(); |
1173 return exprVar(exp); | 1171 return exprVar(exp); |
1174 } | 1172 } |
1175 String name = Name(in); | 1173 String name = Name(); |
1176 if( name != null ) | 1174 if( name != null ) |
1177 return nameVar(name); | 1175 return nameVar(name); |
1178 Expr exp; | 1176 Expr exp; |
1179 exp = TableExpr(in); | 1177 exp = TableExpr(); |
1180 if( exp != null ) | 1178 if( exp != null ) |
1181 return exprVar(exp); | 1179 return exprVar(exp); |
1182 exp = Literal(in); | 1180 exp = Literal(); |
1183 if( exp != null ) | 1181 if( exp != null ) |
1184 return exprVar(exp); | 1182 return exprVar(exp); |
1185 return null; | 1183 return null; |
1186 } | 1184 } |
1187 | 1185 |
1189 parser.begin(); | 1187 parser.begin(); |
1190 Expr exp2 = SubExpr(in); | 1188 Expr exp2 = SubExpr(in); |
1191 if( exp2 != null ) | 1189 if( exp2 != null ) |
1192 return parser.success(indexVar(exp1,exp2)); | 1190 return parser.success(indexVar(exp1,exp2)); |
1193 if( parser.match('.') ) { | 1191 if( parser.match('.') ) { |
1194 Spaces(in); | 1192 Spaces(); |
1195 exp2 = NameExpr(in); | 1193 exp2 = NameExpr(); |
1196 if( exp2!=null ) | 1194 if( exp2!=null ) |
1197 return parser.success(indexVar(exp1,exp2)); | 1195 return parser.success(indexVar(exp1,exp2)); |
1198 return parser.failure(null); | 1196 return parser.failure(null); |
1199 } | 1197 } |
1200 Expr fnCall = Args( in, exp1, new ArrayList<Expr>() ); | 1198 Expr fnCall = Args( in, exp1, new ArrayList<Expr>() ); |
1240 if( sym != null ) { | 1238 if( sym != null ) { |
1241 Stmts stmt = new Stmts(); | 1239 Stmts stmt = new Stmts(); |
1242 stmt.addAll( sym.exp() ); | 1240 stmt.addAll( sym.exp() ); |
1243 stmt.add( " = " ); | 1241 stmt.add( " = " ); |
1244 stmt.addAll( val.single() ); | 1242 stmt.addAll( val.single() ); |
1245 stmt.add( ";\n" ); | 1243 stmt.add( "; " ); |
1246 return stmt; | 1244 return stmt; |
1247 } | 1245 } |
1248 Expr envExpr = env(); | 1246 Expr envExpr = env(); |
1249 if( envExpr != null ) | 1247 if( envExpr != null ) |
1250 return indexVar( envExpr, constExpStr(name) ).set(val); | 1248 return indexVar( envExpr, constExpStr(name) ).set(val); |
1287 stmt.addAll( table.single() ); | 1285 stmt.addAll( table.single() ); |
1288 stmt.add( "," ); | 1286 stmt.add( "," ); |
1289 stmt.addAll( key.single() ); | 1287 stmt.addAll( key.single() ); |
1290 stmt.add( "," ); | 1288 stmt.add( "," ); |
1291 stmt.addAll( val.single() ); | 1289 stmt.addAll( val.single() ); |
1292 stmt.add( ");\n" ); | 1290 stmt.add( "); " ); |
1293 return stmt; | 1291 return stmt; |
1294 } | 1292 } |
1295 }; | 1293 }; |
1296 } | 1294 } |
1297 | 1295 |
1303 } | 1301 } |
1304 | 1302 |
1305 private boolean args(In in,List<Expr> builder) throws ParseException { | 1303 private boolean args(In in,List<Expr> builder) throws ParseException { |
1306 parser.begin(); | 1304 parser.begin(); |
1307 if( parser.match('(') ) { | 1305 if( parser.match('(') ) { |
1308 In inParens = in.parens(); | 1306 Spaces(); |
1309 Spaces(inParens); | 1307 ExpList(in,builder); // optional |
1310 ExpList(inParens,builder); // optional | |
1311 if( !parser.match(')') ) | 1308 if( !parser.match(')') ) |
1312 throw parser.exception("Expression or ')' expected"); | 1309 throw parser.exception("Expression or ')' expected"); |
1313 Spaces(in); | 1310 Spaces(); |
1314 return parser.success(); | 1311 return parser.success(); |
1315 } | 1312 } |
1316 Expr exp = TableExpr(in); | 1313 Expr exp = TableExpr(); |
1317 if( exp != null ) { | 1314 if( exp != null ) { |
1318 builder.add(exp); | 1315 builder.add(exp); |
1319 return parser.success(); | 1316 return parser.success(); |
1320 } | 1317 } |
1321 String s = StringLiteral(in); | 1318 String s = StringLiteral(); |
1322 if( s != null ) { | 1319 if( s != null ) { |
1323 builder.add( constExpStr(s) ); | 1320 builder.add( constExpStr(s) ); |
1324 return parser.success(); | 1321 return parser.success(); |
1325 } | 1322 } |
1326 /* | |
1327 Expressions exps = TemplateExpressions(in); | |
1328 if( exps != null ) { | |
1329 builder.add(exps); | |
1330 return parser.success(); | |
1331 } | |
1332 */ | |
1333 return parser.failure(); | 1323 return parser.failure(); |
1334 } | 1324 } |
1335 | 1325 |
1336 private Expr ExpStringList(In in) throws ParseException { | 1326 private Expr ExpStringList(In in) throws ParseException { |
1337 List<Expr> builder = new ArrayList<Expr>(); | 1327 List<Expr> builder = new ArrayList<Expr>(); |
1348 exp = ExprZ(in); | 1338 exp = ExprZ(in); |
1349 if( exp==null ) | 1339 if( exp==null ) |
1350 return parser.failure(); | 1340 return parser.failure(); |
1351 builder.add(exp); | 1341 builder.add(exp); |
1352 while( parser.match(',') ) { | 1342 while( parser.match(',') ) { |
1353 Spaces(in); | 1343 Spaces(); |
1354 exp = TemplateExpressions(in); | 1344 exp = TemplateExpressions(in); |
1355 if( exp != null ) { | 1345 if( exp != null ) { |
1356 builder.add(exp); | 1346 builder.add(exp); |
1357 return parser.success(); | 1347 return parser.success(); |
1358 } | 1348 } |
1363 | 1353 |
1364 private Expr SubExpr(In in) throws ParseException { | 1354 private Expr SubExpr(In in) throws ParseException { |
1365 parser.begin(); | 1355 parser.begin(); |
1366 if( !parser.match('[') || parser.test("[") || parser.test("=") ) | 1356 if( !parser.match('[') || parser.test("[") || parser.test("=") ) |
1367 return parser.failure(null); | 1357 return parser.failure(null); |
1368 Spaces(In.NOTHING); | 1358 Spaces(); |
1369 Expr exp = RequiredExpr(In.NOTHING).single(); | 1359 Expr exp = RequiredExpr(In.NOTHING).single(); |
1370 RequiredMatch(']'); | 1360 RequiredMatch(']'); |
1371 Spaces(in); | 1361 Spaces(); |
1372 return parser.success(exp); | 1362 return parser.success(exp); |
1373 } | 1363 } |
1374 | 1364 |
1375 private Expr NameExpr(In in) throws ParseException { | 1365 private Expr NameExpr() throws ParseException { |
1376 parser.begin(); | 1366 parser.begin(); |
1377 String name = Name(in); | 1367 String name = Name(); |
1378 if( name==null ) | 1368 if( name==null ) |
1379 return parser.failure(null); | 1369 return parser.failure(null); |
1380 return parser.success(constExpStr(name)); | 1370 return parser.success(constExpStr(name)); |
1381 } | 1371 } |
1382 | 1372 |
1383 private String RequiredName(In in) throws ParseException { | 1373 private String RequiredName() throws ParseException { |
1384 parser.begin(); | 1374 parser.begin(); |
1385 String name = Name(in); | 1375 String name = Name(); |
1386 if( name==null ) | 1376 if( name==null ) |
1387 throw parser.exception("Name expected"); | 1377 throw parser.exception("Name expected"); |
1388 return parser.success(name); | 1378 return parser.success(name); |
1389 } | 1379 } |
1390 | 1380 |
1391 private String Name(In in) throws ParseException { | 1381 private String Name() throws ParseException { |
1392 int start = parser.begin(); | 1382 int start = parser.begin(); |
1393 if( !NameFirstChar() ) | 1383 if( !NameFirstChar() ) |
1394 return parser.failure(null); | 1384 return parser.failure(null); |
1395 while( NameChar() ); | 1385 while( NameChar() ); |
1396 String match = parser.textFrom(start); | 1386 String match = parser.textFrom(start); |
1397 if( keywords.contains(match) ) | 1387 if( keywords.contains(match) ) |
1398 return parser.failure(null); | 1388 return parser.failure(null); |
1399 Spaces(in); | 1389 Spaces(); |
1400 return parser.success(match); | 1390 return parser.success(match); |
1401 } | 1391 } |
1402 | 1392 |
1403 private boolean NameChar() { | 1393 private boolean NameChar() { |
1404 return NameFirstChar() || Digit(); | 1394 return NameFirstChar() || Digit(); |
1417 if( !parser.match(s) ) | 1407 if( !parser.match(s) ) |
1418 throw parser.exception("'"+s+"' expected"); | 1408 throw parser.exception("'"+s+"' expected"); |
1419 } | 1409 } |
1420 | 1410 |
1421 private void RequiredKeyword(String keyword,In in) throws ParseException { | 1411 private void RequiredKeyword(String keyword,In in) throws ParseException { |
1422 if( !Keyword(keyword,in) ) | 1412 if( !Keyword(keyword) ) |
1423 throw parser.exception("'"+keyword+"' expected"); | 1413 throw parser.exception("'"+keyword+"' expected"); |
1424 } | 1414 } |
1425 | 1415 |
1426 private boolean Keyword(String keyword,In in) throws ParseException { | 1416 private boolean Keyword(String keyword) throws ParseException { |
1427 parser.begin(); | 1417 parser.begin(); |
1428 if( !parser.match(keyword) || NameChar() ) | 1418 if( !parser.match(keyword) || NameChar() ) |
1429 return parser.failure(); | 1419 return parser.failure(); |
1430 Spaces(in); | 1420 Spaces(); |
1431 return parser.success(); | 1421 return parser.success(); |
1432 } | 1422 } |
1433 | 1423 |
1434 private static final Set<String> keywords = new HashSet<String>(Arrays.asList( | 1424 private static final Set<String> keywords = new HashSet<String>(Arrays.asList( |
1435 "and", | 1425 "and", |
1454 "true", | 1444 "true", |
1455 "until", | 1445 "until", |
1456 "while" | 1446 "while" |
1457 )); | 1447 )); |
1458 | 1448 |
1459 private Expr Literal(In in) throws ParseException { | 1449 private Expr Literal() throws ParseException { |
1460 parser.begin(); | 1450 parser.begin(); |
1461 if( NilLiteral(in) ) { | 1451 if( NilLiteral() ) { |
1462 Expr exp = new Expr(Val.SINGLE,false); | 1452 Expr exp = new Expr(Val.SINGLE,false); |
1463 exp.add( "null" ); | 1453 exp.add( "null" ); |
1464 return parser.success(exp); | 1454 return parser.success(exp); |
1465 } | 1455 } |
1466 Boolean b = BooleanLiteral(in); | 1456 Boolean b = BooleanLiteral(); |
1467 if( b != null ) { | 1457 if( b != null ) { |
1468 Expr exp = new Expr(Val.SINGLE,false); | 1458 Expr exp = new Expr(Val.SINGLE,false); |
1469 exp.add( b.toString() ); | 1459 exp.add( b.toString() ); |
1470 return parser.success(exp); | 1460 return parser.success(exp); |
1471 } | 1461 } |
1472 Number n = NumberLiteral(in); | 1462 Number n = NumberLiteral(); |
1473 if( n != null ) { | 1463 if( n != null ) { |
1474 String s = n.toString(); | 1464 String s = n.toString(); |
1475 if( n instanceof Long ) | 1465 if( n instanceof Long ) |
1476 s += "L"; | 1466 s += "L"; |
1477 Expr exp = new Expr(Val.SINGLE,false); | 1467 Expr exp = new Expr(Val.SINGLE,false); |
1478 exp.add( s ); | 1468 exp.add( s ); |
1479 return parser.success(exp); | 1469 return parser.success(exp); |
1480 } | 1470 } |
1481 String s = StringLiteral(in); | 1471 String s = StringLiteral(); |
1482 if( s != null ) | 1472 if( s != null ) |
1483 return parser.success(constExpStr(s)); | 1473 return parser.success(constExpStr(s)); |
1484 return parser.failure(null); | 1474 return parser.failure(null); |
1485 } | 1475 } |
1486 | 1476 |
1487 private Expr constExpStr(String s) { | 1477 private Expr constExpStr(String s) { |
1478 int n = 0; | |
1479 int from = 0; | |
1480 while( (from = s.indexOf('\n',from) + 1) != 0 ) { | |
1481 n++; | |
1482 } | |
1488 s = s | 1483 s = s |
1489 .replace("\\","\\\\") | 1484 .replace("\\","\\\\") |
1490 .replace("\"","\\\"") | 1485 .replace("\"","\\\"") |
1491 .replace("\n","\\n") | 1486 .replace("\n","\\n") |
1492 .replace("\r","\\r") | 1487 .replace("\r","\\r") |
1493 .replace("\t","\\t") | 1488 .replace("\t","\\t") |
1494 .replace("\b","\\b") | 1489 .replace("\b","\\b") |
1495 ; | 1490 ; |
1491 s = "\"" + s + "\""; | |
1492 while( n-- > 0 ) | |
1493 s += "\n"; | |
1496 Expr exp = new Expr(Val.SINGLE,false); | 1494 Expr exp = new Expr(Val.SINGLE,false); |
1497 exp.add( "\""+s+"\"" ); | 1495 exp.add( s ); |
1498 return exp; | 1496 return exp; |
1499 } | 1497 } |
1500 | 1498 |
1501 private boolean NilLiteral(In in) throws ParseException { | 1499 private boolean NilLiteral() throws ParseException { |
1502 return Keyword("nil",in); | 1500 return Keyword("nil"); |
1503 } | 1501 } |
1504 | 1502 |
1505 private Boolean BooleanLiteral(In in) throws ParseException { | 1503 private Boolean BooleanLiteral() throws ParseException { |
1506 if( Keyword("true",in) ) | 1504 if( Keyword("true") ) |
1507 return true; | 1505 return true; |
1508 if( Keyword("false",in) ) | 1506 if( Keyword("false") ) |
1509 return false; | 1507 return false; |
1510 return null; | 1508 return null; |
1511 } | 1509 } |
1512 | 1510 |
1513 private Number NumberLiteral(In in) throws ParseException { | 1511 private Number NumberLiteral() throws ParseException { |
1514 parser.begin(); | 1512 parser.begin(); |
1515 Number n; | 1513 Number n; |
1516 if( parser.matchIgnoreCase("0x") ) { | 1514 if( parser.matchIgnoreCase("0x") ) { |
1517 n = HexNumber(); | 1515 n = HexNumber(); |
1518 } else { | 1516 } else { |
1519 n = DecNumber(); | 1517 n = DecNumber(); |
1520 } | 1518 } |
1521 if( n==null || NameChar() ) | 1519 if( n==null || NameChar() ) |
1522 return parser.failure(null); | 1520 return parser.failure(null); |
1523 Spaces(in); | 1521 Spaces(); |
1524 return parser.success(n); | 1522 return parser.success(n); |
1525 } | 1523 } |
1526 | 1524 |
1527 private Number DecNumber() { | 1525 private Number DecNumber() { |
1528 int start = parser.begin(); | 1526 int start = parser.begin(); |
1618 | 1616 |
1619 private boolean HexDigit() { | 1617 private boolean HexDigit() { |
1620 return Digit() || parser.anyOf("abcdefABCDEF"); | 1618 return Digit() || parser.anyOf("abcdefABCDEF"); |
1621 } | 1619 } |
1622 | 1620 |
1623 private String StringLiteral(In in) throws ParseException { | 1621 private String StringLiteral() throws ParseException { |
1624 String s; | 1622 String s; |
1625 if( (s=QuotedString('"'))==null | 1623 if( (s=QuotedString('"'))==null |
1626 && (s=QuotedString('\''))==null | 1624 && (s=QuotedString('\''))==null |
1627 && (s=LongString())==null | 1625 && (s=LongString())==null |
1628 ) | 1626 ) |
1629 return null; | 1627 return null; |
1630 Spaces(in); | 1628 Spaces(); |
1631 return s; | 1629 return s; |
1632 } | 1630 } |
1633 | 1631 |
1634 private String LongString() throws ParseException { | 1632 private String LongString() throws ParseException { |
1635 parser.begin(); | 1633 parser.begin(); |
1687 return parser.success((char)Integer.parseInt(parser.textFrom(start+1),16)); | 1685 return parser.success((char)Integer.parseInt(parser.textFrom(start+1),16)); |
1688 if( Digit() ) { | 1686 if( Digit() ) { |
1689 if( Digit() ) Digit(); // optional | 1687 if( Digit() ) Digit(); // optional |
1690 return parser.success((char)Integer.parseInt(parser.textFrom(start))); | 1688 return parser.success((char)Integer.parseInt(parser.textFrom(start))); |
1691 } | 1689 } |
1692 if( EndOfLine() ) | 1690 if( EndOfLine() ) { |
1691 parser.sb().setLength(parser.sb().length()-1); | |
1693 return parser.success('\n'); | 1692 return parser.success('\n'); |
1693 } | |
1694 return parser.failure(null); | 1694 return parser.failure(null); |
1695 } | 1695 } |
1696 | 1696 |
1697 private void Spaces(In in) throws ParseException { | 1697 private void Spaces() throws ParseException { |
1698 while( parser.anyOf(" \t") || Comment() || ContinueOnNextLine() || in.parens && EndOfLine() ); | 1698 while( parser.anyOf(" \t") || Comment() || ContinueOnNextLine() ); |
1699 } | 1699 } |
1700 | 1700 |
1701 private boolean ContinueOnNextLine() { | 1701 private boolean ContinueOnNextLine() { |
1702 parser.begin(); | 1702 parser.begin(); |
1703 return parser.match('\\') && EndOfLine() ? parser.success() : parser.failure(); | 1703 return parser.match('\\') && EndOfLine() ? parser.success() : parser.failure(); |
1721 while( parser.match('=') ); | 1721 while( parser.match('=') ); |
1722 int nEquals = parser.currentIndex() - start; | 1722 int nEquals = parser.currentIndex() - start; |
1723 if( !parser.match('[') ) | 1723 if( !parser.match('[') ) |
1724 return parser.failure(); | 1724 return parser.failure(); |
1725 while( !LongBracketsEnd(nEquals) ) { | 1725 while( !LongBracketsEnd(nEquals) ) { |
1726 if( !parser.anyChar() ) | 1726 if( !(EndOfLine() || parser.anyChar()) ) |
1727 throw parser.exception("Unclosed comment"); | 1727 throw parser.exception("Unclosed comment"); |
1728 } | 1728 } |
1729 parser.upSb(); | |
1729 return parser.success(); | 1730 return parser.success(); |
1730 } | 1731 } |
1731 | 1732 |
1732 private boolean LongBracketsEnd(int nEquals) { | 1733 private boolean LongBracketsEnd(int nEquals) { |
1733 parser.begin(); | 1734 parser.begin(); |
1742 return parser.success(); | 1743 return parser.success(); |
1743 } | 1744 } |
1744 | 1745 |
1745 | 1746 |
1746 | 1747 |
1747 private static class ParseList extends ArrayList { | 1748 private class ParseList extends ArrayList { |
1749 | |
1750 void addNewLines() { | |
1751 if( parser.sb().length() > 0 ) { | |
1752 add( parser.sb().toString() ); | |
1753 parser.sb().setLength(0); | |
1754 /* | |
1755 if( parser.sourceName.equals("stdin") ) { | |
1756 StringWriter sw = new StringWriter(); | |
1757 new Throwable().printStackTrace(new PrintWriter(sw,true)); | |
1758 // add(sw.toString()); | |
1759 } | |
1760 */ | |
1761 } | |
1762 } | |
1763 | |
1764 ParseList() { | |
1765 addNewLines(); | |
1766 } | |
1748 | 1767 |
1749 @Override public boolean add(Object obj) { | 1768 @Override public boolean add(Object obj) { |
1750 if( obj instanceof List ) throw new RuntimeException(); | 1769 if( obj instanceof List ) throw new RuntimeException(); |
1751 return super.add(obj); | 1770 return super.add(obj); |
1752 } | 1771 } |
1768 | 1787 |
1769 private static AtomicInteger classCounter = new AtomicInteger(); | 1788 private static AtomicInteger classCounter = new AtomicInteger(); |
1770 | 1789 |
1771 private enum Val { SINGLE, ARRAY } | 1790 private enum Val { SINGLE, ARRAY } |
1772 | 1791 |
1773 private static class Expr extends ParseList { | 1792 private class Expr extends ParseList { |
1774 final Val valType; | 1793 final Val valType; |
1775 final boolean isStmt; | 1794 final boolean isStmt; |
1776 | 1795 |
1777 Expr(Val valType,boolean isStmt) { | 1796 Expr(Val valType,boolean isStmt) { |
1778 this.valType = valType; | 1797 this.valType = valType; |
1835 } | 1854 } |
1836 return exp; | 1855 return exp; |
1837 } | 1856 } |
1838 } | 1857 } |
1839 | 1858 |
1840 private static class Stmts extends ParseList { | 1859 private class Stmts extends ParseList { |
1841 boolean hasReturn = false; | 1860 boolean hasReturn = false; |
1842 } | 1861 } |
1843 | 1862 |
1844 private Class toFnClass(Stmts stmts,List<UpSym> upValueSymbols) { | 1863 private Class toFnClass(Stmts stmts,List<UpSym> upValueSymbols) { |
1845 String className = "EXP" + classCounter.incrementAndGet(); | 1864 String className = "EXP" + classCounter.incrementAndGet(); |
1858 return toFnString(stmts,upValueSymbols,className); | 1877 return toFnString(stmts,upValueSymbols,className); |
1859 } | 1878 } |
1860 | 1879 |
1861 private String toFnString(Stmts stmts,List<UpSym> upValueSymbols,String className) { | 1880 private String toFnString(Stmts stmts,List<UpSym> upValueSymbols,String className) { |
1862 if( !stmts.hasReturn ) | 1881 if( !stmts.hasReturn ) |
1863 stmts.add( "return LuanFunction.NOTHING;\n" ); | 1882 stmts.add( "\nreturn LuanFunction.NOTHING;" ); |
1864 return "" | 1883 return "" |
1865 +"package luan.impl;\n" | 1884 +"package luan.impl; " |
1866 +"import luan.Luan;\n" | 1885 +"import luan.Luan; " |
1867 +"import luan.LuanFunction;\n" | 1886 +"import luan.LuanFunction; " |
1868 +"import luan.LuanState;\n" | 1887 +"import luan.LuanState; " |
1869 +"import luan.LuanJava;\n" | 1888 +"import luan.LuanJava; " |
1870 +"import luan.LuanException;\n" | 1889 +"import luan.LuanException; " |
1871 +"import luan.modules.PackageLuan;\n" | 1890 +"import luan.modules.PackageLuan; " |
1872 +"\n" | 1891 |
1873 +"public class " + className +" extends Closure {\n" | 1892 +"public class " + className +" extends Closure { " |
1874 +" public "+className+"(LuanJava java) throws LuanException {\n" | 1893 +"public "+className+"(LuanJava java) throws LuanException { " |
1875 +" super("+upValueSymbols.size()+",java);\n" | 1894 +"super("+upValueSymbols.size()+",java); " |
1876 + init(upValueSymbols) | 1895 + init(upValueSymbols) |
1877 +" }\n" | 1896 +"} " |
1878 +"\n" | 1897 |
1879 +" @Override public Object doCall(LuanState luan,Object[] args) throws LuanException {\n" | 1898 +"@Override public Object doCall(LuanState luan,Object[] args) throws LuanException { " |
1880 +" Object t;\n" | 1899 +"Object t; " |
1881 +" Object[] a;\n" | 1900 +"Object[] a; " |
1882 +" " + stmts | 1901 + stmts |
1883 +" }\n" | 1902 +"\n} " |
1884 +"}\n" | 1903 +"}\n" |
1885 ; | 1904 ; |
1886 } | 1905 } |
1887 | 1906 |
1888 private static Expr toFnExpStr(Stmts stmt,List<UpSym> upValueSymbols) { | 1907 private Expr toFnExpStr(Stmts stmt,List<UpSym> upValueSymbols) { |
1908 stmt.addNewLines(); | |
1889 if( !stmt.hasReturn ) | 1909 if( !stmt.hasReturn ) |
1890 stmt.add( "return LuanFunction.NOTHING;\n" ); | 1910 stmt.add( "return LuanFunction.NOTHING; " ); |
1891 Expr exp = new Expr(Val.SINGLE,false); | 1911 Expr exp = new Expr(Val.SINGLE,false); |
1892 exp.add( "" | 1912 exp.add( "" |
1893 +"\n" | 1913 +"new Closure("+upValueSymbols.size()+",java) { " |
1894 +"new Closure("+upValueSymbols.size()+",java) {\n" | 1914 +"{ " |
1895 +"{\n" | 1915 + init(upValueSymbols) |
1896 + init(upValueSymbols) | 1916 +"} " |
1897 +"}\n" | 1917 +"@Override public Object doCall(LuanState luan,Object[] args) throws LuanException { " |
1898 +" @Override public Object doCall(LuanState luan,Object[] args) throws LuanException {\n" | 1918 +"Object t; " |
1899 +" Object t;\n" | 1919 +"Object[] a; " |
1900 +" Object[] a;\n" | |
1901 +" " | |
1902 ); | 1920 ); |
1903 exp.addAll( stmt ); | 1921 exp.addAll( stmt ); |
1904 exp.add( "" | 1922 exp.add( "" |
1905 +" }\n" | 1923 +"} " |
1906 +"}\n" | 1924 +"} " |
1907 ); | 1925 ); |
1908 return exp; | 1926 return exp; |
1909 } | 1927 } |
1910 | 1928 |
1911 private static String init(List<UpSym> upValueSymbols) { | 1929 private static String init(List<UpSym> upValueSymbols) { |