Mercurial Hosting > luan
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( |