Mercurial Hosting > luan
changeset 12:9cea1aea5eef
CmdLine can run files
git-svn-id: https://luan-java.googlecode.com/svn/trunk@13 21e917c8-12df-6dd8-5cb6-c86387c605b9
author | fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9> |
---|---|
date | Fri, 23 Nov 2012 10:37:40 +0000 |
parents | b7d7069fee58 |
children | 3b22ffbdb83a |
files | src/luan/CmdLine.java src/luan/LuaFunction.java src/luan/LuaJavaFunction.java src/luan/interp/FnCall.java src/luan/interp/LuaParser.java src/luan/interp/Stmt.java src/luan/lib/BasicLib.java |
diffstat | 7 files changed, 207 insertions(+), 37 deletions(-) [+] |
line wrap: on
line diff
--- a/src/luan/CmdLine.java Thu Nov 22 10:51:56 2012 +0000 +++ b/src/luan/CmdLine.java Fri Nov 23 10:37:40 2012 +0000 @@ -1,39 +1,54 @@ package luan; -import java.util.List; import java.util.Scanner; -import org.parboiled.Parboiled; -import org.parboiled.errors.ErrorUtils; -import org.parboiled.parserunners.ReportingParseRunner; -import org.parboiled.support.ParsingResult; -import luan.interp.Expressions; -import luan.interp.Stmt; -import luan.interp.LuaParser; import luan.lib.BasicLib; public class CmdLine { public static void main(String[] args) throws Exception { - LuaParser parser = Parboiled.createParser(LuaParser.class); LuaState lua = new LuaState(); + BasicLib.register(lua); + boolean interactive = false; + int i = 0; + while( i < args.length ) { + String arg = args[i]; + if( !arg.startsWith("-") ) + break; + if( arg.equals("-i") ) { + interactive = true; + } else { + throw new RuntimeException("invalid option: "+arg); + } + i++; + } + if( i == args.length ) { + interactive = true; + } else { + String file = args[i++]; + try { + LuaFunction fn = BasicLib.loadFile(file); + fn.call(lua); + } catch(LuaException e) { + System.out.println(e.getMessage()); + return; + } + } + if( interactive ) + interactive(lua); + } + + static void interactive(LuaState lua) { while( true ) { System.out.print("> "); String input = new Scanner(System.in).nextLine(); - ParsingResult<?> result = new ReportingParseRunner(parser.Target()).run(input); - if( result.hasErrors() ) { - System.out.println("Parse Errors:\n" + ErrorUtils.printParseErrors(result)); - } else { - Object resultValue = result.resultValue; - if( resultValue instanceof Expressions ) { - Expressions expressions = (Expressions)resultValue; - List vals = expressions.eval(lua); - if( !vals.isEmpty() ) - BasicLib.print( vals.toArray() ); - } else { - Stmt stmt = (Stmt)resultValue; - stmt.eval(lua); - } + try { + LuaFunction fn = BasicLib.load(input); + Object[] rtn = fn.call(lua); + if( rtn.length > 0 ) + BasicLib.print(rtn); + } catch(LuaException e) { + System.out.println(e.getMessage()); } } }
--- a/src/luan/LuaFunction.java Thu Nov 22 10:51:56 2012 +0000 +++ b/src/luan/LuaFunction.java Fri Nov 23 10:37:40 2012 +0000 @@ -3,7 +3,9 @@ public abstract class LuaFunction { - public abstract Object[] call(Object... args); + public abstract Object[] call(LuaState lua,Object... args) throws LuaException; + + public static final Object[] EMPTY_RTN = new Object[0]; @Override public String toString() { return "function: " + Integer.toHexString(hashCode());
--- a/src/luan/LuaJavaFunction.java Thu Nov 22 10:51:56 2012 +0000 +++ b/src/luan/LuaJavaFunction.java Fri Nov 23 10:37:40 2012 +0000 @@ -25,7 +25,7 @@ } } - @Override public Object[] call(Object... args) { + @Override public Object[] call(LuaState lua,Object... args) { args = fixArgs(args); Object rtn; try { @@ -76,15 +76,19 @@ public Object[] convert(Object obj); } - private static final Object[] EMPTY = new Object[0]; - private static final RtnConverter RTN_EMPTY = new RtnConverter() { public Object[] convert(Object obj) { - return EMPTY; + return EMPTY_RTN; } }; - private static final RtnConverter RTN_SAME = new RtnConverter() { + private static final RtnConverter RTN_ARRAY = new RtnConverter() { + public Object[] convert(Object obj) { + return (Object[])obj; + } + }; + + private static final RtnConverter RTN_ONE = new RtnConverter() { public Object[] convert(Object obj) { return new Object[]{obj}; } @@ -112,7 +116,9 @@ || rtnType == Double.TYPE ) return RTN_NUMBER; - return RTN_SAME; + if( rtnType.isArray() ) + return RTN_ARRAY; + return RTN_ONE; }
--- a/src/luan/interp/FnCall.java Thu Nov 22 10:51:56 2012 +0000 +++ b/src/luan/interp/FnCall.java Fri Nov 23 10:37:40 2012 +0000 @@ -19,6 +19,6 @@ @Override public List eval(LuaState lua) throws LuaException { LuaFunction fn = Lua.checkFunction( fnExpr.eval(lua) ); - return Arrays.asList( fn.call( args.eval(lua).toArray() ) ); + return Arrays.asList( fn.call( lua, args.eval(lua).toArray() ) ); } }
--- a/src/luan/interp/LuaParser.java Thu Nov 22 10:51:56 2012 +0000 +++ b/src/luan/interp/LuaParser.java Fri Nov 23 10:37:40 2012 +0000 @@ -1,5 +1,8 @@ package luan.interp; +import java.util.Set; +import java.util.HashSet; +import java.util.Arrays; import java.util.List; import java.util.ArrayList; import java.util.Scanner; @@ -20,14 +23,64 @@ return Sequence( Spaces(), FirstOf( - Sequence( Expressions(), EOI ), - Sequence( Stmt(), EOI ) + Sequence( ExpList(), EOI ), + Sequence( Chunk(), EOI ) ) ); } + Rule Chunk() { + return Sequence( + push(new ArrayList<Stmt>()), + Optional( Stmt() ), + ZeroOrMore( + StmtSep(), + Optional( Stmt() ) + ), + push( newChunk() ) + ); + } + + boolean addStmt() { + Stmt stmt = (Stmt)pop(); + @SuppressWarnings("unchecked") + List<Stmt> stmts = (List<Stmt>)peek(); + stmts.add(stmt); + return true; + } + + Stmt newChunk() { + @SuppressWarnings("unchecked") + List<Stmt> stmts = (List<Stmt>)peek(); + switch( stmts.size() ) { + case 0: + return Stmt.EMPTY; + case 1: + return stmts.get(0); + default: + return new Block(stmts.toArray(new Stmt[0])); + } + } + + Rule StmtSep() { + return Sequence( OneOrMore(AnyOf(";\r\n")), Spaces() ); + } + Rule Stmt() { - return SetStmt(); + return Sequence( + FirstOf( + SetStmt(), + ExpressionsStmt() + ), + addStmt() + ); + } + + Rule ExpressionsStmt() { + return Sequence( + ExpList(), + push( new ExpressionsStmt((Expressions)pop()) ) + ); } Rule SetStmt() { @@ -332,7 +385,7 @@ FirstOf( NameStart(), Digit() ) ) ), - push( new ConstExpr(match()) ), + pushNameExpr(), Spaces() ); } @@ -345,6 +398,38 @@ ); } + boolean pushNameExpr() { + String name = match(); + if( keywords.contains(name) ) + return false; + return push( new ConstExpr(name) ); + } + + private static final Set<String> keywords = new HashSet<String>(Arrays.asList( + "and", + "break", + "do", + "else", + "elseif", + "end", + "false", + "for", + "function", + "goto", + "if", + "in", + "local", + "nil", + "not", + "or", + "repeat", + "return", + "then", + "true", + "until", + "while" + )); + Rule LiteralExpr() { return Sequence( Literal(), Spaces(), @@ -493,10 +578,16 @@ return true; } - public Rule Spaces() { + Rule Spaces() { return ZeroOrMore(AnyOf(" \t")); } + // for debugging + boolean print(String s) { + System.out.println(s); + return true; + } + // for testing public static void main(String[] args) throws Exception { LuaParser parser = Parboiled.createParser(LuaParser.class);
--- a/src/luan/interp/Stmt.java Thu Nov 22 10:51:56 2012 +0000 +++ b/src/luan/interp/Stmt.java Fri Nov 23 10:37:40 2012 +0000 @@ -6,4 +6,8 @@ public interface Stmt { public void eval(LuaState lua) throws LuaException; + + static final Stmt EMPTY = new Stmt() { + public void eval(LuaState lua) {} + }; }
--- a/src/luan/lib/BasicLib.java Thu Nov 22 10:51:56 2012 +0000 +++ b/src/luan/lib/BasicLib.java Fri Nov 23 10:37:40 2012 +0000 @@ -1,13 +1,27 @@ package luan.lib; +import java.io.FileReader; +import java.io.IOException; +import org.parboiled.Parboiled; +import org.parboiled.errors.ErrorUtils; +import org.parboiled.parserunners.ReportingParseRunner; +import org.parboiled.parserunners.TracingParseRunner; +import org.parboiled.support.ParsingResult; import luan.Lua; +import luan.LuaState; import luan.LuaTable; +import luan.LuaFunction; import luan.LuaJavaFunction; +import luan.LuaException; +import luan.interp.LuaParser; +import luan.interp.Expressions; +import luan.interp.Stmt; public class BasicLib { - public static void register(LuaTable t) { + public static void register(LuaState lua) { + LuaTable t = lua.env(); add( t, "print", new Object[0].getClass() ); add( t, "type", Object.class ); } @@ -33,4 +47,42 @@ return Lua.type(obj); } + public static LuaFunction load(String ld) throws LuaException { + LuaParser parser = Parboiled.createParser(LuaParser.class); + ParsingResult<?> result = new ReportingParseRunner(parser.Target()).run(ld); + if( result.hasErrors() ) + throw new LuaException( ErrorUtils.printParseErrors(result) ); + Object resultValue = result.resultValue; + if( resultValue instanceof Expressions ) { + final Expressions expressions = (Expressions)resultValue; + return new LuaFunction() { + public Object[] call(LuaState lua,Object... args) throws LuaException { + return expressions.eval(lua).toArray(); + } + }; + } + final Stmt stmt = (Stmt)resultValue; + return new LuaFunction() { + public Object[] call(LuaState lua,Object... args) throws LuaException { + stmt.eval(lua); + return LuaFunction.EMPTY_RTN; + } + }; + } + + public static String readFile(String fileName) throws IOException { + StringBuilder sb = new StringBuilder(); + FileReader in = new FileReader(fileName); + char[] buf = new char[8192]; + int n; + while( (n=in.read(buf)) != -1 ) { + sb.append(buf,0,n); + } + return sb.toString(); + } + + public static LuaFunction loadFile(String fileName) throws LuaException,IOException { + return load(readFile(fileName)); + } + }