Mercurial Hosting > luan
comparison src/luan/interp/LuaParser.java @ 14:2ddf85634d20
whitespace handling;
comments;
if/while/repeat statements;
git-svn-id: https://luan-java.googlecode.com/svn/trunk@15 21e917c8-12df-6dd8-5cb6-c86387c605b9
author | fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9> |
---|---|
date | Mon, 26 Nov 2012 10:18:46 +0000 |
parents | 9cea1aea5eef |
children | bb59d7ea223b |
comparison
equal
deleted
inserted
replaced
13:3b22ffbdb83a | 14:2ddf85634d20 |
---|---|
9 import org.parboiled.BaseParser; | 9 import org.parboiled.BaseParser; |
10 import org.parboiled.Parboiled; | 10 import org.parboiled.Parboiled; |
11 import org.parboiled.Rule; | 11 import org.parboiled.Rule; |
12 import org.parboiled.parserunners.ReportingParseRunner; | 12 import org.parboiled.parserunners.ReportingParseRunner; |
13 import org.parboiled.support.ParsingResult; | 13 import org.parboiled.support.ParsingResult; |
14 import org.parboiled.support.Var; | |
15 import org.parboiled.support.StringVar; | |
16 import org.parboiled.support.ValueStack; | |
14 import org.parboiled.errors.ErrorUtils; | 17 import org.parboiled.errors.ErrorUtils; |
15 import luan.Lua; | 18 import luan.Lua; |
16 import luan.LuaNumber; | 19 import luan.LuaNumber; |
17 import luan.LuaState; | 20 import luan.LuaState; |
18 | 21 |
19 | 22 |
20 public class LuaParser extends BaseParser<Object> { | 23 public class LuaParser extends BaseParser<Object> { |
24 static final Object PAREN = new Object(); | |
21 | 25 |
22 public Rule Target() { | 26 public Rule Target() { |
23 return Sequence( | 27 return Sequence( |
24 Spaces(), | 28 Spaces(), |
25 FirstOf( | 29 FirstOf( |
49 return true; | 53 return true; |
50 } | 54 } |
51 | 55 |
52 Stmt newChunk() { | 56 Stmt newChunk() { |
53 @SuppressWarnings("unchecked") | 57 @SuppressWarnings("unchecked") |
54 List<Stmt> stmts = (List<Stmt>)peek(); | 58 List<Stmt> stmts = (List<Stmt>)pop(); |
55 switch( stmts.size() ) { | 59 switch( stmts.size() ) { |
56 case 0: | 60 case 0: |
57 return Stmt.EMPTY; | 61 return Stmt.EMPTY; |
58 case 1: | 62 case 1: |
59 return stmts.get(0); | 63 return stmts.get(0); |
61 return new Block(stmts.toArray(new Stmt[0])); | 65 return new Block(stmts.toArray(new Stmt[0])); |
62 } | 66 } |
63 } | 67 } |
64 | 68 |
65 Rule StmtSep() { | 69 Rule StmtSep() { |
66 return Sequence( OneOrMore(AnyOf(";\r\n")), Spaces() ); | 70 return Sequence( |
71 FirstOf( | |
72 ';', | |
73 Sequence( | |
74 Optional( "--", ZeroOrMore(NoneOf("\r\n")) ), | |
75 EndOfLine() | |
76 ) | |
77 ), | |
78 Spaces() | |
79 ); | |
80 } | |
81 | |
82 Rule EndOfLine() { | |
83 return FirstOf("\r\n", '\r', '\n'); | |
67 } | 84 } |
68 | 85 |
69 Rule Stmt() { | 86 Rule Stmt() { |
70 return Sequence( | 87 return Sequence( |
71 FirstOf( | 88 FirstOf( |
89 WhileStmt(), | |
90 RepeatStmt(), | |
91 IfStmt(), | |
72 SetStmt(), | 92 SetStmt(), |
73 ExpressionsStmt() | 93 ExpressionsStmt() |
74 ), | 94 ), |
75 addStmt() | 95 addStmt() |
76 ); | 96 ); |
77 } | 97 } |
78 | 98 |
79 Rule ExpressionsStmt() { | 99 Rule WhileStmt() { |
80 return Sequence( | 100 return Sequence( |
81 ExpList(), | 101 "while", Spaces(), Expr(), "do", Spaces(), Chunk(), "end", Spaces(), |
82 push( new ExpressionsStmt((Expressions)pop()) ) | 102 push( new WhileStmt( expr(pop(1)), (Stmt)pop() ) ) |
83 ); | 103 ); |
104 } | |
105 | |
106 Rule RepeatStmt() { | |
107 return Sequence( | |
108 "repeat", Spaces(), Chunk(), "until", Spaces(), Expr(), | |
109 push( new RepeatStmt( (Stmt)pop(1), expr(pop()) ) ) | |
110 ); | |
111 } | |
112 | |
113 Rule IfStmt() { | |
114 Var<Integer> n = new Var<Integer>(1); | |
115 return Sequence( | |
116 "if", Spaces(), Expr(), "then", Spaces(), Chunk(), | |
117 push(Stmt.EMPTY), | |
118 ZeroOrMore( | |
119 "elseif", Spaces(), drop(), Expr(), "then", Spaces(), Chunk(), | |
120 push(Stmt.EMPTY), | |
121 n.set(n.get()+1) | |
122 ), | |
123 Optional( | |
124 "else", Spaces(), drop(), Chunk() | |
125 ), | |
126 "end", Spaces(), | |
127 buildIfStmt(n.get()) | |
128 ); | |
129 } | |
130 | |
131 boolean buildIfStmt(int n) { | |
132 while( n-- > 0 ) { | |
133 Stmt elseStmt = (Stmt)pop(); | |
134 Stmt thenStmt = (Stmt)pop(); | |
135 Expr cnd = expr(pop()); | |
136 push( new IfStmt(cnd,thenStmt,elseStmt) ); | |
137 } | |
138 return true; | |
84 } | 139 } |
85 | 140 |
86 Rule SetStmt() { | 141 Rule SetStmt() { |
87 return Sequence( | 142 return Sequence( |
88 VarList(), | 143 VarList(), |
89 '=', Spaces(), | 144 '=', Spaces(), |
90 ExpList(), | 145 ExpList(), |
91 push( newSetStmt() ) | 146 push( newSetStmt() ) |
147 ); | |
148 } | |
149 | |
150 Rule ExpressionsStmt() { | |
151 return Sequence( | |
152 ExpList(), | |
153 push( new ExpressionsStmt((Expressions)pop()) ) | |
92 ); | 154 ); |
93 } | 155 } |
94 | 156 |
95 SetStmt newSetStmt() { | 157 SetStmt newSetStmt() { |
96 Expressions values = (Expressions)pop(); | 158 Expressions values = (Expressions)pop(); |
168 return Sequence( | 230 return Sequence( |
169 TermExpr(), | 231 TermExpr(), |
170 ZeroOrMore( | 232 ZeroOrMore( |
171 FirstOf( | 233 FirstOf( |
172 Sequence( '+', Spaces(), TermExpr(), push( new AddExpr(expr(pop(1)),expr(pop())) ) ), | 234 Sequence( '+', Spaces(), TermExpr(), push( new AddExpr(expr(pop(1)),expr(pop())) ) ), |
173 Sequence( '-', Spaces(), TermExpr(), push( new SubExpr(expr(pop(1)),expr(pop())) ) ) | 235 Sequence( '-', TestNot('-'), Spaces(), TermExpr(), push( new SubExpr(expr(pop(1)),expr(pop())) ) ) |
174 ) | 236 ) |
175 ) | 237 ) |
176 ); | 238 ); |
177 } | 239 } |
178 | 240 |
190 } | 252 } |
191 | 253 |
192 Rule UnaryExpr() { | 254 Rule UnaryExpr() { |
193 return FirstOf( | 255 return FirstOf( |
194 Sequence( '#', Spaces(), PowExpr(), push( new LenExpr(expr(pop())) ) ), | 256 Sequence( '#', Spaces(), PowExpr(), push( new LenExpr(expr(pop())) ) ), |
195 Sequence( '-', Spaces(), PowExpr(), push( new UnmExpr(expr(pop())) ) ), | 257 Sequence( '-', TestNot('-'), Spaces(), PowExpr(), push( new UnmExpr(expr(pop())) ) ), |
196 Sequence( "not", Spaces(), PowExpr(), push( new NotExpr(expr(pop())) ) ), | 258 Sequence( "not", Spaces(), PowExpr(), push( new NotExpr(expr(pop())) ) ), |
197 PowExpr() | 259 PowExpr() |
198 ); | 260 ); |
199 } | 261 } |
200 | 262 |
214 } | 276 } |
215 | 277 |
216 Rule TableExpr() { | 278 Rule TableExpr() { |
217 return Sequence( | 279 return Sequence( |
218 '{', Spaces(), | 280 '{', Spaces(), |
281 push(PAREN), | |
219 push( new ArrayList<TableExpr.Field>() ), | 282 push( new ArrayList<TableExpr.Field>() ), |
220 push( 1.0 ), // counter | 283 push( 1.0 ), // counter |
221 Optional( | 284 Optional( |
222 Field(), | 285 Field(), |
223 ZeroOrMore( | 286 ZeroOrMore( |
224 FieldSep(), | 287 FieldSep(), |
225 Field() | 288 Field() |
226 ), | 289 ), |
227 Optional( FieldSep() ) | 290 Optional( FieldSep() ) |
228 ), | 291 ), |
229 '}', Spaces(), | 292 '}', |
230 push( newTableExpr() ) | 293 push( newTableExpr() ), |
294 drop(1), | |
295 Spaces() | |
231 ); | 296 ); |
232 } | 297 } |
233 | 298 |
234 TableExpr newTableExpr() { | 299 TableExpr newTableExpr() { |
235 pop(); // counter | 300 pop(); // counter |
290 | 355 |
291 Rule Var() { | 356 Rule Var() { |
292 return Sequence( | 357 return Sequence( |
293 FirstOf( | 358 FirstOf( |
294 Sequence( | 359 Sequence( |
295 '(', Spaces(), Expr(), ')', Spaces(), | 360 '(', Spaces(), push(PAREN), Expr(), ')', drop(1), Spaces(), |
296 push(expr(pop())), | 361 push(expr(pop())), |
297 push(null) // marker | 362 push(null) // marker |
298 ), | 363 ), |
299 Sequence( | 364 Sequence( |
300 push(EnvExpr.INSTANCE), | 365 push(EnvExpr.INSTANCE), |
325 // function should be on top of the stack | 390 // function should be on top of the stack |
326 Rule Args() { | 391 Rule Args() { |
327 return Sequence( | 392 return Sequence( |
328 FirstOf( | 393 FirstOf( |
329 Sequence( | 394 Sequence( |
330 '(', Spaces(), Expressions(), ')', Spaces() | 395 '(', Spaces(), push(PAREN), Expressions(), ')', drop(1), Spaces() |
331 ), | 396 ), |
332 Sequence( | 397 Sequence( |
333 TableExpr(), | 398 TableExpr(), |
334 push( new ExpList.SingleExpList(expr(pop())) ) | 399 push( new ExpList.SingleExpList(expr(pop())) ) |
335 ), | 400 ), |
372 } | 437 } |
373 return true; | 438 return true; |
374 } | 439 } |
375 | 440 |
376 Rule SubExpr() { | 441 Rule SubExpr() { |
377 return Sequence( '[', Spaces(), Expr(), ']', Spaces() ); | 442 return Sequence( '[', Spaces(), push(PAREN), Expr(), ']', drop(1), Spaces() ); |
378 } | 443 } |
379 | 444 |
380 Rule Name() { | 445 Rule Name() { |
381 return Sequence( | 446 return Sequence( |
382 Sequence( | 447 Sequence( |
577 sb.append(ch); | 642 sb.append(ch); |
578 return true; | 643 return true; |
579 } | 644 } |
580 | 645 |
581 Rule Spaces() { | 646 Rule Spaces() { |
582 return ZeroOrMore(AnyOf(" \t")); | 647 return ZeroOrMore( |
648 FirstOf( | |
649 AnyOf(" \t"), | |
650 Comment(), | |
651 Sequence( '\\', EndOfLine() ), | |
652 Sequence( AnyOf("\r\n"), inParen() ) | |
653 ) | |
654 ); | |
655 } | |
656 | |
657 boolean inParen() { | |
658 ValueStack stack = getContext().getValueStack(); | |
659 int size = stack.size(); | |
660 for( int i=0; i<size; i++ ) { | |
661 if( peek(i) == PAREN ) | |
662 return true; | |
663 } | |
664 return false; | |
665 } | |
666 | |
667 Rule Comment() { | |
668 Var<Integer> n = new Var<Integer>(); | |
669 return Sequence( | |
670 "--[", | |
671 ZeroOrMore('='), | |
672 setN(n), | |
673 '[', | |
674 ZeroOrMore( | |
675 TestNot(CommentEnd(n)), | |
676 ANY | |
677 ), | |
678 CommentEnd(n) | |
679 ); | |
680 } | |
681 | |
682 Rule CommentEnd(Var<Integer> n) { | |
683 return Sequence( ']', ZeroOrMore('='), eqN(n), ']' ); | |
684 } | |
685 | |
686 boolean setN(Var<Integer> n) { | |
687 return n.set(matchLength()); | |
688 } | |
689 | |
690 boolean eqN(Var<Integer> n) { | |
691 return n.get()==matchLength(); | |
583 } | 692 } |
584 | 693 |
585 // for debugging | 694 // for debugging |
586 boolean print(String s) { | 695 boolean print(Object o) { |
587 System.out.println(s); | 696 System.out.println(o); |
588 return true; | 697 return true; |
589 } | 698 } |
590 | 699 |
591 // for testing | 700 // for testing |
592 public static void main(String[] args) throws Exception { | 701 public static void main(String[] args) throws Exception { |