compiler/libec2: Indentation, empty statements fixes
[sdk] / compiler / libec2 / src / statements.ec
1 import "expressions"
2 import "externals"
3
4 public class ASTPropertyWatch : ASTNode
5 {
6 public:
7    ASTStatement compound;
8    List<ASTIdentifier> properties;
9    bool deleteWatch;
10 };
11
12 /*
13 class AsmField : struct
14 {
15    AsmField prev, next;
16    Location loc;
17    char * command;
18    Expression expression;
19 };
20 */
21
22 // *** Statements ***
23 public class ASTStmtOrDecl : ASTNode
24 {
25    ASTStmtOrDecl ::parse()
26    {
27       SpecsList specs = null;
28       InitDeclList decls = null;
29       bool isType = false;
30
31       peekToken();
32       if(nextToken.type.isSpecifier || (nextToken.type == IDENTIFIER && isType))
33       {
34          specs = SpecsList::parse();
35          decls = InitDeclList::parse();
36          return ASTDeclaration::parse(specs, decls);
37       }
38       else if(nextToken.type == IDENTIFIER)
39       {
40          ASTStatement stmt;
41          int a = pushAmbiguity();
42          stmt = ASTStatement::parse();
43          if(stmt)
44          {
45             clearAmbiguity();
46             return stmt;
47          }
48          popAmbiguity(a);
49          specs = SpecsList::parse();
50          if(specs)
51             decls = InitDeclList::parse();
52          if(specs && decls)
53             return ASTDeclaration::parse(specs, decls);
54          else
55             return null;
56       }
57       else
58          return ASTStatement::parse();
59    }
60 }
61
62 public class ASTStatement : ASTStmtOrDecl
63 {
64 public:
65    StmtType type;
66
67    ASTStatement ::parse()
68    {
69       switch(peekToken().type)
70       {
71          case ';':      readToken(); return { };
72          case '{':      return StmtCompound::parse();
73          case IF:       return StmtIf::parse();
74          case SWITCH:   return StmtSwitch::parse();
75          case DEFAULT:
76          case CASE:     return StmtCase::parse();
77          case WHILE:    return StmtWhile::parse();
78          case DO:       return StmtDoWhile::parse();
79          case FOR:      return StmtFor::parse();
80          case BREAK:    return StmtBreak::parse();
81          case GOTO:     return StmtGoto::parse();
82          case RETURN:   return StmtReturn::parse();
83          case CONTINUE: return StmtContinue::parse();
84          case IDENTIFIER:
85          {
86             ASTStatement stmt;
87             int a = pushAmbiguity();
88             stmt = StmtLabeled::parse();
89             if(stmt)
90             {
91                clearAmbiguity();
92                return stmt;
93             }
94             popAmbiguity(a);
95          }
96          default:       return StmtExpression::parse();
97       }
98    }
99
100    void print()
101    {
102       PrintLn(";");
103    }
104 };
105
106 public class StmtExpression : ASTStatement
107 {
108    ExpList expressions;
109
110    void print()
111    {
112       if(expressions) expressions.print();
113       Print(";");
114    }
115
116    StmtExpression ::parse()
117    {
118       ExpList exp = ExpList::parse();
119       if(exp)
120       {
121          StmtExpression stmt { expressions = exp };
122          if(peekToken().type == ';')
123             readToken();
124          else
125          {
126             if(ambiguous)
127                delete stmt;
128          }
129          return stmt;
130       }
131       return null;
132    }
133 }
134 int indent;
135 void printIndent()
136 {
137    int i;
138    for(i = 0; i < indent; i++)
139    {
140       Print("   ");
141    }
142 }
143
144 public class StmtCompound : ASTStatement
145 {
146    List<ASTDeclaration> declarations;
147    List<ASTStatement> statements;
148    // Context context;
149    // bool isSwitch;
150
151    void print()
152    {
153       printIndent();
154       PrintLn("{");
155       indent++;
156       if(declarations)
157       {
158          for(d : declarations)
159          {
160             printIndent();
161             d.print();
162             PrintLn("");
163          }
164          if(statements)
165             PrintLn("");
166       }
167       if(statements)
168       {
169          for(s : statements)
170          {
171             if(s._class == class(StmtCase))
172                indent = caseIndent;
173             if(s._class != class(StmtLabeled) && s._class != class(StmtCompound))
174                printIndent();
175             s.print();
176             if(s._class == class(StmtExpression)) 
177                PrintLn("");
178          }
179       }
180       indent--;
181       if(indent == caseIndent)
182          indent--;
183       printIndent();
184       PrintLn("}");
185    }
186
187    StmtCompound ::parse()
188    {
189       StmtCompound stmt { };
190       if(peekToken().type == '{')
191       {
192          bool inDecls = true;
193          readToken();
194          while(true)
195          {
196             if(peekToken().type == '}')
197             {
198                readToken();
199                break;
200             }
201             else if(!nextToken)
202                break;
203             else
204             {
205                ASTStmtOrDecl sod = ASTStmtOrDecl::parse();
206                if(sod)
207                {
208                   if(eClass_IsDerived(sod._class, class(ASTDeclaration)))
209                   {
210                      ASTDeclaration decl = (ASTDeclaration)sod;
211                      if(!stmt.declarations) stmt.declarations = { };
212                      if(inDecls)
213                         stmt.declarations.Add(decl);
214                      else
215                         stmt.statements.Add(StmtDecl { decl = decl });
216                   }
217                   else
218                   {
219                      ASTStatement s = (ASTStatement)sod;
220                      if(!stmt.statements) stmt.statements = { };
221                      stmt.statements.Add(s);
222                      inDecls = false;
223                   }
224                }
225                else
226                {
227                   // ERROR
228                   /*while(readToken())
229                      if(token == ';' || token == '}') break;*/
230                   readToken();
231                }
232             }
233          }
234       }
235       return stmt;
236    }
237 }
238
239 public class StmtIf : ASTStatement
240 {
241    ExpList exp;
242    ASTStatement stmt;
243    ASTStatement elseStmt;
244
245    void print()
246    {
247       Print("if(");
248       if(exp) exp.print();
249       PrintLn(")");
250       if(stmt)
251       {
252          if(stmt._class != class(StmtCompound)) indent++;
253          printIndent();
254          stmt.print();
255          if(stmt._class == class(StmtExpression)) PrintLn(""); 
256          if(stmt._class != class(StmtCompound)) indent--;
257       }
258       if(elseStmt)
259       {
260          printIndent();
261          Print("else");
262          if(elseStmt._class != class(StmtCompound)) { PrintLn(""); indent++; }
263          printIndent();
264          if(elseStmt._class != class(StmtCompound)) elseStmt.print();
265          if(elseStmt._class == class(StmtExpression)) PrintLn(""); 
266          indent--;
267       }
268    }
269
270    StmtIf ::parse()
271    {
272       StmtIf stmt { };
273       readToken();
274       if(peekToken().type == '(')
275       {
276          readToken();
277          stmt.exp = ExpList::parse();
278          if(peekToken().type == ')') readToken();
279          stmt.stmt = ASTStatement::parse();
280          if(peekToken().type == ELSE)
281          {
282             readToken();
283             stmt.elseStmt = ASTStatement::parse();
284          }
285       }
286       return stmt;
287    }
288 }
289
290 int caseIndent = -1;
291
292 public class StmtSwitch : ASTStatement
293 {
294    ExpList exp;
295    ASTStatement stmt;
296
297    void print()
298    {
299       int backCaseIndent = caseIndent;
300       Print("switch(");
301       if(exp) exp.print();
302       PrintLn(")");
303       if(stmt)
304       {
305          caseIndent = indent+1;
306          stmt.print();
307          indent = caseIndent-1;
308       }
309       caseIndent = backCaseIndent;
310    }
311
312    StmtSwitch ::parse()
313    {
314       StmtSwitch stmt { };
315       readToken();
316       if(peekToken().type == '(')
317       {
318          readToken();
319          stmt.exp = ExpList::parse();
320          if(peekToken().type == ')') readToken();
321          stmt.stmt = ASTStatement::parse();
322       }
323       return stmt;
324    }
325 }
326
327 public class StmtLabeled : ASTStatement
328 {
329    ASTIdentifier id;
330    ASTStatement stmt;
331
332    void print()
333    {
334       if(id) id.print();
335       PrintLn(":");
336       if(stmt) stmt.print();
337    }
338
339    StmtLabeled ::parse()
340    {
341       ASTIdentifier id = ASTIdentifier::parse();
342       if(peekToken().type == ':')
343          return StmtLabeled { id = id, stmt = ASTStatement::parse() };
344       delete id;
345       return null;
346    }
347 }
348
349 public class StmtCase : ASTStatement
350 {
351    ASTExpression exp;
352    ASTStatement stmt;
353
354    void print()
355    {
356       if(exp)
357       {
358          Print("case ");
359          exp.print();
360          PrintLn(":");
361       }
362       else
363          PrintLn("default:");
364       if(stmt)
365       {
366          if(stmt._class != class(StmtCompound)) indent++;
367          printIndent();
368          stmt.print();
369          if(stmt._class == class(StmtExpression)) PrintLn(""); 
370       }
371    }
372
373    StmtCase ::parse()
374    {
375       StmtCase stmt { };
376       if(readToken().type == CASE)
377          stmt.exp = ExpConditional::parse();
378       if(peekToken().type == ':')
379       {
380          readToken();
381          stmt.stmt = ASTStatement::parse();
382       }
383       return stmt;
384    }
385 }
386
387 public class StmtWhile : ASTStatement
388 {
389    ExpList exp;
390    ASTStatement stmt;
391
392    StmtWhile ::parse()
393    {
394       StmtWhile stmt { };
395       readToken();
396       if(peekToken().type == '(')
397       {
398          readToken();
399          stmt.exp = ExpList::parse();
400          if(peekToken().type == ')') readToken();
401          stmt.stmt = ASTStatement::parse();
402       }
403       return stmt;
404    }
405 }
406
407 public class StmtDoWhile : ASTStatement
408 {
409    ExpList exp;
410    ASTStatement stmt;
411
412    StmtDoWhile ::parse()
413    {
414       StmtDoWhile stmt { };
415       readToken();
416       stmt.stmt = ASTStatement::parse();
417       if(peekToken().type == WHILE)
418       {
419          readToken();
420          if(peekToken().type == '(')
421          {
422             readToken();
423             stmt.exp = ExpList::parse();
424             if(peekToken().type == ')') readToken();
425          }
426          if(peekToken().type == ';') readToken();
427       }
428       return stmt;
429    }
430 }
431
432 public class StmtFor : ASTStatement
433 {
434    ASTStatement init;
435    ASTStatement check;
436    ExpList increment;
437    ASTStatement stmt;
438
439    void print()
440    {
441       Print("for(");
442       if(init)
443          init.print();
444       if(check)
445       {
446          Print(" ");
447          check.print();
448       }
449       if(increment)
450       {
451          Print(" ");
452          increment.print();
453       }
454       PrintLn(")");
455       
456       if(stmt)
457       {
458          if(stmt._class != class(StmtCompound)) indent++;
459          printIndent();
460          stmt.print();
461          if(stmt._class == class(StmtExpression)) PrintLn(""); 
462          if(stmt._class != class(StmtCompound)) indent--;
463       }
464    }
465
466    StmtFor ::parse()
467    {
468       StmtFor stmt { };
469       readToken();
470       if(peekToken().type == '(')
471       {
472          readToken();
473          stmt.init = ASTStatement::parse();
474          stmt.check = ASTStatement::parse();
475          stmt.increment = ExpList::parse();
476          if(peekToken().type == ')')
477          {
478             readToken();
479             stmt.stmt = ASTStatement::parse();
480          }
481       }
482       return stmt;
483    }
484 }
485
486 public class StmtBreak : ASTStatement
487 {
488    void print()
489    {
490       PrintLn("break;");
491    }
492
493    StmtBreak ::parse()
494    {
495       readToken();
496       if(peekToken().type == ';') readToken();
497       return { };
498    }
499 }
500
501 public class StmtContinue : ASTStatement
502 {
503    void print()
504    {
505       PrintLn("continue;");
506    }
507
508    StmtContinue ::parse()
509    {
510       readToken();
511       if(peekToken().type == ';') readToken();
512       return { };
513    }
514 }
515
516 public class StmtReturn : ASTStatement
517 {
518    ExpList exp;
519    void print()
520    {
521       Print("return");
522       if(exp)
523       {
524          Print(" ");
525          exp.print();
526       }
527       ::PrintLn(";");
528    }
529
530    StmtReturn ::parse()
531    {
532       StmtReturn stmt { };
533       readToken();
534       if(peekToken().type != ';') stmt.exp = ExpList::parse();
535       if(peekToken().type == ';') readToken();
536       return stmt;
537    }
538 }
539
540 public class StmtGoto : ASTStatement
541 {
542    ASTIdentifier id;
543
544    void print()
545    {
546       Print("goto ");
547       if(id) id.print();
548       ::PrintLn(";");
549    }
550
551    StmtGoto ::parse()
552    {
553       StmtGoto stmt { };
554       readToken();
555       stmt.id = ASTIdentifier::parse();
556       if(peekToken().type == ';') readToken();
557       return stmt;
558    }
559 }
560
561 public class StmtAsm : ASTStatement
562 {
563    ASTSpecifier spec;
564    String statements;
565    List<String> inputFields;
566    List<String> outputFields;
567    List<String> clobberedFields;
568 }
569
570 public class StmtWatch : ASTStatement
571 {
572    ASTExpression watcher, object;
573    List<ASTPropertyWatch> watches;
574 }
575
576 public class StmtFireWatch : ASTStatement
577 {
578    ASTExpression watcher, object;
579    List<ASTIdentifiers> watches;
580 }
581
582 public class StmtStopWatching : ASTStatement
583 {
584    ASTExpression watcher, object;
585    List<ASTIdentifiers> watches;
586 }
587
588 public class StmtForEach : ASTStatement
589 {
590    Identifier id;
591    ExpList exp;
592    ExpList filter;
593    Statement stmt;
594 }
595
596 public class StmtDecl : ASTStatement
597 {
598    ASTDeclaration decl;
599
600    void print()
601    {
602       if(decl) { decl.print(); PrintLn(""); }
603    }
604 }