diff src/luan/interp/LuaParser.java @ 19:a7c13c6017f7

add GenericForStmt git-svn-id: https://luan-java.googlecode.com/svn/trunk@20 21e917c8-12df-6dd8-5cb6-c86387c605b9
author fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
date Sun, 02 Dec 2012 10:08:24 +0000
parents 3971113699b8
children d85510d92eee
line wrap: on
line diff
--- a/src/luan/interp/LuaParser.java	Sun Dec 02 07:00:44 2012 +0000
+++ b/src/luan/interp/LuaParser.java	Sun Dec 02 10:08:24 2012 +0000
@@ -45,13 +45,19 @@
 	int index(String name) {
 		int i = symbols.size();
 		while( --i >= 0 ) {
-System.out.println("index ["+name+"] ["+symbols.get(i)+"] "+symbols.get(i).equals(name));
 			if( symbols.get(i).equals(name) )
 				return i;
 		}
 		return -1;
 	}
 
+	boolean popSymbols(int n) {
+		while( n-- > 0 ) {
+			symbols.remove(symbols.size()-1);
+		}
+		return true;
+	}
+
 	public Rule Target() {
 		return Sequence(
 			Spaces(),
@@ -71,28 +77,27 @@
 
 	Rule Block() {
 		Var<List<Stmt>> stmts = new Var<List<Stmt>>(new ArrayList<Stmt>());
-		Var<Integer> stackCount = new Var<Integer>(0);
+		Var<Integer> stackStart = new Var<Integer>(symbols.size());
 		return Sequence(
-			Optional( Stmt(stmts,stackCount) ),
+			Optional( Stmt(stmts) ),
 			ZeroOrMore(
 				StmtSep(),
-				Optional( Stmt(stmts,stackCount) )
+				Optional( Stmt(stmts) )
 			),
-			push( newBlock(stmts.get(),stackCount.get()) )
+			push( newBlock(stmts.get(),stackStart.get()) )
 		);
 	}
 
-	Stmt newBlock(List<Stmt> stmts,int stackN) {
+	Stmt newBlock(List<Stmt> stmts,int stackStart) {
 		if( stackSize < symbols.size() )
 			stackSize = symbols.size();
-		for( int i=0; i<stackN; i++ ) {
-			symbols.remove(symbols.size()-1);  // pop
-		}
+		int stackEnd = symbols.size();
+		popSymbols( stackEnd - stackStart );
 		if( stmts.isEmpty() )
 			return Stmt.EMPTY;
-		if( stmts.size()==1 && stackN==0 )
+		if( stmts.size()==1 && stackStart==stackEnd )
 			return stmts.get(0);
-		return new Block( stmts.toArray(new Stmt[0]), symbols.size(), symbols.size()+stackN );
+		return new Block( stmts.toArray(new Stmt[0]), stackStart, stackEnd );
 	}
 
 	Rule StmtSep() {
@@ -112,11 +117,12 @@
 		return FirstOf("\r\n", '\r', '\n');
 	}
 
-	Rule Stmt(Var<List<Stmt>> stmts,Var<Integer> stackCount) {
+	Rule Stmt(Var<List<Stmt>> stmts) {
 		return FirstOf(
-			LocalStmt(stmts,stackCount),
+			LocalStmt(stmts),
 			Sequence(
 				FirstOf(
+					GenericForStmt(),
 					NumericForStmt(),
 					DoStmt(),
 					WhileStmt(),
@@ -130,6 +136,15 @@
 		);
 	}
 
+	Rule GenericForStmt() {
+		Var<Integer> stackStart = new Var<Integer>(symbols.size());
+		return Sequence(
+			Keyword("for"), NameList(), Keyword("in"), Expr(), Keyword("do"), Block(), Keyword("end"),
+			push( new GenericForStmt( stackStart.get(), symbols.size() - stackStart.get(), expr(pop(1)), (Stmt)pop() ) ),
+			popSymbols( symbols.size() - stackStart.get() )
+		);
+	}
+
 	Rule NumericForStmt() {
 		return Sequence(
 			Keyword("for"), Name(), '=', Spaces(), Expr(), ',', Spaces(), Expr(),
@@ -142,7 +157,7 @@
 			symbols.add( (String)pop(3) ),  // add "for" var to symbols
 			Keyword("do"), Block(), Keyword("end"),
 			push( new NumericForStmt( symbols.size()-1, expr(pop(3)), expr(pop(2)), expr(pop(1)), (Stmt)pop() ) ),
-			action( symbols.remove(symbols.size()-1) )  // pop
+			popSymbols(1)
 		);
 	}
 
@@ -152,37 +167,33 @@
 		);
 	}
 
-	Rule LocalStmt(Var<List<Stmt>> stmts,Var<Integer> stackCount) {
-		Var<List<String>> names = new Var<List<String>>(new ArrayList<String>());
+	Rule LocalStmt(Var<List<Stmt>> stmts) {
+		Var<Integer> stackStart = new Var<Integer>(symbols.size());
 		return Sequence(
-			Keyword("local"),
-			Name(),
-			newName(names.get(),stackCount),
-			ZeroOrMore(
-				',', Spaces(), Name(),
-				newName(names.get(),stackCount)
-			),
+			Keyword("local"), NameList(),
 			Optional(
-				'=', Spaces(),
-				ExpList(),
-				stmts.get().add( newSetLocalStmt(names.get()) )
+				'=', Spaces(), ExpList(),
+				stmts.get().add( newSetLocalStmt(stackStart.get()) )
 			)
 		);
 	}
 
-	boolean newName(List<String> names,Var<Integer> stackCount) {
-		String name = (String)pop();
-		names.add(name);
-		symbols.add(name);
-		stackCount.set( stackCount.get() + 1 );
-		return true;
+	Rule NameList() {
+		return Sequence(
+			Name(),
+			symbols.add( (String)pop() ),
+			ZeroOrMore(
+				',', Spaces(), Name(),
+				symbols.add( (String)pop() )
+			)
+		);
 	}
 
-	SetStmt newSetLocalStmt(List<String> names) {
+	SetStmt newSetLocalStmt(int stackStart) {
 		Expressions values = (Expressions)pop();
-		SetLocalVar[] vars = new SetLocalVar[names.size()];
+		SetLocalVar[] vars = new SetLocalVar[symbols.size()-stackStart];
 		for( int i=0; i<vars.length; i++ ) {
-			vars[i] = new SetLocalVar(index(names.get(i)));
+			vars[i] = new SetLocalVar(stackStart+i);
 		}
 		return new SetStmt( vars, values );
 	}