comparison src/luan/interp/LuaParser.java @ 21:c93d8c781853

add functions git-svn-id: https://luan-java.googlecode.com/svn/trunk@22 21e917c8-12df-6dd8-5cb6-c86387c605b9
author fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
date Tue, 04 Dec 2012 09:16:03 +0000
parents d85510d92eee
children 7ee247560db5
comparison
equal deleted inserted replaced
20:d85510d92eee 21:c93d8c781853
20 import luan.LuaNumber; 20 import luan.LuaNumber;
21 import luan.LuaState; 21 import luan.LuaState;
22 22
23 23
24 public class LuaParser extends BaseParser<Object> { 24 public class LuaParser extends BaseParser<Object> {
25
26 static final class Frame {
27 final Frame parent;
28 final List<String> symbols = new ArrayList<String>();
29 int stackSize = 0;
30 int loops = 0;
31
32 Frame(Frame parent) {
33 this.parent = parent;
34 }
35 }
36
25 int nEquals; 37 int nEquals;
26 int parens = 0; 38 int parens = 0;
27 List<String> symbols = new ArrayList<String>(); 39 Frame frame = new Frame(null);
28 int stackSize = 0;
29 int loops = 0;
30 40
31 boolean nEquals(int n) { 41 boolean nEquals(int n) {
32 nEquals = n; 42 nEquals = n;
33 return true; 43 return true;
34 } 44 }
41 boolean decParens() { 51 boolean decParens() {
42 parens--; 52 parens--;
43 return true; 53 return true;
44 } 54 }
45 55
56 List<String> symbols() {
57 return frame.symbols;
58 }
59
60 int symbolsSize() {
61 return frame.symbols.size();
62 }
63
64 boolean addSymbol(String name) {
65 frame.symbols.add(name);
66 if( frame.stackSize < symbolsSize() )
67 frame.stackSize = symbolsSize();
68 return true;
69 }
70
46 int index(String name) { 71 int index(String name) {
72 List<String> symbols = frame.symbols;
47 int i = symbols.size(); 73 int i = symbols.size();
48 while( --i >= 0 ) { 74 while( --i >= 0 ) {
49 if( symbols.get(i).equals(name) ) 75 if( symbols.get(i).equals(name) )
50 return i; 76 return i;
51 } 77 }
52 return -1; 78 return -1;
53 } 79 }
54 80
55 boolean popSymbols(int n) { 81 boolean popSymbols(int n) {
82 List<String> symbols = frame.symbols;
56 while( n-- > 0 ) { 83 while( n-- > 0 ) {
57 symbols.remove(symbols.size()-1); 84 symbols.remove(symbols.size()-1);
58 } 85 }
59 return true; 86 return true;
60 } 87 }
61 88
62 boolean incLoops() { 89 boolean incLoops() {
63 loops++; 90 frame.loops++;
64 return true; 91 return true;
65 } 92 }
66 93
67 boolean decLoops() { 94 boolean decLoops() {
68 loops--; 95 frame.loops--;
69 return true; 96 return true;
70 } 97 }
71 98
72 99
73 public Rule Target() { 100 public Rule Target() {
74 return Sequence( 101 return Sequence(
75 Spaces(), 102 Spaces(),
76 FirstOf( 103 FirstOf(
77 Sequence( ExpList(), EOI ), 104 Sequence( ExpList(), EOI ),
78 Sequence( Chunk(), EOI ) 105 Sequence(
79 ) 106 Block(),
80 ); 107 EOI,
81 } 108 push( new Chunk( (Stmt)pop(), frame.stackSize, 0 ) )
82 109 )
83 Rule Chunk() { 110 )
84 return Sequence(
85 Block(),
86 push( new Chunk( (Stmt)pop(), stackSize ) )
87 ); 111 );
88 } 112 }
89 113
90 Rule Block() { 114 Rule Block() {
91 Var<List<Stmt>> stmts = new Var<List<Stmt>>(new ArrayList<Stmt>()); 115 Var<List<Stmt>> stmts = new Var<List<Stmt>>(new ArrayList<Stmt>());
92 Var<Integer> stackStart = new Var<Integer>(symbols.size()); 116 Var<Integer> stackStart = new Var<Integer>(symbolsSize());
93 return Sequence( 117 return Sequence(
94 Optional( Stmt(stmts) ), 118 Optional( Stmt(stmts) ),
95 ZeroOrMore( 119 ZeroOrMore(
96 StmtSep(), 120 StmtSep(),
97 Optional( Stmt(stmts) ) 121 Optional( Stmt(stmts) )
99 push( newBlock(stmts.get(),stackStart.get()) ) 123 push( newBlock(stmts.get(),stackStart.get()) )
100 ); 124 );
101 } 125 }
102 126
103 Stmt newBlock(List<Stmt> stmts,int stackStart) { 127 Stmt newBlock(List<Stmt> stmts,int stackStart) {
104 if( stackSize < symbols.size() ) 128 int stackEnd = symbolsSize();
105 stackSize = symbols.size();
106 int stackEnd = symbols.size();
107 popSymbols( stackEnd - stackStart ); 129 popSymbols( stackEnd - stackStart );
108 if( stmts.isEmpty() ) 130 if( stmts.isEmpty() )
109 return Stmt.EMPTY; 131 return Stmt.EMPTY;
110 if( stmts.size()==1 && stackStart==stackEnd ) 132 if( stmts.size()==1 && stackStart==stackEnd )
111 return stmts.get(0); 133 return stmts.get(0);
132 Rule Stmt(Var<List<Stmt>> stmts) { 154 Rule Stmt(Var<List<Stmt>> stmts) {
133 return FirstOf( 155 return FirstOf(
134 LocalStmt(stmts), 156 LocalStmt(stmts),
135 Sequence( 157 Sequence(
136 FirstOf( 158 FirstOf(
159 ReturnStmt(),
160 FunctionStmt(),
161 LocalFunctionStmt(),
137 BreakStmt(), 162 BreakStmt(),
138 GenericForStmt(), 163 GenericForStmt(),
139 NumericForStmt(), 164 NumericForStmt(),
140 DoStmt(), 165 DoStmt(),
141 WhileStmt(), 166 WhileStmt(),
147 stmts.get().add( (Stmt)pop() ) 172 stmts.get().add( (Stmt)pop() )
148 ) 173 )
149 ); 174 );
150 } 175 }
151 176
177 Rule ReturnStmt() {
178 return Sequence(
179 Keyword("return"), Expressions(),
180 push( new ReturnStmt( (Expressions)pop() ) )
181 );
182 }
183
184 Rule FunctionStmt() {
185 return Sequence(
186 Keyword("function"), FnName(), Function(),
187 push( new SetStmt( (Settable)pop(1), expr(pop()) ) )
188 );
189 }
190
191 Rule FnName() {
192 return Sequence(
193 push(null), // marker
194 Name(),
195 ZeroOrMore(
196 '.', Spaces(),
197 makeVarExp(),
198 NameExpr()
199 ),
200 makeSettableVar()
201 );
202 }
203
204 Rule LocalFunctionStmt() {
205 return Sequence(
206 Keyword("local"), Keyword("function"), LocalName(), Function(),
207 push( new SetStmt( new SetLocalVar(symbolsSize()-1), expr(pop()) ) )
208 );
209 }
210
152 Rule BreakStmt() { 211 Rule BreakStmt() {
153 return Sequence( 212 return Sequence(
154 Keyword("break"), 213 Keyword("break"),
155 loops > 0, 214 frame.loops > 0,
156 push( new BreakStmt() ) 215 push( new BreakStmt() )
157 ); 216 );
158 } 217 }
159 218
160 Rule GenericForStmt() { 219 Rule GenericForStmt() {
161 Var<Integer> stackStart = new Var<Integer>(symbols.size()); 220 Var<Integer> stackStart = new Var<Integer>(symbolsSize());
162 return Sequence( 221 return Sequence(
163 Keyword("for"), NameList(), Keyword("in"), Expr(), Keyword("do"), LoopBlock(), Keyword("end"), 222 Keyword("for"), NameList(), Keyword("in"), Expr(), Keyword("do"), LoopBlock(), Keyword("end"),
164 push( new GenericForStmt( stackStart.get(), symbols.size() - stackStart.get(), expr(pop(1)), (Stmt)pop() ) ), 223 push( new GenericForStmt( stackStart.get(), symbolsSize() - stackStart.get(), expr(pop(1)), (Stmt)pop() ) ),
165 popSymbols( symbols.size() - stackStart.get() ) 224 popSymbols( symbolsSize() - stackStart.get() )
166 ); 225 );
167 } 226 }
168 227
169 Rule NumericForStmt() { 228 Rule NumericForStmt() {
170 return Sequence( 229 return Sequence(
173 Optional( 232 Optional(
174 ',', Spaces(), 233 ',', Spaces(),
175 drop(), 234 drop(),
176 Expr() 235 Expr()
177 ), 236 ),
178 symbols.add( (String)pop(3) ), // add "for" var to symbols 237 addSymbol( (String)pop(3) ), // add "for" var to symbols
179 Keyword("do"), LoopBlock(), Keyword("end"), 238 Keyword("do"), LoopBlock(), Keyword("end"),
180 push( new NumericForStmt( symbols.size()-1, expr(pop(3)), expr(pop(2)), expr(pop(1)), (Stmt)pop() ) ), 239 push( new NumericForStmt( symbolsSize()-1, expr(pop(3)), expr(pop(2)), expr(pop(1)), (Stmt)pop() ) ),
181 popSymbols(1) 240 popSymbols(1)
182 ); 241 );
183 } 242 }
184 243
185 Rule DoStmt() { 244 Rule DoStmt() {
187 Keyword("do"), Block(), Keyword("end") 246 Keyword("do"), Block(), Keyword("end")
188 ); 247 );
189 } 248 }
190 249
191 Rule LocalStmt(Var<List<Stmt>> stmts) { 250 Rule LocalStmt(Var<List<Stmt>> stmts) {
192 Var<Integer> stackStart = new Var<Integer>(symbols.size()); 251 Var<Integer> stackStart = new Var<Integer>(symbolsSize());
193 return Sequence( 252 return Sequence(
194 Keyword("local"), NameList(), 253 Keyword("local"), NameList(),
195 Optional( 254 Optional(
196 '=', Spaces(), ExpList(), 255 '=', Spaces(), ExpList(),
197 stmts.get().add( newSetLocalStmt(stackStart.get()) ) 256 stmts.get().add( newSetLocalStmt(stackStart.get()) )
199 ); 258 );
200 } 259 }
201 260
202 Rule NameList() { 261 Rule NameList() {
203 return Sequence( 262 return Sequence(
263 LocalName(),
264 ZeroOrMore(
265 ',', Spaces(), LocalName()
266 )
267 );
268 }
269
270 Rule LocalName() {
271 return Sequence(
204 Name(), 272 Name(),
205 symbols.add( (String)pop() ), 273 addSymbol( (String)pop() )
206 ZeroOrMore(
207 ',', Spaces(), Name(),
208 symbols.add( (String)pop() )
209 )
210 ); 274 );
211 } 275 }
212 276
213 SetStmt newSetLocalStmt(int stackStart) { 277 SetStmt newSetLocalStmt(int stackStart) {
214 Expressions values = (Expressions)pop(); 278 Expressions values = (Expressions)pop();
215 SetLocalVar[] vars = new SetLocalVar[symbols.size()-stackStart]; 279 SetLocalVar[] vars = new SetLocalVar[symbolsSize()-stackStart];
216 for( int i=0; i<vars.length; i++ ) { 280 for( int i=0; i<vars.length; i++ ) {
217 vars[i] = new SetLocalVar(stackStart+i); 281 vars[i] = new SetLocalVar(stackStart+i);
218 } 282 }
219 return new SetStmt( vars, values ); 283 return new SetStmt( vars, values );
220 } 284 }
287 List<Settable> vars = (List<Settable>)pop(); 351 List<Settable> vars = (List<Settable>)pop();
288 return new SetStmt( vars.toArray(new Settable[0]), values ); 352 return new SetStmt( vars.toArray(new Settable[0]), values );
289 } 353 }
290 354
291 Rule VarList() { 355 Rule VarList() {
292 return Sequence( 356 Var<List<Settable>> vars = new Var<List<Settable>>(new ArrayList<Settable>());
293 push(new ArrayList<Settable>()), 357 return Sequence(
294 Var(), 358 SettableVar(),
295 addToVarList(), 359 vars.get().add( (Settable)pop() ),
296 ZeroOrMore( 360 ZeroOrMore(
297 ',', Spaces(), Var(), 361 ',', Spaces(), SettableVar(),
298 addToVarList() 362 vars.get().add( (Settable)pop() )
299 ) 363 ),
300 ); 364 push(vars.get())
301 } 365 );
302 366 }
303 boolean addToVarList() { 367
368 Rule SettableVar() {
369 return Sequence( Var(), makeSettableVar() );
370 }
371
372 boolean makeSettableVar() {
304 Object obj2 = pop(); 373 Object obj2 = pop();
305 if( obj2==null ) 374 if( obj2==null )
306 return false; 375 return false;
307 Object obj1 = pop(); 376 Object obj1 = pop();
308 @SuppressWarnings("unchecked")
309 List<Settable> vars = (List<Settable>)peek();
310 if( obj1==null ) { 377 if( obj1==null ) {
311 String name = (String)obj2; 378 String name = (String)obj2;
312 int index = index(name); 379 int index = index(name);
313 if( index == -1 ) { 380 if( index == -1 ) {
314 vars.add( new SetTableEntry( EnvExpr.INSTANCE, new ConstExpr(name) ) ); 381 push( new SetTableEntry( EnvExpr.INSTANCE, new ConstExpr(name) ) );
315 } else { 382 } else {
316 vars.add( new SetLocalVar(index) ); 383 push( new SetLocalVar(index) );
317 } 384 }
318 } else { 385 } else {
319 Expr key = expr(obj2); 386 Expr key = expr(obj2);
320 Expr table = expr(obj1); 387 Expr table = expr(obj1);
321 vars.add( new SetTableEntry(table,key) ); 388 push( new SetTableEntry(table,key) );
322 } 389 }
323 return true; 390 return true;
324 } 391 }
325 392
326 Rule Expr() { 393 Rule Expr() {
405 ); 472 );
406 } 473 }
407 474
408 Rule SingleExpr() { 475 Rule SingleExpr() {
409 return FirstOf( 476 return FirstOf(
477 FunctionExpr(),
410 TableExpr(), 478 TableExpr(),
411 VarExp(), 479 VarExp(),
412 LiteralExpr() 480 LiteralExpr()
481 );
482 }
483
484 Rule FunctionExpr() {
485 return Sequence( "function", Spaces(), Function() );
486 }
487
488 Rule Function() {
489 return Sequence(
490 action( frame = new Frame(frame) ),
491 '(', incParens(), Spaces(), Optional(NameList()), ')', decParens(), Spaces(), Block(), Keyword("end"),
492 push( new Chunk( (Stmt)pop(), frame.stackSize, symbolsSize() ) ),
493 action( frame = frame.parent )
413 ); 494 );
414 } 495 }
415 496
416 Rule TableExpr() { 497 Rule TableExpr() {
417 return Sequence( 498 return Sequence(