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