changeset 7:bca8fc5d928b

work on expressions git-svn-id: https://luan-java.googlecode.com/svn/trunk@8 21e917c8-12df-6dd8-5cb6-c86387c605b9
author fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
date Tue, 20 Nov 2012 10:06:27 +0000
parents a315783c9524
children 8896068e0a4b
files src/luan/Lua.java src/luan/interp/AndExpr.java src/luan/interp/DivExpr.java src/luan/interp/EqExpr.java src/luan/interp/LenExpr.java src/luan/interp/LengthExpr.java src/luan/interp/LuaParser.java src/luan/interp/ModExpr.java src/luan/interp/MulExpr.java src/luan/interp/NotExpr.java src/luan/interp/OrExpr.java src/luan/interp/UnmExpr.java
diffstat 12 files changed, 313 insertions(+), 78 deletions(-) [+]
line wrap: on
line diff
--- a/src/luan/Lua.java	Mon Nov 19 13:08:30 2012 +0000
+++ b/src/luan/Lua.java	Tue Nov 20 10:06:27 2012 +0000
@@ -15,6 +15,10 @@
 		return "userdata";
 	}
 
+	public static boolean toBoolean(Object obj) {
+		return obj != null && !Boolean.FALSE.equals(obj);
+	}
+
 	public static String toString(Object obj) {
 		if( obj == null )
 			return "nil";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/luan/interp/AndExpr.java	Tue Nov 20 10:06:27 2012 +0000
@@ -0,0 +1,18 @@
+package luan.interp;
+
+import luan.Lua;
+import luan.LuaException;
+import luan.LuaState;
+
+
+final class AndExpr extends BinaryOpExpr {
+
+	AndExpr(Expr op1,Expr op2) {
+		super(op1,op2);
+	}
+
+	@Override Object eval(LuaState lua) throws LuaException {
+		Object v1 = op1.eval(lua);
+		return !Lua.toBoolean(v1) ? v1 : op2.eval(lua);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/luan/interp/DivExpr.java	Tue Nov 20 10:06:27 2012 +0000
@@ -0,0 +1,20 @@
+package luan.interp;
+
+import luan.Lua;
+import luan.LuaNumber;
+import luan.LuaException;
+import luan.LuaState;
+
+
+final class DivExpr extends BinaryOpExpr {
+
+	DivExpr(Expr op1,Expr op2) {
+		super(op1,op2);
+	}
+
+	@Override Object eval(LuaState lua) throws LuaException {
+		double n1 = Lua.checkNumber(op1.eval(lua)).value();
+		double n2 = Lua.checkNumber(op2.eval(lua)).value();
+		return new LuaNumber( n1 / n2 );
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/luan/interp/EqExpr.java	Tue Nov 20 10:06:27 2012 +0000
@@ -0,0 +1,20 @@
+package luan.interp;
+
+import luan.Lua;
+import luan.LuaNumber;
+import luan.LuaException;
+import luan.LuaState;
+
+
+final class EqExpr extends BinaryOpExpr {
+
+	EqExpr(Expr op1,Expr op2) {
+		super(op1,op2);
+	}
+
+	@Override Object eval(LuaState lua) throws LuaException {
+		Object v1 = op1.eval(lua);
+		Object v2 = op2.eval(lua);
+		return v1 == v2 || v1 != null && v1.equals(v2);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/luan/interp/LenExpr.java	Tue Nov 20 10:06:27 2012 +0000
@@ -0,0 +1,31 @@
+package luan.interp;
+
+import luan.Lua;
+import luan.LuaNumber;
+import luan.LuaTable;
+import luan.LuaException;
+import luan.LuaState;
+
+
+final class LenExpr extends UnaryOpExpr {
+
+	LenExpr(Expr op) {
+		super(op);
+	}
+
+	@Override Object eval(LuaState lua) throws LuaException {
+		return new LuaNumber( length(op.eval(lua)) );
+	}
+
+	private static int length(Object obj) throws LuaException {
+		if( obj instanceof String ) {
+			String s = (String)obj;
+			return s.length();
+		}
+		if( obj instanceof LuaTable ) {
+			LuaTable t = (LuaTable)obj;
+			return t.length();
+		}
+		throw new LuaException( "attempt to get length of a " + Lua.type(obj) + " value" );
+	}
+}
--- a/src/luan/interp/LengthExpr.java	Mon Nov 19 13:08:30 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-package luan.interp;
-
-import luan.Lua;
-import luan.LuaNumber;
-import luan.LuaTable;
-import luan.LuaException;
-import luan.LuaState;
-
-
-final class LengthExpr extends UnaryOpExpr {
-
-	LengthExpr(Expr op) {
-		super(op);
-	}
-
-	@Override Object eval(LuaState lua) throws LuaException {
-		return new LuaNumber( length(op.eval(lua)) );
-	}
-
-	private static int length(Object obj) throws LuaException {
-		if( obj instanceof String ) {
-			String s = (String)obj;
-			return s.length();
-		}
-		if( obj instanceof LuaTable ) {
-			LuaTable t = (LuaTable)obj;
-			return t.length();
-		}
-		throw new LuaException( "attempt to get length of a " + Lua.type(obj) + " value" );
-	}
-}
--- a/src/luan/interp/LuaParser.java	Mon Nov 19 13:08:30 2012 +0000
+++ b/src/luan/interp/LuaParser.java	Tue Nov 20 10:06:27 2012 +0000
@@ -15,46 +15,108 @@
 public class LuaParser extends BaseParser<Object> {
 
 	Rule Target() {
-		return Sequence(ConstExpr(), EOI);
+		return Sequence(Spaces(), Expr(), EOI);
+	}
+
+	Rule Expr() {
+		return OrExpr();
+	}
+
+	Rule OrExpr() {
+		return Sequence(
+			AndExpr(),
+			ZeroOrMore( "or", Spaces(), AndExpr(), push( new OrExpr((Expr)pop(1),(Expr)pop()) ) )
+		);
+	}
+
+	Rule AndExpr() {
+		return Sequence(
+			RelExpr(),
+			ZeroOrMore( "and", Spaces(), RelExpr(), push( new AndExpr((Expr)pop(1),(Expr)pop()) ) )
+		);
+	}
+
+	Rule RelExpr() {
+		return Sequence(
+			SumExpr(),
+			ZeroOrMore(
+				FirstOf(
+					Sequence( "==", Spaces(), SumExpr(), push( new EqExpr((Expr)pop(1),(Expr)pop()) ) ),
+					Sequence( "~=", Spaces(), SumExpr(), push( new NotExpr(new EqExpr((Expr)pop(1),(Expr)pop())) ) )
+				)
+			)
+		);
 	}
 
-	Rule ConstExpr() {
+	Rule SumExpr() {
+		return Sequence(
+			TermExpr(),
+			ZeroOrMore(
+				FirstOf(
+					Sequence( '+', Spaces(), TermExpr(), push( new AddExpr((Expr)pop(1),(Expr)pop()) ) ),
+					Sequence( '-', Spaces(), TermExpr(), push( new SubExpr((Expr)pop(1),(Expr)pop()) ) )
+				)
+			)
+		);
+	}
+
+	Rule TermExpr() {
 		return Sequence(
-			Const(),
+			UnaryExpr(),
+			ZeroOrMore(
+				FirstOf(
+					Sequence( '*', Spaces(), UnaryExpr(), push( new MulExpr((Expr)pop(1),(Expr)pop()) ) ),
+					Sequence( '/', Spaces(), UnaryExpr(), push( new DivExpr((Expr)pop(1),(Expr)pop()) ) ),
+					Sequence( '%', Spaces(), UnaryExpr(), push( new ModExpr((Expr)pop(1),(Expr)pop()) ) )
+				)
+			)
+		);
+	}
+
+	Rule UnaryExpr() {
+		return FirstOf(
+			Sequence( '#', Spaces(), SingleExpr(), push( new LenExpr((Expr)pop()) ) ),
+			Sequence( '-', Spaces(), SingleExpr(), push( new UnmExpr((Expr)pop()) ) ),
+			Sequence( "not", Spaces(), SingleExpr(), push( new NotExpr((Expr)pop()) ) ),
+			SingleExpr()
+		);
+	}
+
+	Rule SingleExpr() {
+		return FirstOf(
+			Sequence( '(', Spaces(), Expr(), ')', Spaces() ),
+			LiteralExpr()
+		);
+	}
+
+	Rule LiteralExpr() {
+		return Sequence(
+			Literal(), Spaces(),
 			push(new ConstExpr(pop()))
 		);
 	}
 
-	Rule Const() {
+	Rule Literal() {
 		return FirstOf(
-			NilConst(),
-			BooleanConst(),
-			NumberConst(),
-			StringConst()
+			NilLiteral(),
+			BooleanLiteral(),
+			NumberLiteral(),
+			StringLiteral()
 		);
 	}
 
-	Rule NilConst() {
-		return Sequence(
-			String("nil"),
-			push(null)
+	Rule NilLiteral() {
+		return Sequence( "nil", push(null) );
+	}
+
+	Rule BooleanLiteral() {
+		return FirstOf(
+			Sequence( "true", push(true) ),
+			Sequence( "false", push(false) )
 		);
 	}
 
-	Rule BooleanConst() {
-		return FirstOf(
-			Sequence(
-				String("true"),
-				push(true)
-			),
-			Sequence(
-				String("false"),
-				push(false)
-			)
-		);
-	}
-
-	Rule NumberConst() {
+	Rule NumberLiteral() {
 		return Sequence(
 			Number(),
 			push(new LuaNumber((Double)pop()))
@@ -79,17 +141,10 @@
 		return FirstOf(
 			Sequence(
 				Int(),
-				Optional(
-					Ch('.'),
-					Optional(Int())
-				),
+				Optional( '.', Optional(Int()) ),
 				NumberExp()
 			),
-			Sequence(
-				Ch('.'),
-				Int(),
-				NumberExp()
-			)
+			Sequence( '.', Int(), NumberExp() )
 		);
 	}
 
@@ -116,7 +171,7 @@
 		return CharRange('0', '9');
 	}
 
-	Rule StringConst() {
+	Rule StringLiteral() {
 		return FirstOf(
 			QuotedString('"'),
 			QuotedString('\'')
@@ -125,7 +180,7 @@
 
 	Rule QuotedString(char quote) {
 		return Sequence(
-			Ch(quote),
+			quote,
 			push(new StringBuffer()),
 			ZeroOrMore(
 				FirstOf(
@@ -136,23 +191,42 @@
 					EscSeq()
 				)
 			),
-			Ch(quote),
+			quote,
 			push(((StringBuffer)pop()).toString())
 		);
 	}
 
 	Rule EscSeq() {
 		return Sequence(
-			Ch('\\'),
+			'\\',
 			FirstOf(
-				Sequence( Ch('b'), append('\b') ),
-				Sequence( Ch('f'), append('\f') ),
-				Sequence( Ch('n'), append('\n') ),
-				Sequence( Ch('r'), append('\r') ),
-				Sequence( Ch('t'), append('\t') ),
-				Sequence( Ch('\\'), append('\\') ),
-				Sequence( Ch('"'), append('"') ),
-				Sequence( Ch('\''), append('\'') )
+				Sequence( 'a', append('\u0007') ),
+				Sequence( 'b', append('\b') ),
+				Sequence( 'f', append('\f') ),
+				Sequence( 'n', append('\n') ),
+				Sequence( 'r', append('\r') ),
+				Sequence( 't', append('\t') ),
+				Sequence( 'v', append('\u000b') ),
+				Sequence( '\\', append('\\') ),
+				Sequence( '"', append('"') ),
+				Sequence( '\'', append('\'') ),
+				Sequence(
+					'x',
+					Sequence( HexDigit(), HexDigit() ),
+					append( (char)Integer.parseInt(match(),16) )
+				),
+				Sequence(
+					Sequence(
+						Digit(),
+						Optional(
+							Digit(),
+							Optional(
+								Digit()
+							)
+						)
+					),
+					append( (char)Integer.parseInt(match()) )
+				)
 			)
 		);
 	}
@@ -163,6 +237,10 @@
 		return true;
 	}
 
+	public Rule Spaces() {
+		return ZeroOrMore(AnyOf(" \t"));
+	}
+
 	// for testing
 	public static void main(String[] args) throws Exception {
 		LuaParser parser = Parboiled.createParser(LuaParser.class);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/luan/interp/ModExpr.java	Tue Nov 20 10:06:27 2012 +0000
@@ -0,0 +1,20 @@
+package luan.interp;
+
+import luan.Lua;
+import luan.LuaNumber;
+import luan.LuaException;
+import luan.LuaState;
+
+
+final class ModExpr extends BinaryOpExpr {
+
+	ModExpr(Expr op1,Expr op2) {
+		super(op1,op2);
+	}
+
+	@Override Object eval(LuaState lua) throws LuaException {
+		double n1 = Lua.checkNumber(op1.eval(lua)).value();
+		double n2 = Lua.checkNumber(op2.eval(lua)).value();
+		return new LuaNumber( n1 % n2 );
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/luan/interp/MulExpr.java	Tue Nov 20 10:06:27 2012 +0000
@@ -0,0 +1,20 @@
+package luan.interp;
+
+import luan.Lua;
+import luan.LuaNumber;
+import luan.LuaException;
+import luan.LuaState;
+
+
+final class MulExpr extends BinaryOpExpr {
+
+	MulExpr(Expr op1,Expr op2) {
+		super(op1,op2);
+	}
+
+	@Override Object eval(LuaState lua) throws LuaException {
+		double n1 = Lua.checkNumber(op1.eval(lua)).value();
+		double n2 = Lua.checkNumber(op2.eval(lua)).value();
+		return new LuaNumber( n1 * n2 );
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/luan/interp/NotExpr.java	Tue Nov 20 10:06:27 2012 +0000
@@ -0,0 +1,17 @@
+package luan.interp;
+
+import luan.Lua;
+import luan.LuaException;
+import luan.LuaState;
+
+
+final class NotExpr extends UnaryOpExpr {
+
+	NotExpr(Expr op) {
+		super(op);
+	}
+
+	@Override Object eval(LuaState lua) throws LuaException {
+		return !Lua.toBoolean(op.eval(lua));
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/luan/interp/OrExpr.java	Tue Nov 20 10:06:27 2012 +0000
@@ -0,0 +1,18 @@
+package luan.interp;
+
+import luan.Lua;
+import luan.LuaException;
+import luan.LuaState;
+
+
+final class OrExpr extends BinaryOpExpr {
+
+	OrExpr(Expr op1,Expr op2) {
+		super(op1,op2);
+	}
+
+	@Override Object eval(LuaState lua) throws LuaException {
+		Object v1 = op1.eval(lua);
+		return Lua.toBoolean(v1) ? v1 : op2.eval(lua);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/luan/interp/UnmExpr.java	Tue Nov 20 10:06:27 2012 +0000
@@ -0,0 +1,20 @@
+package luan.interp;
+
+import luan.Lua;
+import luan.LuaNumber;
+import luan.LuaException;
+import luan.LuaState;
+
+
+// unary minus
+final class UnmExpr extends UnaryOpExpr {
+
+	UnmExpr(Expr op) {
+		super(op);
+	}
+
+	@Override Object eval(LuaState lua) throws LuaException {
+		double n = Lua.checkNumber(op.eval(lua)).value();
+		return new LuaNumber( -n );
+	}
+}