98ce45132bebea858c612efb2dcecd37b0fa274d
[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     currentPHPString = 0;
775
776     try {
777       int i = 0;
778       while (i < input.length()) {
779         ch = input.charAt(i++);
780         if (ch == '\n') {
781           lineNumber++;
782         }
783         if ((!phpMode) && ch == '<') {
784           ch2 = input.charAt(i++);
785           if (ch2 == '?') {
786             ch2 = input.charAt(i++);
787             if (Character.isWhitespace(ch2)) {
788               // php start 
789               phpMode = true;
790               phpFound = true;
791               startIndex = i;
792               startLineNumber = lineNumber;
793               continue;
794             } else if (ch2 == 'p') {
795               ch2 = input.charAt(i++);
796               if (ch2 == 'h') {
797                 ch2 = input.charAt(i++);
798                 if (ch2 == 'p') {
799                   phpMode = true;
800                   phpFound = true;
801                   startIndex = i;
802                   startLineNumber = lineNumber;
803                   continue;
804                 }
805                 i--;
806               }
807               i--;
808             } else if (ch2 == 'P') {
809               ch2 = input.charAt(i++);
810               if (ch2 == 'H') {
811                 ch2 = input.charAt(i++);
812                 if (ch2 == 'P') {
813                   phpMode = true;
814                   phpFound = true;
815                   startIndex = i;
816                   startLineNumber = lineNumber;
817                   continue;
818                 }
819                 i--;
820               }
821               i--;
822             }
823             i--;
824           }
825           i--;
826         }
827
828         if (phpMode) {
829           buf.append(ch);
830           if (lineCommentMode && (ch == '\n')) {
831             lineCommentMode = false;
832             // read until end of line
833           } else if ((!stringMode) && (ch == '#')) {
834             // read until end of line
835             lineCommentMode = true;
836             continue;
837           } else if ((!stringMode) && (!multiLineCommentMode) && (ch == '/')) {
838             ch2 = input.charAt(i++);
839             if (ch2 == '/') {
840               lineCommentMode = true;
841               continue;
842             } else if (ch2 == '*') {
843               multiLineCommentMode = true;
844               continue;
845             } else {
846               i--;
847             }
848           } else if (ch == '*' && multiLineCommentMode) {
849             ch2 = input.charAt(i++);
850             if (ch2 == '/') {
851               multiLineCommentMode = false;
852               continue;
853             } else {
854               i--;
855             }
856           } else if (ch == '\\' && stringMode) {
857             ch2 = input.charAt(i++);
858             if (ch2 == '"') {
859               continue;
860             } else {
861               i--;
862             }
863           } else if ((!lineCommentMode) && (!multiLineCommentMode) && (ch == '"')) {
864             if (stringMode) {
865               stringMode = false;
866             } else {
867               stringMode = true;
868             }
869             continue;
870           }
871           if (lineCommentMode || multiLineCommentMode || stringMode) {
872             continue;
873           }
874
875           if (ch == '?') {
876             ch2 = input.charAt(i++);
877             if (ch2 == '>') {
878               // php end
879               phpMode = false;
880               phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber));
881               continue;
882             }
883             i--;
884           }
885         } else {
886         }
887       }
888       if (!phpFound) {
889         setMarker("No PHP source code found.", lineNumber, PHPParser.INFO);
890       } else {
891         //        for (int j=0;j<phpList.size();j++) {
892         //          String temp = ((PHPString)phpList.get(j)).getPHPString();
893         //          int startIndx = temp.length()-10;
894         //          if (startIndx<0) {
895         //            startIndx = 0; 
896         //          }
897         //          System.out.println(temp.substring(startIndx)+"?>");
898         //        }
899         phpParse(null, 1);
900         //        PHPString temp;
901         //        for(int j=0;j<phpList.size();j++) {
902         //          temp = (PHPString) phpList.get(j);
903         //          parser.start(temp.getPHPString(), temp.getLineNumber());
904         //        } 
905       }
906     } catch (CoreException e) {
907     }
908   }
909
910   public void phpParse(String s, int rowCount) throws CoreException {
911     // start up
912     try {
913       this.str = s;
914       if (s == null) {
915         if (phpList.size() != 0) {
916           this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
917         }
918       }
919       this.token = TT_EOF;
920       this.chIndx = 0;
921       this.rowCount = rowCount;
922       this.columnCount = 0;
923       this.phpEnd = false;
924       getNextToken();
925       if (token != TT_EOF && token != TT_UNDEFINED) {
926         statementList();
927       }
928       if (token != TT_EOF && token != TT_UNDEFINED) {
929         if (token == TT_ARGCLOSE) {
930           throwSyntaxError("too many closing ')'; end-of-file not reached");
931         }
932         if (token == TT_LISTCLOSE) {
933           throwSyntaxError("too many closing '}'; end-of-file not reached");
934         }
935         if (token == TT_PARTCLOSE) {
936           throwSyntaxError("too many closing ']'; end-of-file not reached");
937         }
938
939         if (token == TT_ARGOPEN) {
940           throwSyntaxError("read character '('; end-of-file not reached");
941         }
942         if (token == TT_LISTOPEN) {
943           throwSyntaxError("read character '{';  end-of-file not reached");
944         }
945         if (token == TT_PARTOPEN) {
946           throwSyntaxError("read character '[';  end-of-file not reached");
947         }
948
949         throwSyntaxError("end-of-file not reached");
950       }
951     } catch (SyntaxError err) {
952       if (s != null) {
953         throw err;
954       } else {
955         setMarker(err.getMessage(), err.getLine(), ERROR);
956       }
957     }
958   }
959
960   public void statementList() throws CoreException {
961     do {
962       statement();
963       if ((token == TT_LISTCLOSE)
964         || (token == TT_case)
965         || (token == TT_default)
966         || (token == TT_elseif)
967         || (token == TT_endif)
968         || (token == TT_endfor)
969         || (token == TT_endforeach)
970         || (token == TT_endwhile)
971         || (token == TT_endswitch)
972         || (token == TT_EOF)
973         || (token == TT_UNDEFINED)) {
974         return;
975       }
976     } while (true);
977   }
978
979   public void compoundStatement() throws CoreException {
980     // '{' [statement-list] '}'
981     if (token == TT_LISTOPEN) {
982       getNextToken();
983     } else {
984       throwSyntaxError("'{' expected in compound-statement.");
985     }
986     if (token != TT_LISTCLOSE) {
987       statementList();
988     }
989     if (token == TT_LISTCLOSE) {
990       getNextToken();
991     } else {
992       throwSyntaxError("'}' expected in compound-statement.");
993     }
994   }
995
996   public void statement() throws CoreException {
997     if (token > TT_KEYWORD && token != TT_list) {
998       String keyword = identifier;
999       if (token == TT_include || token == TT_include_once) {
1000         getNextToken();
1001         expression();
1002         if (token == TT_SEMICOLON) {
1003           getNextToken();
1004         } else {
1005           if (!phpEnd) {
1006             throwSyntaxError("';' character after 'include' or 'include_once' expected.");
1007           }
1008         }
1009         return;
1010       } else if (token == TT_require || token == TT_require_once) {
1011         getNextToken();
1012         //constant();
1013         expression();
1014         if (token == TT_SEMICOLON) {
1015           getNextToken();
1016         } else {
1017           if (!phpEnd) {
1018             throwSyntaxError("';' character after 'require' or 'require_once' expected.");
1019           }
1020         }
1021         return;
1022       } else if (token == TT_if) {
1023         getNextToken();
1024         if (token == TT_ARGOPEN) {
1025           getNextToken();
1026         } else {
1027           throwSyntaxError("'(' expected after 'if' keyword.");
1028         }
1029         expression();
1030         if (token == TT_ARGCLOSE) {
1031           getNextToken();
1032         } else {
1033           throwSyntaxError("')' expected after 'if' condition.");
1034         }
1035         ifStatement();
1036         return;
1037
1038       } else if (token == TT_switch) {
1039         getNextToken();
1040         if (token == TT_ARGOPEN) {
1041           getNextToken();
1042         } else {
1043           throwSyntaxError("'(' expected after 'switch' keyword.");
1044         }
1045         expression();
1046         if (token == TT_ARGCLOSE) {
1047           getNextToken();
1048         } else {
1049           throwSyntaxError("')' expected after 'switch' condition.");
1050         }
1051         switchStatement();
1052         return;
1053       } else if (token == TT_for) {
1054         getNextToken();
1055         if (token == TT_ARGOPEN) {
1056           getNextToken();
1057         } else {
1058           throwSyntaxError("'(' expected after 'for' keyword.");
1059         }
1060         if (token == TT_SEMICOLON) {
1061           getNextToken();
1062         } else {
1063           expression();
1064           if (token == TT_SEMICOLON) {
1065             getNextToken();
1066           } else {
1067             throwSyntaxError("';' character after 'for' expected.");
1068           }
1069         }
1070         if (token == TT_SEMICOLON) {
1071           getNextToken();
1072         } else {
1073           expression();
1074           if (token == TT_SEMICOLON) {
1075             getNextToken();
1076           } else {
1077             throwSyntaxError("';' character after 'for' expected.");
1078           }
1079         }
1080         if (token == TT_ARGCLOSE) {
1081           getNextToken();
1082         } else {
1083           expression();
1084           if (token == TT_ARGCLOSE) {
1085             getNextToken();
1086           } else {
1087             throwSyntaxError("')' expected after 'for' condition.");
1088           }
1089         }
1090         forStatement();
1091         return;
1092       } else if (token == TT_while) {
1093         getNextToken();
1094         if (token == TT_ARGOPEN) {
1095           getNextToken();
1096         } else {
1097           throwSyntaxError("'(' expected after 'while' keyword.");
1098         }
1099         expression();
1100         if (token == TT_ARGCLOSE) {
1101           getNextToken();
1102         } else {
1103           throwSyntaxError("')' expected after 'while' condition.");
1104         }
1105         whileStatement();
1106         return;
1107       } else if (token == TT_do) {
1108         getNextToken();
1109         if (token == TT_LISTOPEN) {
1110           getNextToken();
1111         } else {
1112           throwSyntaxError("'{' expected after 'do' keyword.");
1113         }
1114         if (token != TT_LISTCLOSE) {
1115           statementList();
1116         }
1117         if (token == TT_LISTCLOSE) {
1118           getNextToken();
1119         } else {
1120           throwSyntaxError("'}' expected after 'do' keyword.");
1121         }
1122         if (token == TT_while) {
1123           getNextToken();
1124           if (token == TT_ARGOPEN) {
1125             getNextToken();
1126           } else {
1127             throwSyntaxError("'(' expected after 'while' keyword.");
1128           }
1129           expression();
1130           if (token == TT_ARGCLOSE) {
1131             getNextToken();
1132           } else {
1133             throwSyntaxError("')' expected after 'while' condition.");
1134           }
1135         } else {
1136           throwSyntaxError("'while' expected after 'do' keyword.");
1137         }
1138         if (token == TT_SEMICOLON) {
1139           getNextToken();
1140         } else {
1141           if (!phpEnd) {
1142             throwSyntaxError("';' expected after do-while statement.");
1143           }
1144         }
1145         return;
1146       } else if (token == TT_foreach) {
1147         getNextToken();
1148         if (token == TT_ARGOPEN) {
1149           getNextToken();
1150         } else {
1151           throwSyntaxError("'(' expected after 'foreach' keyword.");
1152         }
1153         expression();
1154         if (token == TT_as) {
1155           getNextToken();
1156         } else {
1157           throwSyntaxError("'as' expected after 'foreach' exxpression.");
1158         }
1159         variable();
1160         if (token == TT_FOREACH) {
1161           getNextToken();
1162           variable();
1163         }
1164         if (token == TT_ARGCLOSE) {
1165           getNextToken();
1166         } else {
1167           throwSyntaxError("')' expected after 'foreach' expression.");
1168         }
1169         foreachStatement();
1170         return;
1171
1172       } else if (token == TT_continue || token == TT_break || token == TT_return) {
1173         getNextToken();
1174         if (token != TT_SEMICOLON) {
1175           expression();
1176         }
1177         if (token == TT_SEMICOLON) {
1178           getNextToken();
1179         } else {
1180           if (!phpEnd) {
1181             throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
1182           }
1183         }
1184         return;
1185
1186       } else if (token == TT_echo) {
1187         getNextToken();
1188         expressionList();
1189         if (token == TT_SEMICOLON) {
1190           getNextToken();
1191         } else {
1192           if (!phpEnd) {
1193             throwSyntaxError("';' expected after 'echo' statement.");
1194           }
1195         }
1196         return;
1197       } else if (token == TT_print) {
1198         getNextToken();
1199         expression();
1200         if (token == TT_SEMICOLON) {
1201           getNextToken();
1202         } else {
1203           if (!phpEnd) {
1204             throwSyntaxError("';' expected after 'print' statement.");
1205           }
1206         }
1207         return;
1208
1209       } else if (token == TT_global || token == TT_static) {
1210         getNextToken();
1211         variableList();
1212         if (token == TT_SEMICOLON) {
1213           getNextToken();
1214         } else {
1215           if (!phpEnd) {
1216             throwSyntaxError("';' expected after 'global' or 'static' statement.");
1217           }
1218         }
1219         return;
1220
1221       } else if (token == TT_unset) {
1222         getNextToken();
1223         if (token == TT_ARGOPEN) {
1224           getNextToken();
1225         } else {
1226           throwSyntaxError("'(' expected after 'unset' keyword.");
1227         }
1228         variableList();
1229         if (token == TT_ARGCLOSE) {
1230           getNextToken();
1231         } else {
1232           throwSyntaxError("')' expected after 'unset' statement.");
1233         }
1234         if (token == TT_SEMICOLON) {
1235           getNextToken();
1236         } else {
1237           if (!phpEnd) {
1238             throwSyntaxError("';' expected after 'unset' statement.");
1239           }
1240         }
1241         return;
1242
1243         //      } else if (token == TT_exit || token == TT_die) {
1244         //        getNextToken();
1245         //        if (token != TT_SEMICOLON) {
1246         //          exitStatus();
1247         //        }
1248         //        if (token == TT_SEMICOLON) {
1249         //          getNextToken();
1250         //        } else {
1251         //          if (!phpEnd) {
1252         //            throwSyntaxError("';' expected after 'exit' or 'die' statement.");
1253         //          }
1254         //        }
1255         //        return;
1256
1257       } else if (token == TT_define) {
1258         getNextToken();
1259         if (token == TT_ARGOPEN) {
1260           getNextToken();
1261         } else {
1262           throwSyntaxError("'(' expected after 'define' keyword.");
1263         }
1264         constant();
1265         if (token == TT_COMMA) {
1266           getNextToken();
1267         } else {
1268           throwSyntaxError("',' expected after first 'define' constant.");
1269         }
1270         constant();
1271         if (token == TT_ARGCLOSE) {
1272           getNextToken();
1273         } else {
1274           throwSyntaxError("')' expected after 'define' statement.");
1275         }
1276         if (token == TT_SEMICOLON) {
1277           getNextToken();
1278         } else {
1279           if (!phpEnd) {
1280             throwSyntaxError("';' expected after 'define' statement.");
1281           }
1282         }
1283         return;
1284       } else if (token == TT_function) {
1285         getNextToken();
1286         functionDefinition();
1287         return;
1288       } else if (token == TT_class) {
1289         getNextToken();
1290         classDeclarator();
1291         classBody();
1292         return;
1293       } else {
1294         throwSyntaxError("Unexpected keyword '" + keyword + "'");
1295       }
1296
1297     } else if (token == TT_LISTOPEN) {
1298       // compoundStatement
1299       getNextToken();
1300       if (token != TT_LISTCLOSE) {
1301         statementList();
1302       }
1303       if (token == TT_LISTCLOSE) {
1304         getNextToken();
1305         return;
1306       } else {
1307         throwSyntaxError("'}' expected.");
1308       }
1309     } else {
1310       if (token != TT_SEMICOLON) {
1311         expression();
1312       }
1313       if (token == TT_SEMICOLON) {
1314         getNextToken();
1315         return;
1316       } else {
1317         if (!phpEnd) {
1318           throwSyntaxError("';' expected after expression.");
1319         }
1320       }
1321     }
1322
1323   }
1324
1325   public void classDeclarator() {
1326     //identifier
1327     //identifier 'extends' identifier
1328     if (token == TT_IDENTIFIER) {
1329       getNextToken();
1330       if (token == TT_extends) {
1331         getNextToken();
1332         if (token == TT_IDENTIFIER) {
1333           getNextToken();
1334         } else {
1335           throwSyntaxError("Class name expected after keyword 'extends'.");
1336         }
1337       }
1338     } else {
1339       throwSyntaxError("Class name expected after keyword 'class'.");
1340     }
1341   }
1342
1343   public void classBody() throws CoreException {
1344     //'{' [class-element-list] '}'
1345     if (token == TT_LISTOPEN) {
1346       getNextToken();
1347       if (token != TT_LISTCLOSE) {
1348         classElementList();
1349       }
1350       if (token == TT_LISTCLOSE) {
1351         getNextToken();
1352       } else {
1353         throwSyntaxError("'}' expected at end of class body.");
1354       }
1355     } else {
1356       throwSyntaxError("'{' expected at start of class body.");
1357     }
1358   }
1359
1360   public void classElementList() throws CoreException {
1361     do {
1362       classElement();
1363     } while (token == TT_function || token == TT_var);
1364   }
1365
1366   public void classElement() throws CoreException {
1367     //class-property
1368     //function-definition
1369     if (token == TT_function) {
1370       getNextToken();
1371       functionDefinition();
1372     } else if (token == TT_var) {
1373       getNextToken();
1374       classProperty();
1375     } else {
1376       throwSyntaxError("'function' or 'var' expected.");
1377     }
1378   }
1379
1380   public void classProperty() {
1381     //'var' variable ';'
1382     //'var' variable '=' constant ';'
1383     if (token == TT_VARIABLE) {
1384       getNextToken();
1385       if (token == TT_ASSIGN) {
1386         getNextToken();
1387         constant();
1388         if (token == TT_SEMICOLON) {
1389           getNextToken();
1390         } else {
1391           throwSyntaxError("';' expected after variable declaration.");
1392         }
1393       } else if (token == TT_SEMICOLON) {
1394         getNextToken();
1395       } else {
1396         throwSyntaxError("';' or '=' expected after variable declaration.");
1397       }
1398     } else {
1399       throwSyntaxError("Variable expected after keyword 'var'.");
1400     }
1401   }
1402
1403   public void functionDefinition() throws CoreException {
1404     functionDeclarator();
1405     compoundStatement();
1406   }
1407
1408   public void functionDeclarator() {
1409     //identifier '(' [parameter-list] ')'
1410     if (token == TT_IDENTIFIER) {
1411       getNextToken();
1412       if (token == TT_ARGOPEN) {
1413         getNextToken();
1414       } else {
1415         throwSyntaxError("'(' expected in function declaration.");
1416       }
1417       if (token != TT_ARGCLOSE) {
1418         parameterList();
1419       }
1420       if (token != TT_ARGCLOSE) {
1421         throwSyntaxError("')' expected in function declaration.");
1422       } else {
1423         getNextToken();
1424       }
1425     }
1426   }
1427   //
1428   public void parameterList() {
1429     //parameter-declaration
1430     //parameter-list ',' parameter-declaration
1431     do {
1432       parameterDeclaration();
1433       if (token != TT_COMMA) {
1434         break;
1435       }
1436       getNextToken();
1437     } while (true);
1438   }
1439
1440   public void parameterDeclaration() {
1441     //variable
1442     //variable-reference
1443     //variable '=' constant
1444     if (token == TT_VARIABLE) {
1445       getNextToken();
1446       if (token == TT_ASSIGN) {
1447         getNextToken();
1448         constant();
1449       }
1450       return;
1451     }
1452   }
1453
1454   public void labeledStatementList() throws CoreException {
1455     if (token != TT_case && token != TT_default) {
1456       throwSyntaxError("'case' or 'default' expected.");
1457     }
1458     do {
1459       if (token == TT_case) {
1460         getNextToken();
1461         constant();
1462         if (token == TT_DDOT) {
1463           getNextToken();
1464           statementList();
1465         } else if (token == TT_SEMICOLON) {
1466           setMarker("':' expected after 'case' keyword found ';'.", rowCount, PHPParser.INFO);
1467           getNextToken();
1468           statementList();
1469         } else {
1470           throwSyntaxError("':' character after 'case' constant expected.");
1471         }
1472       } else { // TT_default 
1473         getNextToken();
1474         if (token == TT_DDOT) {
1475           getNextToken();
1476           statementList();
1477         } else {
1478           throwSyntaxError("':' character after 'default' expected.");
1479         }
1480       }
1481     } while (token == TT_case || token == TT_default);
1482   }
1483
1484   //  public void labeledStatement() {
1485   //    if (token == TT_case) {
1486   //      getNextToken();
1487   //      constant();
1488   //      if (token == TT_DDOT) {
1489   //        getNextToken();
1490   //        statement();
1491   //      } else {
1492   //        throwSyntaxError("':' character after 'case' constant expected.");
1493   //      }
1494   //      return;
1495   //    } else if (token == TT_default) {
1496   //      getNextToken();
1497   //      if (token == TT_DDOT) {
1498   //        getNextToken();
1499   //        statement();
1500   //      } else {
1501   //        throwSyntaxError("':' character after 'default' expected.");
1502   //      }
1503   //      return;
1504   //    }
1505   //  }
1506
1507   public void expressionStatement() {
1508   }
1509
1510   public void inclusionStatement() {
1511   }
1512
1513   //  public void compoundStatement() {
1514   //  }
1515
1516   //  public void selectionStatement() {
1517   //  }
1518   //
1519   //  public void iterationStatement() {
1520   //  }
1521   //
1522   //  public void jumpStatement() {
1523   //  }
1524   //
1525   //  public void outputStatement() {
1526   //  }
1527   //
1528   //  public void scopeStatement() {
1529   //  }
1530   //
1531   //  public void flowStatement() {
1532   //  }
1533   //
1534   //  public void definitionStatement() {
1535   //  }
1536
1537   public void ifStatement() throws CoreException {
1538     // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
1539     if (token == TT_DDOT) {
1540       getNextToken();
1541       statementList();
1542       switch (token) {
1543         case TT_else :
1544           getNextToken();
1545           if (token == TT_DDOT) {
1546             getNextToken();
1547             statementList();
1548           } else {
1549             if (token == TT_if) { //'else if'
1550               getNextToken();
1551               elseifStatementList();
1552             } else {
1553               throwSyntaxError("':' expected after 'else'.");
1554             }
1555           }
1556           break;
1557         case TT_elseif :
1558           getNextToken();
1559           elseifStatementList();
1560           break;
1561       }
1562
1563       if (token != TT_endif) {
1564         throwSyntaxError("'endif' expected.");
1565       }
1566       getNextToken();
1567       if (token != TT_SEMICOLON) {
1568         throwSyntaxError("';' expected after if-statement.");
1569       }
1570       getNextToken();
1571     } else {
1572       // statement [else-statement]
1573       statement();
1574       if (token == TT_elseif) {
1575         getNextToken();
1576         if (token == TT_ARGOPEN) {
1577           getNextToken();
1578         } else {
1579           throwSyntaxError("'(' expected after 'elseif' keyword.");
1580         }
1581         expression();
1582         if (token == TT_ARGCLOSE) {
1583           getNextToken();
1584         } else {
1585           throwSyntaxError("')' expected after 'elseif' condition.");
1586         }
1587         ifStatement();
1588       } else if (token == TT_else) {
1589         getNextToken();
1590         statement();
1591       }
1592     }
1593   }
1594   public void elseifStatementList() throws CoreException {
1595     do {
1596       elseifStatement();
1597       switch (token) {
1598         case TT_else :
1599           getNextToken();
1600           if (token == TT_DDOT) {
1601             getNextToken();
1602             statementList();
1603             return;
1604           } else {
1605             if (token == TT_if) { //'else if'
1606               getNextToken();
1607             } else {
1608               throwSyntaxError("':' expected after 'else'.");
1609             }
1610           }
1611           break;
1612         case TT_elseif :
1613           getNextToken();
1614           break;
1615         default :
1616           return;
1617       }
1618     } while (true);
1619   }
1620
1621   public void elseifStatement() throws CoreException {
1622     if (token == TT_ARGOPEN) {
1623       getNextToken();
1624       expression();
1625       if (token != TT_ARGOPEN) {
1626         throwSyntaxError("')' expected in else-if-statement.");
1627       }
1628       getNextToken();
1629       if (token != TT_DDOT) {
1630         throwSyntaxError("':' expected in else-if-statement.");
1631       }
1632       getNextToken();
1633       statementList();
1634     }
1635   }
1636
1637   public void switchStatement() throws CoreException {
1638     if (token == TT_DDOT) {
1639       // ':' [labeled-statement-list] 'endswitch' ';'
1640       getNextToken();
1641       labeledStatementList();
1642       if (token != TT_endswitch) {
1643         throwSyntaxError("'endswitch' expected.");
1644       }
1645       getNextToken();
1646       if (token != TT_SEMICOLON) {
1647         throwSyntaxError("';' expected after switch-statement.");
1648       }
1649       getNextToken();
1650     } else {
1651       // '{' [labeled-statement-list] '}'
1652       if (token != TT_LISTOPEN) {
1653         throwSyntaxError("'{' expected in switch statement.");
1654       }
1655       getNextToken();
1656       if (token != TT_LISTCLOSE) {
1657         labeledStatementList();
1658       }
1659       if (token != TT_LISTCLOSE) {
1660         throwSyntaxError("'}' expected in switch statement.");
1661       }
1662       getNextToken();
1663
1664     }
1665   }
1666
1667   public void forStatement() throws CoreException {
1668     if (token == TT_DDOT) {
1669       getNextToken();
1670       statementList();
1671       if (token != TT_endfor) {
1672         throwSyntaxError("'endfor' expected.");
1673       }
1674       getNextToken();
1675       if (token != TT_SEMICOLON) {
1676         throwSyntaxError("';' expected after for-statement.");
1677       }
1678       getNextToken();
1679     } else {
1680       statement();
1681     }
1682   }
1683
1684   public void whileStatement() throws CoreException {
1685     // ':' statement-list 'endwhile' ';'
1686     if (token == TT_DDOT) {
1687       getNextToken();
1688       statementList();
1689       if (token != TT_endwhile) {
1690         throwSyntaxError("'endwhile' expected.");
1691       }
1692       getNextToken();
1693       if (token != TT_SEMICOLON) {
1694         throwSyntaxError("';' expected after while-statement.");
1695       }
1696       getNextToken();
1697     } else {
1698       statement();
1699     }
1700   }
1701
1702   public void foreachStatement() throws CoreException {
1703     if (token == TT_DDOT) {
1704       getNextToken();
1705       statementList();
1706       if (token != TT_endforeach) {
1707         throwSyntaxError("'endforeach' expected.");
1708       }
1709       getNextToken();
1710       if (token != TT_SEMICOLON) {
1711         throwSyntaxError("';' expected after foreach-statement.");
1712       }
1713       getNextToken();
1714     } else {
1715       statement();
1716     }
1717   }
1718
1719   public void exitStatus() {
1720     if (token == TT_ARGOPEN) {
1721       getNextToken();
1722     } else {
1723       throwSyntaxError("'(' expected in 'exit-status'.");
1724     }
1725     if (token != TT_ARGCLOSE) {
1726       expression();
1727     }
1728     if (token == TT_ARGCLOSE) {
1729       getNextToken();
1730     } else {
1731       throwSyntaxError("')' expected after 'exit-status'.");
1732     }
1733   }
1734
1735   public void expressionList() {
1736     do {
1737       expression();
1738       if (token == TT_COMMA) {
1739         getNextToken();
1740       } else {
1741         break;
1742       }
1743     } while (true);
1744   }
1745
1746   public void expression() {
1747     //    if (token == TT_STRING_CONSTANT || token == TT_INTERPOLATED_STRING) {
1748     //      getNextToken();
1749     //    } else {
1750     logicalinclusiveorExpression();
1751     //      while (token != TT_SEMICOLON) {
1752     //        getNextToken();
1753     //      //      }
1754     //    }
1755   }
1756
1757   public void postfixExpression() {
1758     String ident;
1759     boolean castFlag = false;
1760     switch (token) {
1761       case TT_new :
1762         getNextToken();
1763         expression();
1764         break;
1765       case TT_null :
1766         getNextToken();
1767         break;
1768       case TT_false :
1769         getNextToken();
1770         break;
1771       case TT_true :
1772         getNextToken();
1773         break;
1774       case TT_STRING_CONSTANT :
1775         getNextToken();
1776         break;
1777       case TT_INTERPOLATED_STRING :
1778         getNextToken();
1779         break;
1780       case TT_ARGOPEN :
1781         getNextToken();
1782         if (token == TT_IDENTIFIER) {
1783           // check if identifier is a type:
1784           ident = identifier;
1785           String str = identifier.toLowerCase();
1786           for (int i = 0; i < PHP_TYPES.length; i++) {
1787             if (PHP_TYPES[i].equals(str)) {
1788               castFlag = true;
1789               break;
1790             }
1791           }
1792           if (castFlag) {
1793             getNextToken();
1794             if (token != TT_ARGCLOSE) {
1795               throwSyntaxError(") expected after cast-type '" + ident + "'.");
1796             }
1797             getNextToken();
1798             expression();
1799             break;
1800           }
1801         }
1802         if (!castFlag) {
1803           expression();
1804         }
1805         if (token != TT_ARGCLOSE) {
1806           throwSyntaxError(") expected in postfix-expression.");
1807         }
1808         getNextToken();
1809         break;
1810       case TT_DOUBLE_NUMBER :
1811         getNextToken();
1812         break;
1813       case TT_INT_NUMBER :
1814         getNextToken();
1815         break;
1816       case TT_VARIABLE :
1817         ident = identifier;
1818         getNextToken();
1819         if (token == TT_LISTOPEN) {
1820           getNextToken();
1821           expression();
1822           if (token != TT_LISTCLOSE) {
1823             throwSyntaxError("'}' expected after variable '" + ident + "' in variable-expression.");
1824           }
1825           getNextToken();
1826         }
1827         break;
1828       case TT_IDENTIFIER :
1829         ident = identifier;
1830         getNextToken();
1831         if (token == TT_ARGOPEN) {
1832           getNextToken();
1833           if (token != TT_ARGCLOSE) {
1834             expressionList();
1835             if (token != TT_ARGCLOSE) {
1836               throwSyntaxError("')' expected after identifier '" + ident + "' in postfix-expression.");
1837             }
1838           }
1839           getNextToken();
1840         }
1841         break;
1842       case TT_list :
1843         getNextToken();
1844         if (token == TT_ARGOPEN) {
1845           getNextToken();
1846           if (token == TT_COMMA) {
1847             getNextToken();
1848           }
1849           expressionList();
1850           if (token != TT_ARGCLOSE) {
1851             throwSyntaxError("')' expected after 'list' keyword.");
1852           }
1853           getNextToken();
1854           //          if (token == TT_SET) {
1855           //            getNextToken();
1856           //            logicalinclusiveorExpression();
1857           //          }
1858         } else {
1859           throwSyntaxError("'(' expected after 'list' keyword.");
1860         }
1861         break;
1862         //      case TT_exit :
1863         //        getNextToken();
1864         //        if (token != TT_SEMICOLON) {
1865         //          exitStatus();
1866         //        }
1867         //        if (token == TT_SEMICOLON) {
1868         //          getNextToken();
1869         //        } else {
1870         //          if (!phpEnd) {
1871         //            throwSyntaxError("';' expected after 'exit' expression.");
1872         //          }
1873         //        }
1874         //        break;
1875         //      case TT_die :
1876         //        getNextToken();
1877         //        if (token != TT_SEMICOLON) {
1878         //          exitStatus();
1879         //        }
1880         //        if (token == TT_SEMICOLON) {
1881         //          getNextToken();
1882         //        } else {
1883         //          if (!phpEnd) {
1884         //            throwSyntaxError("';' expected after 'die' expression.");
1885         //          }
1886         //        }
1887         //        break;
1888
1889         //      case TT_array :
1890         //        getNextToken();
1891         //        if (token == TT_ARGOPEN) {
1892         //          getNextToken();
1893         //          if (token == TT_COMMA) {
1894         //            getNextToken();
1895         //          }
1896         //          expressionList();
1897         //          if (token != TT_ARGCLOSE) {
1898         //            throwSyntaxError("')' expected after 'list' keyword.");
1899         //          }
1900         //          getNextToken();
1901         //          if (token == TT_SET) {
1902         //            getNextToken();
1903         //            logicalinclusiveorExpression();
1904         //          }
1905         //        } else {
1906         //          throwSyntaxError("'(' expected after 'list' keyword.");
1907         //        }
1908         //        break;
1909     }
1910     boolean while_flag = true;
1911     do {
1912       switch (token) {
1913         case TT_PARTOPEN :
1914           getNextToken();
1915           expression();
1916           if (token != TT_PARTCLOSE) {
1917             throwSyntaxError("] expected in postfix-expression.");
1918           }
1919           getNextToken();
1920           break;
1921         case TT_REF : // ->
1922           getNextToken();
1923           switch (token) {
1924             case TT_VARIABLE :
1925               ident = identifier;
1926               getNextToken();
1927               //              if (token == TT_ARGOPEN) {
1928               //                getNextToken();
1929               //                expressionList();
1930               //                if (token != TT_ARGCLOSE) {
1931               //                  throwSyntaxError(") expected after variable '" + ident + "'.");
1932               //                }
1933               //                getNextToken();
1934               //              }
1935               break;
1936             case TT_IDENTIFIER :
1937               ident = identifier;
1938               getNextToken();
1939               if (token == TT_ARGOPEN) {
1940                 getNextToken();
1941                 expressionList();
1942                 if (token != TT_ARGCLOSE) {
1943                   throwSyntaxError(") expected after identifier '" + ident + "'.");
1944                 }
1945                 getNextToken();
1946               }
1947               break;
1948             case TT_LISTOPEN :
1949               getNextToken();
1950               expression();
1951               if (token != TT_LISTCLOSE) {
1952                 throwSyntaxError("} expected in postfix-expression.");
1953               }
1954               getNextToken();
1955               break;
1956             default :
1957               throwSyntaxError("Syntax error after '->' token.");
1958           }
1959           break;
1960         case TT_INCREMENT :
1961           getNextToken();
1962           break;
1963         case TT_DECREMENT :
1964           getNextToken();
1965           break;
1966         default :
1967           while_flag = false;
1968       }
1969     } while (while_flag);
1970   }
1971
1972   public void unaryExpression() {
1973     switch (token) {
1974       case TT_INCREMENT :
1975         getNextToken();
1976         unaryExpression();
1977         break;
1978       case TT_DECREMENT :
1979         getNextToken();
1980         unaryExpression();
1981         break;
1982         //'&' '*' '+' '-' '~' '!' 
1983       case TT_AMPERSAND :
1984         getNextToken();
1985         castExpression();
1986         break;
1987       case TT_MULTIPLY :
1988         getNextToken();
1989         castExpression();
1990         break;
1991       case TT_ADD :
1992         getNextToken();
1993         castExpression();
1994         break;
1995       case TT_SUBTRACT :
1996         getNextToken();
1997         castExpression();
1998         break;
1999       case TT_TILDE :
2000         getNextToken();
2001         castExpression();
2002         break;
2003       case TT_NOT :
2004         getNextToken();
2005         castExpression();
2006         break;
2007       default :
2008         postfixExpression();
2009     }
2010   }
2011
2012   public void castExpression() {
2013     //    if (token == TT_ARGOPEN) {
2014     //      getNextToken();
2015     //      typeName();
2016     //      if (token != TT_ARGCLOSE) {
2017     //        throwSyntaxError(") expected after cast-expression.");
2018     //      }
2019     //      getNextToken();
2020     //    }
2021     unaryExpression();
2022   }
2023
2024   public void typeName() {
2025     //'string' 'unset' 'array' 'object'
2026     //'bool' 'boolean'
2027     //'real' 'double' 'float'
2028     //'int' 'integer'
2029     String ident = "";
2030     if (token == TT_IDENTIFIER) {
2031       ident = identifier;
2032       String str = identifier.toLowerCase();
2033       getNextToken();
2034       for (int i = 0; i < PHP_TYPES.length; i++) {
2035         if (PHP_TYPES[i].equals(str)) {
2036           return;
2037         }
2038       }
2039     }
2040     throwSyntaxError("Expected type cast '( <type-name> )'; Got '" + ident + "'.");
2041   }
2042
2043   public void assignExpression() {
2044     castExpression();
2045     if (token == TT_ASSIGN) { // =
2046       getNextToken();
2047       logicalinclusiveorExpression();
2048     } else if (token == TT_DOTASSIGN) { // .=
2049       getNextToken();
2050       logicalinclusiveorExpression();
2051     } else if (token == TT_FOREACH) { // =>
2052       getNextToken();
2053       logicalinclusiveorExpression();
2054     } else if (token == TT_ADDTO) { // +=
2055       getNextToken();
2056       logicalinclusiveorExpression();
2057     } else if (token == TT_SUBTRACTFROM) { // -=
2058       getNextToken();
2059       logicalinclusiveorExpression();
2060     } else if (token == TT_TIMESBY) { // *=
2061       getNextToken();
2062       logicalinclusiveorExpression();
2063     } else if (token == TT_DIVIDEBY) { // *=
2064       getNextToken();
2065       logicalinclusiveorExpression();
2066     } else if (token == TT_MODASSIGN) { // %=
2067       getNextToken();
2068       logicalinclusiveorExpression();
2069     } else if (token == TT_ANDASSIGN) { // &=
2070       getNextToken();
2071       logicalinclusiveorExpression();
2072     } else if (token == TT_POWASSIGN) { // ^=
2073       getNextToken();
2074       logicalinclusiveorExpression();
2075     } else if (token == TT_LSHIFTASSIGN) { // <<=
2076       getNextToken();
2077       logicalinclusiveorExpression();
2078     } else if (token == TT_RSHIFTASSIGN) { // >>=
2079       getNextToken();
2080       logicalinclusiveorExpression();
2081     } else if (token == TT_TILDEASSIGN) { // ~=
2082       getNextToken();
2083       logicalinclusiveorExpression();
2084     }
2085   }
2086
2087   public void multiplicativeExpression() {
2088     do {
2089       assignExpression();
2090       if (token != TT_MULTIPLY && token != TT_DIV && token != TT_MOD) {
2091         return;
2092       }
2093       getNextToken();
2094     } while (true);
2095   }
2096
2097   public void concatenationExpression() {
2098     do {
2099       multiplicativeExpression();
2100       if (token != TT_DOT) {
2101         return;
2102       }
2103       getNextToken();
2104     } while (true);
2105   }
2106
2107   public void additiveExpression() {
2108     do {
2109       concatenationExpression();
2110       if (token != TT_ADD && token != TT_SUBTRACT) {
2111         return;
2112       }
2113       getNextToken();
2114     } while (true);
2115   }
2116
2117   public void shiftExpression() {
2118     do {
2119       additiveExpression();
2120       if (token != TT_LSHIFT && token != TT_RSHIFT) {
2121         return;
2122       }
2123       getNextToken();
2124     } while (true);
2125   }
2126
2127   public void relationalExpression() {
2128     do {
2129       shiftExpression();
2130       if (token != TT_LESS && token != TT_GREATER && token != TT_LESSEQUAL && token != TT_GREATEREQUAL) {
2131         return;
2132       }
2133       getNextToken();
2134     } while (true);
2135   }
2136
2137   public void identicalExpression() {
2138     do {
2139       relationalExpression();
2140       if (token != TT_EX_EQUAL && token != TT_EX_UNEQUAL) {
2141         return;
2142       }
2143       getNextToken();
2144     } while (true);
2145   }
2146
2147   public void equalityExpression() {
2148     do {
2149       identicalExpression();
2150       if (token != TT_EQUAL && token != TT_UNEQUAL) {
2151         return;
2152       }
2153       getNextToken();
2154     } while (true);
2155   }
2156
2157   public void ternaryExpression() {
2158     equalityExpression();
2159     if (token == TT_QUESTIONMARK) {
2160       getNextToken();
2161       expression();
2162       if (token == TT_DDOT) {
2163         getNextToken();
2164         expression();
2165       } else {
2166         throwSyntaxError("':' expected in ternary operator '? :'.");
2167       }
2168     }
2169   }
2170
2171   public void andExpression() {
2172     do {
2173       ternaryExpression();
2174       if (token != TT_AMPERSAND) {
2175         return;
2176       }
2177       getNextToken();
2178     } while (true);
2179   }
2180
2181   public void exclusiveorExpression() {
2182     do {
2183       andExpression();
2184       if (token != TT_POW) {
2185         return;
2186       }
2187       getNextToken();
2188     } while (true);
2189   }
2190
2191   public void inclusiveorExpression() {
2192     do {
2193       exclusiveorExpression();
2194       if (token != TT_LINE) {
2195         return;
2196       }
2197       getNextToken();
2198     } while (true);
2199   }
2200
2201   public void booleanandExpression() {
2202     do {
2203       inclusiveorExpression();
2204       if (token != TT_AND) {
2205         return;
2206       }
2207       getNextToken();
2208     } while (true);
2209   }
2210
2211   public void booleanorExpression() {
2212     do {
2213       booleanandExpression();
2214       if (token != TT_OR) {
2215         return;
2216       }
2217       getNextToken();
2218     } while (true);
2219   }
2220
2221   public void logicalandExpression() {
2222     do {
2223       booleanorExpression();
2224       if (token != TT_and) {
2225         return;
2226       }
2227       getNextToken();
2228     } while (true);
2229   }
2230
2231   public void logicalexclusiveorExpression() {
2232     do {
2233       logicalandExpression();
2234       if (token != TT_xor) {
2235         return;
2236       }
2237       getNextToken();
2238     } while (true);
2239   }
2240
2241   public void logicalinclusiveorExpression() {
2242     do {
2243       logicalexclusiveorExpression();
2244       if (token != TT_or) {
2245         return;
2246       }
2247       getNextToken();
2248     } while (true);
2249   }
2250
2251   //  public void assignmentExpression() {
2252   //    if (token == TT_VARIABLE) {
2253   //      getNextToken();
2254   //      if (token == TT_SET) {
2255   //        getNextToken();
2256   //        logicalinclusiveorExpression();
2257   //      }
2258   //    } else {
2259   //      logicalinclusiveorExpression();
2260   //    }
2261   //  }
2262
2263   public void variableList() {
2264     do {
2265       variable();
2266       if (token == TT_COMMA) {
2267         getNextToken();
2268       } else {
2269         break;
2270       }
2271     } while (true);
2272   }
2273
2274   public void variable() {
2275     if (token == TT_VARIABLE) {
2276       getNextToken();
2277     } else {
2278       throwSyntaxError("$-variable expected in variable-list.");
2279     }
2280   }
2281
2282   public void constant() {
2283     switch (token) {
2284       case TT_ADD :
2285         getNextToken();
2286         switch (token) {
2287           case TT_DOUBLE_NUMBER :
2288             getNextToken();
2289             break;
2290           case TT_INT_NUMBER :
2291             getNextToken();
2292             break;
2293           default :
2294             throwSyntaxError("Constant expected after '+' presign.");
2295         }
2296         break;
2297       case TT_SUBTRACT :
2298         getNextToken();
2299         switch (token) {
2300           case TT_DOUBLE_NUMBER :
2301             getNextToken();
2302             break;
2303           case TT_INT_NUMBER :
2304             getNextToken();
2305             break;
2306           default :
2307             throwSyntaxError("Constant expected after '-' presign.");
2308         }
2309         break;
2310       case TT_null :
2311         getNextToken();
2312         break;
2313       case TT_false :
2314         getNextToken();
2315         break;
2316       case TT_true :
2317         getNextToken();
2318         break;
2319       case TT_STRING_CONSTANT :
2320         getNextToken();
2321         break;
2322       case TT_INTERPOLATED_STRING :
2323         getNextToken();
2324         break;
2325       case TT_DOUBLE_NUMBER :
2326         getNextToken();
2327         break;
2328       case TT_INT_NUMBER :
2329         getNextToken();
2330         break;
2331       default :
2332         throwSyntaxError("Constant expected.");
2333     }
2334   }
2335
2336 }