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) { |
