Mercurial Hosting > luan
comparison core/src/luan/impl/LuanParser.java @ 651:140cc5191b7a
start compiling statements
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Fri, 01 Apr 2016 17:24:44 -0600 |
parents | d658eab7bf4c |
children | 067d9470184d |
comparison
equal
deleted
inserted
replaced
650:d658eab7bf4c | 651:140cc5191b7a |
---|---|
191 | 191 |
192 FnDef RequiredModule() throws ParseException { | 192 FnDef RequiredModule() throws ParseException { |
193 Spaces(In.NOTHING); | 193 Spaces(In.NOTHING); |
194 int start = parser.begin(); | 194 int start = parser.begin(); |
195 frame.isVarArg = true; | 195 frame.isVarArg = true; |
196 Stmt stmt = RequiredBlock(); | 196 Stmt stmt = stmt(RequiredBlock()); |
197 if( parser.endOfInput() ) | 197 if( parser.endOfInput() ) |
198 return parser.success(newFnDef(start,stmt)); | 198 return parser.success(newFnDef(start,stmt)); |
199 throw parser.exception(); | 199 throw parser.exception(); |
200 } | 200 } |
201 | 201 |
202 private Stmt RequiredBlock() throws ParseException { | 202 private StmtString RequiredBlock() throws ParseException { |
203 List<Stmt> stmts = new ArrayList<Stmt>(); | 203 StringBuilder stmts = new StringBuilder(); |
204 int stackStart = symbolsSize(); | 204 int stackStart = symbolsSize(); |
205 Stmt(stmts); | 205 Stmt(stmts); |
206 while( StmtSep(stmts) ) { | 206 while( StmtSep(stmts) ) { |
207 Spaces(In.NOTHING); | 207 Spaces(In.NOTHING); |
208 Stmt(stmts); | 208 Stmt(stmts); |
209 } | 209 } |
210 int stackEnd = symbolsSize(); | 210 int stackEnd = symbolsSize(); |
211 popSymbols( stackEnd - stackStart ); | 211 popSymbols( stackEnd - stackStart ); |
212 if( stmts.isEmpty() ) | 212 if( stmts.length() == 0 ) |
213 return Stmt.EMPTY; | 213 return EMPTY_STMT; |
214 if( stmts.size()==1 && stackStart==stackEnd ) | 214 String code = stmts.toString(); |
215 return stmts.get(0); | 215 if( stackStart < stackEnd ) |
216 return new Block( stmts.toArray(new Stmt[0]), stackStart, stackEnd ); | 216 code = "" |
217 } | 217 +"try {\n" |
218 | 218 + code |
219 private boolean StmtSep(List<Stmt> stmts) throws ParseException { | 219 +"} finally {\n" |
220 +" $luan.stackClear("+stackStart+","+stackEnd+");\n" | |
221 +"}\n" | |
222 ; | |
223 return new StmtString(code); | |
224 } | |
225 | |
226 private boolean StmtSep(StringBuilder stmts) throws ParseException { | |
220 parser.begin(); | 227 parser.begin(); |
221 if( parser.match( ';' ) ) | 228 if( parser.match( ';' ) ) |
222 return parser.success(); | 229 return parser.success(); |
223 if( EndOfLine() ) | 230 if( EndOfLine() ) |
224 return parser.success(); | 231 return parser.success(); |
225 parser.rollback(); | 232 parser.rollback(); |
226 Stmt stmt = TemplateStmt(); | 233 StmtString stmt = stmtStr(TemplateStmt()); |
227 if( stmt != null ) { | 234 if( stmt != null ) { |
228 stmts.add(stmt); | 235 stmts.append(stmt.code); |
229 return parser.success(); | 236 return parser.success(); |
230 } | 237 } |
231 return parser.failure(); | 238 return parser.failure(); |
232 } | 239 } |
233 | 240 |
234 private boolean EndOfLine() { | 241 private boolean EndOfLine() { |
235 return parser.match( "\r\n" ) || parser.match( '\r' ) || parser.match( '\n' ); | 242 return parser.match( "\r\n" ) || parser.match( '\r' ) || parser.match( '\n' ); |
236 } | 243 } |
237 | 244 |
238 private void Stmt(List<Stmt> stmts) throws ParseException { | 245 private void Stmt(StringBuilder stmts) throws ParseException { |
239 if( LocalStmt(stmts) ) | 246 if( LocalStmt(stmts) ) |
240 return; | 247 return; |
241 Stmt stmt; | 248 StmtString stmt; |
242 if( (stmt=ReturnStmt()) != null | 249 if( (stmt=stmtStr(ReturnStmt())) != null |
243 || (stmt=FunctionStmt()) != null | 250 || (stmt=stmtStr(FunctionStmt())) != null |
244 || (stmt=LocalFunctionStmt()) != null | 251 || (stmt=stmtStr(LocalFunctionStmt())) != null |
245 || (stmt=BreakStmt()) != null | 252 || (stmt=stmtStr(BreakStmt())) != null |
246 || (stmt=ForStmt()) != null | 253 || (stmt=stmtStr(ForStmt())) != null |
247 || (stmt=DoStmt()) != null | 254 || (stmt=DoStmt()) != null |
248 || (stmt=WhileStmt()) != null | 255 || (stmt=WhileStmt()) != null |
249 || (stmt=RepeatStmt()) != null | 256 || (stmt=RepeatStmt()) != null |
250 || (stmt=IfStmt()) != null | 257 || (stmt=stmtStr(IfStmt())) != null |
251 || (stmt=SetStmt()) != null | 258 || (stmt=stmtStr(SetStmt())) != null |
252 || (stmt=ExpressionsStmt()) != null | 259 || (stmt=ExpressionsStmt()) != null |
253 ) { | 260 ) { |
254 stmts.add(stmt); | 261 stmts.append(stmt.code); |
255 } | 262 } |
256 } | 263 } |
257 | 264 |
258 private Stmt TemplateStmt() throws ParseException { | 265 private Stmt TemplateStmt() throws ParseException { |
259 parser.currentIndex(); | 266 parser.currentIndex(); |
356 if( !Keyword("in",In.NOTHING) ) | 363 if( !Keyword("in",In.NOTHING) ) |
357 return parser.failure(null); | 364 return parser.failure(null); |
358 Expr expr = expr(exp(RequiredExpr(In.NOTHING))); | 365 Expr expr = expr(exp(RequiredExpr(In.NOTHING))); |
359 RequiredKeyword("do",In.NOTHING); | 366 RequiredKeyword("do",In.NOTHING); |
360 addSymbols(names); | 367 addSymbols(names); |
361 Stmt loop = RequiredLoopBlock(); | 368 Stmt loop = stmt(RequiredLoopBlock()); |
362 RequiredKeyword("end",In.NOTHING); | 369 RequiredKeyword("end",In.NOTHING); |
363 Stmt stmt = new ForStmt( stackStart, symbolsSize() - stackStart, expr, loop ); | 370 Stmt stmt = new ForStmt( stackStart, symbolsSize() - stackStart, expr, loop ); |
364 popSymbols( symbolsSize() - stackStart ); | 371 popSymbols( symbolsSize() - stackStart ); |
365 return parser.success(stmt); | 372 return parser.success(stmt); |
366 } | 373 } |
367 | 374 |
368 private Stmt DoStmt() throws ParseException { | 375 private StmtString DoStmt() throws ParseException { |
369 parser.begin(); | 376 parser.begin(); |
370 if( !Keyword("do",In.NOTHING) ) | 377 if( !Keyword("do",In.NOTHING) ) |
371 return parser.failure(null); | 378 return parser.failure(null); |
372 Stmt stmt = RequiredBlock(); | 379 StmtString stmt = RequiredBlock(); |
373 RequiredKeyword("end",In.NOTHING); | 380 RequiredKeyword("end",In.NOTHING); |
374 return parser.success(stmt); | 381 return parser.success(stmt); |
375 } | 382 } |
376 | 383 |
377 private boolean LocalStmt(List<Stmt> stmts) throws ParseException { | 384 private boolean LocalStmt(StringBuilder stmts) throws ParseException { |
378 parser.begin(); | 385 parser.begin(); |
379 if( !Keyword("local",In.NOTHING) ) | 386 if( !Keyword("local",In.NOTHING) ) |
380 return parser.failure(); | 387 return parser.failure(); |
381 List<String> names = NameList(In.NOTHING); | 388 List<String> names = NameList(In.NOTHING); |
382 if( names==null ) { | 389 if( names==null ) { |
392 SetLocalVar[] vars = new SetLocalVar[names.size()]; | 399 SetLocalVar[] vars = new SetLocalVar[names.size()]; |
393 int stackStart = symbolsSize(); | 400 int stackStart = symbolsSize(); |
394 for( int i=0; i<vars.length; i++ ) { | 401 for( int i=0; i<vars.length; i++ ) { |
395 vars[i] = new SetLocalVar(stackStart+i); | 402 vars[i] = new SetLocalVar(stackStart+i); |
396 } | 403 } |
397 stmts.add( new SetStmt( vars, values ) ); | 404 stmts.append( new StmtString(new SetStmt( vars, values )).code ); |
398 } | 405 } |
399 addSymbols(names); | 406 addSymbols(names); |
400 return parser.success(); | 407 return parser.success(); |
401 } | 408 } |
402 | 409 |
429 if( name==null ) | 436 if( name==null ) |
430 return parser.failure(null); | 437 return parser.failure(null); |
431 return parser.success(name); | 438 return parser.success(name); |
432 } | 439 } |
433 | 440 |
434 private Stmt WhileStmt() throws ParseException { | 441 private StmtString WhileStmt() throws ParseException { |
435 parser.begin(); | 442 parser.begin(); |
436 if( !Keyword("while",In.NOTHING) ) | 443 if( !Keyword("while",In.NOTHING) ) |
437 return parser.failure(null); | 444 return parser.failure(null); |
438 Expr cnd = expr(exp(RequiredExpr(In.NOTHING))); | 445 ExpString cnd = RequiredExpr(In.NOTHING).expr(); |
439 RequiredKeyword("do",In.NOTHING); | 446 RequiredKeyword("do",In.NOTHING); |
440 Stmt loop = RequiredLoopBlock(); | 447 StmtString loop = RequiredLoopBlock(); |
441 RequiredKeyword("end",In.NOTHING); | 448 RequiredKeyword("end",In.NOTHING); |
442 return parser.success( new WhileStmt(cnd,loop) ); | 449 String code = "" |
443 } | 450 +"try {\n" |
444 | 451 +" while( $Luan.checkBoolean(" + cnd.code + ") ) {\n" |
445 private Stmt RepeatStmt() throws ParseException { | 452 + loop.code |
453 +" }\n" | |
454 +"} catch(BreakException e) {}\n" | |
455 ; | |
456 return parser.success( new StmtString(code) ); | |
457 } | |
458 | |
459 private StmtString RepeatStmt() throws ParseException { | |
446 parser.begin(); | 460 parser.begin(); |
447 if( !Keyword("repeat",In.NOTHING) ) | 461 if( !Keyword("repeat",In.NOTHING) ) |
448 return parser.failure(null); | 462 return parser.failure(null); |
449 Stmt loop = RequiredLoopBlock(); | 463 StmtString loop =RequiredLoopBlock(); |
450 RequiredKeyword("until",In.NOTHING); | 464 RequiredKeyword("until",In.NOTHING); |
451 Expr cnd = expr(exp(RequiredExpr(In.NOTHING))); | 465 ExpString cnd = RequiredExpr(In.NOTHING).expr(); |
452 return parser.success( new RepeatStmt(loop,cnd) ); | 466 String code = "" |
453 } | 467 +"try {\n" |
454 | 468 +" do {\n" |
455 private Stmt RequiredLoopBlock() throws ParseException { | 469 + loop.code |
470 +" } while( !$Luan.checkBoolean(" + cnd.code + ") );\n" | |
471 +"} catch(BreakException e) {}\n" | |
472 ; | |
473 return parser.success( new StmtString(code) ); | |
474 } | |
475 | |
476 private StmtString RequiredLoopBlock() throws ParseException { | |
456 incLoops(); | 477 incLoops(); |
457 Stmt stmt = RequiredBlock(); | 478 StmtString stmt = RequiredBlock(); |
458 decLoops(); | 479 decLoops(); |
459 return stmt; | 480 return stmt; |
460 } | 481 } |
461 | 482 |
462 private Stmt IfStmt() throws ParseException { | 483 private Stmt IfStmt() throws ParseException { |
468 | 489 |
469 private Stmt IfStmt2() throws ParseException { | 490 private Stmt IfStmt2() throws ParseException { |
470 parser.currentIndex(); | 491 parser.currentIndex(); |
471 Expr cnd = expr(exp(RequiredExpr(In.NOTHING))); | 492 Expr cnd = expr(exp(RequiredExpr(In.NOTHING))); |
472 RequiredKeyword("then",In.NOTHING); | 493 RequiredKeyword("then",In.NOTHING); |
473 Stmt thenBlock = RequiredBlock(); | 494 Stmt thenBlock = stmt(RequiredBlock()); |
474 Stmt elseBlock; | 495 Stmt elseBlock; |
475 if( Keyword("elseif",In.NOTHING) ) { | 496 if( Keyword("elseif",In.NOTHING) ) { |
476 elseBlock = IfStmt2(); | 497 elseBlock = IfStmt2(); |
477 } else { | 498 } else { |
478 elseBlock = Keyword("else",In.NOTHING) ? RequiredBlock() : Stmt.EMPTY; | 499 elseBlock = Keyword("else",In.NOTHING) ? stmt(RequiredBlock()) : Stmt.EMPTY; |
479 RequiredKeyword("end",In.NOTHING); | 500 RequiredKeyword("end",In.NOTHING); |
480 } | 501 } |
481 return new IfStmt(cnd,thenBlock,elseBlock); | 502 return new IfStmt(cnd,thenBlock,elseBlock); |
482 } | 503 } |
483 | 504 |
503 // throw parser.exception("Expressions expected"); | 524 // throw parser.exception("Expressions expected"); |
504 return parser.failure(null); | 525 return parser.failure(null); |
505 return parser.success( new SetStmt( vars.toArray(new Settable[0]), values ) ); | 526 return parser.success( new SetStmt( vars.toArray(new Settable[0]), values ) ); |
506 } | 527 } |
507 | 528 |
508 private Stmt ExpressionsStmt() throws ParseException { | 529 private StmtString ExpressionsStmt() throws ParseException { |
509 parser.begin(); | 530 parser.begin(); |
510 Expressions exp = exp(ExprZ(In.NOTHING)); | 531 ExpString exp = ExprZ(In.NOTHING); |
511 if( exp instanceof StmtExp ) | 532 if( exp != null && exp.isStmt ) { |
512 return parser.success( new ExpressionsStmt(exp) ); | 533 String code = exp.code; |
534 if( exp.isExpr ) | |
535 code = "$Luan.nop(" + code + ")"; | |
536 code += ";\n"; | |
537 return parser.success( new StmtString(code) ); | |
538 } | |
513 return parser.failure(null); | 539 return parser.failure(null); |
514 } | 540 } |
515 | 541 |
516 private Settable SettableVar() throws ParseException { | 542 private Settable SettableVar() throws ParseException { |
517 int start = parser.begin(); | 543 int start = parser.begin(); |
770 Spaces(inParens); | 796 Spaces(inParens); |
771 frame.isVarArg = true; | 797 frame.isVarArg = true; |
772 } | 798 } |
773 RequiredMatch(')'); | 799 RequiredMatch(')'); |
774 Spaces(in); | 800 Spaces(in); |
775 Stmt block = RequiredBlock(); | 801 Stmt block = stmt(RequiredBlock()); |
776 RequiredKeyword("end",in); | 802 RequiredKeyword("end",in); |
777 FnDef fnDef = newFnDef(start,block); | 803 FnDef fnDef = newFnDef(start,block); |
778 frame = frame.parent; | 804 frame = frame.parent; |
779 return parser.success(fnDef); | 805 return parser.success(fnDef); |
780 } | 806 } |
1441 | 1467 |
1442 private static Expressions exp(ExpString expStr) { | 1468 private static Expressions exp(ExpString expStr) { |
1443 return expStr==null ? null : expStr.toExpressions(); | 1469 return expStr==null ? null : expStr.toExpressions(); |
1444 } | 1470 } |
1445 | 1471 |
1472 | |
1473 private static class StmtString { | |
1474 final String code; | |
1475 | |
1476 StmtString(Stmt stmt) { | |
1477 if( stmt==null ) throw new NullPointerException(); | |
1478 int i = $Luan.addStmt(stmt); | |
1479 code = "$Luan.getStmt(" + i + ").eval($luan);\n"; | |
1480 } | |
1481 | |
1482 StmtString(String code) { | |
1483 this.code = code; | |
1484 } | |
1485 | |
1486 Stmt toStmt() { | |
1487 String className = "EXP" + ++classCounter; | |
1488 String classCode = "" | |
1489 +"package luan.impl;\n" | |
1490 +"import luan.LuanException;\n" | |
1491 +"\n" | |
1492 +"public class " + className +" implements Stmt {\n" | |
1493 +" @Override public void eval(LuanStateImpl $luan) throws LuanException {\n" | |
1494 +" Object $cnd;\n" | |
1495 +" " + code | |
1496 +" }\n" | |
1497 +"}\n" | |
1498 ; | |
1499 //System.out.println(code); | |
1500 try { | |
1501 Class cls = LuanJavaCompiler.compile("luan.impl."+className,code,classCode); | |
1502 return (Stmt)cls.newInstance(); | |
1503 } catch(ClassNotFoundException e) { | |
1504 throw new RuntimeException(e); | |
1505 } catch(InstantiationException e) { | |
1506 throw new RuntimeException(e); | |
1507 } catch(IllegalAccessException e) { | |
1508 throw new RuntimeException(e); | |
1509 } | |
1510 } | |
1511 } | |
1512 | |
1513 private static StmtString EMPTY_STMT = new StmtString(""); | |
1514 | |
1515 private static Stmt stmt(StmtString stmtStr) { | |
1516 return stmtStr==null ? null : stmtStr.toStmt(); | |
1517 } | |
1518 | |
1519 private static StmtString stmtStr(Stmt stmt) { | |
1520 return stmt==null ? null : new StmtString(stmt); | |
1521 } | |
1522 | |
1446 } | 1523 } |