improved php parser for keywords do-while, null, false, true...
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / phpeditor / PHPParser.java
1 package net.sourceforge.phpeclipse.phpeditor;
2
3 import java.util.HashMap;
4
5 import net.sourceforge.phpeclipse.phpeditor.php.PHPKeywords;
6
7 /**********************************************************************
8 Copyright (c) 2000, 2002 IBM Corp. and others.
9 All rights reserved. This program and the accompanying materials
10 are made available under the terms of the Common Public License v1.0
11 which accompanies this distribution, and is available at
12 http://www.eclipse.org/legal/cpl-v10.html
13
14 Contributors:
15     IBM Corporation - Initial implementation
16     Klaus Hartlage - www.eclipseproject.de
17 **********************************************************************/
18
19 public class PHPParser extends PHPKeywords {
20
21   private static HashMap keywordMap = null;
22   private String str;
23
24   // current character
25   char ch;
26   // current token
27   int token;
28
29   // row counter for syntax errors:
30   int rowCount;
31   // column counter for syntax errors:
32   int columnCount;
33
34   int chIndx;
35
36   // current identifier
37   String identifier;
38
39   Long longNumber;
40   Double doubleNumber;
41
42   final static int TT_EOF = 0;
43   final static int TT_UNDEFINED = 1;
44
45   final static int TT_MOD = 30;
46   final static int TT_NOT = 31;
47   final static int TT_DOT = 32;
48   final static int TT_POW = 33;
49   final static int TT_DIV = 34;
50   final static int TT_MULTIPLY = 35;
51   final static int TT_SUBTRACT = 36;
52   final static int TT_ADD = 37;
53   final static int TT_EQUAL = 38;
54   final static int TT_UNEQUAL = 39;
55   final static int TT_GREATER = 40;
56   final static int TT_GREATEREQUAL = 41;
57   final static int TT_LESS = 42;
58   final static int TT_LESSEQUAL = 43;
59   final static int TT_AND = 44;
60   final static int TT_OR = 45;
61   final static int TT_HASH = 46;
62   final static int TT_DDOT = 47;
63   final static int TT_DOTASSIGN = 48;
64
65   final static int TT_ASSIGN = 49;
66   final static int TT_REF = 50;
67   final static int TT_FOREACH = 51;
68   final static int TT_AMPERSAND = 52;
69   final static int TT_DOLLARLISTOPEN = 53;
70   final static int TT_TILDE = 54;
71
72   final static int TT_ARGOPEN = 128;
73   final static int TT_ARGCLOSE = 129;
74   final static int TT_LISTOPEN = 130;
75   final static int TT_LISTCLOSE = 131;
76   final static int TT_PARTOPEN = 132;
77   final static int TT_PARTCLOSE = 133;
78   final static int TT_COMMA = 134;
79
80   final static int TT_STRING = 136;
81   final static int TT_IDENTIFIER = 138;
82   final static int TT_DIGIT = 139;
83   final static int TT_SEMICOLON = 140;
84   final static int TT_SLOT = 141;
85   final static int TT_SLOTSEQUENCE = 142;
86   final static int TT_DECREMENT = 144;
87   final static int TT_INCREMENT = 145;
88   final static int TT_ADDTO = 146;
89   final static int TT_DIVIDEBY = 147;
90   final static int TT_SUBTRACTFROM = 148;
91   final static int TT_TIMESBY = 149;
92   final static int TT_VARIABLE = 150;
93   final static int TT_INT_NUMBER = 151;
94   final static int TT_DOUBLE_NUMBER = 152;
95   final static int TT_INTERPOLATED_STRING = 153;
96   final static int TT_STRING_CONSTANT = 154;
97
98   final static int TT_LSHIFT = 155;
99   final static int TT_RSHIFT = 156;
100   final static int TT_EX_EQUAL = 157;
101   final static int TT_EX_UNEQUAL = 158;
102   final static int TT_LINE = 159;
103   //  final static int TT_AT = 153; // @
104   /**
105    *  Class Constructor.
106    *
107    *@param  s
108    *@param  sess  Description of Parameter
109    *@see
110    */
111   public PHPParser() {
112     if (keywordMap == null) {
113       keywordMap = new HashMap();
114       for (int i = 0; i < PHP_KEYWORS.length; i++) {
115         keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
116       }
117     }
118     this.str = "";
119     this.token = TT_EOF;
120     this.chIndx = 0;
121     this.rowCount = 1;
122     this.columnCount = 0;
123
124     getNextToken();
125   }
126
127   private void throwSyntaxError(String error) {
128
129     if (str.length() < chIndx) {
130       chIndx--;
131     }
132     // read until end-of-line
133     int eol = chIndx;
134     while (str.length() > eol) {
135       ch = str.charAt(eol++);
136       if (ch == '\n') {
137         eol--;
138         break;
139       }
140     }
141     throw new SyntaxError(rowCount, chIndx - columnCount + 1, str.substring(columnCount, eol), error);
142   }
143
144   /**
145    *  Method Declaration.
146    *
147    *@see
148    */
149   void getChar() {
150     if (str.length() > chIndx) {
151       ch = str.charAt(chIndx++);
152
153       return;
154     }
155
156     chIndx = str.length() + 1;
157     ch = ' ';
158     token = TT_EOF;
159   }
160
161   /**
162    * gets the next token from input
163    */
164   void getNextToken() {
165     while (str.length() > chIndx) {
166       ch = str.charAt(chIndx++);
167       token = TT_UNDEFINED;
168       if (ch == '\n') {
169         rowCount++;
170         columnCount = chIndx;
171         continue; // while loop
172       }
173
174       if (!Character.isWhitespace(ch)) {
175         if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_') || (ch == '$') || (ch == '@')) {
176           getIdentifier();
177           return;
178         }
179         if (ch >= '0' && ch <= '9') {
180           getNumber();
181           return;
182         }
183         if (ch == '/') {
184           if (str.length() > chIndx) {
185             if (str.charAt(chIndx) == '/') {
186               chIndx++;
187               // read comment until end of line:
188               while ((str.length() > chIndx) && (str.charAt(chIndx) != '\n')) {
189                 chIndx++;
190               }
191               continue;
192             } else if (str.charAt(chIndx) == '*') {
193               chIndx++;
194               // multi line comment:
195               while (str.length() > chIndx) {
196                 if (str.charAt(chIndx) == '*' && (str.length() > (chIndx + 1)) && str.charAt(chIndx + 1) == '/') {
197                   chIndx += 2;
198                   break;
199                 }
200                 ch = str.charAt(chIndx++);
201                 if (ch == '\n') {
202                   rowCount++;
203                   columnCount = chIndx;
204                 }
205               }
206               continue;
207             }
208           }
209         } else if (ch == '#') {
210           // read comment until end of line:
211           while ((str.length() > chIndx) && (str.charAt(chIndx) != '\n')) {
212             chIndx++;
213           }
214           continue;
215         } else if (ch == '"') {
216           // read string until end
217           boolean openString = true;
218           while (str.length() > chIndx) {
219             ch = str.charAt(chIndx++);
220             if (ch == '\\') {
221               if (str.length() > chIndx) {
222                 ch = str.charAt(chIndx++);
223               }
224             } else if (ch == '"') {
225               openString = false;
226               break;
227             } else if (ch == '\n') {
228               rowCount++;
229               columnCount = chIndx;
230             }
231           }
232           if (openString) {
233             throwSyntaxError("Open string character '\"' at end of file.");
234           }
235           token = TT_INTERPOLATED_STRING;
236           return;
237         } else if (ch == '\'') {
238           // read string until end
239           boolean openString = true;
240           while (str.length() > chIndx) {
241             ch = str.charAt(chIndx++);
242             if (ch == '\\') {
243               if (str.length() > chIndx) {
244                 ch = str.charAt(chIndx++);
245               }
246             } else if (ch == '\'') {
247               openString = false;
248               break;
249             } else if (ch == '\n') {
250               rowCount++;
251               columnCount = chIndx;
252             }
253           }
254           if (openString) {
255             throwSyntaxError("Open string character \"'\" at end of file.");
256           }
257           token = TT_STRING_CONSTANT;
258           return;
259         }
260
261         switch (ch) {
262
263           case '(' :
264             token = TT_ARGOPEN;
265
266             break;
267           case ')' :
268             token = TT_ARGCLOSE;
269
270             break;
271           case '{' :
272             token = TT_LISTOPEN;
273
274             break;
275           case '}' :
276             token = TT_LISTCLOSE;
277
278             break;
279           case '[' :
280             token = TT_PARTOPEN;
281
282             break;
283           case ']' :
284             token = TT_PARTCLOSE;
285
286             break;
287           case ',' :
288             token = TT_COMMA;
289
290             break;
291           case '~' :
292             token = TT_TILDE;
293
294             break;
295           case '.' :
296             token = TT_DOT;
297             if (str.length() > chIndx) {
298               if (str.charAt(chIndx) == '=') {
299                 chIndx++;
300                 token = TT_DOTASSIGN;
301
302                 break;
303               }
304             }
305
306             break;
307           case '"' :
308             token = TT_STRING;
309
310             break;
311           case '%' :
312             token = TT_MOD;
313
314             break;
315           case ';' :
316             token = TT_SEMICOLON;
317
318             break;
319           case '^' :
320             token = TT_POW;
321
322             break;
323           case '/' :
324             token = TT_DIV;
325
326             if (str.length() > chIndx) {
327               if (str.charAt(chIndx) == '=') {
328                 chIndx++;
329                 token = TT_DIVIDEBY;
330
331                 break;
332               }
333             }
334
335             break;
336           case '*' :
337             token = TT_MULTIPLY;
338             if (str.length() > chIndx) {
339               if (str.charAt(chIndx) == '*') {
340                 chIndx++;
341                 token = TT_POW;
342
343                 break;
344               }
345               if (str.charAt(chIndx) == '=') {
346                 chIndx++;
347                 token = TT_TIMESBY;
348
349                 break;
350               }
351             }
352
353             break;
354           case '+' :
355             token = TT_ADD;
356             if (str.length() > chIndx) {
357               if (str.charAt(chIndx) == '+') {
358                 chIndx++;
359                 token = TT_INCREMENT;
360
361                 break;
362               }
363               if (str.charAt(chIndx) == '=') {
364                 chIndx++;
365                 token = TT_ADDTO;
366
367                 break;
368               }
369             }
370             break;
371           case '-' :
372             token = TT_SUBTRACT;
373             if (str.length() > chIndx) {
374               if (str.charAt(chIndx) == '-') {
375                 chIndx++;
376                 token = TT_DECREMENT;
377
378                 break;
379               }
380               if (str.charAt(chIndx) == '=') {
381                 chIndx++;
382                 token = TT_SUBTRACTFROM;
383
384                 break;
385               }
386               if (str.charAt(chIndx) == '>') {
387                 chIndx++;
388                 token = TT_REF;
389
390                 break;
391               }
392             }
393
394             break;
395           case '=' :
396             token = TT_ASSIGN;
397
398             if (str.length() > chIndx) {
399               ch = str.charAt(chIndx);
400
401               if (ch == '=') {
402                 chIndx++;
403                 token = TT_EQUAL;
404                 if (str.length() > chIndx) {
405                   ch = str.charAt(chIndx);
406
407                   if (ch == '=') {
408                     chIndx++;
409                     token = TT_EX_EQUAL;
410                   }
411                 }
412                 break;
413               }
414               if (ch == '>') {
415                 chIndx++;
416                 token = TT_FOREACH;
417
418                 break;
419               }
420             }
421
422             break;
423           case '!' :
424             token = TT_NOT;
425
426             if (str.length() > chIndx) {
427               if (str.charAt(chIndx) == '=') {
428                 chIndx++;
429                 token = TT_UNEQUAL;
430                 if (str.length() > chIndx) {
431                   ch = str.charAt(chIndx);
432
433                   if (ch == '=') {
434                     chIndx++;
435                     token = TT_EX_UNEQUAL;
436                   }
437                 }
438                 break;
439               }
440             }
441
442             break;
443           case '>' :
444             token = TT_GREATER;
445
446             if (str.length() > chIndx) {
447               if (str.charAt(chIndx) == '=') {
448                 chIndx++;
449                 token = TT_GREATEREQUAL;
450
451                 break;
452               }
453               if (str.charAt(chIndx) == '>') {
454                 chIndx++;
455                 token = TT_RSHIFT;
456
457                 break;
458               }
459             }
460
461             break;
462           case '<' :
463             token = TT_LESS;
464
465             if (str.length() > chIndx) {
466               if (str.charAt(chIndx) == '=') {
467                 chIndx++;
468                 token = TT_LESSEQUAL;
469
470                 break;
471               }
472               if (str.charAt(chIndx) == '<') {
473                 chIndx++;
474                 token = TT_LSHIFT;
475
476                 break;
477               }
478             }
479
480             break;
481
482           case '|' :
483             token = TT_LINE;
484
485             if (str.length() > chIndx) {
486               if (str.charAt(chIndx) == '|') {
487                 chIndx++;
488                 token = TT_OR;
489
490                 break;
491               }
492             }
493
494             break;
495           case '&' :
496             if (str.length() > chIndx) {
497               if (str.charAt(chIndx) == '&') {
498                 chIndx++;
499                 token = TT_AND;
500
501                 break;
502               } else {
503                 token = TT_AMPERSAND;
504
505                 break;
506               }
507             }
508
509             break;
510           case ':' :
511             token = TT_DDOT;
512
513             break;
514           case '#' :
515             token = TT_HASH;
516
517             break;
518             //          case '@' :
519             //            token = TT_AT;
520             //
521             //            break;
522           default :
523             throwSyntaxError("unexpected character: '" + ch + "'");
524         }
525
526         if (token == TT_UNDEFINED) {
527           throwSyntaxError("token not found");
528         }
529
530         return;
531       }
532     }
533
534     chIndx = str.length() + 1;
535     ch = ' ';
536     token = TT_EOF;
537   }
538
539   void getIdentifier() {
540     StringBuffer ident = new StringBuffer();
541
542     ident.append(ch);
543     if (ch == '$') {
544       token = TT_VARIABLE;
545     } else {
546       token = TT_IDENTIFIER;
547     }
548     getChar();
549     while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || (ch == '_')) {
550       ident.append(ch);
551       getChar();
552     }
553     identifier = ident.toString();
554     chIndx--;
555
556     Integer i = (Integer) keywordMap.get(identifier.toLowerCase());
557     if (i != null) {
558       token = i.intValue();
559     }
560   }
561
562   void getNumber() {
563     StringBuffer inum = new StringBuffer();
564     char dFlag = ' ';
565     int numFormat = 10;
566
567     // save first digit
568     char firstCh = ch;
569     inum.append(ch);
570
571     getChar();
572     // determine number conversions:
573     if (firstCh == '0') {
574       switch (ch) {
575         case 'b' :
576           numFormat = 2;
577           getChar();
578           break;
579         case 'B' :
580           numFormat = 2;
581           getChar();
582           break;
583         case 'o' :
584           numFormat = 8;
585           getChar();
586           break;
587         case 'O' :
588           numFormat = 8;
589           getChar();
590           break;
591         case 'x' :
592           numFormat = 16;
593           getChar();
594           break;
595         case 'X' :
596           numFormat = 16;
597           getChar();
598           break;
599       }
600     }
601
602     if (numFormat == 16) {
603       while ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
604         inum.append(ch);
605         getChar();
606       }
607     } else {
608       while ((ch >= '0' && ch <= '9') || (ch == '.') || (ch == 'E') || (ch == 'e')) {
609         if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
610           if (ch == '.' && dFlag != ' ') {
611             break;
612           }
613           if ((dFlag == 'E') || (dFlag == 'e')) {
614             break;
615           }
616           dFlag = ch;
617           inum.append(ch);
618           getChar();
619           if ((ch == '-') || (ch == '+')) {
620             inum.append(ch);
621             getChar();
622           }
623         } else {
624           inum.append(ch);
625           getChar();
626         }
627       }
628     }
629     chIndx--;
630
631     try {
632       if (dFlag != ' ') {
633         doubleNumber = new Double(inum.toString());
634         token = TT_DOUBLE_NUMBER;
635         return;
636       } else {
637         longNumber = Long.valueOf(inum.toString(), numFormat);
638         token = TT_INT_NUMBER;
639         return;
640       }
641
642     } catch (Throwable e) {
643       throwSyntaxError("Number format error: " + inum.toString());
644     }
645   }
646
647   public void start(String s, int rowCount) throws SyntaxError {
648     // start up
649     this.str = s;
650     this.token = TT_EOF;
651     this.chIndx = 0;
652     this.rowCount = rowCount;
653     this.columnCount = 0;
654     getNextToken();
655     if (token != TT_EOF) {
656       statementList();
657     }
658     if (token != TT_EOF) {
659       if (token == TT_ARGCLOSE) {
660         throwSyntaxError("too many closing ')'; end-of-file not reached");
661       }
662       if (token == TT_LISTCLOSE) {
663         throwSyntaxError("too many closing '}'; end-of-file not reached");
664       }
665       if (token == TT_PARTCLOSE) {
666         throwSyntaxError("too many closing ']'; end-of-file not reached");
667       }
668
669       if (token == TT_ARGOPEN) {
670         throwSyntaxError("read character '('; end-of-file not reached");
671       }
672       if (token == TT_LISTOPEN) {
673         throwSyntaxError("read character '{';  end-of-file not reached");
674       }
675       if (token == TT_PARTOPEN) {
676         throwSyntaxError("read character '[';  end-of-file not reached");
677       }
678
679       throwSyntaxError("end-of-file not reached");
680     }
681
682   }
683
684   public void statementList() {
685     do {
686       statement();
687       if ((token == TT_LISTCLOSE)
688         || (token == TT_case)
689         || (token == TT_default)
690         || (token == TT_elseif)
691         || (token == TT_endif)
692         || (token == TT_endfor)
693         || (token == TT_endforeach)
694         || (token == TT_endwhile)
695         || (token == TT_endswitch)
696         || (token == TT_EOF)) {
697         return;
698       }
699     } while (true);
700   }
701
702   public void compoundStatement() {
703     // '{' [statement-list] '}'
704     if (token == TT_LISTOPEN) {
705       getNextToken();
706     } else {
707       throwSyntaxError("'{' expected in compound-statement.");
708     }
709     if (token != TT_LISTCLOSE) {
710       statementList();
711     }
712     if (token == TT_LISTCLOSE) {
713       getNextToken();
714     } else {
715       throwSyntaxError("'}' expected in compound-statement.");
716     }
717   }
718
719   public void statement() {
720     if (token > TT_KEYWORD && token != TT_list) {
721       String keyword = identifier;
722       if (token == TT_include || token == TT_include_once) {
723         getNextToken();
724         expression();
725         if (token == TT_SEMICOLON) {
726           getNextToken();
727         } else {
728           if (token != TT_EOF) {
729             throwSyntaxError("';' character after 'include' or 'include_once' expected.");
730           }
731         }
732         return;
733       } else if (token == TT_require || token == TT_require_once) {
734         getNextToken();
735         //constant();
736         expression();
737         if (token == TT_SEMICOLON) {
738           getNextToken();
739         } else {
740           if (token != TT_EOF) {
741             throwSyntaxError("';' character after 'require' or 'require_once' expected.");
742           }
743         }
744         return;
745       } else if (token == TT_if) {
746         getNextToken();
747         if (token == TT_ARGOPEN) {
748           getNextToken();
749         } else {
750           throwSyntaxError("'(' expected after 'if' keyword.");
751         }
752         expression();
753         if (token == TT_ARGCLOSE) {
754           getNextToken();
755         } else {
756           throwSyntaxError("')' expected after 'if' condition.");
757         }
758         ifStatement();
759         return;
760
761       } else if (token == TT_switch) {
762         getNextToken();
763         if (token == TT_ARGOPEN) {
764           getNextToken();
765         } else {
766           throwSyntaxError("'(' expected after 'switch' keyword.");
767         }
768         expression();
769         if (token == TT_ARGCLOSE) {
770           getNextToken();
771         } else {
772           throwSyntaxError("')' expected after 'switch' condition.");
773         }
774         switchStatement();
775         return;
776       } else if (token == TT_for) {
777         getNextToken();
778         if (token == TT_ARGOPEN) {
779           getNextToken();
780         } else {
781           throwSyntaxError("'(' expected after 'for' keyword.");
782         }
783         if (token == TT_SEMICOLON) {
784           getNextToken();
785         } else {
786           expression();
787           if (token == TT_SEMICOLON) {
788             getNextToken();
789           } else {
790             throwSyntaxError("';' character after 'for' expected.");
791           }
792         }
793         if (token == TT_SEMICOLON) {
794           getNextToken();
795         } else {
796           expression();
797           if (token == TT_SEMICOLON) {
798             getNextToken();
799           } else {
800             throwSyntaxError("';' character after 'for' expected.");
801           }
802         }
803         if (token == TT_ARGCLOSE) {
804           getNextToken();
805         } else {
806           expression();
807           if (token == TT_ARGCLOSE) {
808             getNextToken();
809           } else {
810             throwSyntaxError("')' expected after 'for' condition.");
811           }
812         }
813         forStatement();
814         return;
815       } else if (token == TT_while) {
816         getNextToken();
817         if (token == TT_ARGOPEN) {
818           getNextToken();
819         } else {
820           throwSyntaxError("'(' expected after 'while' keyword.");
821         }
822         expression();
823         if (token == TT_ARGCLOSE) {
824           getNextToken();
825         } else {
826           throwSyntaxError("')' expected after 'while' condition.");
827         }
828         whileStatement();
829         return;
830       } else if (token == TT_do) {
831         getNextToken();
832         if (token == TT_LISTOPEN) {
833           getNextToken();
834         } else {
835           throwSyntaxError("'{' expected after 'do' keyword.");
836         }
837         if (token != TT_LISTCLOSE) {
838           statementList();
839         }
840         if (token == TT_LISTCLOSE) {
841           getNextToken();
842         } else {
843           throwSyntaxError("'}' expected after 'do' keyword.");
844         }
845         if (token == TT_while) {
846           getNextToken();
847           if (token == TT_ARGOPEN) {
848             getNextToken();
849           } else {
850             throwSyntaxError("'(' expected after 'while' keyword.");
851           }
852           expression();
853           if (token == TT_ARGCLOSE) {
854             getNextToken();
855           } else {
856             throwSyntaxError("')' expected after 'while' condition.");
857           }
858         } else {
859           throwSyntaxError("'while' expected after 'do' keyword.");
860         }
861         if (token == TT_SEMICOLON) {
862           getNextToken();
863         } else {
864           if (token != TT_EOF) {
865             throwSyntaxError("';' expected after do-while statement.");
866           }
867         }
868         return;
869       } else if (token == TT_foreach) {
870         getNextToken();
871         if (token == TT_ARGOPEN) {
872           getNextToken();
873         } else {
874           throwSyntaxError("'(' expected after 'foreach' keyword.");
875         }
876         expression();
877         if (token == TT_as) {
878           getNextToken();
879         } else {
880           throwSyntaxError("'as' expected after 'foreach' exxpression.");
881         }
882         variable();
883         if (token == TT_FOREACH) {
884           getNextToken();
885           variable();
886         }
887         if (token == TT_ARGCLOSE) {
888           getNextToken();
889         } else {
890           throwSyntaxError("')' expected after 'foreach' expression.");
891         }
892         foreachStatement();
893         return;
894
895       } else if (token == TT_continue || token == TT_break || token == TT_return) {
896         getNextToken();
897         if (token != TT_SEMICOLON) {
898           expression();
899         }
900         if (token == TT_SEMICOLON) {
901           getNextToken();
902         } else {
903           if (token != TT_EOF) {
904             throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
905           }
906         }
907         return;
908
909       } else if (token == TT_echo) {
910         getNextToken();
911         expressionList();
912         if (token == TT_SEMICOLON) {
913           getNextToken();
914         } else {
915           if (token != TT_EOF) {
916             throwSyntaxError("';' expected after 'echo' statement.");
917           }
918         }
919         return;
920
921       } else if (token == TT_print) {
922         getNextToken();
923         expression();
924         if (token == TT_SEMICOLON) {
925           getNextToken();
926         } else {
927           if (token != TT_EOF) {
928             throwSyntaxError("';' expected after 'print' statement.");
929           }
930         }
931         return;
932
933       } else if (token == TT_global || token == TT_static) {
934         getNextToken();
935         variableList();
936         if (token == TT_SEMICOLON) {
937           getNextToken();
938         } else {
939           if (token != TT_EOF) {
940             throwSyntaxError("';' expected after 'global' or 'static' statement.");
941           }
942         }
943         return;
944
945       } else if (token == TT_unset) {
946         getNextToken();
947         if (token == TT_ARGOPEN) {
948           getNextToken();
949         } else {
950           throwSyntaxError("'(' expected after 'unset' keyword.");
951         }
952         variableList();
953         if (token == TT_ARGCLOSE) {
954           getNextToken();
955         } else {
956           throwSyntaxError("')' expected after 'unset' statement.");
957         }
958         if (token == TT_SEMICOLON) {
959           getNextToken();
960         } else {
961           if (token != TT_EOF) {
962             throwSyntaxError("';' expected after 'unset' statement.");
963           }
964         }
965         return;
966
967       } else if (token == TT_exit || token == TT_die) {
968         getNextToken();
969         if (token != TT_SEMICOLON) {
970           exitStatus();
971         }
972         if (token == TT_SEMICOLON) {
973           getNextToken();
974         } else {
975           if (token != TT_EOF) {
976             throwSyntaxError("';' expected after 'exit' or 'die' statement.");
977           }
978         }
979         return;
980
981       } else if (token == TT_define) {
982         getNextToken();
983         if (token == TT_ARGOPEN) {
984           getNextToken();
985         } else {
986           throwSyntaxError("'(' expected after 'define' keyword.");
987         }
988         constant();
989         if (token == TT_COMMA) {
990           getNextToken();
991         } else {
992           throwSyntaxError("',' expected after first 'define' constant.");
993         }
994         constant();
995         if (token == TT_ARGCLOSE) {
996           getNextToken();
997         } else {
998           throwSyntaxError("')' expected after 'define' statement.");
999         }
1000         if (token == TT_SEMICOLON) {
1001           getNextToken();
1002         } else {
1003           if (token != TT_EOF) {
1004             throwSyntaxError("';' expected after 'define' statement.");
1005           }
1006         }
1007         return;
1008       } else if (token == TT_function) {
1009         getNextToken();
1010         functionDefinition();
1011         return;
1012       } else if (token == TT_class) {
1013         getNextToken();
1014         classDeclarator();
1015         classBody();
1016         return;
1017       } else {
1018         throwSyntaxError("Unexpected keyword '" + keyword + "'");
1019       }
1020
1021     } else if (token == TT_LISTOPEN) {
1022       // compoundStatement
1023       getNextToken();
1024       if (token != TT_LISTCLOSE) {
1025         statementList();
1026       }
1027       if (token == TT_LISTCLOSE) {
1028         getNextToken();
1029         return;
1030       } else {
1031         throwSyntaxError("'}' expected.");
1032       }
1033     } else {
1034       if (token != TT_SEMICOLON) {
1035         expression();
1036       }
1037       if (token == TT_SEMICOLON) {
1038         getNextToken();
1039         return;
1040       } else {
1041         if (token != TT_EOF) {
1042           throwSyntaxError("';' expected after expression.");
1043         }
1044       }
1045     }
1046
1047   }
1048
1049   public void classDeclarator() {
1050     //identifier
1051     //identifier 'extends' identifier
1052     if (token == TT_IDENTIFIER) {
1053       getNextToken();
1054       if (token == TT_extends) {
1055         getNextToken();
1056         if (token == TT_IDENTIFIER) {
1057           getNextToken();
1058         } else {
1059           throwSyntaxError("Class name expected after keyword 'extends'.");
1060         }
1061       }
1062     } else {
1063       throwSyntaxError("Class name expected after keyword 'class'.");
1064     }
1065   }
1066
1067   public void classBody() {
1068     //'{' [class-element-list] '}'
1069     if (token == TT_LISTOPEN) {
1070       getNextToken();
1071       if (token != TT_LISTCLOSE) {
1072         classElementList();
1073       }
1074       if (token == TT_LISTCLOSE) {
1075         getNextToken();
1076       } else {
1077         throwSyntaxError("'}' expected at end of class body.");
1078       }
1079     } else {
1080       throwSyntaxError("'{' expected at start of class body.");
1081     }
1082   }
1083
1084   public void classElementList() {
1085     do {
1086       classElement();
1087     } while (token != TT_function || token != TT_var);
1088   }
1089
1090   public void classElement() {
1091     //class-property
1092     //function-definition
1093     if (token == TT_function) {
1094       getNextToken();
1095       functionDefinition();
1096     } else if (token == TT_var) {
1097       getNextToken();
1098       classProperty();
1099     } else {
1100       throwSyntaxError("'function' or 'var' expected.");
1101     }
1102   }
1103
1104   public void classProperty() {
1105     //'var' variable ';'
1106     //'var' variable '=' constant ';'
1107     if (token == TT_VARIABLE) {
1108       getNextToken();
1109       if (token == TT_ASSIGN) {
1110         getNextToken();
1111         constant();
1112         if (token == TT_SEMICOLON) {
1113           getNextToken();
1114         } else {
1115           throwSyntaxError("';' expected after variable declaration.");
1116         }
1117       } else if (token == TT_SEMICOLON) {
1118         getNextToken();
1119       } else {
1120         throwSyntaxError("';' or '=' expected after variable declaration.");
1121       }
1122     } else {
1123       throwSyntaxError("Variable expected after keyword 'var'.");
1124     }
1125   }
1126
1127   public void functionDefinition() {
1128     functionDeclarator();
1129     compoundStatement();
1130   }
1131
1132   public void functionDeclarator() {
1133     //identifier '(' [parameter-list] ')'
1134     if (token == TT_IDENTIFIER) {
1135       getNextToken();
1136       if (token == TT_ARGOPEN) {
1137         getNextToken();
1138       } else {
1139         throwSyntaxError("'(' expected in function declaration.");
1140       }
1141       if (token != TT_ARGCLOSE) {
1142         parameterList();
1143       }
1144       if (token != TT_ARGCLOSE) {
1145         throwSyntaxError("')' expected in function declaration.");
1146       } else {
1147         getNextToken();
1148       }
1149     }
1150   }
1151   //
1152   public void parameterList() {
1153     //parameter-declaration
1154     //parameter-list ',' parameter-declaration
1155     do {
1156       parameterDeclaration();
1157       if (token != TT_COMMA) {
1158         break;
1159       }
1160       getNextToken();
1161     } while (true);
1162   }
1163
1164   public void parameterDeclaration() {
1165     //variable
1166     //variable-reference
1167     //variable '=' constant
1168     if (token == TT_VARIABLE) {
1169       getNextToken();
1170       if (token == TT_ASSIGN) {
1171         getNextToken();
1172         constant();
1173       }
1174       return;
1175     }
1176   }
1177
1178   public void labeledStatementList() {
1179     if (token != TT_case && token != TT_default) {
1180       throwSyntaxError("'case' or 'default' expected.");
1181     }
1182     do {
1183       if (token == TT_case) {
1184         getNextToken();
1185         constant();
1186         if (token == TT_DDOT) {
1187           getNextToken();
1188           statementList();
1189         } else {
1190           throwSyntaxError("':' character after 'case' constant expected.");
1191         }
1192       } else { // TT_default 
1193         getNextToken();
1194         if (token == TT_DDOT) {
1195           getNextToken();
1196           statementList();
1197         } else {
1198           throwSyntaxError("':' character after 'default' expected.");
1199         }
1200       }
1201     } while (token == TT_case || token == TT_default);
1202   }
1203
1204   //  public void labeledStatement() {
1205   //    if (token == TT_case) {
1206   //      getNextToken();
1207   //      constant();
1208   //      if (token == TT_DDOT) {
1209   //        getNextToken();
1210   //        statement();
1211   //      } else {
1212   //        throwSyntaxError("':' character after 'case' constant expected.");
1213   //      }
1214   //      return;
1215   //    } else if (token == TT_default) {
1216   //      getNextToken();
1217   //      if (token == TT_DDOT) {
1218   //        getNextToken();
1219   //        statement();
1220   //      } else {
1221   //        throwSyntaxError("':' character after 'default' expected.");
1222   //      }
1223   //      return;
1224   //    }
1225   //  }
1226
1227   public void expressionStatement() {
1228   }
1229
1230   public void inclusionStatement() {
1231   }
1232
1233   //  public void compoundStatement() {
1234   //  }
1235
1236   //  public void selectionStatement() {
1237   //  }
1238   //
1239   //  public void iterationStatement() {
1240   //  }
1241   //
1242   //  public void jumpStatement() {
1243   //  }
1244   //
1245   //  public void outputStatement() {
1246   //  }
1247   //
1248   //  public void scopeStatement() {
1249   //  }
1250   //
1251   //  public void flowStatement() {
1252   //  }
1253   //
1254   //  public void definitionStatement() {
1255   //  }
1256
1257   public void ifStatement() {
1258     // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
1259     if (token == TT_DDOT) {
1260       getNextToken();
1261       statementList();
1262       switch (token) {
1263         case TT_else :
1264           getNextToken();
1265           if (token == TT_DDOT) {
1266             getNextToken();
1267             statementList();
1268           } else {
1269             if (token == TT_if) { //'else if'
1270               getNextToken();
1271               elseifStatementList();
1272             } else {
1273               throwSyntaxError("':' expected after 'else'.");
1274             }
1275           }
1276           break;
1277         case TT_elseif :
1278           getNextToken();
1279           elseifStatementList();
1280           break;
1281       }
1282
1283       if (token != TT_endif) {
1284         throwSyntaxError("'endif' expected.");
1285       }
1286       getNextToken();
1287       if (token != TT_SEMICOLON) {
1288         throwSyntaxError("';' expected after if-statement.");
1289       }
1290       getNextToken();
1291     } else {
1292       // statement [else-statement]
1293       statement();
1294       if (token == TT_elseif) {
1295         getNextToken();
1296         if (token == TT_ARGOPEN) {
1297           getNextToken();
1298         } else {
1299           throwSyntaxError("'(' expected after 'elseif' keyword.");
1300         }
1301         expression();
1302         if (token == TT_ARGCLOSE) {
1303           getNextToken();
1304         } else {
1305           throwSyntaxError("')' expected after 'elseif' condition.");
1306         }
1307         ifStatement();
1308       } else if (token == TT_else) {
1309         getNextToken();
1310         statement();
1311       }
1312     }
1313   }
1314   public void elseifStatementList() {
1315     do {
1316       elseifStatement();
1317       switch (token) {
1318         case TT_else :
1319           getNextToken();
1320           if (token == TT_DDOT) {
1321             getNextToken();
1322             statementList();
1323             return;
1324           } else {
1325             if (token == TT_if) { //'else if'
1326               getNextToken();
1327             } else {
1328               throwSyntaxError("':' expected after 'else'.");
1329             }
1330           }
1331           break;
1332         case TT_elseif :
1333           getNextToken();
1334           break;
1335         default :
1336           return;
1337       }
1338     } while (true);
1339   }
1340
1341   public void elseifStatement() {
1342     if (token == TT_ARGOPEN) {
1343       getNextToken();
1344       expression();
1345       if (token != TT_ARGOPEN) {
1346         throwSyntaxError("')' expected in else-if-statement.");
1347       }
1348       getNextToken();
1349       if (token != TT_DDOT) {
1350         throwSyntaxError("':' expected in else-if-statement.");
1351       }
1352       getNextToken();
1353       statementList();
1354     }
1355   }
1356
1357   public void switchStatement() {
1358     if (token == TT_DDOT) {
1359       // ':' [labeled-statement-list] 'endswitch' ';'
1360       getNextToken();
1361       labeledStatementList();
1362       if (token != TT_endswitch) {
1363         throwSyntaxError("'endswitch' expected.");
1364       }
1365       getNextToken();
1366       if (token != TT_SEMICOLON) {
1367         throwSyntaxError("';' expected after switch-statement.");
1368       }
1369       getNextToken();
1370     } else {
1371       // '{' [labeled-statement-list] '}'
1372       if (token != TT_LISTOPEN) {
1373         throwSyntaxError("'{' expected in switch statement.");
1374       }
1375       getNextToken();
1376       if (token != TT_LISTCLOSE) {
1377         labeledStatementList();
1378       }
1379       if (token != TT_LISTCLOSE) {
1380         throwSyntaxError("'}' expected in switch statement.");
1381       }
1382       getNextToken();
1383
1384     }
1385   }
1386
1387   public void forStatement() {
1388     if (token == TT_DDOT) {
1389       getNextToken();
1390       statementList();
1391       if (token != TT_endfor) {
1392         throwSyntaxError("'endfor' expected.");
1393       }
1394       getNextToken();
1395       if (token != TT_SEMICOLON) {
1396         throwSyntaxError("';' expected after for-statement.");
1397       }
1398       getNextToken();
1399     } else {
1400       statement();
1401     }
1402   }
1403
1404   public void whileStatement() {
1405     // ':' statement-list 'endwhile' ';'
1406     if (token == TT_DDOT) {
1407       getNextToken();
1408       statementList();
1409       if (token != TT_endwhile) {
1410         throwSyntaxError("'endwhile' expected.");
1411       }
1412       getNextToken();
1413       if (token != TT_SEMICOLON) {
1414         throwSyntaxError("';' expected after while-statement.");
1415       }
1416       getNextToken();
1417     } else {
1418       statement();
1419     }
1420   }
1421
1422   public void foreachStatement() {
1423     if (token == TT_DDOT) {
1424       getNextToken();
1425       statementList();
1426       if (token != TT_endforeach) {
1427         throwSyntaxError("'endforeach' expected.");
1428       }
1429       getNextToken();
1430       if (token != TT_SEMICOLON) {
1431         throwSyntaxError("';' expected after foreach-statement.");
1432       }
1433       getNextToken();
1434     } else {
1435       statement();
1436     }
1437   }
1438
1439   public void exitStatus() {
1440     if (token == TT_ARGOPEN) {
1441       getNextToken();
1442     } else {
1443       throwSyntaxError("'(' expected in 'exit-status'.");
1444     }
1445     if (token != TT_ARGCLOSE) {
1446       expression();
1447     }
1448     if (token == TT_ARGCLOSE) {
1449       getNextToken();
1450     } else {
1451       throwSyntaxError("')' expected after 'exit-status'.");
1452     }
1453   }
1454
1455   public void expressionList() {
1456     do {
1457       expression();
1458       if (token == TT_COMMA) {
1459         getNextToken();
1460       } else {
1461         break;
1462       }
1463     } while (true);
1464   }
1465
1466   public void expression() {
1467     //    if (token == TT_STRING_CONSTANT || token == TT_INTERPOLATED_STRING) {
1468     //      getNextToken();
1469     //    } else {
1470     logicalinclusiveorExpression();
1471     //      while (token != TT_SEMICOLON) {
1472     //        getNextToken();
1473     //      //      }
1474     //    }
1475   }
1476
1477   public void postfixExpression() {
1478     String ident;
1479     boolean castFlag = false;
1480     switch (token) {
1481       case TT_new :
1482         getNextToken();
1483         expression();
1484         break;
1485       case TT_null :
1486         getNextToken();
1487         break;
1488       case TT_false :
1489         getNextToken();
1490         break;
1491       case TT_true :
1492         getNextToken();
1493         break;
1494       case TT_STRING_CONSTANT :
1495         getNextToken();
1496         break;
1497       case TT_INTERPOLATED_STRING :
1498         getNextToken();
1499         break;
1500       case TT_ARGOPEN :
1501         getNextToken();
1502         if (token == TT_IDENTIFIER) {
1503           // check if identifier is a type:
1504           ident = identifier;
1505           String str = identifier.toLowerCase();
1506           for (int i = 0; i < PHP_TYPES.length; i++) {
1507             if (PHP_TYPES[i].equals(str)) {
1508               castFlag = true;
1509               break;
1510             }
1511           }
1512           if (castFlag) {
1513             getNextToken();
1514             if (token != TT_ARGCLOSE) {
1515               throwSyntaxError(") expected after cast-type '" + ident + "'.");
1516             }
1517             getNextToken();
1518             expression();
1519             break;
1520           }
1521         }
1522         if (!castFlag) {
1523           expression();
1524         }
1525         if (token != TT_ARGCLOSE) {
1526           throwSyntaxError(") expected in postfix-expression.");
1527         }
1528         getNextToken();
1529         break;
1530       case TT_DOUBLE_NUMBER :
1531         getNextToken();
1532         break;
1533       case TT_INT_NUMBER :
1534         getNextToken();
1535         break;
1536       case TT_VARIABLE :
1537         ident = identifier;
1538         getNextToken();
1539         if (token == TT_LISTOPEN) {
1540           getNextToken();
1541           expression();
1542           if (token != TT_LISTCLOSE) {
1543             throwSyntaxError("'}' expected after variable '" + ident + "' in variable-expression.");
1544           }
1545           getNextToken();
1546         }
1547         break;
1548       case TT_IDENTIFIER :
1549         ident = identifier;
1550         getNextToken();
1551         if (token == TT_ARGOPEN) {
1552           getNextToken();
1553           if (token != TT_ARGCLOSE) {
1554             expressionList();
1555             if (token != TT_ARGCLOSE) {
1556               throwSyntaxError("')' expected after identifier '" + ident + "' in postfix-expression.");
1557             }
1558           }
1559           getNextToken();
1560         }
1561         break;
1562       case TT_list :
1563         getNextToken();
1564         if (token == TT_ARGOPEN) {
1565           getNextToken();
1566           if (token == TT_COMMA) {
1567             getNextToken();
1568           }
1569           expressionList();
1570           if (token != TT_ARGCLOSE) {
1571             throwSyntaxError("')' expected after 'list' keyword.");
1572           }
1573           getNextToken();
1574           //          if (token == TT_SET) {
1575           //            getNextToken();
1576           //            logicalinclusiveorExpression();
1577           //          }
1578         } else {
1579           throwSyntaxError("'(' expected after 'list' keyword.");
1580         }
1581         break;
1582         //      case TT_array :
1583         //        getNextToken();
1584         //        if (token == TT_ARGOPEN) {
1585         //          getNextToken();
1586         //          if (token == TT_COMMA) {
1587         //            getNextToken();
1588         //          }
1589         //          expressionList();
1590         //          if (token != TT_ARGCLOSE) {
1591         //            throwSyntaxError("')' expected after 'list' keyword.");
1592         //          }
1593         //          getNextToken();
1594         //          if (token == TT_SET) {
1595         //            getNextToken();
1596         //            logicalinclusiveorExpression();
1597         //          }
1598         //        } else {
1599         //          throwSyntaxError("'(' expected after 'list' keyword.");
1600         //        }
1601         //        break;
1602     }
1603     boolean while_flag = true;
1604     do {
1605       switch (token) {
1606         case TT_PARTOPEN :
1607           getNextToken();
1608           expression();
1609           if (token != TT_PARTCLOSE) {
1610             throwSyntaxError("] expected in postfix-expression.");
1611           }
1612           getNextToken();
1613           break;
1614         case TT_REF : // ->
1615           getNextToken();
1616           switch (token) {
1617             case TT_VARIABLE :
1618               ident = identifier;
1619               getNextToken();
1620               //              if (token == TT_ARGOPEN) {
1621               //                getNextToken();
1622               //                expressionList();
1623               //                if (token != TT_ARGCLOSE) {
1624               //                  throwSyntaxError(") expected after variable '" + ident + "'.");
1625               //                }
1626               //                getNextToken();
1627               //              }
1628               break;
1629             case TT_IDENTIFIER :
1630               ident = identifier;
1631               getNextToken();
1632               if (token == TT_ARGOPEN) {
1633                 getNextToken();
1634                 expressionList();
1635                 if (token != TT_ARGCLOSE) {
1636                   throwSyntaxError(") expected after identifier '" + ident + "'.");
1637                 }
1638                 getNextToken();
1639               }
1640               break;
1641             case TT_LISTOPEN :
1642               getNextToken();
1643               expression();
1644               if (token != TT_LISTCLOSE) {
1645                 throwSyntaxError("} expected in postfix-expression.");
1646               }
1647               getNextToken();
1648               break;
1649             default :
1650               throwSyntaxError("Syntax error after '->' token.");
1651           }
1652           break;
1653         case TT_INCREMENT :
1654           getNextToken();
1655           break;
1656         case TT_DECREMENT :
1657           getNextToken();
1658           break;
1659         default :
1660           while_flag = false;
1661       }
1662     } while (while_flag);
1663   }
1664
1665   public void unaryExpression() {
1666     switch (token) {
1667       case TT_INCREMENT :
1668         getNextToken();
1669         unaryExpression();
1670         break;
1671       case TT_DECREMENT :
1672         getNextToken();
1673         unaryExpression();
1674         break;
1675         //'&' '*' '+' '-' '~' '!' 
1676       case TT_AMPERSAND :
1677         getNextToken();
1678         castExpression();
1679         break;
1680       case TT_MULTIPLY :
1681         getNextToken();
1682         castExpression();
1683         break;
1684       case TT_ADD :
1685         getNextToken();
1686         castExpression();
1687         break;
1688       case TT_SUBTRACT :
1689         getNextToken();
1690         castExpression();
1691         break;
1692       case TT_TILDE :
1693         getNextToken();
1694         castExpression();
1695         break;
1696       case TT_NOT :
1697         getNextToken();
1698         castExpression();
1699         break;
1700       default :
1701         postfixExpression();
1702     }
1703   }
1704
1705   public void castExpression() {
1706     //    if (token == TT_ARGOPEN) {
1707     //      getNextToken();
1708     //      typeName();
1709     //      if (token != TT_ARGCLOSE) {
1710     //        throwSyntaxError(") expected after cast-expression.");
1711     //      }
1712     //      getNextToken();
1713     //    }
1714     unaryExpression();
1715   }
1716
1717   public void typeName() {
1718     //'string' 'unset' 'array' 'object'
1719     //'bool' 'boolean'
1720     //'real' 'double' 'float'
1721     //'int' 'integer'
1722     String ident = "";
1723     if (token == TT_IDENTIFIER) {
1724       ident = identifier;
1725       String str = identifier.toLowerCase();
1726       getNextToken();
1727       for (int i = 0; i < PHP_TYPES.length; i++) {
1728         if (PHP_TYPES[i].equals(str)) {
1729           return;
1730         }
1731       }
1732     }
1733     throwSyntaxError("Expected type cast '( <type-name> )'; Got '" + ident + "'.");
1734   }
1735
1736   public void assignExpression() {
1737     castExpression();
1738     if (token == TT_ASSIGN) { // =
1739       getNextToken();
1740       logicalinclusiveorExpression();
1741     } else if (token == TT_DOTASSIGN) { // .=
1742       getNextToken();
1743       logicalinclusiveorExpression();
1744     } else if (token == TT_FOREACH) { // =>
1745       getNextToken();
1746       logicalinclusiveorExpression();
1747     } else if (token == TT_ADDTO) { // +=
1748       getNextToken();
1749       logicalinclusiveorExpression();
1750     } else if (token == TT_SUBTRACTFROM) { // -=
1751       getNextToken();
1752       logicalinclusiveorExpression();
1753     } else if (token == TT_TIMESBY) { // *=
1754       getNextToken();
1755       logicalinclusiveorExpression();
1756     } else if (token == TT_DIVIDEBY) { // *=
1757       getNextToken();
1758       logicalinclusiveorExpression();
1759     }
1760   }
1761
1762   public void multiplicativeExpression() {
1763     do {
1764       assignExpression();
1765       if (token != TT_MULTIPLY && token != TT_DIV && token != TT_MOD) {
1766         return;
1767       }
1768       getNextToken();
1769     } while (true);
1770   }
1771
1772   public void concatenationExpression() {
1773     do {
1774       multiplicativeExpression();
1775       if (token != TT_DOT) {
1776         return;
1777       }
1778       getNextToken();
1779     } while (true);
1780   }
1781
1782   public void additiveExpression() {
1783     do {
1784       concatenationExpression();
1785       if (token != TT_ADD && token != TT_SUBTRACT) {
1786         return;
1787       }
1788       getNextToken();
1789     } while (true);
1790   }
1791
1792   public void shiftExpression() {
1793     do {
1794       additiveExpression();
1795       if (token != TT_LSHIFT && token != TT_RSHIFT) {
1796         return;
1797       }
1798       getNextToken();
1799     } while (true);
1800   }
1801
1802   public void relationalExpression() {
1803     do {
1804       shiftExpression();
1805       if (token != TT_LESS && token != TT_GREATER && token != TT_LESSEQUAL && token != TT_GREATEREQUAL) {
1806         return;
1807       }
1808       getNextToken();
1809     } while (true);
1810   }
1811
1812   public void identicalExpression() {
1813     do {
1814       relationalExpression();
1815       if (token != TT_EX_EQUAL && token != TT_EX_UNEQUAL) {
1816         return;
1817       }
1818       getNextToken();
1819     } while (true);
1820   }
1821
1822   public void equalityExpression() {
1823     do {
1824       identicalExpression();
1825       if (token != TT_EQUAL && token != TT_UNEQUAL) {
1826         return;
1827       }
1828       getNextToken();
1829     } while (true);
1830   }
1831
1832   public void andExpression() {
1833     do {
1834       equalityExpression();
1835       if (token != TT_AMPERSAND) {
1836         return;
1837       }
1838       getNextToken();
1839     } while (true);
1840   }
1841
1842   public void exclusiveorExpression() {
1843     do {
1844       andExpression();
1845       if (token != TT_POW) {
1846         return;
1847       }
1848       getNextToken();
1849     } while (true);
1850   }
1851
1852   public void inclusiveorExpression() {
1853     do {
1854       exclusiveorExpression();
1855       if (token != TT_LINE) {
1856         return;
1857       }
1858       getNextToken();
1859     } while (true);
1860   }
1861
1862   public void booleanandExpression() {
1863     do {
1864       inclusiveorExpression();
1865       if (token != TT_AND) {
1866         return;
1867       }
1868       getNextToken();
1869     } while (true);
1870   }
1871
1872   public void booleanorExpression() {
1873     do {
1874       booleanandExpression();
1875       if (token != TT_OR) {
1876         return;
1877       }
1878       getNextToken();
1879     } while (true);
1880   }
1881
1882   public void logicalandExpression() {
1883     do {
1884       booleanorExpression();
1885       if (token != TT_and) {
1886         return;
1887       }
1888       getNextToken();
1889     } while (true);
1890   }
1891
1892   public void logicalexclusiveorExpression() {
1893     do {
1894       logicalandExpression();
1895       if (token != TT_xor) {
1896         return;
1897       }
1898       getNextToken();
1899     } while (true);
1900   }
1901
1902   public void logicalinclusiveorExpression() {
1903     do {
1904       logicalexclusiveorExpression();
1905       if (token != TT_or) {
1906         return;
1907       }
1908       getNextToken();
1909     } while (true);
1910   }
1911
1912   //  public void assignmentExpression() {
1913   //    if (token == TT_VARIABLE) {
1914   //      getNextToken();
1915   //      if (token == TT_SET) {
1916   //        getNextToken();
1917   //        logicalinclusiveorExpression();
1918   //      }
1919   //    } else {
1920   //      logicalinclusiveorExpression();
1921   //    }
1922   //  }
1923
1924   public void variableList() {
1925     do {
1926       variable();
1927       if (token == TT_COMMA) {
1928         getNextToken();
1929       } else {
1930         break;
1931       }
1932     } while (true);
1933   }
1934
1935   public void variable() {
1936     if (token == TT_VARIABLE) {
1937       getNextToken();
1938     } else {
1939       throwSyntaxError("$-variable expected in variable-list.");
1940     }
1941   }
1942
1943   public void constant() {
1944     switch (token) {
1945       case TT_null :
1946         getNextToken();
1947         break;
1948       case TT_false :
1949         getNextToken();
1950         break;
1951       case TT_true :
1952         getNextToken();
1953         break;
1954       case TT_STRING_CONSTANT :
1955         getNextToken();
1956         break;
1957       case TT_INTERPOLATED_STRING :
1958         getNextToken();
1959         break;
1960       case TT_DOUBLE_NUMBER :
1961         getNextToken();
1962         break;
1963       case TT_INT_NUMBER :
1964         getNextToken();
1965         break;
1966       default :
1967         throwSyntaxError("Constant expected.");
1968     }
1969   }
1970
1971 }