Mercurial Hosting > luan
changeset 14:2ddf85634d20
whitespace handling;
comments;
if/while/repeat statements;
git-svn-id: https://luan-java.googlecode.com/svn/trunk@15 21e917c8-12df-6dd8-5cb6-c86387c605b9
author | fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9> |
---|---|
date | Mon, 26 Nov 2012 10:18:46 +0000 |
parents | 3b22ffbdb83a |
children | bb59d7ea223b |
files | src/luan/interp/IfStmt.java src/luan/interp/LuaParser.java src/luan/interp/RepeatStmt.java src/luan/interp/WhileStmt.java src/luan/lib/BasicLib.java |
diffstat | 5 files changed, 195 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/interp/IfStmt.java Mon Nov 26 10:18:46 2012 +0000 @@ -0,0 +1,26 @@ +package luan.interp; + +import luan.Lua; +import luan.LuaState; +import luan.LuaException; + + +final class IfStmt implements Stmt { + private final Expr cnd; + private final Stmt thenStmt; + private final Stmt elseStmt; + + IfStmt(Expr cnd,Stmt thenStmt,Stmt elseStmt) { + this.cnd = cnd; + this.thenStmt = thenStmt; + this.elseStmt = elseStmt; + } + + @Override public void eval(LuaState lua) throws LuaException { + if( Lua.toBoolean( cnd.eval(lua) ) ) { + thenStmt.eval(lua); + } else { + elseStmt.eval(lua); + } + } +}
--- a/src/luan/interp/LuaParser.java Fri Nov 23 13:04:03 2012 +0000 +++ b/src/luan/interp/LuaParser.java Mon Nov 26 10:18:46 2012 +0000 @@ -11,6 +11,9 @@ import org.parboiled.Rule; import org.parboiled.parserunners.ReportingParseRunner; import org.parboiled.support.ParsingResult; +import org.parboiled.support.Var; +import org.parboiled.support.StringVar; +import org.parboiled.support.ValueStack; import org.parboiled.errors.ErrorUtils; import luan.Lua; import luan.LuaNumber; @@ -18,6 +21,7 @@ public class LuaParser extends BaseParser<Object> { + static final Object PAREN = new Object(); public Rule Target() { return Sequence( @@ -51,7 +55,7 @@ Stmt newChunk() { @SuppressWarnings("unchecked") - List<Stmt> stmts = (List<Stmt>)peek(); + List<Stmt> stmts = (List<Stmt>)pop(); switch( stmts.size() ) { case 0: return Stmt.EMPTY; @@ -63,12 +67,28 @@ } Rule StmtSep() { - return Sequence( OneOrMore(AnyOf(";\r\n")), Spaces() ); + return Sequence( + FirstOf( + ';', + Sequence( + Optional( "--", ZeroOrMore(NoneOf("\r\n")) ), + EndOfLine() + ) + ), + Spaces() + ); + } + + Rule EndOfLine() { + return FirstOf("\r\n", '\r', '\n'); } Rule Stmt() { return Sequence( FirstOf( + WhileStmt(), + RepeatStmt(), + IfStmt(), SetStmt(), ExpressionsStmt() ), @@ -76,13 +96,48 @@ ); } - Rule ExpressionsStmt() { + Rule WhileStmt() { + return Sequence( + "while", Spaces(), Expr(), "do", Spaces(), Chunk(), "end", Spaces(), + push( new WhileStmt( expr(pop(1)), (Stmt)pop() ) ) + ); + } + + Rule RepeatStmt() { + return Sequence( + "repeat", Spaces(), Chunk(), "until", Spaces(), Expr(), + push( new RepeatStmt( (Stmt)pop(1), expr(pop()) ) ) + ); + } + + Rule IfStmt() { + Var<Integer> n = new Var<Integer>(1); return Sequence( - ExpList(), - push( new ExpressionsStmt((Expressions)pop()) ) + "if", Spaces(), Expr(), "then", Spaces(), Chunk(), + push(Stmt.EMPTY), + ZeroOrMore( + "elseif", Spaces(), drop(), Expr(), "then", Spaces(), Chunk(), + push(Stmt.EMPTY), + n.set(n.get()+1) + ), + Optional( + "else", Spaces(), drop(), Chunk() + ), + "end", Spaces(), + buildIfStmt(n.get()) ); } + boolean buildIfStmt(int n) { + while( n-- > 0 ) { + Stmt elseStmt = (Stmt)pop(); + Stmt thenStmt = (Stmt)pop(); + Expr cnd = expr(pop()); + push( new IfStmt(cnd,thenStmt,elseStmt) ); + } + return true; + } + Rule SetStmt() { return Sequence( VarList(), @@ -92,6 +147,13 @@ ); } + Rule ExpressionsStmt() { + return Sequence( + ExpList(), + push( new ExpressionsStmt((Expressions)pop()) ) + ); + } + SetStmt newSetStmt() { Expressions values = (Expressions)pop(); @SuppressWarnings("unchecked") @@ -170,7 +232,7 @@ ZeroOrMore( FirstOf( Sequence( '+', Spaces(), TermExpr(), push( new AddExpr(expr(pop(1)),expr(pop())) ) ), - Sequence( '-', Spaces(), TermExpr(), push( new SubExpr(expr(pop(1)),expr(pop())) ) ) + Sequence( '-', TestNot('-'), Spaces(), TermExpr(), push( new SubExpr(expr(pop(1)),expr(pop())) ) ) ) ) ); @@ -192,7 +254,7 @@ Rule UnaryExpr() { return FirstOf( Sequence( '#', Spaces(), PowExpr(), push( new LenExpr(expr(pop())) ) ), - Sequence( '-', Spaces(), PowExpr(), push( new UnmExpr(expr(pop())) ) ), + Sequence( '-', TestNot('-'), Spaces(), PowExpr(), push( new UnmExpr(expr(pop())) ) ), Sequence( "not", Spaces(), PowExpr(), push( new NotExpr(expr(pop())) ) ), PowExpr() ); @@ -216,6 +278,7 @@ Rule TableExpr() { return Sequence( '{', Spaces(), + push(PAREN), push( new ArrayList<TableExpr.Field>() ), push( 1.0 ), // counter Optional( @@ -226,8 +289,10 @@ ), Optional( FieldSep() ) ), - '}', Spaces(), - push( newTableExpr() ) + '}', + push( newTableExpr() ), + drop(1), + Spaces() ); } @@ -292,7 +357,7 @@ return Sequence( FirstOf( Sequence( - '(', Spaces(), Expr(), ')', Spaces(), + '(', Spaces(), push(PAREN), Expr(), ')', drop(1), Spaces(), push(expr(pop())), push(null) // marker ), @@ -327,7 +392,7 @@ return Sequence( FirstOf( Sequence( - '(', Spaces(), Expressions(), ')', Spaces() + '(', Spaces(), push(PAREN), Expressions(), ')', drop(1), Spaces() ), Sequence( TableExpr(), @@ -374,7 +439,7 @@ } Rule SubExpr() { - return Sequence( '[', Spaces(), Expr(), ']', Spaces() ); + return Sequence( '[', Spaces(), push(PAREN), Expr(), ']', drop(1), Spaces() ); } Rule Name() { @@ -579,12 +644,56 @@ } Rule Spaces() { - return ZeroOrMore(AnyOf(" \t")); + return ZeroOrMore( + FirstOf( + AnyOf(" \t"), + Comment(), + Sequence( '\\', EndOfLine() ), + Sequence( AnyOf("\r\n"), inParen() ) + ) + ); + } + + boolean inParen() { + ValueStack stack = getContext().getValueStack(); + int size = stack.size(); + for( int i=0; i<size; i++ ) { + if( peek(i) == PAREN ) + return true; + } + return false; + } + + Rule Comment() { + Var<Integer> n = new Var<Integer>(); + return Sequence( + "--[", + ZeroOrMore('='), + setN(n), + '[', + ZeroOrMore( + TestNot(CommentEnd(n)), + ANY + ), + CommentEnd(n) + ); + } + + Rule CommentEnd(Var<Integer> n) { + return Sequence( ']', ZeroOrMore('='), eqN(n), ']' ); + } + + boolean setN(Var<Integer> n) { + return n.set(matchLength()); + } + + boolean eqN(Var<Integer> n) { + return n.get()==matchLength(); } // for debugging - boolean print(String s) { - System.out.println(s); + boolean print(Object o) { + System.out.println(o); return true; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/interp/RepeatStmt.java Mon Nov 26 10:18:46 2012 +0000 @@ -0,0 +1,22 @@ +package luan.interp; + +import luan.Lua; +import luan.LuaState; +import luan.LuaException; + + +final class RepeatStmt implements Stmt { + private final Stmt doStmt; + private final Expr cnd; + + RepeatStmt(Stmt doStmt,Expr cnd) { + this.doStmt = doStmt; + this.cnd = cnd; + } + + @Override public void eval(LuaState lua) throws LuaException { + do { + doStmt.eval(lua); + } while( !Lua.toBoolean( cnd.eval(lua) ) ); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/interp/WhileStmt.java Mon Nov 26 10:18:46 2012 +0000 @@ -0,0 +1,22 @@ +package luan.interp; + +import luan.Lua; +import luan.LuaState; +import luan.LuaException; + + +final class WhileStmt implements Stmt { + private final Expr cnd; + private final Stmt doStmt; + + WhileStmt(Expr cnd,Stmt doStmt) { + this.cnd = cnd; + this.doStmt = doStmt; + } + + @Override public void eval(LuaState lua) throws LuaException { + while( Lua.toBoolean( cnd.eval(lua) ) ) { + doStmt.eval(lua); + } + } +}
--- a/src/luan/lib/BasicLib.java Fri Nov 23 13:04:03 2012 +0000 +++ b/src/luan/lib/BasicLib.java Mon Nov 26 10:18:46 2012 +0000 @@ -50,6 +50,7 @@ public static LuaFunction load(String ld) throws LuaException { LuaParser parser = Parboiled.createParser(LuaParser.class); ParsingResult<?> result = new ReportingParseRunner(parser.Target()).run(ld); +// ParsingResult<?> result = new TracingParseRunner(parser.Target()).run(ld); if( result.hasErrors() ) throw new LuaException( ErrorUtils.printParseErrors(result) ); Object resultValue = result.resultValue;