changeset 65:1ff53a88579a

multi-line statements git-svn-id: https://luan-java.googlecode.com/svn/trunk@66 21e917c8-12df-6dd8-5cb6-c86387c605b9
author fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
date Thu, 17 Jan 2013 23:09:50 +0000
parents 177cfdc2bdb3
children f7e17cfb35f9
files src/luan/interp/LuanParser.java
diffstat 1 files changed, 192 insertions(+), 172 deletions(-) [+]
line wrap: on
line diff
--- a/src/luan/interp/LuanParser.java	Thu Jan 17 19:29:58 2013 +0000
+++ b/src/luan/interp/LuanParser.java	Thu Jan 17 23:09:50 2013 +0000
@@ -16,6 +16,7 @@
 import org.parboiled.support.StringBuilderVar;
 import org.parboiled.support.ValueStack;
 import org.parboiled.errors.ErrorUtils;
+import org.parboiled.annotations.Cached;
 import luan.Luan;
 import luan.LuanState;
 import luan.LuanSource;
@@ -84,7 +85,6 @@
 	static final UpValue.Getter[] NO_UP_VALUE_GETTERS = new UpValue.Getter[0];
 
 	int nEquals;
-	int parens = 0;
 	Frame frame = new Frame();
 
 	boolean nEquals(int n) {
@@ -92,16 +92,6 @@
 		return true;
 	}
 
-	boolean incParens() {
-		parens++;
-		return true;
-	}
-
-	boolean decParens() {
-		parens--;
-		return true;
-	}
-
 	List<String> symbols() {
 		return frame.symbols;
 	}
@@ -157,11 +147,11 @@
 	Rule Target() {
 		Var<Integer> start = new Var<Integer>();
 		return Sequence(
-			Spaces(),
+			Spaces(false),
 			start.set(currentIndex()),
 			FirstOf(
 				Sequence(
-					ExpList(),
+					ExpList(false),
 					push( new ReturnStmt( se(start.get()), (Expressions)pop() ) ),
 					push( newChunk(start.get()) ),
 					EOI
@@ -208,7 +198,7 @@
 					EndOfLine()
 				)
 			),
-			Spaces()
+			Spaces(false)
 		);
 	}
 
@@ -257,14 +247,14 @@
 						addToExpList(builder.get(),new ConstExpr(match()))
 					),
 					Sequence(
-						"<%=", Spaces(),
-						Expr(),
+						"<%=", Spaces(false),
+						Expr(false),
 						addToExpList(builder.get()),
 						"%>"
 					)
 				)
 			),
-			"<%", Spaces(),
+			"<%", Spaces(false),
 			push( new OutputStmt( se(start.get()), builder.get().build() ) )
 		);
 	}
@@ -273,14 +263,14 @@
 		Var<Integer> start = new Var<Integer>();
 		return Sequence(
 			start.set(currentIndex()),
-			Keyword("return"), Expressions(),
+			Keyword("return",false), Expressions(false),
 			push( new ReturnStmt( se(start.get()), (Expressions)pop() ) )
 		);
 	}
 
 	Rule FunctionStmt() {
 		return Sequence(
-			Keyword("function"), FnName(), Function(),
+			Keyword("function",false), FnName(), Function(false),
 			push( new SetStmt( (Settable)pop(1), expr(pop()) ) )
 		);
 	}
@@ -290,11 +280,11 @@
 		return Sequence(
 			start.set(currentIndex()),
 			push(null),  // marker
-			Name(),
+			Name(false),
 			ZeroOrMore(
-				'.', Spaces(),
+				'.', Spaces(false),
 				makeVarExp(start.get()),
-				NameExpr()
+				NameExpr(false)
 			),
 			makeSettableVar(start.get())
 		);
@@ -302,17 +292,17 @@
 
 	Rule LocalFunctionStmt() {
 		return Sequence(
-			Keyword("local"), Keyword("function"),
-			Name(),
+			Keyword("local",false), Keyword("function",false),
+			Name(false),
 			addSymbol( (String)pop() ),
-			Function(),
+			Function(false),
 			push( new SetStmt( new SetLocalVar(symbolsSize()-1), expr(pop()) ) )
 		);
 	}
 
 	Rule BreakStmt() {
 		return Sequence(
-			Keyword("break"),
+			Keyword("break",false),
 			frame.loops > 0,
 			push( new BreakStmt() )
 		);
@@ -324,9 +314,9 @@
 		Var<List<String>> names = new Var<List<String>>(new ArrayList<String>());
 		return Sequence(
 			start.set(currentIndex()),
-			Keyword("for"), NameList(names), Keyword("in"), Expr(), Keyword("do"),
+			Keyword("for",false), NameList(false,names), Keyword("in",false), Expr(false), Keyword("do",false),
 			addSymbols(names.get()),
-			LoopBlock(), Keyword("end"),
+			LoopBlock(), Keyword("end",false),
 			push( new GenericForStmt( se(start.get()), stackStart.get(), symbolsSize() - stackStart.get(), expr(pop(1)), (Stmt)pop() ) ),
 			popSymbols( symbolsSize() - stackStart.get() )
 		);
@@ -336,15 +326,15 @@
 		Var<Integer> start = new Var<Integer>();
 		return Sequence(
 			start.set(currentIndex()),
-			Keyword("for"), Name(), '=', Spaces(), Expr(), Keyword("to"), Expr(),
+			Keyword("for",false), Name(false), '=', Spaces(false), Expr(false), Keyword("to",false), Expr(false),
 			push( new ConstExpr(1) ),  // default step
 			Optional(
-				Keyword("step"),
+				Keyword("step",false),
 				drop(),
-				Expr()
+				Expr(false)
 			),
 			addSymbol( (String)pop(3) ),  // add "for" var to symbols
-			Keyword("do"), LoopBlock(), Keyword("end"),
+			Keyword("do",false), LoopBlock(), Keyword("end",false),
 			push( new NumericForStmt( se(start.get()), symbolsSize()-1, expr(pop(3)), expr(pop(2)), expr(pop(1)), (Stmt)pop() ) ),
 			popSymbols(1)
 		);
@@ -352,9 +342,9 @@
 
 	Rule TryStmt() {
 		return Sequence(
-			Keyword("try"), Block(),
-			Keyword("catch"), Name(), addSymbol( (String)pop() ),
-			Keyword("do"), Block(), Keyword("end"),
+			Keyword("try",false), Block(),
+			Keyword("catch",false), Name(false), addSymbol( (String)pop() ),
+			Keyword("do",false), Block(), Keyword("end",false),
 			push( new TryStmt( (Stmt)pop(1), symbolsSize()-1, (Stmt)pop() ) ),
 			popSymbols(1)
 		);
@@ -362,28 +352,28 @@
 
 	Rule DoStmt() {
 		return Sequence(
-			Keyword("do"), Block(), Keyword("end")
+			Keyword("do",false), Block(), Keyword("end",false)
 		);
 	}
 
 	Rule LocalStmt(Var<List<Stmt>> stmts) {
 		Var<List<String>> names = new Var<List<String>>(new ArrayList<String>());
 		return Sequence(
-			Keyword("local"), NameList(names),
+			Keyword("local",false), NameList(false,names),
 			Optional(
-				'=', Spaces(), ExpList(),
+				'=', Spaces(false), ExpList(false),
 				stmts.get().add( newSetLocalStmt(names.get().size()) )
 			),
 			addSymbols(names.get())
 		);
 	}
 
-	Rule NameList(Var<List<String>> names) {
+	Rule NameList(boolean inParens,Var<List<String>> names) {
 		return Sequence(
-			Name(),
+			Name(inParens),
 			names.get().add( (String)pop() ),
 			ZeroOrMore(
-				',', Spaces(), Name(),
+				',', Spaces(inParens), Name(inParens),
 				names.get().add( (String)pop() )
 			)
 		);
@@ -401,14 +391,14 @@
 
 	Rule WhileStmt() {
 		return Sequence(
-			Keyword("while"), Expr(), Keyword("do"), LoopBlock(), Keyword("end"),
+			Keyword("while",false), Expr(false), Keyword("do",false), LoopBlock(), Keyword("end",false),
 			push( new WhileStmt( expr(pop(1)), (Stmt)pop() ) )
 		);
 	}
 
 	Rule RepeatStmt() {
 		return Sequence(
-			Keyword("repeat"), LoopBlock(), Keyword("until"), Expr(),
+			Keyword("repeat",false), LoopBlock(), Keyword("until",false), Expr(false),
 			push( new RepeatStmt( (Stmt)pop(1), expr(pop()) ) )
 		);
 	}
@@ -420,17 +410,17 @@
 	Rule IfStmt() {
 		Var<Integer> n = new Var<Integer>(1);
 		return Sequence(
-			Keyword("if"), Expr(), Keyword("then"), Block(),
+			Keyword("if",false), Expr(false), Keyword("then",false), Block(),
 			push(Stmt.EMPTY),
 			ZeroOrMore(
-				Keyword("elseif"), drop(), Expr(), Keyword("then"), Block(),
+				Keyword("elseif",false), drop(), Expr(false), Keyword("then",false), Block(),
 				push(Stmt.EMPTY),
 				n.set(n.get()+1)
 			),
 			Optional(
-				Keyword("else"), drop(), Block()
+				Keyword("else",false), drop(), Block()
 			),
-			Keyword("end"),
+			Keyword("end",false),
 			buildIfStmt(n.get())
 		);
 	}
@@ -448,15 +438,15 @@
 	Rule SetStmt() {
 		return Sequence(
 			VarList(),
-			'=', Spaces(),
-			ExpList(),
+			'=', Spaces(false),
+			ExpList(false),
 			push( newSetStmt() )
 		);
 	}
 
 	Rule ExpressionsStmt() {
 		return Sequence(
-			ExpList(),
+			ExpList(false),
 			push( new ExpressionsStmt((Expressions)pop()) )
 		);
 	}
@@ -474,7 +464,7 @@
 			SettableVar(),
 			vars.get().add( (Settable)pop() ),
 			ZeroOrMore(
-				',', Spaces(), SettableVar(),
+				',', Spaces(false), SettableVar(),
 				vars.get().add( (Settable)pop() )
 			),
 			push(vars.get())
@@ -485,7 +475,7 @@
 		Var<Integer> start = new Var<Integer>();
 		return Sequence(
 			start.set(currentIndex()),
-			Var(),
+			Var(false),
 			makeSettableVar(start.get())
 		);
 	}
@@ -510,139 +500,151 @@
 		return push( new SetTableEntry( se(start), env(), new ConstExpr(name) ) );
 	}
 
-	Rule Expr() {
+	@Cached
+	Rule Expr(boolean inParens) {
 		return FirstOf(
-			VarArgs(),
-			OrExpr()
+			VarArgs(inParens),
+			OrExpr(inParens)
 		);
 	}
 
-	Rule OrExpr() {
+	@Cached
+	Rule OrExpr(boolean inParens) {
 		Var<Integer> start = new Var<Integer>();
 		return Sequence(
 			start.set(currentIndex()),
-			AndExpr(),
-			ZeroOrMore( "or", Spaces(), AndExpr(), push( new OrExpr(se(start.get()),expr(pop(1)),expr(pop())) ) )
+			AndExpr(inParens),
+			ZeroOrMore( Keyword("or",inParens), AndExpr(inParens), push( new OrExpr(se(start.get()),expr(pop(1)),expr(pop())) ) )
 		);
 	}
 
-	Rule AndExpr() {
+	@Cached
+	Rule AndExpr(boolean inParens) {
 		Var<Integer> start = new Var<Integer>();
 		return Sequence(
 			start.set(currentIndex()),
-			RelExpr(),
-			ZeroOrMore( "and", Spaces(), RelExpr(), push( new AndExpr(se(start.get()),expr(pop(1)),expr(pop())) ) )
+			RelExpr(inParens),
+			ZeroOrMore( Keyword("and",inParens), RelExpr(inParens), push( new AndExpr(se(start.get()),expr(pop(1)),expr(pop())) ) )
 		);
 	}
 
-	Rule RelExpr() {
+	@Cached
+	Rule RelExpr(boolean inParens) {
 		Var<Integer> start = new Var<Integer>();
 		return Sequence(
 			start.set(currentIndex()),
-			ConcatExpr(),
+			ConcatExpr(inParens),
 			ZeroOrMore(
 				FirstOf(
-					Sequence( "==", Spaces(), ConcatExpr(), push( new EqExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ),
-					Sequence( "~=", Spaces(), ConcatExpr(), push( new NotExpr(se(start.get()),new EqExpr(se(start.get()),expr(pop(1)),expr(pop()))) ) ),
-					Sequence( "<=", Spaces(), ConcatExpr(), push( new LeExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ),
-					Sequence( ">=", Spaces(), ConcatExpr(), push( new LeExpr(se(start.get()),expr(pop()),expr(pop())) ) ),
-					Sequence( "<", Spaces(), ConcatExpr(), push( new LtExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ),
-					Sequence( ">", Spaces(), ConcatExpr(), push( new LtExpr(se(start.get()),expr(pop()),expr(pop())) ) )
+					Sequence( "==", Spaces(inParens), ConcatExpr(inParens), push( new EqExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ),
+					Sequence( "~=", Spaces(inParens), ConcatExpr(inParens), push( new NotExpr(se(start.get()),new EqExpr(se(start.get()),expr(pop(1)),expr(pop()))) ) ),
+					Sequence( "<=", Spaces(inParens), ConcatExpr(inParens), push( new LeExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ),
+					Sequence( ">=", Spaces(inParens), ConcatExpr(inParens), push( new LeExpr(se(start.get()),expr(pop()),expr(pop())) ) ),
+					Sequence( "<", Spaces(inParens), ConcatExpr(inParens), push( new LtExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ),
+					Sequence( ">", Spaces(inParens), ConcatExpr(inParens), push( new LtExpr(se(start.get()),expr(pop()),expr(pop())) ) )
 				)
 			)
 		);
 	}
 
-	Rule ConcatExpr() {
+	@Cached
+	Rule ConcatExpr(boolean inParens) {
 		Var<Integer> start = new Var<Integer>();
 		return Sequence(
 			start.set(currentIndex()),
-			SumExpr(),
-			Optional( "..", Spaces(), ConcatExpr(), push( new ConcatExpr(se(start.get()),expr(pop(1)),expr(pop())) ) )
+			SumExpr(inParens),
+			Optional( "..", Spaces(inParens), ConcatExpr(inParens), push( new ConcatExpr(se(start.get()),expr(pop(1)),expr(pop())) ) )
 		);
 	}
 
-	Rule SumExpr() {
+	@Cached
+	Rule SumExpr(boolean inParens) {
 		Var<Integer> start = new Var<Integer>();
 		return Sequence(
 			start.set(currentIndex()),
-			TermExpr(),
+			TermExpr(inParens),
 			ZeroOrMore(
 				FirstOf(
-					Sequence( '+', Spaces(), TermExpr(), push( new AddExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ),
-					Sequence( '-', TestNot('-'), Spaces(), TermExpr(), push( new SubExpr(se(start.get()),expr(pop(1)),expr(pop())) ) )
+					Sequence( '+', Spaces(inParens), TermExpr(inParens), push( new AddExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ),
+					Sequence( '-', TestNot('-'), Spaces(inParens), TermExpr(inParens), push( new SubExpr(se(start.get()),expr(pop(1)),expr(pop())) ) )
 				)
 			)
 		);
 	}
 
-	Rule TermExpr() {
+	@Cached
+	Rule TermExpr(boolean inParens) {
 		Var<Integer> start = new Var<Integer>();
 		return Sequence(
 			start.set(currentIndex()),
-			UnaryExpr(),
+			UnaryExpr(inParens),
 			ZeroOrMore(
 				FirstOf(
-					Sequence( '*', Spaces(), UnaryExpr(), push( new MulExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ),
-					Sequence( '/', Spaces(), UnaryExpr(), push( new DivExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ),
-					Sequence( '%', Spaces(), UnaryExpr(), push( new ModExpr(se(start.get()),expr(pop(1)),expr(pop())) ) )
+					Sequence( '*', Spaces(inParens), UnaryExpr(inParens), push( new MulExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ),
+					Sequence( '/', Spaces(inParens), UnaryExpr(inParens), push( new DivExpr(se(start.get()),expr(pop(1)),expr(pop())) ) ),
+					Sequence( '%', Spaces(inParens), UnaryExpr(inParens), push( new ModExpr(se(start.get()),expr(pop(1)),expr(pop())) ) )
 				)
 			)
 		);
 	}
 
-	Rule UnaryExpr() {
+	@Cached
+	Rule UnaryExpr(boolean inParens) {
 		Var<Integer> start = new Var<Integer>();
 		return Sequence(
 			start.set(currentIndex()),
 			FirstOf(
-				Sequence( '#', Spaces(), PowExpr(), push( new LenExpr(se(start.get()),expr(pop())) ) ),
-				Sequence( '-', TestNot('-'), Spaces(), PowExpr(), push( new UnmExpr(se(start.get()),expr(pop())) ) ),
-				Sequence( "not", Spaces(), PowExpr(), push( new NotExpr(se(start.get()),expr(pop())) ) ),
-				PowExpr()
+				Sequence( '#', Spaces(inParens), PowExpr(inParens), push( new LenExpr(se(start.get()),expr(pop())) ) ),
+				Sequence( '-', TestNot('-'), Spaces(inParens), PowExpr(inParens), push( new UnmExpr(se(start.get()),expr(pop())) ) ),
+				Sequence( Keyword("not",inParens), PowExpr(inParens), push( new NotExpr(se(start.get()),expr(pop())) ) ),
+				PowExpr(inParens)
 			)
 		);
 	}
 
-	Rule PowExpr() {
+	@Cached
+	Rule PowExpr(boolean inParens) {
 		Var<Integer> start = new Var<Integer>();
 		return Sequence(
 			start.set(currentIndex()),
-			SingleExpr(),
-			Optional( '^', Spaces(), PowExpr(), push( new PowExpr(se(start.get()),expr(pop(1)),expr(pop())) ) )
+			SingleExpr(inParens),
+			Optional( '^', Spaces(inParens), PowExpr(inParens), push( new PowExpr(se(start.get()),expr(pop(1)),expr(pop())) ) )
 		);
 	}
 
-	Rule SingleExpr() {
+	@Cached
+	Rule SingleExpr(boolean inParens) {
 		return FirstOf(
-			FunctionExpr(),
-			TableExpr(),
-			VarExp(),
-			LiteralExpr()
+			FunctionExpr(inParens),
+			TableExpr(inParens),
+			VarExp(inParens),
+			Literal(inParens)
 		);
 	}
 
-	Rule FunctionExpr() {
-		return Sequence( "function", Spaces(), Function() );
+	@Cached
+	Rule FunctionExpr(boolean inParens) {
+		return Sequence( "function", Spaces(inParens), Function(inParens) );
 	}
 
-	Rule Function() {
+	@Cached
+	Rule Function(boolean inParens) {
 		Var<Integer> start = new Var<Integer>();
 		Var<List<String>> names = new Var<List<String>>(new ArrayList<String>());
 		return Sequence(
 			start.set(currentIndex()),
-			'(', incParens(), Spaces(),
+			'(', Spaces(true),
 			action( frame = new Frame(frame) ),
 			Optional(
 				FirstOf(
 					Sequence(
-						NameList(names), addSymbols(names.get()),
-						Optional( ',', Spaces(), VarArgName() )
+						NameList(true,names), addSymbols(names.get()),
+						Optional( ',', Spaces(true), VarArgName() )
 					),
 					VarArgName()
 				)
 			),
-			')', decParens(), Spaces(), Block(), Keyword("end"),
+			')', Spaces(inParens), Block(), Keyword("end",inParens),
 			push( newChunk(start.get()) ),
 			action( frame = frame.parent )
 		);
@@ -650,28 +652,30 @@
 
 	Rule VarArgName() {
 		return Sequence(
-			"...", Spaces(),
+			"...", Spaces(true),
 			action( frame.isVarArg = true )
 		);
 	}
 
-	Rule VarArgs() {
+	@Cached
+	Rule VarArgs(boolean inParens) {
 		Var<Integer> start = new Var<Integer>();
 		return Sequence(
 			start.set(currentIndex()),
-			"...", Spaces(),
+			"...", Spaces(inParens),
 			frame.isVarArg,
 			push( new VarArgs(se(start.get())) )
 		);
 	}
 
-	Rule TableExpr() {
+	@Cached
+	Rule TableExpr(boolean inParens) {
 		Var<Integer> start = new Var<Integer>();
 		Var<List<TableExpr.Field>> fields = new Var<List<TableExpr.Field>>(new ArrayList<TableExpr.Field>());
 		Var<ExpList.Builder> builder = new Var<ExpList.Builder>(new ExpList.Builder());
 		return Sequence(
 			start.set(currentIndex()),
-			'{', incParens(), Spaces(),
+			'{', Spaces(true),
 			Optional(
 				Field(fields,builder),
 				ZeroOrMore(
@@ -680,25 +684,25 @@
 				),
 				Optional( FieldSep() )
 			),
-			'}', decParens(),
-			Spaces(),
+			'}',
+			Spaces(inParens),
 			push( new TableExpr( se(start.get()), fields.get().toArray(new TableExpr.Field[0]), builder.get().build() ) )
 		);
 	}
 
 	Rule FieldSep() {
-		return Sequence( AnyOf(",;"), Spaces() );
+		return Sequence( AnyOf(",;"), Spaces(true) );
 	}
 
 	Rule Field(Var<List<TableExpr.Field>> fields,Var<ExpList.Builder> builder) {
 		return FirstOf(
 			Sequence(
-				FirstOf( SubExpr(), NameExpr() ),
-				'=', Spaces(), Expr(),
+				FirstOf( SubExpr(true), NameExpr(true) ),
+				'=', Spaces(true), Expr(true),
 				fields.get().add( new TableExpr.Field( expr(pop(1)), expr(pop()) ) )
 			),
 			Sequence(
-				Expr(),
+				Expr(true),
 				addToExpList(builder.get())
 			)
 		);
@@ -710,37 +714,39 @@
 		return (Expr)obj;
 	}
 
-	Rule VarExp() {
+	@Cached
+	Rule VarExp(boolean inParens) {
 		Var<Integer> start = new Var<Integer>();
 		return Sequence(
 			start.set(currentIndex()),
-			Var(),
+			Var(inParens),
 			makeVarExp(start.get())
 		);
 	}
 
-	Rule Var() {
+	@Cached
+	Rule Var(boolean inParens) {
 		Var<Integer> start = new Var<Integer>();
 		return Sequence(
 			start.set(currentIndex()),
 			FirstOf(
 				Sequence(
-					'(', incParens(), Spaces(), Expr(), ')', decParens(), Spaces(),
+					'(', Spaces(true), Expr(true), ')', Spaces(inParens),
 					push(expr(pop())),
 					push(null)  // marker
 				),
 				Sequence(
 					push(null),  // marker
-					Name()
+					Name(inParens)
 				)
 			),
 			ZeroOrMore(
 				makeVarExp(start.get()),
 				FirstOf(
-					SubExpr(),
-					Sequence( '.', Spaces(), NameExpr() ),
+					SubExpr(inParens),
+					Sequence( '.', Spaces(inParens), NameExpr(inParens) ),
 					Sequence(
-						Args(start),
+						Args(inParens,start),
 						push(null)  // marker
 					)
 				)
@@ -776,18 +782,18 @@
 	}
 
 	// function should be on top of the stack
-	Rule Args(Var<Integer> start) {
+	Rule Args(boolean inParens,Var<Integer> start) {
 		return Sequence(
 			FirstOf(
 				Sequence(
-					'(', incParens(), Spaces(), Expressions(), ')', decParens(), Spaces()
+					'(', Spaces(true), Expressions(true), ')', Spaces(inParens)
 				),
 				Sequence(
-					TableExpr(),
+					TableExpr(inParens),
 					push( new ExpList.SingleExpList(expr(pop())) )
 				),
 				Sequence(
-					StringLiteral(), Spaces(),
+					StringLiteral(inParens),
 					push( new ExpList.SingleExpList(new ConstExpr(pop())) )
 				)
 			),
@@ -795,20 +801,22 @@
 		);
 	}
 
-	Rule Expressions() {
+	@Cached
+	Rule Expressions(boolean inParens) {
 		return FirstOf(
-			ExpList(),
+			ExpList(inParens),
 			push( ExpList.emptyExpList )
 		);
 	}
 
-	Rule ExpList() {
+	@Cached
+	Rule ExpList(boolean inParens) {
 		Var<ExpList.Builder> builder = new Var<ExpList.Builder>(new ExpList.Builder());
 		return Sequence(
-			Expr(),
+			Expr(inParens),
 			addToExpList(builder.get()),
 			ZeroOrMore(
-				',', Spaces(), Expr(),
+				',', Spaces(inParens), Expr(inParens),
 				addToExpList(builder.get())
 			),
 			push( builder.get().build() )
@@ -830,18 +838,21 @@
 		return true;
 	}
 
-	Rule SubExpr() {
-		return Sequence( '[', incParens(), Spaces(), Expr(), ']', decParens(), Spaces() );
+	@Cached
+	Rule SubExpr(boolean inParens) {
+		return Sequence( '[', Spaces(true), Expr(true), ']', Spaces(inParens) );
 	}
 
-	Rule NameExpr() {
+	@Cached
+	Rule NameExpr(boolean inParens) {
 		return Sequence(
-			Name(),
+			Name(inParens),
 			push( new ConstExpr((String)pop()) )
 		);
 	}
 
-	Rule Name() {
+	@Cached
+	Rule Name(boolean inParens) {
 		return Sequence(
 			Sequence(
 				NameFirstChar(),
@@ -849,7 +860,7 @@
 			),
 			!keywords.contains(match()),
 			push(match()),
-			Spaces()
+			Spaces(inParens)
 		);
 	}
 
@@ -865,11 +876,11 @@
 		);
 	}
 
-	Rule Keyword(String keyword) {
+	Rule Keyword(String keyword,boolean inParens) {
 		return Sequence(
 			keyword,
 			TestNot( NameChar() ),
-			Spaces()
+			Spaces(inParens)
 		);
 	}
 
@@ -902,43 +913,47 @@
 		"while"
 	));
 
-	Rule LiteralExpr() {
+	@Cached
+	Rule Literal(boolean inParens) {
 		return Sequence(
-			Literal(), Spaces(),
+			FirstOf(
+				NilLiteral(inParens),
+				BooleanLiteral(inParens),
+				NumberLiteral(inParens),
+				StringLiteral(inParens)
+			),
 			push(new ConstExpr(pop()))
 		);
 	}
 
-	Rule Literal() {
+	@Cached
+	Rule NilLiteral(boolean inParens) {
+		return Sequence( Keyword("nil",inParens), push(null) );
+	}
+
+	@Cached
+	Rule BooleanLiteral(boolean inParens) {
 		return FirstOf(
-			NilLiteral(),
-			BooleanLiteral(),
-			NumberLiteral(),
-			StringLiteral()
+			Sequence( Keyword("true",inParens), push(true) ),
+			Sequence( Keyword("false",inParens), push(false) )
 		);
 	}
 
-	Rule NilLiteral() {
-		return Sequence( "nil", push(null) );
-	}
-
-	Rule BooleanLiteral() {
-		return FirstOf(
-			Sequence( "true", push(true) ),
-			Sequence( "false", push(false) )
-		);
-	}
-
-	Rule NumberLiteral() {
-		return FirstOf(
-			Sequence(
-				IgnoreCase("0x"),
-				HexNumber()
+	@Cached
+	Rule NumberLiteral(boolean inParens) {
+		return Sequence(
+			FirstOf(
+				Sequence(
+					IgnoreCase("0x"),
+					HexNumber()
+				),
+				Sequence(
+					DecNumber(),
+					push(Double.valueOf(match()))
+				)
 			),
-			Sequence(
-				DecNumber(),
-				push(Double.valueOf(match()))
-			)
+			TestNot( NameChar() ),
+			Spaces(inParens)
 		);
 	}
 
@@ -1011,11 +1026,15 @@
 		);
 	}
 
-	Rule StringLiteral() {
-		return FirstOf(
-			QuotedString('"'),
-			QuotedString('\''),
-			LongString()
+	@Cached
+	Rule StringLiteral(boolean inParens) {
+		return Sequence(
+			FirstOf(
+				QuotedString('"'),
+				QuotedString('\''),
+				LongString()
+			),
+			Spaces(inParens)
 		);
 	}
 
@@ -1087,13 +1106,14 @@
 		);
 	}
 
-	Rule Spaces() {
+	@Cached
+	Rule Spaces(boolean inParens) {
 		return ZeroOrMore(
 			FirstOf(
 				AnyOf(" \t"),
 				Comment(),
-				Sequence( '\\', EndOfLine() )//,
-//				Sequence( AnyOf("\r\n"), parens > 0 )
+				Sequence( '\\', EndOfLine() ),
+				Sequence( AnyOf("\r\n"), inParens )
 			)
 		);
 	}