Mercurial Hosting > luan
changeset 129:486a0641bca4
add pickle client/server;
fix parser bugs;
git-svn-id: https://luan-java.googlecode.com/svn/trunk@130 21e917c8-12df-6dd8-5cb6-c86387c605b9
author | fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9> |
---|---|
date | Mon, 09 Jun 2014 09:16:16 +0000 |
parents | f0a4abe58593 |
children | 0594c132888b |
files | src/luan/LuanJavaFunction.java src/luan/interp/LuanParser.java src/luan/lib/IoLib.java src/luan/lib/PickleClient.java src/luan/lib/PickleCon.java src/luan/lib/PickleServer.java src/luan/tools/CmdLine.java |
diffstat | 7 files changed, 530 insertions(+), 249 deletions(-) [+] |
line wrap: on
line diff
--- a/src/luan/LuanJavaFunction.java Sun Jun 08 03:38:25 2014 +0000 +++ b/src/luan/LuanJavaFunction.java Mon Jun 09 09:16:16 2014 +0000 @@ -69,7 +69,7 @@ try { rtn = method.invoke(obj,args); } catch(IllegalAccessException e) { - throw new RuntimeException(e); + throw new RuntimeException("method = "+method,e); } catch(InvocationTargetException e) { Throwable cause = e.getCause(); if( cause instanceof Error )
--- a/src/luan/interp/LuanParser.java Sun Jun 08 03:38:25 2014 +0000 +++ b/src/luan/interp/LuanParser.java Mon Jun 09 09:16:16 2014 +0000 @@ -72,6 +72,26 @@ } } + private static class In { + static final In NOTHING = new In(false,false); + + final boolean parens; + final boolean jsp; + + private In(boolean parens,boolean jsp) { + this.parens = parens; + this.jsp = jsp; + } + + In parens() { + return parens ? this : new In(true,jsp); + } + + In jsp() { + return jsp ? this : new In(parens,true); + } + } + private static final String _ENV = "_ENV"; private static final UpValue.Getter[] NO_UP_VALUE_GETTERS = new UpValue.Getter[0]; @@ -161,9 +181,9 @@ } FnDef Expressions() throws ParseException { - Spaces(); + Spaces(In.NOTHING); int start = parser.begin(); - Expressions exprs = ExpList(); + Expressions exprs = ExpList(In.NOTHING); if( exprs != null && parser.endOfInput() ) { Stmt stmt = new ReturnStmt( se(start), exprs ); return parser.success(newFnDef(start,stmt)); @@ -172,7 +192,7 @@ } FnDef RequiredModule() throws ParseException { - Spaces(); + Spaces(In.NOTHING); int start = parser.begin(); frame.isVarArg = true; Stmt stmt = RequiredBlock(); @@ -186,7 +206,7 @@ int stackStart = symbolsSize(); Stmt(stmts); while( StmtSep(stmts) ) { - Spaces(); + Spaces(In.NOTHING); Stmt(stmts); } int stackEnd = symbolsSize(); @@ -235,19 +255,22 @@ } } - private Expressions JspExpressions() throws ParseException { + private Expressions JspExpressions(In in) throws ParseException { + if( in.jsp ) + return null; int start = parser.begin(); if( !parser.match( "%>" ) ) return parser.failure(null); EndOfLine(); + In inJsp = in.jsp(); ExpList.Builder builder = new ExpList.Builder(); while(true) { if( parser.match( "<%=" ) ) { - Spaces(); - builder.add( RequiredExpr() ); + Spaces(inJsp); + builder.add( RequiredExpr(inJsp) ); RequiredMatch( "%>" ); } else if( parser.match( "<%" ) ) { - Spaces(); + Spaces(inJsp); return parser.success(builder.build()); } else { int i = parser.currentIndex(); @@ -265,9 +288,9 @@ private Stmt ReturnStmt() throws ParseException { int start = parser.begin(); - if( !Keyword("return") ) + if( !Keyword("return",In.NOTHING) ) return parser.failure(null); - Expressions exprs = ExpList(); + Expressions exprs = ExpList(In.NOTHING); if( exprs==null ) exprs = ExpList.emptyExpList; return parser.success( new ReturnStmt(se(start),exprs) ); @@ -275,37 +298,37 @@ private Stmt FunctionStmt() throws ParseException { parser.begin(); - if( !Keyword("function") ) + if( !Keyword("function",In.NOTHING) ) return parser.failure(null); int start = parser.currentIndex(); - Var var = nameVar(start,RequiredName()); + Var var = nameVar(start,RequiredName(In.NOTHING)); while( parser.match( '.' ) ) { - Spaces(); - var = indexVar( start, expr(var.expr()), NameExpr(false) ); + Spaces(In.NOTHING); + var = indexVar( start, expr(var.expr()), NameExpr(In.NOTHING) ); } Settable fnName = var.settable(); - FnDef fnDef = RequiredFunction(false); + FnDef fnDef = RequiredFunction(In.NOTHING); return parser.success( new SetStmt(fnName,fnDef) ); } private Stmt LocalFunctionStmt() throws ParseException { parser.begin(); - if( !(Keyword("local") && Keyword("function")) ) + if( !(Keyword("local",In.NOTHING) && Keyword("function",In.NOTHING)) ) return parser.failure(null); - String name = RequiredName(); + String name = RequiredName(In.NOTHING); addSymbol( name ); - FnDef fnDef = RequiredFunction(false); + FnDef fnDef = RequiredFunction(In.NOTHING); return parser.success( new SetStmt( new SetLocalVar(symbolsSize()-1), fnDef ) ); } private Stmt ImportStmt() throws ParseException { int start = parser.begin(); - if( !Keyword("import") ) + if( !Keyword("import",In.NOTHING) ) return parser.failure(null); Expr importExpr = (Expr)nameVar(start,"require").expr(); - String modName = StringLiteral(false); + String modName = StringLiteral(In.NOTHING); if( modName==null ) return parser.failure(null); String varName = modName.substring(modName.lastIndexOf('.')+1); @@ -323,7 +346,7 @@ private Stmt BreakStmt() throws ParseException { parser.begin(); - if( !Keyword("break") ) + if( !Keyword("break",In.NOTHING) ) return parser.failure(null); if( frame.loops <= 0 ) throw parser.exception("'break' outside of loop"); @@ -333,16 +356,16 @@ private Stmt ForStmt() throws ParseException { int start = parser.begin(); int stackStart = symbolsSize(); - if( !Keyword("for") ) + if( !Keyword("for",In.NOTHING) ) return parser.failure(null); - List<String> names = RequiredNameList(false); - if( !Keyword("in") ) + List<String> names = RequiredNameList(In.NOTHING); + if( !Keyword("in",In.NOTHING) ) return parser.failure(null); - Expr expr = expr(RequiredExpr()); - RequiredKeyword("do"); + Expr expr = expr(RequiredExpr(In.NOTHING)); + RequiredKeyword("do",In.NOTHING); addSymbols(names); Stmt loop = RequiredLoopBlock(); - RequiredKeyword("end"); + RequiredKeyword("end",In.NOTHING); Stmt stmt = new ForStmt( se(start), stackStart, symbolsSize() - stackStart, expr, loop ); popSymbols( symbolsSize() - stackStart ); return parser.success(stmt); @@ -350,15 +373,15 @@ private Stmt TryStmt() throws ParseException { parser.begin(); - if( !Keyword("try") ) + if( !Keyword("try",In.NOTHING) ) return parser.failure(null); Stmt tryBlock = RequiredBlock(); - RequiredKeyword("catch"); - String name = RequiredName(); + RequiredKeyword("catch",In.NOTHING); + String name = RequiredName(In.NOTHING); addSymbol(name); - RequiredKeyword("do"); + RequiredKeyword("do",In.NOTHING); Stmt catchBlock = RequiredBlock(); - RequiredKeyword("end"); + RequiredKeyword("end",In.NOTHING); Stmt stmt = new TryStmt( tryBlock, symbolsSize()-1, catchBlock ); popSymbols(1); return parser.success(stmt); @@ -366,23 +389,23 @@ private Stmt DoStmt() throws ParseException { parser.begin(); - if( !Keyword("do") ) + if( !Keyword("do",In.NOTHING) ) return parser.failure(null); Stmt stmt = RequiredBlock(); - RequiredKeyword("end"); + RequiredKeyword("end",In.NOTHING); return parser.success(stmt); } private boolean LocalStmt(List<Stmt> stmts) throws ParseException { parser.begin(); - if( !Keyword("local") ) + if( !Keyword("local",In.NOTHING) ) return parser.failure(); - List<String> names = NameList(false); + List<String> names = NameList(In.NOTHING); if( names==null ) return parser.failure(); if( parser.match( '=' ) ) { - Spaces(); - Expressions values = ExpList(); + Spaces(In.NOTHING); + Expressions values = ExpList(In.NOTHING); if( values==null ) throw parser.exception("Expressions expected"); SetLocalVar[] vars = new SetLocalVar[names.size()]; @@ -396,45 +419,45 @@ return parser.success(); } - private List<String> RequiredNameList(boolean inParens) throws ParseException { + private List<String> RequiredNameList(In in) throws ParseException { parser.begin(); - List<String> names = NameList(inParens); + List<String> names = NameList(in); if( names==null ) parser.exception("Name expected"); return parser.success(names); } - private List<String> NameList(boolean inParens) throws ParseException { - String name = Name(inParens); + private List<String> NameList(In in) throws ParseException { + String name = Name(in); if( name==null ) return null; List<String> names = new ArrayList<String>(); names.add(name); while( parser.match( ',' ) ) { - Spaces(inParens); - names.add( RequiredName() ); + Spaces(in); + names.add( RequiredName(in) ); } return names; } private Stmt WhileStmt() throws ParseException { parser.begin(); - if( !Keyword("while") ) + if( !Keyword("while",In.NOTHING) ) return parser.failure(null); - Expr cnd = expr(RequiredExpr()); - RequiredKeyword("do"); + Expr cnd = expr(RequiredExpr(In.NOTHING)); + RequiredKeyword("do",In.NOTHING); Stmt loop = RequiredLoopBlock(); - RequiredKeyword("end"); + RequiredKeyword("end",In.NOTHING); return parser.success( new WhileStmt(cnd,loop) ); } private Stmt RepeatStmt() throws ParseException { parser.begin(); - if( !Keyword("repeat") ) + if( !Keyword("repeat",In.NOTHING) ) return parser.failure(null); Stmt loop = RequiredLoopBlock(); - RequiredKeyword("until"); - Expr cnd = expr(RequiredExpr()); + RequiredKeyword("until",In.NOTHING); + Expr cnd = expr(RequiredExpr(In.NOTHING)); return parser.success( new RepeatStmt(loop,cnd) ); } @@ -447,21 +470,21 @@ private Stmt IfStmt() throws ParseException { parser.begin(); - if( !Keyword("if") ) + if( !Keyword("if",In.NOTHING) ) return parser.failure(null); return parser.success( IfStmt2() ); } private Stmt IfStmt2() throws ParseException { - Expr cnd = expr(RequiredExpr()); - RequiredKeyword("then"); + Expr cnd = expr(RequiredExpr(In.NOTHING)); + RequiredKeyword("then",In.NOTHING); Stmt thenBlock = RequiredBlock(); Stmt elseBlock; - if( Keyword("elseif") ) { + if( Keyword("elseif",In.NOTHING) ) { elseBlock = IfStmt2(); } else { - elseBlock = Keyword("else") ? RequiredBlock() : Stmt.EMPTY; - RequiredKeyword("end"); + elseBlock = Keyword("else",In.NOTHING) ? RequiredBlock() : Stmt.EMPTY; + RequiredKeyword("end",In.NOTHING); } return new IfStmt(cnd,thenBlock,elseBlock); } @@ -474,7 +497,7 @@ return parser.failure(null); vars.add(s); while( parser.match( ',' ) ) { - Spaces(); + Spaces(In.NOTHING); s = SettableVar(); if( s == null ) return parser.failure(null); @@ -482,8 +505,8 @@ } if( !parser.match( '=' ) ) return parser.failure(null); - Spaces(); - Expressions values = ExpList(); + Spaces(In.NOTHING); + Expressions values = ExpList(In.NOTHING); if( values==null ) throw parser.exception("Expressions expected"); return parser.success( new SetStmt( vars.toArray(new Settable[0]), values ) ); @@ -491,7 +514,7 @@ private Stmt ExpressionsStmt() throws ParseException { parser.begin(); - Expressions exprs = ExpList(); + Expressions exprs = ExpList(In.NOTHING); if( exprs==null ) return parser.failure(null); return parser.success( new ExpressionsStmt(exprs) ); @@ -499,112 +522,104 @@ private Settable SettableVar() throws ParseException { int start = parser.begin(); - Var var = VarZ(false); + Var var = VarZ(In.NOTHING); if( var==null ) return null; return var.settable(); } - private Code RequiredExpr() throws ParseException { - return RequiredExpr(false); - } - - private Code Expr() throws ParseException { - return Expr(false); + private Code RequiredExpr(In in) throws ParseException { + parser.begin(); + return parser.success(required(Expr(in),"Bad expression")); } - private Code RequiredExpr(boolean inParens) throws ParseException { - parser.begin(); - return parser.success(required(Expr(inParens),"Bad expression")); - } - - private Code Expr(boolean inParens) throws ParseException { + private Code Expr(In in) throws ParseException { parser.begin(); Code exp; - return (exp = VarArgs(inParens)) != null - || (exp = JspExpressions()) != null - || (exp = OrExpr(inParens)) != null + return (exp = VarArgs(in)) != null + || (exp = JspExpressions(in)) != null + || (exp = OrExpr(in)) != null ? parser.success(exp) : parser.failure((Code)null) ; } - private Code OrExpr(boolean inParens) throws ParseException { + private Code OrExpr(In in) throws ParseException { int start = parser.begin(); - Code exp = AndExpr(inParens); + Code exp = AndExpr(in); if( exp==null ) return parser.failure(null); - while( Keyword("or",inParens) ) { - exp = new OrExpr( se(start), expr(exp), required(expr(AndExpr(inParens))) ); + while( Keyword("or",in) ) { + exp = new OrExpr( se(start), expr(exp), required(expr(AndExpr(in))) ); } return parser.success(exp); } - private Code AndExpr(boolean inParens) throws ParseException { + private Code AndExpr(In in) throws ParseException { int start = parser.begin(); - Code exp = RelExpr(inParens); + Code exp = RelExpr(in); if( exp==null ) return parser.failure(null); - while( Keyword("and",inParens) ) { - exp = new AndExpr( se(start), expr(exp), required(expr(RelExpr(inParens))) ); + while( Keyword("and",in) ) { + exp = new AndExpr( se(start), expr(exp), required(expr(RelExpr(in))) ); } return parser.success(exp); } - private Code RelExpr(boolean inParens) throws ParseException { + private Code RelExpr(In in) throws ParseException { int start = parser.begin(); - Code exp = ConcatExpr(inParens); + Code exp = ConcatExpr(in); if( exp==null ) return parser.failure(null); while(true) { if( parser.match("==") ) { - Spaces(inParens); - exp = new EqExpr( se(start), expr(exp), required(expr(ConcatExpr(inParens))) ); + Spaces(in); + exp = new EqExpr( se(start), expr(exp), required(expr(ConcatExpr(in))) ); } else if( parser.match("~=") ) { - Spaces(inParens); - exp = new NotExpr( se(start), new EqExpr( se(start), expr(exp), required(expr(ConcatExpr(inParens))) ) ); + Spaces(in); + exp = new NotExpr( se(start), new EqExpr( se(start), expr(exp), required(expr(ConcatExpr(in))) ) ); } else if( parser.match("<=") ) { - Spaces(inParens); - exp = new LeExpr( se(start), expr(exp), required(expr(ConcatExpr(inParens))) ); + Spaces(in); + exp = new LeExpr( se(start), expr(exp), required(expr(ConcatExpr(in))) ); } else if( parser.match(">=") ) { - Spaces(inParens); - exp = new LeExpr( se(start), required(expr(ConcatExpr(inParens))), expr(exp) ); + Spaces(in); + exp = new LeExpr( se(start), required(expr(ConcatExpr(in))), expr(exp) ); } else if( parser.match("<") ) { - Spaces(inParens); - exp = new LtExpr( se(start), expr(exp), required(expr(ConcatExpr(inParens))) ); + Spaces(in); + exp = new LtExpr( se(start), expr(exp), required(expr(ConcatExpr(in))) ); } else if( parser.match(">") ) { - Spaces(inParens); - exp = new LtExpr( se(start), required(expr(ConcatExpr(inParens))), expr(exp) ); + Spaces(in); + exp = new LtExpr( se(start), required(expr(ConcatExpr(in))), expr(exp) ); } else break; } return parser.success(exp); } - private Code ConcatExpr(boolean inParens) throws ParseException { + private Code ConcatExpr(In in) throws ParseException { int start = parser.begin(); - Code exp = SumExpr(inParens); + Code exp = SumExpr(in); if( exp==null ) return parser.failure(null); if( parser.match("..") ) { - Spaces(inParens); - exp = new ConcatExpr( se(start), expr(exp), required(expr(ConcatExpr(inParens))) ); + Spaces(in); + exp = new ConcatExpr( se(start), expr(exp), required(expr(ConcatExpr(in))) ); } return parser.success(exp); } - private Code SumExpr(boolean inParens) throws ParseException { + private Code SumExpr(In in) throws ParseException { int start = parser.begin(); - Code exp = TermExpr(inParens); + Code exp = TermExpr(in); if( exp==null ) return parser.failure(null); while(true) { if( parser.match('+') ) { - Spaces(inParens); - exp = new AddExpr( se(start), expr(exp), required(expr(TermExpr(inParens))) ); + Spaces(in); + exp = new AddExpr( se(start), expr(exp), required(expr(TermExpr(in))) ); } else if( Minus() ) { - Spaces(inParens); - exp = new SubExpr( se(start), expr(exp), required(expr(TermExpr(inParens))) ); + Spaces(in); + exp = new SubExpr( se(start), expr(exp), required(expr(TermExpr(in))) ); } else break; } @@ -616,21 +631,21 @@ return parser.match('-') && !parser.match('-') ? parser.success() : parser.failure(); } - private Code TermExpr(boolean inParens) throws ParseException { + private Code TermExpr(In in) throws ParseException { int start = parser.begin(); - Code exp = UnaryExpr(inParens); + Code exp = UnaryExpr(in); if( exp==null ) return parser.failure(null); while(true) { if( parser.match('*') ) { - Spaces(inParens); - exp = new MulExpr( se(start), expr(exp), required(expr(UnaryExpr(inParens))) ); + Spaces(in); + exp = new MulExpr( se(start), expr(exp), required(expr(UnaryExpr(in))) ); } else if( parser.match('/') ) { - Spaces(inParens); - exp = new DivExpr( se(start), expr(exp), required(expr(UnaryExpr(inParens))) ); + Spaces(in); + exp = new DivExpr( se(start), expr(exp), required(expr(UnaryExpr(in))) ); } else if( Mod() ) { - Spaces(inParens); - exp = new ModExpr( se(start), expr(exp), required(expr(UnaryExpr(inParens))) ); + Spaces(in); + exp = new ModExpr( se(start), expr(exp), required(expr(UnaryExpr(in))) ); } else break; } @@ -642,128 +657,130 @@ return parser.match('%') && !parser.match('>') ? parser.success() : parser.failure(); } - private Code UnaryExpr(boolean inParens) throws ParseException { + private Code UnaryExpr(In in) throws ParseException { int start = parser.begin(); if( parser.match('#') ) { - Spaces(inParens); - return parser.success( new LenExpr( se(start), required(expr(UnaryExpr(inParens))) ) ); + Spaces(in); + return parser.success( new LenExpr( se(start), required(expr(UnaryExpr(in))) ) ); } if( Minus() ) { - Spaces(inParens); - return parser.success( new UnmExpr( se(start), required(expr(UnaryExpr(inParens))) ) ); + Spaces(in); + return parser.success( new UnmExpr( se(start), required(expr(UnaryExpr(in))) ) ); } - if( Keyword("not",inParens) ) { - Spaces(inParens); - return parser.success( new NotExpr( se(start), required(expr(UnaryExpr(inParens))) ) ); + if( Keyword("not",in) ) { + Spaces(in); + return parser.success( new NotExpr( se(start), required(expr(UnaryExpr(in))) ) ); } - Code exp = PowExpr(inParens); + Code exp = PowExpr(in); if( exp==null ) return parser.failure(null); return parser.success(exp); } - private Code PowExpr(boolean inParens) throws ParseException { + private Code PowExpr(In in) throws ParseException { int start = parser.begin(); - Code exp = SingleExpr(inParens); + Code exp = SingleExpr(in); if( exp==null ) return parser.failure(null); if( parser.match('^') ) { - Spaces(inParens); - exp = new ConcatExpr( se(start), expr(exp), required(expr(PowExpr(inParens))) ); + Spaces(in); + exp = new ConcatExpr( se(start), expr(exp), required(expr(PowExpr(in))) ); } return parser.success(exp); } - private Code SingleExpr(boolean inParens) throws ParseException { + private Code SingleExpr(In in) throws ParseException { parser.begin(); Code exp; - exp = FunctionExpr(inParens); + exp = FunctionExpr(in); if( exp != null ) return parser.success(exp); - exp = TableExpr(inParens); + exp = TableExpr(in); if( exp != null ) return parser.success(exp); - exp = VarExp(inParens); + exp = VarExp(in); if( exp != null ) return parser.success(exp); - exp = Literal(inParens); + exp = Literal(in); if( exp != null ) return parser.success(exp); return parser.failure(null); } - private Expr FunctionExpr(boolean inParens) throws ParseException { - if( !Keyword("function",inParens) ) + private Expr FunctionExpr(In in) throws ParseException { + if( !Keyword("function",in) ) return null; - return RequiredFunction(inParens); + return RequiredFunction(in); } - private FnDef RequiredFunction(boolean inParens) throws ParseException { + private FnDef RequiredFunction(In in) throws ParseException { int start = parser.begin(); RequiredMatch('('); - Spaces(true); + In inParens = in.parens(); + Spaces(inParens); frame = new Frame(frame); - List<String> names = NameList(false); + List<String> names = NameList(in); if( names != null ) { addSymbols(names); if( parser.match(',') ) { - Spaces(true); + Spaces(inParens); if( !parser.match("...") ) throw parser.exception(); frame.isVarArg = true; } } else if( parser.match("...") ) { - Spaces(true); + Spaces(inParens); frame.isVarArg = true; } RequiredMatch(')'); - Spaces(inParens); + Spaces(in); Stmt block = RequiredBlock(); - RequiredKeyword("end",inParens); + RequiredKeyword("end",in); FnDef fnDef = newFnDef(start,block); frame = frame.parent; return parser.success(fnDef); } - private VarArgs VarArgs(boolean inParens) throws ParseException { + private VarArgs VarArgs(In in) throws ParseException { int start = parser.begin(); if( !frame.isVarArg || !parser.match("...") ) return parser.failure(null); - Spaces(inParens); + Spaces(in); return parser.success( new VarArgs(se(start)) ); } - private Expr TableExpr(boolean inParens) throws ParseException { + private Expr TableExpr(In in) throws ParseException { int start = parser.begin(); if( !parser.match('{') ) return parser.failure(null); - Spaces(true); + In inParens = in.parens(); + Spaces(inParens); List<TableExpr.Field> fields = new ArrayList<TableExpr.Field>(); ExpList.Builder builder = new ExpList.Builder(); - while( Field(fields,builder) && FieldSep() ); + while( Field(fields,builder,in) && FieldSep(inParens) ); if( !parser.match('}') ) throw parser.exception("Expected table element or '}'"); return parser.success( new TableExpr( se(start), fields.toArray(new TableExpr.Field[0]), builder.build() ) ); } - private boolean FieldSep() throws ParseException { + private boolean FieldSep(In in) throws ParseException { if( !parser.anyOf(",;") ) return false; - Spaces(true); + Spaces(in); return true; } - private boolean Field(List<TableExpr.Field> fields,ExpList.Builder builder) throws ParseException { + private boolean Field(List<TableExpr.Field> fields,ExpList.Builder builder,In in) throws ParseException { parser.begin(); - Expr exp = SubExpr(true); + Expr exp = SubExpr(in); if( exp==null ) - exp = NameExpr(true); + exp = NameExpr(in); if( exp!=null && parser.match('=') ) { - fields.add( new TableExpr.Field( exp, required(expr(Expr(true))) ) ); + fields.add( new TableExpr.Field( exp, required(expr(Expr(in))) ) ); return parser.success(); } parser.rollback(); - Code code = Expr(true); + Code code = Expr(in); if( code != null ) { builder.add(code); return parser.success(); @@ -771,75 +788,76 @@ return parser.failure(); } - private Code VarExp(boolean inParens) throws ParseException { - Var var = VarZ(inParens); + private Code VarExp(In in) throws ParseException { + Var var = VarZ(in); return var==null ? null : var.expr(); } - private Var VarZ(boolean inParens) throws ParseException { + private Var VarZ(In in) throws ParseException { int start = parser.begin(); - Var var = VarStart(inParens); + Var var = VarStart(in); if( var==null ) return parser.failure(null); Var var2; - while( (var2=Var2(inParens,start,var.expr())) != null ) { + while( (var2=Var2(in,start,var.expr())) != null ) { var = var2; } return parser.success(var); } - private Var Var2(boolean inParens,int start,Code exp1) throws ParseException { - Var var = VarExt(inParens,start,exp1); + private Var Var2(In in,int start,Code exp1) throws ParseException { + Var var = VarExt(in,start,exp1); if( var != null ) return var; if( parser.match("->") ) { - Spaces(inParens); + Spaces(in); ExpList.Builder builder = new ExpList.Builder(); builder.add(exp1); - Expr exp2 = expr(RequiredVarExpB(inParens)); - FnCall fnCall = required(Args( inParens, start, exp2, builder )); + Expr exp2 = expr(RequiredVarExpB(in)); + FnCall fnCall = required(Args( in, start, exp2, builder )); return exprVar(fnCall); } - FnCall fnCall = Args( inParens, start, expr(exp1), new ExpList.Builder() ); + FnCall fnCall = Args( in, start, expr(exp1), new ExpList.Builder() ); if( fnCall != null ) return exprVar(fnCall); return null; } - private Code RequiredVarExpB(boolean inParens) throws ParseException { + private Code RequiredVarExpB(In in) throws ParseException { int start = parser.begin(); - Var var = required(VarStart(inParens)); + Var var = required(VarStart(in)); Var var2; - while( (var2=VarExt(inParens,start,var.expr())) != null ) { + while( (var2=VarExt(in,start,var.expr())) != null ) { var = var2; } return parser.success(var.expr()); } - private Var VarExt(boolean inParens,int start,Code exp1) throws ParseException { + private Var VarExt(In in,int start,Code exp1) throws ParseException { parser.begin(); - Expr exp2 = SubExpr(inParens); + Expr exp2 = SubExpr(in); if( exp2 != null ) return parser.success(indexVar(start,expr(exp1),exp2)); if( parser.match('.') ) { - Spaces(inParens); - exp2 = NameExpr(inParens); + Spaces(in); + exp2 = NameExpr(in); if( exp2!=null ) return parser.success(indexVar(start,expr(exp1),exp2)); } return parser.failure(null); } - private Var VarStart(boolean inParens) throws ParseException { + private Var VarStart(In in) throws ParseException { int start = parser.begin(); if( parser.match('(') ) { - Spaces(true); - Expr exp = expr(Expr(true)); + In inParens = in.parens(); + Spaces(inParens); + Expr exp = expr(Expr(inParens)); RequiredMatch(')'); - Spaces(inParens); + Spaces(in); return parser.success(exprVar(exp)); } - String name = Name(inParens); + String name = Name(in); if( name != null ) return parser.success(nameVar(start,name)); return parser.failure(null); @@ -911,33 +929,34 @@ }; } - private FnCall Args(boolean inParens,int start,Expr fn,ExpList.Builder builder) throws ParseException { + private FnCall Args(In in,int start,Expr fn,ExpList.Builder builder) throws ParseException { parser.begin(); - return args(inParens,builder) + return args(in,builder) ? parser.success( new FnCall( se(start), fn, builder.build() ) ) : parser.failure((FnCall)null); } - private boolean args(boolean inParens,ExpList.Builder builder) throws ParseException { + private boolean args(In in,ExpList.Builder builder) throws ParseException { if( parser.match('(') ) { - Spaces(true); - ExpList(true,builder); // optional + In inParens = in.parens(); + Spaces(inParens); + ExpList(inParens,builder); // optional if( !parser.match(')') ) throw parser.exception("Expression or ')' expected"); - Spaces(inParens); + Spaces(in); return true; } - Expr exp = TableExpr(inParens); + Expr exp = TableExpr(in); if( exp != null ) { builder.add(exp); return true; } - String s = StringLiteral(inParens); + String s = StringLiteral(in); if( s != null ) { builder.add( new ConstExpr(s) ); return true; } - Expressions exps = JspExpressions(); + Expressions exps = JspExpressions(in); if( exps != null ) { builder.add(exps); return true; @@ -945,57 +964,50 @@ return false; } - private Expressions ExpList() throws ParseException { - return ExpList(false); + private Expressions ExpList(In in) throws ParseException { + ExpList.Builder builder = new ExpList.Builder(); + return ExpList(in,builder) ? builder.build() : null; } - private Expressions ExpList(boolean inParens) throws ParseException { - ExpList.Builder builder = new ExpList.Builder(); - return ExpList(inParens,builder) ? builder.build() : null; - } - - private boolean ExpList(boolean inParens,ExpList.Builder builder) throws ParseException { + private boolean ExpList(In in,ExpList.Builder builder) throws ParseException { parser.begin(); - Code exp = Expr(inParens); + Code exp = Expr(in); if( exp==null ) return parser.failure(); builder.add(exp); while( parser.match(',') ) { - Spaces(inParens); - builder.add( RequiredExpr(inParens) ); + Spaces(in); + builder.add( RequiredExpr(in) ); } return parser.success(); } - private Expr SubExpr(boolean inParens) throws ParseException { + private Expr SubExpr(In in) throws ParseException { parser.begin(); if( !parser.match('[') ) return parser.failure(null); - Spaces(true); - Expr exp = expr(RequiredExpr(true)); + In inParens = in.parens(); + Spaces(inParens); + Expr exp = expr(RequiredExpr(inParens)); RequiredMatch(']'); - Spaces(inParens); + Spaces(in); return parser.success(exp); } - private Expr NameExpr(boolean inParens) throws ParseException { - String name = Name(inParens); + private Expr NameExpr(In in) throws ParseException { + String name = Name(in); return name==null ? null : new ConstExpr(name); } - private String RequiredName() throws ParseException { + private String RequiredName(In in) throws ParseException { parser.begin(); - String name = Name(); + String name = Name(in); if( name==null ) parser.exception("Name expected"); return parser.success(name); } - private String Name() throws ParseException { - return Name(false); - } - - private String Name(boolean inParens) throws ParseException { + private String Name(In in) throws ParseException { int start = parser.begin(); if( !NameFirstChar() ) return parser.failure(null); @@ -1003,7 +1015,7 @@ String match = parser.textFrom(start); if( keywords.contains(match) ) return parser.failure(null); - Spaces(inParens); + Spaces(in); return parser.success(match); } @@ -1025,24 +1037,16 @@ throw parser.exception("'"+s+"' expected"); } - private void RequiredKeyword(String keyword) throws ParseException { - RequiredKeyword(keyword,false); - } - - private boolean Keyword(String keyword) throws ParseException { - return Keyword(keyword,false); - } - - private void RequiredKeyword(String keyword,boolean inParens) throws ParseException { - if( !Keyword(keyword,inParens) ) + private void RequiredKeyword(String keyword,In in) throws ParseException { + if( !Keyword(keyword,in) ) throw parser.exception("'"+keyword+"' expected"); } - private boolean Keyword(String keyword,boolean inParens) throws ParseException { + private boolean Keyword(String keyword,In in) throws ParseException { parser.begin(); if( !parser.match(keyword) || NameChar() ) return parser.failure(); - Spaces(inParens); + Spaces(in); return parser.success(); } @@ -1074,34 +1078,34 @@ "while" )); - private Expr Literal(boolean inParens) throws ParseException { - if( NilLiteral(inParens) ) + private Expr Literal(In in) throws ParseException { + if( NilLiteral(in) ) return new ConstExpr(null); - Boolean b = BooleanLiteral(inParens); + Boolean b = BooleanLiteral(in); if( b != null ) return new ConstExpr(b); - Number n = NumberLiteral(inParens); + Number n = NumberLiteral(in); if( n != null ) return new ConstExpr(n); - String s = StringLiteral(inParens); + String s = StringLiteral(in); if( s != null ) return new ConstExpr(s); return null; } - private boolean NilLiteral(boolean inParens) throws ParseException { - return Keyword("nil",inParens); + private boolean NilLiteral(In in) throws ParseException { + return Keyword("nil",in); } - private Boolean BooleanLiteral(boolean inParens) throws ParseException { - if( Keyword("true",inParens) ) + private Boolean BooleanLiteral(In in) throws ParseException { + if( Keyword("true",in) ) return true; - if( Keyword("false",inParens) ) + if( Keyword("false",in) ) return false; return null; } - private Number NumberLiteral(boolean inParens) throws ParseException { + private Number NumberLiteral(In in) throws ParseException { parser.begin(); Number n; if( parser.matchIgnoreCase("0x") ) { @@ -1111,7 +1115,7 @@ } if( n==null || NameChar() ) return parser.failure(null); - Spaces(inParens); + Spaces(in); return parser.success(n); } @@ -1189,14 +1193,14 @@ return Digit() || parser.anyOf("abcdefABCDEF"); } - private String StringLiteral(boolean inParens) throws ParseException { + private String StringLiteral(In in) throws ParseException { String s; if( (s=QuotedString('"'))==null && (s=QuotedString('\''))==null && (s=LongString())==null ) return null; - Spaces(inParens); + Spaces(in); return s; } @@ -1261,12 +1265,8 @@ return parser.failure(null); } - private void Spaces() throws ParseException { - Spaces(false); - } - - private void Spaces(boolean inParens) throws ParseException { - while( parser.anyOf(" \t") || Comment() || ContinueOnNextLine() || inParens && NewLine() ); + private void Spaces(In in) throws ParseException { + while( parser.anyOf(" \t") || Comment() || ContinueOnNextLine() || in.parens && NewLine() ); } private boolean ContinueOnNextLine() {
--- a/src/luan/lib/IoLib.java Sun Jun 08 03:38:25 2014 +0000 +++ b/src/luan/lib/IoLib.java Mon Jun 09 09:16:16 2014 +0000 @@ -9,6 +9,7 @@ import java.io.FileWriter; import java.io.BufferedReader; import java.io.BufferedWriter; +import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; @@ -16,6 +17,8 @@ import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; import java.io.IOException; import java.net.URL; import java.net.Socket; @@ -300,7 +303,7 @@ return binaryWriter(new BufferedOutputStream(outputStream())); } - LuanTable table() { + @Override LuanTable table() { LuanTable tbl = super.table(); try { tbl.put( "write", new LuanJavaFunction( @@ -373,6 +376,33 @@ OutputStream outputStream() throws IOException { return socket.getOutputStream(); } + + public LuanTable pickle_client(LuanState luan) throws IOException { + DataInputStream in = new DataInputStream(new BufferedInputStream(inputStream())); + DataOutputStream out = new DataOutputStream(new BufferedOutputStream(outputStream())); + return new PickleClient(luan,in,out).table(); + } + + public void run_pickle_server(LuanState luan) throws IOException { + DataInputStream in = new DataInputStream(new BufferedInputStream(inputStream())); + DataOutputStream out = new DataOutputStream(new BufferedOutputStream(outputStream())); + new PickleServer(luan,in,out).run(); + } + + @Override LuanTable table() { + LuanTable tbl = super.table(); + try { + tbl.put( "pickle_client", new LuanJavaFunction( + LuanSocket.class.getMethod( "pickle_client", LuanState.class ), this + ) ); + tbl.put( "run_pickle_server", new LuanJavaFunction( + LuanSocket.class.getMethod( "run_pickle_server", LuanState.class ), this + ) ); + } catch(NoSuchMethodException e) { + throw new RuntimeException(e); + } + return tbl; + } } public static LuanTable socket(String host,int port) throws IOException {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/lib/PickleClient.java Mon Jun 09 09:16:16 2014 +0000 @@ -0,0 +1,60 @@ +package luan.lib; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import luan.Luan; +import luan.LuanState; +import luan.LuanException; +import luan.LuanTable; +import luan.LuanJavaFunction; + + +public final class PickleClient { + + private final PickleCon con; + + PickleClient(LuanState luan,DataInputStream in,DataOutputStream out) { + con = new PickleCon(luan,in,out); + } + + public Object call(Object... args) throws LuanException, IOException { + con.write(args); + Object[] result = Luan.array(con.read()); + boolean ok = (boolean)result[0]; + if( ok ) { + Object[] rtn = new Object[result.length-1]; + System.arraycopy(result,1,rtn,0,rtn.length); + return rtn; + } else { + String msg = (String)result[1]; + String src = (String)result[2]; + throw con.luan.JAVA.exception( + msg + "\n" + + "in:\n" + + "------------------\n" + + src + "\n" + + "------------------\n" + ); + } + } + + LuanTable table() { + LuanTable tbl = new LuanTable(); + try { + tbl.put( "pickle", new LuanJavaFunction( + PickleCon.class.getMethod( "pickle", Object.class ), con + ) ); + tbl.put( "call", new LuanJavaFunction( + PickleClient.class.getMethod( "call", new Object[0].getClass() ), this + ) ); + tbl.put( "close", new LuanJavaFunction( + PickleCon.class.getMethod( "close" ), con + ) ); + } catch(NoSuchMethodException e) { + throw new RuntimeException(e); + } + return tbl; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/lib/PickleCon.java Mon Jun 09 09:16:16 2014 +0000 @@ -0,0 +1,128 @@ +package luan.lib; + +import java.io.OutputStream; +import java.io.BufferedOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.Set; +import java.util.IdentityHashMap; +import java.util.Collections; +import java.util.Map; +import java.util.List; +import java.util.ArrayList; +import luan.Luan; +import luan.LuanTable; +import luan.LuanState; +import luan.LuanFunction; +import luan.LuanJavaFunction; +import luan.LuanException; + + +public final class PickleCon { + final LuanState luan; + private final DataInputStream in; + private final LuanFunction _read_binary; + private final LuanTable ioModule; + private final DataOutputStream out; + private final List<byte[]> binaries = new ArrayList<byte[]>(); + String src; + + PickleCon(LuanState luan,DataInputStream in,DataOutputStream out) { + this.in = in; + this.luan = luan; + try { + this._read_binary = new LuanJavaFunction( + PickleCon.class.getMethod( "_read_binary", Integer.TYPE ), this + ); + } catch(NoSuchMethodException e) { + throw new RuntimeException(e); + } + this.ioModule = (LuanTable)luan.loaded().get("Io"); + + this.out = out; + } + + public byte[] _read_binary(int size) throws IOException, LuanException { + byte[] a = new byte[size]; + int i = 0; + while( i < size ) { + int n = in.read(a,i,size-i); + if( n == -1 ) + throw luan.JAVA.exception( "end of stream" ); + i += n; + } + return a; + } + + public Object read() throws IOException, LuanException { + ioModule.put("_read_binary",_read_binary); + src = in.readUTF(); + LuanFunction fn = BasicLib.load(luan,src,"pickle-reader",true,false); + Object rtn = luan.JAVA.call(fn,null); + ioModule.put("_binaries",null); + return rtn; + } + + public String pickle(Object obj) throws LuanException { + if( obj == null ) + return "nil"; + if( obj instanceof Number ) + return Luan.toString((Number)obj); + if( obj instanceof String ) + return "\"" + Luan.stringEncode((String)obj) + "\""; + if( obj instanceof LuanTable ) + return pickle( (LuanTable)obj, Collections.newSetFromMap(new IdentityHashMap<LuanTable,Boolean>()) ); + if( obj instanceof byte[] ) { + byte[] a = (byte[])obj; + binaries.add(a); + return "Io._binaries[" + binaries.size() + "]"; + } + throw luan.JAVA.exception( "invalid type: " + obj.getClass() ); + } + + private String pickle(Object obj,Set<LuanTable> set) throws LuanException { + return obj instanceof LuanTable ? pickle((LuanTable)obj,set) : pickle(obj); + } + + private String pickle(LuanTable tbl,Set<LuanTable> set) throws LuanException { + if( !set.add(tbl) ) { + throw luan.JAVA.exception( "circular reference in table" ); + } + StringBuilder sb = new StringBuilder(); + sb.append( "{" ); + for( Map.Entry<Object,Object> entry : tbl ) { + sb.append( "[" ); + sb.append( pickle(entry.getKey(),set) ); + sb.append( "]=" ); + sb.append( pickle(entry.getValue(),set) ); + sb.append( ", " ); + } + sb.append( "}" ); + return sb.toString(); + } + + public void write(Object... args) throws LuanException, IOException { + StringBuilder sb = new StringBuilder(); + if( !binaries.isEmpty() ) { + sb.append( "Io._binaries = {}\n" ); + for( byte[] a : binaries ) { + sb.append( "Io._binaries[#Io._binaries+1] = Io._read_binary(" + a.length + ")\n" ); + } + } + for( Object obj : args ) { + sb.append( luan.JAVA.toString(obj) ); + } + out.writeUTF( sb.toString() ); + for( byte[] a : binaries ) { + out.write(a); + } + out.flush(); + binaries.clear(); + } + + public void close() throws IOException { + in.close(); + out.close(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/lib/PickleServer.java Mon Jun 09 09:16:16 2014 +0000 @@ -0,0 +1,62 @@ +package luan.lib; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.EOFException; +import java.util.List; +import java.util.ArrayList; +import luan.Luan; +import luan.LuanState; +import luan.LuanException; + + +final class PickleServer { + + private final PickleCon con; + + PickleServer(LuanState luan,DataInputStream in,DataOutputStream out) { + con = new PickleCon(luan,in,out); + } + + void next() throws IOException { + try { + List<String> list = new ArrayList<String>(); + try { + Object[] result = Luan.array(con.read()); + list.add( "return true" ); + for( Object obj : result ) { + list.add( ", " ); + list.add( con.pickle(obj) ); + } + } catch(LuanException e) { + list.add( "return false, " ); + list.add( con.pickle(e.getMessage()) ); + list.add( ", " ); + list.add( con.pickle(con.src) ); + } + list.add( "\n" ); + con.write( list.toArray() ); + } catch(LuanException e2) { + throw new RuntimeException(e2); + } + } + + public void run() { + try { + while( true ) { + next(); + } + } catch(EOFException e) { + // done + } catch(IOException e) { + e.printStackTrace(); + } + try { + con.close(); + } catch(IOException e) { + throw new RuntimeException(e); + } + } + +}
--- a/src/luan/tools/CmdLine.java Sun Jun 08 03:38:25 2014 +0000 +++ b/src/luan/tools/CmdLine.java Mon Jun 09 09:16:16 2014 +0000 @@ -18,7 +18,8 @@ LuanFunction standalone = (LuanFunction)luan.get("Basic.standalone"); luan.JAVA.call(standalone,"standalone",args); } catch(LuanException e) { - System.err.println(e.getMessage()); +// System.err.println(e.getMessage()); + e.printStackTrace(); System.exit(-1); } System.exit(0);