misc changes
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / phpeditor / phpparser / PHPParser.java
1 /**********************************************************************
2 Copyright (c) 2002 Klaus Hartlage - www.eclipseproject.de
3 All rights reserved. This program and the accompanying materials
4 are made available under the terms of the Common Public License v1.0
5 which accompanies this distribution, and is available at
6 http://www.eclipse.org/legal/cpl-v10.html
7
8 Contributors:
9     Klaus Hartlage - www.eclipseproject.de
10 **********************************************************************/
11 package net.sourceforge.phpeclipse.phpeditor.phpparser;
12
13 import java.text.MessageFormat;
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.Hashtable;
17 import java.util.Stack;
18
19 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
20 import net.sourceforge.phpeclipse.actions.PHPStartApacheAction;
21 import net.sourceforge.phpeclipse.phpeditor.PHPString;
22 import net.sourceforge.phpeclipse.phpeditor.php.PHPKeywords;
23 import org.eclipse.core.resources.IFile;
24 import org.eclipse.core.resources.IMarker;
25 import org.eclipse.core.runtime.CoreException;
26 import org.eclipse.core.runtime.IPath;
27 import org.eclipse.jface.preference.IPreferenceStore;
28 import org.eclipse.ui.texteditor.MarkerUtilities;
29
30 public class PHPParser extends PHPKeywords {
31   // strings for external parser call
32   private static final String PARSE_ERROR_STRING = "Parse error"; //$NON-NLS-1$
33   private static final String PARSE_WARNING_STRING = "Warning"; //$NON-NLS-1$
34
35   public static final int ERROR = 2;
36   public static final int WARNING = 1;
37   public static final int INFO = 0;
38   private IFile fileToParse;
39   private ArrayList phpList;
40
41   private int currentPHPString;
42   private boolean phpEnd;
43
44   private static HashMap keywordMap = null;
45   private String str;
46
47   // current character
48   char ch;
49   // current token
50   int token;
51
52   // row counter for syntax errors:
53   int rowCount;
54   // column counter for syntax errors:
55   int columnCount;
56
57   int chIndx;
58
59   // current identifier
60   String identifier;
61
62   Long longNumber;
63   Double doubleNumber;
64   private boolean phpMode;
65
66   final static int TT_EOF = 0;
67   final static int TT_UNDEFINED = 1;
68   final static int TT_HTML = 2;
69
70   final static int TT_MOD = 30;
71   final static int TT_NOT = 31;
72   final static int TT_DOT = 32;
73   final static int TT_POW = 33;
74   final static int TT_DIV = 34;
75   final static int TT_MULTIPLY = 35;
76   final static int TT_SUBTRACT = 36;
77   final static int TT_ADD = 37;
78   final static int TT_EQUAL = 38;
79   final static int TT_UNEQUAL = 39;
80   final static int TT_GREATER = 40;
81   final static int TT_GREATEREQUAL = 41;
82   final static int TT_LESS = 42;
83   final static int TT_LESSEQUAL = 43;
84   final static int TT_AND = 44;
85   final static int TT_OR = 45;
86   final static int TT_HASH = 46;
87   final static int TT_DDOT = 47;
88   final static int TT_DOTASSIGN = 48;
89
90   final static int TT_ASSIGN = 49;
91   final static int TT_REF = 50;
92   final static int TT_FOREACH = 51;
93   final static int TT_AMPERSAND = 52;
94   final static int TT_DOLLARLISTOPEN = 53;
95   final static int TT_TILDE = 54;
96   final static int TT_TILDEASSIGN = 55;
97   final static int TT_MODASSIGN = 56;
98   final static int TT_POWASSIGN = 57;
99   final static int TT_RSHIFTASSIGN = 58;
100   final static int TT_LSHIFTASSIGN = 59;
101   final static int TT_ANDASSIGN = 60;
102   final static int TT_QUESTIONMARK = 61;
103   final static int TT_DDOT2 = 62;
104   final static int TT_AT = 63;
105   // final static int TT_HEREDOC = 64;
106
107   final static int TT_DOLLAROPEN = 127;
108   final static int TT_ARGOPEN = 128;
109   final static int TT_ARGCLOSE = 129;
110   final static int TT_LISTOPEN = 130;
111   final static int TT_LISTCLOSE = 131;
112   final static int TT_PARTOPEN = 132;
113   final static int TT_PARTCLOSE = 133;
114   final static int TT_COMMA = 134;
115
116   final static int TT_STRING = 136;
117   final static int TT_IDENTIFIER = 138;
118   final static int TT_DIGIT = 139;
119   final static int TT_SEMICOLON = 140;
120   final static int TT_SLOT = 141;
121   final static int TT_SLOTSEQUENCE = 142;
122   final static int TT_DECREMENT = 144;
123   final static int TT_INCREMENT = 145;
124   final static int TT_ADDTO = 146;
125   final static int TT_DIVIDEBY = 147;
126   final static int TT_SUBTRACTFROM = 148;
127   final static int TT_TIMESBY = 149;
128   final static int TT_VARIABLE = 150;
129   final static int TT_INT_NUMBER = 151;
130   final static int TT_DOUBLE_NUMBER = 152;
131   final static int TT_INTERPOLATED_STRING = 153;
132   final static int TT_STRING_CONSTANT = 154;
133
134   final static int TT_LSHIFT = 155;
135   final static int TT_RSHIFT = 156;
136   final static int TT_EX_EQUAL = 157;
137   final static int TT_EX_UNEQUAL = 158;
138   final static int TT_LINE = 159;
139   //  final static int TT_AT = 153; // @
140   /**
141    *  Class Constructor.
142    *
143    *@param  s
144    *@param  sess  Description of Parameter
145    *@see
146    */
147   public PHPParser(IFile fileToParse) {
148     if (keywordMap == null) {
149       keywordMap = new HashMap();
150       for (int i = 0; i < PHP_KEYWORS.length; i++) {
151         keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
152       }
153     }
154     this.currentPHPString = 0;
155     this.fileToParse = fileToParse;
156     this.phpList = null;
157     this.str = "";
158     this.token = TT_EOF;
159     this.chIndx = 0;
160     this.rowCount = 1;
161     this.columnCount = 0;
162     this.phpEnd = false;
163
164     //   getNextToken();
165   }
166
167   /**
168    * Create marker for the parse error
169    */
170   private void setMarker(String message, int lineNumber, int errorLevel) throws CoreException {
171     setMarker(fileToParse, message, lineNumber, errorLevel);
172   }
173
174   public static void setMarker(IFile file, String message, int lineNumber, int errorLevel) throws CoreException {
175     if (file != null) {
176       Hashtable attributes = new Hashtable();
177       MarkerUtilities.setMessage(attributes, message);
178       switch (errorLevel) {
179         case ERROR :
180           attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR));
181           break;
182         case WARNING :
183           attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_WARNING));
184           break;
185         case INFO :
186           attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO));
187           break;
188       }
189       MarkerUtilities.setLineNumber(attributes, lineNumber);
190       MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM);
191     }
192   }
193
194   private void throwSyntaxError(String error) {
195
196     if (str.length() < chIndx) {
197       chIndx--;
198     }
199     // read until end-of-line
200     int eol = chIndx;
201     while (str.length() > eol) {
202       ch = str.charAt(eol++);
203       if (ch == '\n') {
204         eol--;
205         break;
206       }
207     }
208     throw new SyntaxError(rowCount, chIndx - columnCount + 1, str.substring(columnCount, eol), error);
209   }
210
211   private void throwSyntaxError(String error, int startRow) {
212
213     throw new SyntaxError(startRow, 0, " ", error);
214   }
215
216   /**
217    *  Method Declaration.
218    *
219    *@see
220    */
221   private void getChar() {
222     if (str.length() > chIndx) {
223       ch = str.charAt(chIndx++);
224
225       return;
226     }
227
228     chIndx = str.length() + 1;
229     ch = ' ';
230     //  token = TT_EOF;
231     phpEnd = true;
232   }
233
234   private void getNextToken_OldVersion() throws CoreException {
235     phpEnd = false;
236
237     while (str.length() > chIndx) {
238       ch = str.charAt(chIndx++);
239       token = TT_UNDEFINED;
240       if (ch == '\n') {
241         rowCount++;
242         columnCount = chIndx;
243         continue; // while loop
244       }
245       if (str.length() == chIndx) {
246         phpEnd = true;
247       }
248       if (!Character.isWhitespace(ch)) {
249         if (ch == '$') {
250           if (str.length() > chIndx) {
251             if (str.charAt(chIndx) == '{') {
252               chIndx++;
253               token = TT_DOLLAROPEN;
254               return;
255             }
256           }
257           getIdentifier();
258           return;
259         }
260         if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_') || (ch == '$')) {
261           getIdentifier();
262           return;
263         }
264         if (ch >= '0' && ch <= '9') {
265           getNumber();
266           return;
267         }
268         if (ch == '/') {
269           if (str.length() > chIndx) {
270             if (str.charAt(chIndx) == '/') {
271               chIndx++;
272               // read comment until end of line:
273               while ((str.length() > chIndx) && (str.charAt(chIndx) != '\n')) {
274                 chIndx++;
275               }
276               continue;
277             } else if (str.charAt(chIndx) == '*') {
278               chIndx++;
279               // multi line comment:
280               while (str.length() > chIndx) {
281                 if (str.charAt(chIndx) == '*' && (str.length() > (chIndx + 1)) && str.charAt(chIndx + 1) == '/') {
282                   chIndx += 2;
283                   break;
284                 }
285                 ch = str.charAt(chIndx++);
286                 if (ch == '\n') {
287                   rowCount++;
288                   columnCount = chIndx;
289                 }
290               }
291               continue;
292             }
293           }
294         } else if (ch == '#') {
295           // read comment until end of line:
296           while ((str.length() > chIndx) && (str.charAt(chIndx) != '\n')) {
297             chIndx++;
298           }
299           continue;
300         } else if (ch == '"') {
301           // read string until end
302           boolean openString = true;
303           while (str.length() > chIndx) {
304             ch = str.charAt(chIndx++);
305             if (ch == '\\') {
306               if (str.length() > chIndx) {
307                 ch = str.charAt(chIndx++);
308               }
309             } else if (ch == '"') {
310               openString = false;
311               break;
312             } else if (ch == '\n') {
313               rowCount++;
314               columnCount = chIndx;
315             }
316           }
317           if (openString) {
318             throwSyntaxError("Open string character '\"' at end of file.");
319           }
320           token = TT_INTERPOLATED_STRING;
321           return;
322         } else if (ch == '\'') {
323           // read string until end
324           boolean openString = true;
325           int startRow = rowCount;
326           while (str.length() > chIndx) {
327             ch = str.charAt(chIndx++);
328             if (ch == '\\') {
329               if (str.length() > chIndx) {
330                 ch = str.charAt(chIndx++);
331               }
332             } else if (ch == '\'') {
333               openString = false;
334               break;
335             } else if (ch == '\n') {
336               rowCount++;
337               columnCount = chIndx;
338             }
339           }
340           if (openString) {
341             throwSyntaxError("Open string character \"'\" at end of file.", startRow);
342           }
343           token = TT_STRING_CONSTANT;
344           return;
345         } else if (ch == '`') {
346           // read string until end
347           boolean openString = true;
348           int startRow = rowCount;
349           while (str.length() > chIndx) {
350             ch = str.charAt(chIndx++);
351             if (ch == '\\') {
352               if (str.length() > chIndx) {
353                 ch = str.charAt(chIndx++);
354               }
355             } else if (ch == '`') {
356               openString = false;
357               break;
358             } else if (ch == '\n') {
359               rowCount++;
360               columnCount = chIndx;
361             }
362           }
363           if (openString) {
364             throwSyntaxError("Open string character \"`\" at end of file.", startRow);
365           }
366           token = TT_STRING_CONSTANT;
367           return;
368         }
369
370         switch (ch) {
371
372           case '(' :
373             token = TT_ARGOPEN;
374
375             break;
376           case ')' :
377             token = TT_ARGCLOSE;
378
379             break;
380           case '{' :
381             token = TT_LISTOPEN;
382
383             break;
384           case '}' :
385             token = TT_LISTCLOSE;
386
387             break;
388           case '[' :
389             token = TT_PARTOPEN;
390
391             break;
392           case ']' :
393             token = TT_PARTCLOSE;
394
395             break;
396           case ',' :
397             token = TT_COMMA;
398
399             break;
400           case '?' :
401             token = TT_QUESTIONMARK;
402             break;
403           case '@' :
404             token = TT_AT;
405             break;
406           case '~' :
407             token = TT_TILDE;
408             if (str.length() > chIndx) {
409               if (str.charAt(chIndx) == '=') {
410                 chIndx++;
411                 token = TT_TILDEASSIGN;
412
413                 break;
414               }
415             }
416             break;
417           case '.' :
418             token = TT_DOT;
419             if (str.length() > chIndx) {
420               if (str.charAt(chIndx) == '=') {
421                 chIndx++;
422                 token = TT_DOTASSIGN;
423
424                 break;
425               }
426             }
427
428             break;
429           case '"' :
430             token = TT_STRING;
431
432             break;
433           case '%' :
434             token = TT_MOD;
435             if (str.length() > chIndx) {
436               if (str.charAt(chIndx) == '=') {
437                 chIndx++;
438                 token = TT_MODASSIGN;
439
440                 break;
441               }
442             }
443             break;
444           case ';' :
445             token = TT_SEMICOLON;
446
447             break;
448           case '^' :
449             token = TT_POW;
450             if (str.length() > chIndx) {
451               if (str.charAt(chIndx) == '=') {
452                 chIndx++;
453                 token = TT_POWASSIGN;
454
455                 break;
456               }
457             }
458             break;
459           case '/' :
460             token = TT_DIV;
461
462             if (str.length() > chIndx) {
463               if (str.charAt(chIndx) == '=') {
464                 chIndx++;
465                 token = TT_DIVIDEBY;
466
467                 break;
468               }
469             }
470
471             break;
472           case '*' :
473             token = TT_MULTIPLY;
474             if (str.length() > chIndx) {
475               if (str.charAt(chIndx) == '*') {
476                 chIndx++;
477                 token = TT_POW;
478
479                 break;
480               }
481               if (str.charAt(chIndx) == '=') {
482                 chIndx++;
483                 token = TT_TIMESBY;
484
485                 break;
486               }
487             }
488
489             break;
490           case '+' :
491             token = TT_ADD;
492             if (str.length() > chIndx) {
493               if (str.charAt(chIndx) == '+') {
494                 chIndx++;
495                 token = TT_INCREMENT;
496
497                 break;
498               }
499               if (str.charAt(chIndx) == '=') {
500                 chIndx++;
501                 token = TT_ADDTO;
502
503                 break;
504               }
505             }
506             break;
507           case '-' :
508             token = TT_SUBTRACT;
509             if (str.length() > chIndx) {
510               if (str.charAt(chIndx) == '-') {
511                 chIndx++;
512                 token = TT_DECREMENT;
513
514                 break;
515               }
516               if (str.charAt(chIndx) == '=') {
517                 chIndx++;
518                 token = TT_SUBTRACTFROM;
519
520                 break;
521               }
522               if (str.charAt(chIndx) == '>') {
523                 chIndx++;
524                 token = TT_REF;
525
526                 break;
527               }
528             }
529
530             break;
531           case '=' :
532             token = TT_ASSIGN;
533
534             if (str.length() > chIndx) {
535               ch = str.charAt(chIndx);
536
537               if (ch == '=') {
538                 chIndx++;
539                 token = TT_EQUAL;
540                 if (str.length() > chIndx) {
541                   ch = str.charAt(chIndx);
542
543                   if (ch == '=') {
544                     chIndx++;
545                     token = TT_EX_EQUAL;
546                   }
547                 }
548                 break;
549               }
550               if (ch == '>') {
551                 chIndx++;
552                 token = TT_FOREACH;
553
554                 break;
555               }
556             }
557
558             break;
559           case '!' :
560             token = TT_NOT;
561
562             if (str.length() > chIndx) {
563               if (str.charAt(chIndx) == '=') {
564                 chIndx++;
565                 token = TT_UNEQUAL;
566                 if (str.length() > chIndx) {
567                   ch = str.charAt(chIndx);
568
569                   if (ch == '=') {
570                     chIndx++;
571                     token = TT_EX_UNEQUAL;
572                   }
573                 }
574                 break;
575               }
576             }
577
578             break;
579           case '>' :
580             token = TT_GREATER;
581
582             if (str.length() > chIndx) {
583               if (str.charAt(chIndx) == '=') {
584                 chIndx++;
585                 token = TT_GREATEREQUAL;
586                 break;
587               }
588               if (str.charAt(chIndx) == '>') {
589                 chIndx++;
590                 token = TT_RSHIFT;
591                 if (str.length() > chIndx) {
592                   if (str.charAt(chIndx) == '=') {
593                     chIndx++;
594                     token = TT_RSHIFTASSIGN;
595                     break;
596                   }
597                 }
598                 break;
599               }
600             }
601
602             break;
603           case '<' :
604             token = TT_LESS;
605
606             if (str.length() > chIndx) {
607               if (str.charAt(chIndx) == '=') {
608                 chIndx++;
609                 token = TT_LESSEQUAL;
610
611                 break;
612               }
613               if (str.charAt(chIndx) == '<') {
614                 chIndx++;
615                 token = TT_LSHIFT;
616                 if (str.charAt(chIndx) == '<') {
617                   // heredoc
618                   int startRow = rowCount;
619                   if (str.length() > chIndx) {
620
621                     ch = str.charAt(++chIndx);
622                     if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_')) {
623                       chIndx++;
624                       getIdentifier();
625                       token = TT_STRING_CONSTANT;
626                       while (str.length() > chIndx) {
627                         ch = str.charAt(chIndx++);
628                         if (ch == '\n') {
629                           if (str.length() >= chIndx + identifier.length()) {
630                             if (str.substring(chIndx, chIndx + identifier.length()).equals(identifier)) {
631                               chIndx += identifier.length();
632                               return;
633                             }
634                           }
635                         }
636                       }
637                     }
638                   }
639                   throwSyntaxError("Open heredoc syntax after operator '<<<'.", startRow);
640                 } else if (str.charAt(chIndx) == '=') {
641                   chIndx++;
642                   token = TT_LSHIFTASSIGN;
643                   break;
644                 }
645                 break;
646               }
647             }
648
649             break;
650
651           case '|' :
652             token = TT_LINE;
653
654             if (str.length() > chIndx) {
655               if (str.charAt(chIndx) == '|') {
656                 chIndx++;
657                 token = TT_OR;
658
659                 break;
660               }
661             }
662
663             break;
664           case '&' :
665             token = TT_AMPERSAND;
666             if (str.length() > chIndx) {
667               if (str.charAt(chIndx) == '&') {
668                 chIndx++;
669                 token = TT_AND;
670                 break;
671               }
672               if (str.charAt(chIndx) == '=') {
673                 chIndx++;
674                 token = TT_ANDASSIGN;
675                 break;
676               }
677               break;
678             }
679
680             break;
681           case ':' :
682             token = TT_DDOT;
683             if (str.length() > chIndx) {
684               if (str.charAt(chIndx) == ':') {
685                 chIndx++;
686                 token = TT_DDOT2;
687               }
688             }
689             break;
690           case '#' :
691             token = TT_HASH;
692
693             break;
694             //          case '@' :
695             //            token = TT_AT;
696             //
697             //            break;
698           default :
699             throwSyntaxError("unexpected character: '" + ch + "'");
700         }
701
702         if (token == TT_UNDEFINED) {
703           throwSyntaxError("token not found");
704         }
705
706         return;
707       }
708     }
709
710     chIndx = str.length() + 1;
711     ch = ' ';
712     token = TT_EOF;
713     phpEnd = true;
714     PHPString temp;
715     if (phpList != null) {
716       if (currentPHPString < phpList.size()) {
717         token = TT_UNDEFINED;
718         temp = (PHPString) phpList.get(currentPHPString++);
719         this.str = temp.getPHPString();
720         this.token = TT_EOF;
721         this.chIndx = 0;
722         this.rowCount = temp.getLineNumber();
723         this.columnCount = 0;
724         getNextToken();
725         phpEnd = true;
726       } else {
727         token = TT_UNDEFINED;
728         return;
729       }
730     }
731   }
732   /**
733    * gets the next token from input
734    */
735   private void getNextToken() throws CoreException {
736     boolean phpFound = false;
737     char ch2;
738
739     phpEnd = false;
740     try {
741       if (!phpMode) {
742
743         while (str.length() > chIndx) {
744           token = TT_UNDEFINED;
745           ch = str.charAt(chIndx++);
746
747           if (ch == '\n') {
748             rowCount++;
749           }
750           if (ch == '<') {
751             ch2 = str.charAt(chIndx++);
752             if (ch2 == '?') {
753               ch2 = str.charAt(chIndx++);
754               if (Character.isWhitespace(ch2)) {
755                 // php start 
756                 phpMode = true;
757                 phpFound = true;
758                 break;
759               } else if (ch2 == 'p') {
760                 ch2 = str.charAt(chIndx++);
761                 if (ch2 == 'h') {
762                   ch2 = str.charAt(chIndx++);
763                   if (ch2 == 'p') {
764                     phpMode = true;
765                     phpFound = true;
766                     break;
767                   }
768                   chIndx--;
769                 }
770                 chIndx--;
771               } else if (ch2 == 'P') {
772                 ch2 = str.charAt(chIndx++);
773                 if (ch2 == 'H') {
774                   ch2 = str.charAt(chIndx++);
775                   if (ch2 == 'P') {
776                     phpMode = true;
777                     phpFound = true;
778                     break;
779                   }
780                   chIndx--;
781                 }
782                 chIndx--;
783               }
784               chIndx--;
785             }
786             chIndx--;
787           }
788         }
789
790       }
791
792       if (phpMode) {
793         while (str.length() > chIndx) {
794           ch = str.charAt(chIndx++);
795           token = TT_UNDEFINED;
796           if (ch == '\n') {
797             rowCount++;
798             columnCount = chIndx;
799             continue; // while loop
800           }
801           if (str.length() == chIndx) {
802             phpEnd = true;
803           }
804           if (!Character.isWhitespace(ch)) {
805             if (ch == '$') {
806               if (str.length() > chIndx) {
807                 if (str.charAt(chIndx) == '{') {
808                   chIndx++;
809                   token = TT_DOLLAROPEN;
810                   return;
811                 }
812               }
813               getIdentifier();
814               return;
815             }
816             if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_') || (ch == '$')) {
817               getIdentifier();
818               return;
819             }
820             if (ch >= '0' && ch <= '9') {
821               getNumber();
822               return;
823             }
824             if (ch == '/') {
825               if (str.length() > chIndx) {
826                 if (str.charAt(chIndx) == '/') {
827                   ch = '/';
828                   chIndx++;
829                   // read comment until end of line:
830                   while ((str.length() > chIndx) && (ch != '\n')) {
831                     ch = str.charAt(chIndx++);
832                     if (ch == '?') {
833                       ch2 = str.charAt(chIndx);
834                       if (ch2 == '>') {
835                         chIndx++;
836                         token = TT_HTML;
837                         // php end
838                         phpMode = false;
839                         phpEnd = true;
840                         return;
841                       }
842                     }
843                   }
844                   rowCount++;
845                   continue;
846
847                 } else if (str.charAt(chIndx) == '*') {
848                   chIndx++;
849                   // multi line comment:
850                   while (str.length() > chIndx) {
851                     if (str.charAt(chIndx) == '*' && (str.length() > (chIndx + 1)) && str.charAt(chIndx + 1) == '/') {
852                       chIndx += 2;
853                       break;
854                     }
855                     ch = str.charAt(chIndx++);
856                     if (ch == '\n') {
857                       rowCount++;
858                       columnCount = chIndx;
859                     }
860                   }
861                   continue;
862                 }
863               }
864             } else if (ch == '#') {
865               // read comment until end of line:
866               while ((str.length() > chIndx) && (ch != '\n')) {
867                 ch = str.charAt(chIndx++);
868                 if (ch == '?') {
869                   ch2 = str.charAt(chIndx);
870                   if (ch2 == '>') {
871                     chIndx++;
872                     token = TT_HTML;
873                     // php end
874                     phpMode = false;
875                     phpEnd = true;
876                     return;
877                   }
878                 }
879               }
880               rowCount++;
881               continue;
882
883             } else if (ch == '"') {
884               // read string until end
885               boolean openString = true;
886               while (str.length() > chIndx) {
887                 ch = str.charAt(chIndx++);
888                 if (ch == '\\') {
889                   if (str.length() > chIndx) {
890                     ch = str.charAt(chIndx++);
891                   }
892                 } else if (ch == '"') {
893                   openString = false;
894                   break;
895                 } else if (ch == '\n') {
896                   rowCount++;
897                   columnCount = chIndx;
898                 }
899               }
900               if (openString) {
901                 throwSyntaxError("Open string character '\"' at end of file.");
902               }
903               token = TT_INTERPOLATED_STRING;
904               return;
905             } else if (ch == '\'') {
906               // read string until end
907               boolean openString = true;
908               int startRow = rowCount;
909               while (str.length() > chIndx) {
910                 ch = str.charAt(chIndx++);
911                 if (ch == '\\') {
912                   if (str.length() > chIndx) {
913                     ch = str.charAt(chIndx++);
914                   }
915                 } else if (ch == '\'') {
916                   openString = false;
917                   break;
918                 } else if (ch == '\n') {
919                   rowCount++;
920                   columnCount = chIndx;
921                 }
922               }
923               if (openString) {
924                 throwSyntaxError("Open string character \"'\" at end of file.", startRow);
925               }
926               token = TT_STRING_CONSTANT;
927               return;
928             } else if (ch == '`') {
929               // read string until end
930               boolean openString = true;
931               int startRow = rowCount;
932               while (str.length() > chIndx) {
933                 ch = str.charAt(chIndx++);
934                 if (ch == '\\') {
935                   if (str.length() > chIndx) {
936                     ch = str.charAt(chIndx++);
937                   }
938                 } else if (ch == '`') {
939                   openString = false;
940                   break;
941                 } else if (ch == '\n') {
942                   rowCount++;
943                   columnCount = chIndx;
944                 }
945               }
946               if (openString) {
947                 throwSyntaxError("Open string character \"`\" at end of file.", startRow);
948               }
949               setMarker("Other string delimiters prefered (found \"`\").", rowCount, PHPParser.INFO);
950               token = TT_STRING_CONSTANT;
951               return;
952             }
953
954             switch (ch) {
955
956               case '(' :
957                 token = TT_ARGOPEN;
958
959                 break;
960               case ')' :
961                 token = TT_ARGCLOSE;
962
963                 break;
964               case '{' :
965                 token = TT_LISTOPEN;
966
967                 break;
968               case '}' :
969                 token = TT_LISTCLOSE;
970
971                 break;
972               case '[' :
973                 token = TT_PARTOPEN;
974
975                 break;
976               case ']' :
977                 token = TT_PARTCLOSE;
978
979                 break;
980               case ',' :
981                 token = TT_COMMA;
982
983                 break;
984               case '?' :
985                 token = TT_QUESTIONMARK;
986                 if (str.length() > chIndx) {
987                   if (str.charAt(chIndx) == '>') {
988                     chIndx++;
989                     token = TT_HTML;
990                     // php end
991                     phpMode = false;
992                     phpEnd = true;
993                     break;
994                   }
995                 }
996
997                 break;
998               case '@' :
999                 token = TT_AT;
1000                 break;
1001               case '~' :
1002                 token = TT_TILDE;
1003                 if (str.length() > chIndx) {
1004                   if (str.charAt(chIndx) == '=') {
1005                     chIndx++;
1006                     token = TT_TILDEASSIGN;
1007
1008                     break;
1009                   }
1010                 }
1011                 break;
1012               case '.' :
1013                 token = TT_DOT;
1014                 if (str.length() > chIndx) {
1015                   if (str.charAt(chIndx) == '=') {
1016                     chIndx++;
1017                     token = TT_DOTASSIGN;
1018
1019                     break;
1020                   }
1021                 }
1022
1023                 break;
1024               case '"' :
1025                 token = TT_STRING;
1026
1027                 break;
1028               case '%' :
1029                 token = TT_MOD;
1030                 if (str.length() > chIndx) {
1031                   if (str.charAt(chIndx) == '=') {
1032                     chIndx++;
1033                     token = TT_MODASSIGN;
1034
1035                     break;
1036                   }
1037                 }
1038                 break;
1039               case ';' :
1040                 token = TT_SEMICOLON;
1041
1042                 break;
1043               case '^' :
1044                 token = TT_POW;
1045                 if (str.length() > chIndx) {
1046                   if (str.charAt(chIndx) == '=') {
1047                     chIndx++;
1048                     token = TT_POWASSIGN;
1049
1050                     break;
1051                   }
1052                 }
1053                 break;
1054               case '/' :
1055                 token = TT_DIV;
1056
1057                 if (str.length() > chIndx) {
1058                   if (str.charAt(chIndx) == '=') {
1059                     chIndx++;
1060                     token = TT_DIVIDEBY;
1061
1062                     break;
1063                   }
1064                 }
1065
1066                 break;
1067               case '*' :
1068                 token = TT_MULTIPLY;
1069                 if (str.length() > chIndx) {
1070                   if (str.charAt(chIndx) == '*') {
1071                     chIndx++;
1072                     token = TT_POW;
1073
1074                     break;
1075                   }
1076                   if (str.charAt(chIndx) == '=') {
1077                     chIndx++;
1078                     token = TT_TIMESBY;
1079
1080                     break;
1081                   }
1082                 }
1083
1084                 break;
1085               case '+' :
1086                 token = TT_ADD;
1087                 if (str.length() > chIndx) {
1088                   if (str.charAt(chIndx) == '+') {
1089                     chIndx++;
1090                     token = TT_INCREMENT;
1091
1092                     break;
1093                   }
1094                   if (str.charAt(chIndx) == '=') {
1095                     chIndx++;
1096                     token = TT_ADDTO;
1097
1098                     break;
1099                   }
1100                 }
1101                 break;
1102               case '-' :
1103                 token = TT_SUBTRACT;
1104                 if (str.length() > chIndx) {
1105                   if (str.charAt(chIndx) == '-') {
1106                     chIndx++;
1107                     token = TT_DECREMENT;
1108
1109                     break;
1110                   }
1111                   if (str.charAt(chIndx) == '=') {
1112                     chIndx++;
1113                     token = TT_SUBTRACTFROM;
1114
1115                     break;
1116                   }
1117                   if (str.charAt(chIndx) == '>') {
1118                     chIndx++;
1119                     token = TT_REF;
1120
1121                     break;
1122                   }
1123                 }
1124
1125                 break;
1126               case '=' :
1127                 token = TT_ASSIGN;
1128
1129                 if (str.length() > chIndx) {
1130                   ch = str.charAt(chIndx);
1131
1132                   if (ch == '=') {
1133                     chIndx++;
1134                     token = TT_EQUAL;
1135                     if (str.length() > chIndx) {
1136                       ch = str.charAt(chIndx);
1137
1138                       if (ch == '=') {
1139                         chIndx++;
1140                         token = TT_EX_EQUAL;
1141                       }
1142                     }
1143                     break;
1144                   }
1145                   if (ch == '>') {
1146                     chIndx++;
1147                     token = TT_FOREACH;
1148
1149                     break;
1150                   }
1151                 }
1152
1153                 break;
1154               case '!' :
1155                 token = TT_NOT;
1156
1157                 if (str.length() > chIndx) {
1158                   if (str.charAt(chIndx) == '=') {
1159                     chIndx++;
1160                     token = TT_UNEQUAL;
1161                     if (str.length() > chIndx) {
1162                       ch = str.charAt(chIndx);
1163
1164                       if (ch == '=') {
1165                         chIndx++;
1166                         token = TT_EX_UNEQUAL;
1167                       }
1168                     }
1169                     break;
1170                   }
1171                 }
1172
1173                 break;
1174               case '>' :
1175                 token = TT_GREATER;
1176
1177                 if (str.length() > chIndx) {
1178                   if (str.charAt(chIndx) == '=') {
1179                     chIndx++;
1180                     token = TT_GREATEREQUAL;
1181                     break;
1182                   }
1183                   if (str.charAt(chIndx) == '>') {
1184                     chIndx++;
1185                     token = TT_RSHIFT;
1186                     if (str.length() > chIndx) {
1187                       if (str.charAt(chIndx) == '=') {
1188                         chIndx++;
1189                         token = TT_RSHIFTASSIGN;
1190                         break;
1191                       }
1192                     }
1193                     break;
1194                   }
1195                 }
1196
1197                 break;
1198               case '<' :
1199                 token = TT_LESS;
1200
1201                 if (str.length() > chIndx) {
1202                   if (str.charAt(chIndx) == '=') {
1203                     chIndx++;
1204                     token = TT_LESSEQUAL;
1205
1206                     break;
1207                   }
1208                   if (str.charAt(chIndx) == '<') {
1209                     chIndx++;
1210                     token = TT_LSHIFT;
1211                     if (str.charAt(chIndx) == '<') {
1212                       // heredoc
1213                       int startRow = rowCount;
1214                       if (str.length() > chIndx) {
1215
1216                         ch = str.charAt(++chIndx);
1217                         if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '_')) {
1218                           chIndx++;
1219                           getIdentifier();
1220                           token = TT_STRING_CONSTANT;
1221                           while (str.length() > chIndx) {
1222                             ch = str.charAt(chIndx++);
1223                             if (ch == '\n') {
1224                               if (str.length() >= chIndx + identifier.length()) {
1225                                 if (str.substring(chIndx, chIndx + identifier.length()).equals(identifier)) {
1226                                   chIndx += identifier.length();
1227                                   return;
1228                                 }
1229                               }
1230                             }
1231                           }
1232                         }
1233                       }
1234                       throwSyntaxError("Open heredoc syntax after operator '<<<'.", startRow);
1235                     } else if (str.charAt(chIndx) == '=') {
1236                       chIndx++;
1237                       token = TT_LSHIFTASSIGN;
1238                       break;
1239                     }
1240                     break;
1241                   }
1242                 }
1243
1244                 break;
1245
1246               case '|' :
1247                 token = TT_LINE;
1248
1249                 if (str.length() > chIndx) {
1250                   if (str.charAt(chIndx) == '|') {
1251                     chIndx++;
1252                     token = TT_OR;
1253
1254                     break;
1255                   }
1256                 }
1257
1258                 break;
1259               case '&' :
1260                 token = TT_AMPERSAND;
1261                 if (str.length() > chIndx) {
1262                   if (str.charAt(chIndx) == '&') {
1263                     chIndx++;
1264                     token = TT_AND;
1265                     break;
1266                   }
1267                   if (str.charAt(chIndx) == '=') {
1268                     chIndx++;
1269                     token = TT_ANDASSIGN;
1270                     break;
1271                   }
1272                   break;
1273                 }
1274
1275                 break;
1276               case ':' :
1277                 token = TT_DDOT;
1278                 if (str.length() > chIndx) {
1279                   if (str.charAt(chIndx) == ':') {
1280                     chIndx++;
1281                     token = TT_DDOT2;
1282                   }
1283                 }
1284                 break;
1285               case '#' :
1286                 token = TT_HASH;
1287
1288                 break;
1289                 //          case '@' :
1290                 //            token = TT_AT;
1291                 //
1292                 //            break;
1293               default :
1294                 throwSyntaxError("unexpected character: '" + ch + "'");
1295             }
1296
1297             if (token == TT_UNDEFINED) {
1298               throwSyntaxError("token not found");
1299             }
1300
1301             return;
1302           }
1303         }
1304       }
1305     } catch (StringIndexOutOfBoundsException e) {
1306       // catched from charAt
1307     }
1308
1309     chIndx = str.length() + 1;
1310     ch = ' ';
1311     token = TT_EOF;
1312     phpEnd = true;
1313     //PHPString temp;
1314     //    if (phpList != null) {
1315     //      if (currentPHPString < phpList.size()) {
1316     //        token = TT_UNDEFINED;
1317     //        temp = (PHPString) phpList.get(currentPHPString++);
1318     //        this.str = temp.getPHPString();
1319     //        this.token = TT_EOF;
1320     //        this.chIndx = 0;
1321     //        this.rowCount = temp.getLineNumber();
1322     //        this.columnCount = 0;
1323     //        getNextToken();
1324     //        phpEnd = true;
1325     //      } else {
1326     //        token = TT_UNDEFINED;
1327     //        return;
1328     //      }
1329     //    }
1330   }
1331
1332   private void getIdentifier() {
1333     StringBuffer ident = new StringBuffer();
1334
1335     ident.append(ch);
1336     if (ch == '$') {
1337       getChar();
1338       // attention recursive call:
1339       getIdentifier();
1340       token = TT_VARIABLE;
1341       return;
1342     } else {
1343       token = TT_IDENTIFIER;
1344     }
1345
1346     getChar();
1347     while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || (ch == '_')) {
1348       ident.append(ch);
1349       getChar();
1350     }
1351     identifier = ident.toString();
1352     chIndx--;
1353
1354     // determine if this identitfer is a keyword
1355     // @todo improve this in future version 
1356     Integer i = (Integer) keywordMap.get(identifier.toLowerCase());
1357     if (i != null) {
1358       token = i.intValue();
1359     }
1360   }
1361
1362   private void getNumber() {
1363     StringBuffer inum = new StringBuffer();
1364     char dFlag = ' ';
1365     int numFormat = 10;
1366
1367     // save first digit
1368     char firstCh = ch;
1369     inum.append(ch);
1370
1371     getChar();
1372     // determine number conversions:
1373     if (firstCh == '0') {
1374       switch (ch) {
1375         case 'b' :
1376           numFormat = 2;
1377           getChar();
1378           break;
1379         case 'B' :
1380           numFormat = 2;
1381           getChar();
1382           break;
1383         case 'o' :
1384           numFormat = 8;
1385           getChar();
1386           break;
1387         case 'O' :
1388           numFormat = 8;
1389           getChar();
1390           break;
1391         case 'x' :
1392           numFormat = 16;
1393           getChar();
1394           break;
1395         case 'X' :
1396           numFormat = 16;
1397           getChar();
1398           break;
1399       }
1400     }
1401
1402     if (numFormat == 16) {
1403       while ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
1404         inum.append(ch);
1405         getChar();
1406       }
1407     } else {
1408       while ((ch >= '0' && ch <= '9') || (ch == '.') || (ch == 'E') || (ch == 'e')) {
1409         if ((ch == '.') || (ch == 'E') || (ch == 'e')) {
1410           if (ch == '.' && dFlag != ' ') {
1411             break;
1412           }
1413           if ((dFlag == 'E') || (dFlag == 'e')) {
1414             break;
1415           }
1416           dFlag = ch;
1417           inum.append(ch);
1418           getChar();
1419           if ((ch == '-') || (ch == '+')) {
1420             inum.append(ch);
1421             getChar();
1422           }
1423         } else {
1424           inum.append(ch);
1425           getChar();
1426         }
1427       }
1428     }
1429     chIndx--;
1430
1431     try {
1432       if (dFlag != ' ') {
1433         doubleNumber = new Double(inum.toString());
1434         token = TT_DOUBLE_NUMBER;
1435         return;
1436       } else {
1437         longNumber = Long.valueOf(inum.toString(), numFormat);
1438         token = TT_INT_NUMBER;
1439         return;
1440       }
1441
1442     } catch (Throwable e) {
1443       throwSyntaxError("Number format error: " + inum.toString());
1444     }
1445   }
1446
1447   public void htmlParserTester(String input) {
1448     int lineNumber = 1;
1449     int startLineNumber = 1;
1450     int startIndex = 0;
1451     char ch;
1452     char ch2;
1453     boolean phpMode = false;
1454     boolean phpFound = false;
1455
1456     phpList = new ArrayList();
1457     currentPHPString = 0;
1458
1459     try {
1460       int i = 0;
1461       while (i < input.length()) {
1462         ch = input.charAt(i++);
1463         if (ch == '\n') {
1464           lineNumber++;
1465         }
1466         if ((!phpMode) && ch == '<') {
1467           ch2 = input.charAt(i++);
1468           if (ch2 == '?') {
1469             ch2 = input.charAt(i++);
1470             if (Character.isWhitespace(ch2)) {
1471               // php start 
1472               phpMode = true;
1473               phpFound = true;
1474               startIndex = i;
1475               startLineNumber = lineNumber;
1476               continue;
1477             } else if (ch2 == 'p') {
1478               ch2 = input.charAt(i++);
1479               if (ch2 == 'h') {
1480                 ch2 = input.charAt(i++);
1481                 if (ch2 == 'p') {
1482                   phpMode = true;
1483                   phpFound = true;
1484                   startIndex = i;
1485                   startLineNumber = lineNumber;
1486                   continue;
1487                 }
1488                 i--;
1489               }
1490               i--;
1491             } else if (ch2 == 'P') {
1492               ch2 = input.charAt(i++);
1493               if (ch2 == 'H') {
1494                 ch2 = input.charAt(i++);
1495                 if (ch2 == 'P') {
1496                   phpMode = true;
1497                   phpFound = true;
1498                   startIndex = i;
1499                   startLineNumber = lineNumber;
1500                   continue;
1501                 }
1502                 i--;
1503               }
1504               i--;
1505             }
1506             i--;
1507           }
1508           i--;
1509         }
1510
1511         if (phpMode) {
1512           if (ch == '/' && i < input.length()) {
1513             ch2 = input.charAt(i++);
1514             if (ch2 == '/') {
1515               while (i < input.length()) {
1516                 ch = input.charAt(i++);
1517                 if (ch == '?' && i < input.length()) {
1518                   ch2 = input.charAt(i++);
1519                   if (ch2 == '>') {
1520                     // php end
1521                     phpMode = false;
1522                     phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber));
1523                     continue;
1524                   }
1525                   i--;
1526                 } else if (ch == '\n') {
1527                   lineNumber++;
1528                   break;
1529                 }
1530               }
1531               continue;
1532             } else if (ch2 == '*') {
1533               // multi-line comment
1534               while (i < input.length()) {
1535                 ch = input.charAt(i++);
1536                 if (ch == '\n') {
1537                   lineNumber++;
1538                 } else if (ch == '*' && i < input.length()) {
1539                   ch2 = input.charAt(i++);
1540                   if (ch2 == '/') {
1541                     break;
1542                   }
1543                   i--;
1544                 }
1545               }
1546               continue;
1547             } else {
1548               i--;
1549             }
1550           } else if (ch == '#') {
1551             while (i < input.length()) {
1552               ch = input.charAt(i++);
1553               if (ch == '?' && i < input.length()) {
1554                 ch2 = input.charAt(i++);
1555                 if (ch2 == '>') {
1556                   // php end
1557                   phpMode = false;
1558                   phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber));
1559                   continue;
1560                 }
1561                 i--;
1562               } else if (ch == '\n') {
1563                 lineNumber++;
1564                 break;
1565               }
1566             }
1567             continue;
1568           } else if (ch == '"') {
1569             ch = ' ';
1570             while (i < input.length()) {
1571               ch = input.charAt(i++);
1572               if (ch == '\n') {
1573                 lineNumber++;
1574               } else if (ch == '\\' && i < input.length()) { // escape
1575                 i++;
1576               } else if (ch == '"') {
1577                 break;
1578               }
1579             }
1580             continue;
1581           } else if (ch == '\'') {
1582             ch = ' ';
1583             while (i < input.length()) {
1584               ch = input.charAt(i++);
1585               if (ch == '\n') {
1586                 lineNumber++;
1587               } else if (ch == '\\' && i < input.length()) { // escape
1588                 i++;
1589               } else if (ch == '\'') {
1590                 break;
1591               }
1592             }
1593             continue;
1594           }
1595
1596           if (ch == '?' && i < input.length()) {
1597             ch2 = input.charAt(i++);
1598             if (ch2 == '>') {
1599               // php end
1600               phpMode = false;
1601               phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber));
1602               continue;
1603             }
1604             i--;
1605           }
1606         }
1607       }
1608
1609       if (!phpFound) {
1610         setMarker("No PHP source code found.", lineNumber, PHPParser.INFO);
1611       } else {
1612         if (phpMode) {
1613           setMarker("Open PHP tag at end of file.", lineNumber, PHPParser.INFO);
1614           phpList.add(new PHPString(input.substring(startIndex, i - 2), startLineNumber));
1615         }
1616         //        for (int j=0;j<phpList.size();j++) {
1617         //          String temp = ((PHPString)phpList.get(j)).getPHPString();
1618         //          int startIndx = temp.length()-10;
1619         //          if (startIndx<0) {
1620         //            startIndx = 0; 
1621         //          }
1622         //          System.out.println(temp.substring(startIndx)+"?>");
1623         //        }
1624         phpParserTester(null, 1);
1625         //        PHPString temp;
1626         //        for(int j=0;j<phpList.size();j++) {
1627         //          temp = (PHPString) phpList.get(j);
1628         //          parser.start(temp.getPHPString(), temp.getLineNumber());
1629         //        } 
1630       }
1631     } catch (CoreException e) {
1632     }
1633   }
1634
1635   public void phpParserTester(String s, int rowCount) throws CoreException {
1636     this.str = s;
1637     if (s == null) {
1638       if (phpList.size() != 0) {
1639         this.str = ((PHPString) phpList.get(currentPHPString++)).getPHPString();
1640       }
1641     }
1642     this.token = TT_EOF;
1643     this.chIndx = 0;
1644     this.rowCount = rowCount;
1645     this.columnCount = 0;
1646     this.phpEnd = false;
1647     this.phpMode = true;
1648     getNextToken();
1649     do {
1650       try {
1651         if (token != TT_EOF && token != TT_UNDEFINED) {
1652           statementList();
1653         }
1654         if (token != TT_EOF && token != TT_UNDEFINED) {
1655           if (token == TT_ARGCLOSE) {
1656             throwSyntaxError("Too many closing ')'; end-of-file not reached.");
1657           }
1658           if (token == TT_LISTCLOSE) {
1659             throwSyntaxError("Too many closing '}'; end-of-file not reached.");
1660           }
1661           if (token == TT_PARTCLOSE) {
1662             throwSyntaxError("Too many closing ']'; end-of-file not reached.");
1663           }
1664
1665           if (token == TT_ARGOPEN) {
1666             throwSyntaxError("Read character '('; end-of-file not reached.");
1667           }
1668           if (token == TT_LISTOPEN) {
1669             throwSyntaxError("Read character '{';  end-of-file not reached.");
1670           }
1671           if (token == TT_PARTOPEN) {
1672             throwSyntaxError("Read character '[';  end-of-file not reached.");
1673           }
1674
1675           throwSyntaxError("End-of-file not reached.");
1676         }
1677         return;
1678       } catch (SyntaxError err) {
1679         if (s != null) {
1680           throw err;
1681         } else {
1682           setMarker(err.getMessage(), err.getLine(), ERROR);
1683         }
1684         // if an error occured, 
1685         // try to find keywords 'class' or 'function'
1686         // to parse the rest of the string
1687         while (token != TT_EOF && token != TT_UNDEFINED) {
1688           if (token == TT_class || token == TT_function) {
1689             break;
1690           }
1691           getNextToken();
1692         }
1693         if (token == TT_EOF || token == TT_UNDEFINED) {
1694           return;
1695         }
1696       }
1697     }
1698     while (true);
1699   }
1700
1701   /**
1702    * Parses a string with php tags
1703    * i.e. '&lt;body&gt; &lt;?php phpinfo() ?&gt; &lt;/body&gt;'
1704    */
1705   public void parse(String s) throws CoreException {
1706     this.str = s;
1707     this.token = TT_EOF;
1708     this.chIndx = 0;
1709     this.rowCount = 1;
1710     this.columnCount = 0;
1711     this.phpEnd = false;
1712     this.phpMode = false;
1713     getNextToken();
1714     do {
1715       try {
1716         if (token != TT_EOF && token != TT_UNDEFINED) {
1717           statementList();
1718         }
1719         if (token != TT_EOF && token != TT_UNDEFINED) {
1720           if (token == TT_ARGCLOSE) {
1721             throwSyntaxError("Too many closing ')'; end-of-file not reached.");
1722           }
1723           if (token == TT_LISTCLOSE) {
1724             throwSyntaxError("Too many closing '}'; end-of-file not reached.");
1725           }
1726           if (token == TT_PARTCLOSE) {
1727             throwSyntaxError("Too many closing ']'; end-of-file not reached.");
1728           }
1729
1730           if (token == TT_ARGOPEN) {
1731             throwSyntaxError("Read character '('; end-of-file not reached.");
1732           }
1733           if (token == TT_LISTOPEN) {
1734             throwSyntaxError("Read character '{';  end-of-file not reached.");
1735           }
1736           if (token == TT_PARTOPEN) {
1737             throwSyntaxError("Read character '[';  end-of-file not reached.");
1738           }
1739
1740           throwSyntaxError("End-of-file not reached.");
1741         }
1742         return;
1743       } catch (SyntaxError sytaxErr1) {
1744         setMarker(sytaxErr1.getMessage(), sytaxErr1.getLine(), ERROR);
1745         try {
1746           // if an error occured, 
1747           // try to find keywords 'class' or 'function'
1748           // to parse the rest of the string
1749           while (token != TT_EOF && token != TT_UNDEFINED) {
1750             if (token == TT_class || token == TT_function) {
1751               break;
1752             }
1753             getNextToken();
1754           }
1755           if (token == TT_EOF || token == TT_UNDEFINED) {
1756             return;
1757           }
1758         } catch (SyntaxError sytaxErr2) {
1759           setMarker(sytaxErr2.getMessage(), sytaxErr2.getLine(), ERROR);
1760           return;
1761         }
1762       }
1763     }
1764     while (true);
1765   }
1766
1767   public PHPOutlineInfo parseInfo(Object parent, String s) {
1768     PHPOutlineInfo outlineInfo = new PHPOutlineInfo(parent);
1769     //    Stack stack = new Stack();
1770     //    stack.push(outlineInfo.getDeclarations());
1771
1772     this.str = s;
1773     this.token = TT_EOF;
1774     this.chIndx = 0;
1775     this.rowCount = 1;
1776     this.columnCount = 0;
1777     this.phpEnd = false;
1778     this.phpMode = false;
1779
1780     try {
1781       getNextToken();
1782       parseDeclarations(outlineInfo, outlineInfo.getDeclarations(), false);
1783     } catch (CoreException e) {
1784     }
1785     return outlineInfo;
1786   }
1787
1788   private void parseDeclarations(PHPOutlineInfo outlineInfo, PHPClassDeclaration current, boolean goBack) {
1789     //   PHPClassDeclaration current = (PHPClassDeclaration) stack.peek();
1790     PHPClassDeclaration temp;
1791     int counter = 0;
1792
1793     try {
1794       while (token != TT_EOF && token != TT_UNDEFINED) {
1795         if (token == TT_VARIABLE) {
1796           outlineInfo.addVariable(identifier);
1797           getNextToken();
1798         } else if (token == TT_function) {
1799           getNextToken();
1800           if (token == TT_AMPERSAND) {
1801             getNextToken();
1802           }
1803           if (token == TT_IDENTIFIER) {
1804             outlineInfo.addVariable(identifier);
1805             current.add(new PHPFunctionDeclaration(current, identifier, chIndx - identifier.length()));
1806             getNextToken();
1807           }
1808         } else if (token == TT_class) {
1809           getNextToken();
1810           if (token == TT_IDENTIFIER) {
1811             outlineInfo.addVariable(identifier);
1812             temp = new PHPClassDeclaration(current, identifier, chIndx - identifier.length());
1813             current.add(temp);
1814             //        stack.push(temp);
1815             getNextToken();
1816             while (token != TT_LISTOPEN && token != TT_EOF && token != TT_UNDEFINED) {
1817               getNextToken();
1818             }
1819             parseDeclarations(outlineInfo, temp, true);
1820             //        stack.pop();
1821           }
1822         } else if (token == TT_LISTOPEN) {
1823           getNextToken();
1824           counter++;
1825         } else if (token == TT_LISTCLOSE) {
1826           getNextToken();
1827           --counter;
1828           if (counter == 0 && goBack) {
1829             return;
1830           }
1831         } else {
1832           getNextToken();
1833         }
1834       }
1835     } catch (CoreException e) {
1836     }
1837   }
1838
1839   private void statementList() throws CoreException {
1840     do {
1841       statement();
1842       if ((token == TT_LISTCLOSE)
1843         || (token == TT_case)
1844         || (token == TT_default)
1845         || (token == TT_elseif)
1846         || (token == TT_endif)
1847         || (token == TT_endfor)
1848         || (token == TT_endforeach)
1849         || (token == TT_endwhile)
1850         || (token == TT_endswitch)
1851         || (token == TT_EOF)
1852         || (token == TT_UNDEFINED)) {
1853         return;
1854       }
1855     } while (true);
1856   }
1857
1858   private void compoundStatement() throws CoreException {
1859     // '{' [statement-list] '}'
1860     if (token == TT_LISTOPEN) {
1861       getNextToken();
1862     } else {
1863       throwSyntaxError("'{' expected in compound-statement.");
1864     }
1865     if (token != TT_LISTCLOSE) {
1866       statementList();
1867     }
1868     if (token == TT_LISTCLOSE) {
1869       getNextToken();
1870     } else {
1871       throwSyntaxError("'}' expected in compound-statement.");
1872     }
1873   }
1874
1875   private void statement() throws CoreException {
1876     //   if (token > TT_KEYWORD && token != TT_list && token != TT_new) {
1877     String keyword = identifier;
1878     if (token == TT_include || token == TT_include_once) {
1879       getNextToken();
1880       expression();
1881       if (token == TT_SEMICOLON) {
1882         getNextToken();
1883       } else {
1884         if (!phpEnd) {
1885           throwSyntaxError("';' character after 'include' or 'include_once' expected.");
1886         }
1887         getNextToken();
1888       }
1889       return;
1890     } else if (token == TT_require || token == TT_require_once) {
1891       getNextToken();
1892       //constant();
1893       expression();
1894       if (token == TT_SEMICOLON) {
1895         getNextToken();
1896       } else {
1897         if (!phpEnd) {
1898           throwSyntaxError("';' character after 'require' or 'require_once' expected.");
1899         }
1900         getNextToken();
1901       }
1902       return;
1903     } else if (token == TT_if) {
1904       getNextToken();
1905       if (token == TT_ARGOPEN) {
1906         getNextToken();
1907       } else {
1908         throwSyntaxError("'(' expected after 'if' keyword.");
1909       }
1910       expression();
1911       if (token == TT_ARGCLOSE) {
1912         getNextToken();
1913       } else {
1914         throwSyntaxError("')' expected after 'if' condition.");
1915       }
1916       ifStatement();
1917       return;
1918
1919     } else if (token == TT_switch) {
1920       getNextToken();
1921       if (token == TT_ARGOPEN) {
1922         getNextToken();
1923       } else {
1924         throwSyntaxError("'(' expected after 'switch' keyword.");
1925       }
1926       expression();
1927       if (token == TT_ARGCLOSE) {
1928         getNextToken();
1929       } else {
1930         throwSyntaxError("')' expected after 'switch' condition.");
1931       }
1932       switchStatement();
1933       return;
1934     } else if (token == TT_for) {
1935       getNextToken();
1936       if (token == TT_ARGOPEN) {
1937         getNextToken();
1938       } else {
1939         throwSyntaxError("'(' expected after 'for' keyword.");
1940       }
1941       if (token == TT_SEMICOLON) {
1942         getNextToken();
1943       } else {
1944         expressionList();
1945         if (token == TT_SEMICOLON) {
1946           getNextToken();
1947         } else {
1948           throwSyntaxError("';' expected after 'for'.");
1949         }
1950       }
1951       if (token == TT_SEMICOLON) {
1952         getNextToken();
1953       } else {
1954         expressionList();
1955         if (token == TT_SEMICOLON) {
1956           getNextToken();
1957         } else {
1958           throwSyntaxError("';' expected after 'for'.");
1959         }
1960       }
1961       if (token == TT_ARGCLOSE) {
1962         getNextToken();
1963       } else {
1964         expressionList();
1965         if (token == TT_ARGCLOSE) {
1966           getNextToken();
1967         } else {
1968           throwSyntaxError("')' expected after 'for'.");
1969         }
1970       }
1971       forStatement();
1972       return;
1973     } else if (token == TT_while) {
1974       getNextToken();
1975       if (token == TT_ARGOPEN) {
1976         getNextToken();
1977       } else {
1978         throwSyntaxError("'(' expected after 'while' keyword.");
1979       }
1980       expression();
1981       if (token == TT_ARGCLOSE) {
1982         getNextToken();
1983       } else {
1984         throwSyntaxError("')' expected after 'while' condition.");
1985       }
1986       whileStatement();
1987       return;
1988     } else if (token == TT_do) {
1989       getNextToken();
1990       if (token == TT_LISTOPEN) {
1991         getNextToken();
1992       } else {
1993         throwSyntaxError("'{' expected after 'do' keyword.");
1994       }
1995       if (token != TT_LISTCLOSE) {
1996         statementList();
1997       }
1998       if (token == TT_LISTCLOSE) {
1999         getNextToken();
2000       } else {
2001         throwSyntaxError("'}' expected after 'do' keyword.");
2002       }
2003       if (token == TT_while) {
2004         getNextToken();
2005         if (token == TT_ARGOPEN) {
2006           getNextToken();
2007         } else {
2008           throwSyntaxError("'(' expected after 'while' keyword.");
2009         }
2010         expression();
2011         if (token == TT_ARGCLOSE) {
2012           getNextToken();
2013         } else {
2014           throwSyntaxError("')' expected after 'while' condition.");
2015         }
2016       } else {
2017         throwSyntaxError("'while' expected after 'do' keyword.");
2018       }
2019       if (token == TT_SEMICOLON) {
2020         getNextToken();
2021       } else {
2022         if (!phpEnd) {
2023           throwSyntaxError("';' expected after do-while statement.");
2024         }
2025         getNextToken();
2026       }
2027       return;
2028     } else if (token == TT_foreach) {
2029       getNextToken();
2030       if (token == TT_ARGOPEN) {
2031         getNextToken();
2032       } else {
2033         throwSyntaxError("'(' expected after 'foreach' keyword.");
2034       }
2035       expression();
2036       if (token == TT_as) {
2037         getNextToken();
2038       } else {
2039         throwSyntaxError("'as' expected after 'foreach' exxpression.");
2040       }
2041       variable();
2042       if (token == TT_FOREACH) {
2043         getNextToken();
2044         variable();
2045       }
2046       if (token == TT_ARGCLOSE) {
2047         getNextToken();
2048       } else {
2049         throwSyntaxError("')' expected after 'foreach' expression.");
2050       }
2051       foreachStatement();
2052       return;
2053
2054     } else if (token == TT_continue || token == TT_break || token == TT_return) {
2055       getNextToken();
2056       if (token != TT_SEMICOLON) {
2057         expression();
2058       }
2059       if (token == TT_SEMICOLON) {
2060         getNextToken();
2061       } else {
2062         if (!phpEnd) {
2063           throwSyntaxError("';' expected after 'continue', 'break' or 'return'.");
2064         }
2065         getNextToken();
2066       }
2067       return;
2068
2069     } else if (token == TT_echo) {
2070       getNextToken();
2071       expressionList();
2072       if (token == TT_SEMICOLON) {
2073         getNextToken();
2074       } else {
2075         if (!phpEnd) {
2076           throwSyntaxError("';' expected after 'echo' statement.");
2077         }
2078         getNextToken();
2079       }
2080       return;
2081       //    } else if (token == TT_print) {
2082       //      getNextToken();
2083       //      expression();
2084       //      if (token == TT_SEMICOLON) {
2085       //        getNextToken();
2086       //      } else {
2087       //        if (!phpEnd) {
2088       //          throwSyntaxError("';' expected after 'print' statement.");
2089       //        }
2090       //        getNextToken();
2091       //      }
2092       //      return;
2093
2094     } else if (token == TT_global || token == TT_static) {
2095       getNextToken();
2096       variableList();
2097       if (token == TT_SEMICOLON) {
2098         getNextToken();
2099       } else {
2100         if (!phpEnd) {
2101           throwSyntaxError("';' expected after 'global' or 'static' statement.");
2102         }
2103         getNextToken();
2104       }
2105       return;
2106
2107       //      } else if (token == TT_unset) {
2108       //        getNextToken();
2109       //        if (token == TT_ARGOPEN) {
2110       //          getNextToken();
2111       //        } else {
2112       //          throwSyntaxError("'(' expected after 'unset' keyword.");
2113       //        }
2114       //        variableList();
2115       //        if (token == TT_ARGCLOSE) {
2116       //          getNextToken();
2117       //        } else {
2118       //          throwSyntaxError("')' expected after 'unset' statement.");
2119       //        }
2120       //        if (token == TT_SEMICOLON) {
2121       //          getNextToken();
2122       //        } else {
2123       //          if (!phpEnd) {
2124       //            throwSyntaxError("';' expected after 'unset' statement.");
2125       //          }
2126       //          getNextToken();
2127       //        }
2128       //        return;
2129
2130       //      } else if (token == TT_exit || token == TT_die) {
2131       //        getNextToken();
2132       //        if (token != TT_SEMICOLON) {
2133       //          exitStatus();
2134       //        }
2135       //        if (token == TT_SEMICOLON) {
2136       //          getNextToken();
2137       //        } else {
2138       //          if (!phpEnd) {
2139       //            throwSyntaxError("';' expected after 'exit' or 'die' statement.");
2140       //          }
2141       //          getNextToken();
2142       //        }
2143       //        return;
2144
2145     } else if (token == TT_define) {
2146       getNextToken();
2147       if (token == TT_ARGOPEN) {
2148         getNextToken();
2149       } else {
2150         throwSyntaxError("'(' expected after 'define' keyword.");
2151       }
2152       expression();
2153       if (token == TT_COMMA) {
2154         getNextToken();
2155       } else {
2156         throwSyntaxError("',' expected after first 'define' constant.");
2157       }
2158       expression();
2159       if (token == TT_COMMA) {
2160         getNextToken();
2161         expression();
2162       }
2163       if (token == TT_ARGCLOSE) {
2164         getNextToken();
2165       } else {
2166         throwSyntaxError("')' expected after 'define' statement.");
2167       }
2168       if (token == TT_SEMICOLON) {
2169         getNextToken();
2170       } else {
2171         if (!phpEnd) {
2172           throwSyntaxError("';' expected after 'define' statement.");
2173         }
2174         getNextToken();
2175       }
2176       return;
2177     } else if (token == TT_function) {
2178       getNextToken();
2179       functionDefinition();
2180       return;
2181     } else if (token == TT_class) {
2182       getNextToken();
2183       classDeclarator();
2184       classBody();
2185       return;
2186       //      } else {
2187       //        throwSyntaxError("Unexpected keyword '" + keyword + "'");
2188     } else if (token == TT_LISTOPEN) {
2189       // compoundStatement
2190       getNextToken();
2191       if (token != TT_LISTCLOSE) {
2192         statementList();
2193       }
2194       if (token == TT_LISTCLOSE) {
2195         getNextToken();
2196         return;
2197       } else {
2198         throwSyntaxError("'}' expected.");
2199       }
2200     } else {
2201       if (token != TT_SEMICOLON) {
2202         expression();
2203       }
2204       if (token == TT_SEMICOLON) {
2205         getNextToken();
2206         return;
2207       } else {
2208         if (!phpEnd) {
2209           throwSyntaxError("';' expected after expression.");
2210         }
2211         getNextToken();
2212       }
2213     }
2214   }
2215
2216   private void classDeclarator() throws CoreException {
2217     //identifier
2218     //identifier 'extends' identifier
2219     if (token == TT_IDENTIFIER) {
2220       getNextToken();
2221       if (token == TT_extends) {
2222         getNextToken();
2223         if (token == TT_IDENTIFIER) {
2224           getNextToken();
2225         } else {
2226           throwSyntaxError("Class name expected after keyword 'extends'.");
2227         }
2228       }
2229     } else {
2230       throwSyntaxError("Class name expected after keyword 'class'.");
2231     }
2232   }
2233
2234   private void classBody() throws CoreException {
2235     //'{' [class-element-list] '}'
2236     if (token == TT_LISTOPEN) {
2237       getNextToken();
2238       if (token != TT_LISTCLOSE) {
2239         classElementList();
2240       }
2241       if (token == TT_LISTCLOSE) {
2242         getNextToken();
2243       } else {
2244         throwSyntaxError("'}' expected at end of class body.");
2245       }
2246     } else {
2247       throwSyntaxError("'{' expected at start of class body.");
2248     }
2249   }
2250
2251   private void classElementList() throws CoreException {
2252     do {
2253       classElement();
2254     } while (token == TT_function || token == TT_var);
2255   }
2256
2257   private void classElement() throws CoreException {
2258     //class-property
2259     //function-definition
2260     if (token == TT_function) {
2261       getNextToken();
2262       functionDefinition();
2263     } else if (token == TT_var) {
2264       getNextToken();
2265       classProperty();
2266     } else {
2267       throwSyntaxError("'function' or 'var' expected.");
2268     }
2269   }
2270
2271   private void classProperty() throws CoreException {
2272     //'var' variable ';'
2273     //'var' variable '=' constant ';'
2274     do {
2275       if (token == TT_VARIABLE) {
2276         getNextToken();
2277         if (token == TT_ASSIGN) {
2278           getNextToken();
2279           constant();
2280         }
2281       } else {
2282         throwSyntaxError("Variable expected after keyword 'var'.");
2283       }
2284       if (token != TT_COMMA) {
2285         break;
2286       }
2287       getNextToken();
2288     } while (true);
2289     if (token == TT_SEMICOLON) {
2290       getNextToken();
2291     } else {
2292       throwSyntaxError("';' expected after variable declaration.");
2293     }
2294   }
2295
2296   private void functionDefinition() throws CoreException {
2297     functionDeclarator();
2298     compoundStatement();
2299   }
2300
2301   private void functionDeclarator() throws CoreException {
2302     //identifier '(' [parameter-list] ')'
2303     if (token == TT_AMPERSAND) {
2304       getNextToken();
2305     }
2306     if (token == TT_IDENTIFIER) {
2307       getNextToken();
2308       if (token == TT_ARGOPEN) {
2309         getNextToken();
2310       } else {
2311         throwSyntaxError("'(' expected in function declaration.");
2312       }
2313       if (token != TT_ARGCLOSE) {
2314         parameterList();
2315       }
2316       if (token != TT_ARGCLOSE) {
2317         throwSyntaxError("')' expected in function declaration.");
2318       } else {
2319         getNextToken();
2320       }
2321     }
2322   }
2323   //
2324   private void parameterList() throws CoreException {
2325     //parameter-declaration
2326     //parameter-list ',' parameter-declaration
2327     do {
2328       parameterDeclaration();
2329       if (token != TT_COMMA) {
2330         break;
2331       }
2332       getNextToken();
2333     } while (true);
2334   }
2335
2336   private void parameterDeclaration() throws CoreException {
2337     //variable
2338     //variable-reference
2339     if (token == TT_AMPERSAND) {
2340       getNextToken();
2341       if (token == TT_VARIABLE) {
2342         getNextToken();
2343       } else {
2344         throwSyntaxError("Variable expected after reference operator '&'.");
2345       }
2346     }
2347     //variable '=' constant
2348     if (token == TT_VARIABLE) {
2349       getNextToken();
2350       if (token == TT_ASSIGN) {
2351         getNextToken();
2352         constant();
2353       }
2354       return;
2355     }
2356   }
2357
2358   private void labeledStatementList() throws CoreException {
2359     if (token != TT_case && token != TT_default) {
2360       throwSyntaxError("'case' or 'default' expected.");
2361     }
2362     do {
2363       if (token == TT_case) {
2364         getNextToken();
2365         constant();
2366         if (token == TT_DDOT) {
2367           getNextToken();
2368           if (token == TT_case || token == TT_default) { // empty case statement ?
2369             continue;
2370           }
2371           statementList();
2372         } else if (token == TT_SEMICOLON) {
2373           setMarker("':' expected after 'case' keyword found ';'.", rowCount, PHPParser.INFO);
2374           getNextToken();
2375           if (token == TT_case) { // empty case statement ?
2376             continue;
2377           }
2378           statementList();
2379         } else {
2380           throwSyntaxError("':' character after 'case' constant expected.");
2381         }
2382       } else { // TT_default 
2383         getNextToken();
2384         if (token == TT_DDOT) {
2385           getNextToken();
2386           statementList();
2387         } else {
2388           throwSyntaxError("':' character after 'default' expected.");
2389         }
2390       }
2391     } while (token == TT_case || token == TT_default);
2392   }
2393
2394   //  public void labeledStatement() {
2395   //    if (token == TT_case) {
2396   //      getNextToken();
2397   //      constant();
2398   //      if (token == TT_DDOT) {
2399   //        getNextToken();
2400   //        statement();
2401   //      } else {
2402   //        throwSyntaxError("':' character after 'case' constant expected.");
2403   //      }
2404   //      return;
2405   //    } else if (token == TT_default) {
2406   //      getNextToken();
2407   //      if (token == TT_DDOT) {
2408   //        getNextToken();
2409   //        statement();
2410   //      } else {
2411   //        throwSyntaxError("':' character after 'default' expected.");
2412   //      }
2413   //      return;
2414   //    }
2415   //  }
2416
2417   //  public void expressionStatement() {
2418   //  }
2419
2420   //  private void inclusionStatement() {
2421   //  }
2422
2423   //  public void compoundStatement() {
2424   //  }
2425
2426   //  public void selectionStatement() {
2427   //  }
2428   //
2429   //  public void iterationStatement() {
2430   //  }
2431   //
2432   //  public void jumpStatement() {
2433   //  }
2434   //
2435   //  public void outputStatement() {
2436   //  }
2437   //
2438   //  public void scopeStatement() {
2439   //  }
2440   //
2441   //  public void flowStatement() {
2442   //  }
2443   //
2444   //  public void definitionStatement() {
2445   //  }
2446
2447   private void ifStatement() throws CoreException {
2448     // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
2449     if (token == TT_DDOT) {
2450       getNextToken();
2451       statementList();
2452       switch (token) {
2453         case TT_else :
2454           getNextToken();
2455           if (token == TT_DDOT) {
2456             getNextToken();
2457             statementList();
2458           } else {
2459             if (token == TT_if) { //'else if'
2460               getNextToken();
2461               elseifStatementList();
2462             } else {
2463               throwSyntaxError("':' expected after 'else'.");
2464             }
2465           }
2466           break;
2467         case TT_elseif :
2468           getNextToken();
2469           elseifStatementList();
2470           break;
2471       }
2472
2473       if (token != TT_endif) {
2474         throwSyntaxError("'endif' expected.");
2475       }
2476       getNextToken();
2477       if (token != TT_SEMICOLON) {
2478         throwSyntaxError("';' expected after if-statement.");
2479       }
2480       getNextToken();
2481     } else {
2482       // statement [else-statement]
2483       statement();
2484       if (token == TT_elseif) {
2485         getNextToken();
2486         if (token == TT_ARGOPEN) {
2487           getNextToken();
2488         } else {
2489           throwSyntaxError("'(' expected after 'elseif' keyword.");
2490         }
2491         expression();
2492         if (token == TT_ARGCLOSE) {
2493           getNextToken();
2494         } else {
2495           throwSyntaxError("')' expected after 'elseif' condition.");
2496         }
2497         ifStatement();
2498       } else if (token == TT_else) {
2499         getNextToken();
2500         statement();
2501       }
2502     }
2503   }
2504
2505   private void elseifStatementList() throws CoreException {
2506     do {
2507       elseifStatement();
2508       switch (token) {
2509         case TT_else :
2510           getNextToken();
2511           if (token == TT_DDOT) {
2512             getNextToken();
2513             statementList();
2514             return;
2515           } else {
2516             if (token == TT_if) { //'else if'
2517               getNextToken();
2518             } else {
2519               throwSyntaxError("':' expected after 'else'.");
2520             }
2521           }
2522           break;
2523         case TT_elseif :
2524           getNextToken();
2525           break;
2526         default :
2527           return;
2528       }
2529     } while (true);
2530   }
2531
2532   private void elseifStatement() throws CoreException {
2533     if (token == TT_ARGOPEN) {
2534       getNextToken();
2535       expression();
2536       if (token != TT_ARGOPEN) {
2537         throwSyntaxError("')' expected in else-if-statement.");
2538       }
2539       getNextToken();
2540       if (token != TT_DDOT) {
2541         throwSyntaxError("':' expected in else-if-statement.");
2542       }
2543       getNextToken();
2544       statementList();
2545     }
2546   }
2547
2548   private void switchStatement() throws CoreException {
2549     if (token == TT_DDOT) {
2550       // ':' [labeled-statement-list] 'endswitch' ';'
2551       getNextToken();
2552       labeledStatementList();
2553       if (token != TT_endswitch) {
2554         throwSyntaxError("'endswitch' expected.");
2555       }
2556       getNextToken();
2557       if (token != TT_SEMICOLON) {
2558         throwSyntaxError("';' expected after switch-statement.");
2559       }
2560       getNextToken();
2561     } else {
2562       // '{' [labeled-statement-list] '}'
2563       if (token != TT_LISTOPEN) {
2564         throwSyntaxError("'{' expected in switch statement.");
2565       }
2566       getNextToken();
2567       if (token != TT_LISTCLOSE) {
2568         labeledStatementList();
2569       }
2570       if (token != TT_LISTCLOSE) {
2571         throwSyntaxError("'}' expected in switch statement.");
2572       }
2573       getNextToken();
2574
2575     }
2576   }
2577
2578   private void forStatement() throws CoreException {
2579     if (token == TT_DDOT) {
2580       getNextToken();
2581       statementList();
2582       if (token != TT_endfor) {
2583         throwSyntaxError("'endfor' expected.");
2584       }
2585       getNextToken();
2586       if (token != TT_SEMICOLON) {
2587         throwSyntaxError("';' expected after for-statement.");
2588       }
2589       getNextToken();
2590     } else {
2591       statement();
2592     }
2593   }
2594
2595   private void whileStatement() throws CoreException {
2596     // ':' statement-list 'endwhile' ';'
2597     if (token == TT_DDOT) {
2598       getNextToken();
2599       statementList();
2600       if (token != TT_endwhile) {
2601         throwSyntaxError("'endwhile' expected.");
2602       }
2603       getNextToken();
2604       if (token != TT_SEMICOLON) {
2605         throwSyntaxError("';' expected after while-statement.");
2606       }
2607       getNextToken();
2608     } else {
2609       statement();
2610     }
2611   }
2612
2613   private void foreachStatement() throws CoreException {
2614     if (token == TT_DDOT) {
2615       getNextToken();
2616       statementList();
2617       if (token != TT_endforeach) {
2618         throwSyntaxError("'endforeach' expected.");
2619       }
2620       getNextToken();
2621       if (token != TT_SEMICOLON) {
2622         throwSyntaxError("';' expected after foreach-statement.");
2623       }
2624       getNextToken();
2625     } else {
2626       statement();
2627     }
2628   }
2629
2630   private void exitStatus() throws CoreException {
2631     if (token == TT_ARGOPEN) {
2632       getNextToken();
2633     } else {
2634       throwSyntaxError("'(' expected in 'exit-status'.");
2635     }
2636     if (token != TT_ARGCLOSE) {
2637       expression();
2638     }
2639     if (token == TT_ARGCLOSE) {
2640       getNextToken();
2641     } else {
2642       throwSyntaxError("')' expected after 'exit-status'.");
2643     }
2644   }
2645
2646   private void expressionList() throws CoreException {
2647     do {
2648       expression();
2649       if (token == TT_COMMA) {
2650         getNextToken();
2651       } else {
2652         break;
2653       }
2654     } while (true);
2655   }
2656
2657   private void expression() throws CoreException {
2658     //    if (token == TT_STRING_CONSTANT || token == TT_INTERPOLATED_STRING) {
2659     //      getNextToken();
2660     //    } else {
2661     logicalinclusiveorExpression();
2662     //      while (token != TT_SEMICOLON) {
2663     //        getNextToken();
2664     //      //      }
2665     //    }
2666   }
2667
2668   private void postfixExpression() throws CoreException {
2669     String ident;
2670     boolean castFlag = false;
2671     switch (token) {
2672       case TT_new :
2673         getNextToken();
2674         expression();
2675         break;
2676       case TT_null :
2677         getNextToken();
2678         break;
2679       case TT_false :
2680         getNextToken();
2681         break;
2682       case TT_true :
2683         getNextToken();
2684         break;
2685       case TT_STRING_CONSTANT :
2686         getNextToken();
2687         break;
2688       case TT_INTERPOLATED_STRING :
2689         getNextToken();
2690         break;
2691       case TT_ARGOPEN :
2692         getNextToken();
2693         if (token == TT_IDENTIFIER) {
2694           // check if identifier is a type:
2695           ident = identifier;
2696           String str = identifier.toLowerCase();
2697           for (int i = 0; i < PHP_TYPES.length; i++) {
2698             if (PHP_TYPES[i].equals(str)) {
2699               castFlag = true;
2700               break;
2701             }
2702           }
2703           if (castFlag) {
2704             getNextToken();
2705             if (token != TT_ARGCLOSE) {
2706               throwSyntaxError(") expected after cast-type '" + ident + "'.");
2707             }
2708             getNextToken();
2709             expression();
2710             break;
2711           }
2712         }
2713         if (!castFlag) {
2714           expression();
2715         }
2716         if (token != TT_ARGCLOSE) {
2717           throwSyntaxError(") expected in postfix-expression.");
2718         }
2719         getNextToken();
2720         break;
2721       case TT_DOUBLE_NUMBER :
2722         getNextToken();
2723         break;
2724       case TT_INT_NUMBER :
2725         getNextToken();
2726         break;
2727       case TT_DOLLAROPEN :
2728         getNextToken();
2729         expression();
2730         if (token != TT_LISTCLOSE) {
2731           throwSyntaxError("'}' expected after indirect variable token '${'.");
2732         }
2733         getNextToken();
2734         break;
2735       case TT_VARIABLE :
2736         ident = identifier;
2737         getNextToken();
2738         if (token == TT_LISTOPEN) {
2739           getNextToken();
2740           expression();
2741           if (token != TT_LISTCLOSE) {
2742             throwSyntaxError("'}' expected after variable '" + ident + "' in variable-expression.");
2743           }
2744           getNextToken();
2745         } else if (token == TT_ARGOPEN) {
2746           getNextToken();
2747           if (token != TT_ARGCLOSE) {
2748             expressionList();
2749             if (token != TT_ARGCLOSE) {
2750               throwSyntaxError("')' expected after variable '" + ident + "' in postfix-expression.");
2751             }
2752           }
2753           getNextToken();
2754         }
2755         break;
2756       case TT_IDENTIFIER :
2757         ident = identifier;
2758         getNextToken();
2759         if (token == TT_ARGOPEN) {
2760           getNextToken();
2761           if (token != TT_ARGCLOSE) {
2762             expressionList();
2763             if (token != TT_ARGCLOSE) {
2764               throwSyntaxError("')' expected after identifier '" + ident + "' in postfix-expression.");
2765             }
2766           }
2767           getNextToken();
2768         }
2769         break;
2770       case TT_print :
2771         getNextToken();
2772         expression();
2773         //        if (token == TT_SEMICOLON) {
2774         //          getNextToken();
2775         //        } else {
2776         //          if (!phpEnd) {
2777         //            throwSyntaxError("';' expected after 'print' statement.");
2778         //          }
2779         //          getNextToken();
2780         //        }
2781         break;
2782       case TT_list :
2783         getNextToken();
2784         if (token == TT_ARGOPEN) {
2785           getNextToken();
2786           if (token == TT_COMMA) {
2787             getNextToken();
2788           }
2789           expressionList();
2790           if (token != TT_ARGCLOSE) {
2791             throwSyntaxError("')' expected after 'list' keyword.");
2792           }
2793           getNextToken();
2794           //          if (token == TT_SET) {
2795           //            getNextToken();
2796           //            logicalinclusiveorExpression();
2797           //          }
2798         } else {
2799           throwSyntaxError("'(' expected after 'list' keyword.");
2800         }
2801         break;
2802         //      case TT_exit :
2803         //        getNextToken();
2804         //        if (token != TT_SEMICOLON) {
2805         //          exitStatus();
2806         //        }
2807         //        if (token == TT_SEMICOLON) {
2808         //          getNextToken();
2809         //        } else {
2810         //          if (!phpEnd) {
2811         //            throwSyntaxError("';' expected after 'exit' expression.");
2812         //          }
2813         //          getNextToken();
2814         //        }
2815         //        break;
2816         //      case TT_die :
2817         //        getNextToken();
2818         //        if (token != TT_SEMICOLON) {
2819         //          exitStatus();
2820         //        }
2821         //        if (token == TT_SEMICOLON) {
2822         //          getNextToken();
2823         //        } else {
2824         //          if (!phpEnd) {
2825         //            throwSyntaxError("';' expected after 'die' expression.");
2826         //          }
2827         //        }
2828         //        break;
2829
2830         //      case TT_array :
2831         //        getNextToken();
2832         //        if (token == TT_ARGOPEN) {
2833         //          getNextToken();
2834         //          if (token == TT_COMMA) {
2835         //            getNextToken();
2836         //          }
2837         //          expressionList();
2838         //          if (token != TT_ARGCLOSE) {
2839         //            throwSyntaxError("')' expected after 'list' keyword.");
2840         //          }
2841         //          getNextToken();
2842         //          if (token == TT_SET) {
2843         //            getNextToken();
2844         //            logicalinclusiveorExpression();
2845         //          }
2846         //        } else {
2847         //          throwSyntaxError("'(' expected after 'list' keyword.");
2848         //        }
2849         //        break;
2850     }
2851     boolean while_flag = true;
2852     do {
2853       switch (token) {
2854         case TT_PARTOPEN :
2855           getNextToken();
2856           expression();
2857           if (token != TT_PARTCLOSE) {
2858             throwSyntaxError("] expected in postfix-expression.");
2859           }
2860           getNextToken();
2861           break;
2862         case TT_DDOT2 : // ::
2863         case TT_REF : // ->
2864           getNextToken();
2865           if (token > TT_KEYWORD) {
2866             ident = identifier;
2867             setMarker("Avoid using keyword '" + ident + "' as variable name.", rowCount, PHPParser.INFO);
2868           }
2869           switch (token) {
2870             case TT_VARIABLE :
2871               ident = identifier;
2872               getNextToken();
2873               //              if (token == TT_ARGOPEN) {
2874               //                getNextToken();
2875               //                expressionList();
2876               //                if (token != TT_ARGCLOSE) {
2877               //                  throwSyntaxError(") expected after variable '" + ident + "'.");
2878               //                }
2879               //                getNextToken();
2880               //              }
2881               break;
2882             case TT_IDENTIFIER :
2883               ident = identifier;
2884               getNextToken();
2885               break;
2886             case TT_LISTOPEN :
2887               getNextToken();
2888               expression();
2889               if (token != TT_LISTCLOSE) {
2890                 throwSyntaxError("} expected in postfix-expression.");
2891               }
2892               getNextToken();
2893               break;
2894             default :
2895               throwSyntaxError("Syntax error after '->' token.");
2896           } while (token == TT_PARTOPEN || token == TT_ARGOPEN || token == TT_LISTOPEN) {
2897               if (token == TT_PARTOPEN) {
2898                 getNextToken();
2899                 expressionList();
2900                 if (token != TT_PARTCLOSE) {
2901                   throwSyntaxError("] expected after '->'.");
2902                 }
2903                 getNextToken();
2904               }
2905               if (token == TT_ARGOPEN) {
2906                 getNextToken();
2907                 expressionList();
2908                 if (token != TT_ARGCLOSE) {
2909                   throwSyntaxError(") expected after '->'.");
2910                 }
2911                 getNextToken();
2912               }
2913               if (token == TT_LISTOPEN) {
2914                 getNextToken();
2915                 expression();
2916                 if (token != TT_LISTCLOSE) {
2917                   throwSyntaxError("} expected after '->'.");
2918                 }
2919                 getNextToken();
2920               }
2921             }
2922           break;
2923         case TT_INCREMENT :
2924           getNextToken();
2925           break;
2926         case TT_DECREMENT :
2927           getNextToken();
2928           break;
2929         default :
2930           while_flag = false;
2931       }
2932
2933     }
2934     while (while_flag);
2935   }
2936
2937   private void unaryExpression() throws CoreException {
2938     switch (token) {
2939       case TT_INCREMENT :
2940         getNextToken();
2941         unaryExpression();
2942         break;
2943       case TT_DECREMENT :
2944         getNextToken();
2945         unaryExpression();
2946         break;
2947         // '@' '&' '*' '+' '-' '~' '!' 
2948       case TT_AT :
2949         getNextToken();
2950         castExpression();
2951         break;
2952       case TT_AMPERSAND :
2953         getNextToken();
2954         castExpression();
2955         break;
2956       case TT_MULTIPLY :
2957         getNextToken();
2958         castExpression();
2959         break;
2960       case TT_ADD :
2961         getNextToken();
2962         castExpression();
2963         break;
2964       case TT_SUBTRACT :
2965         getNextToken();
2966         castExpression();
2967         break;
2968       case TT_TILDE :
2969         getNextToken();
2970         castExpression();
2971         break;
2972       case TT_NOT :
2973         getNextToken();
2974         castExpression();
2975         break;
2976       default :
2977         postfixExpression();
2978     }
2979   }
2980
2981   private void castExpression() throws CoreException {
2982     //    if (token == TT_ARGOPEN) {
2983     //      getNextToken();
2984     //      typeName();
2985     //      if (token != TT_ARGCLOSE) {
2986     //        throwSyntaxError(") expected after cast-expression.");
2987     //      }
2988     //      getNextToken();
2989     //    }
2990     unaryExpression();
2991   }
2992
2993   private void typeName() throws CoreException {
2994     //'string' 'unset' 'array' 'object'
2995     //'bool' 'boolean'
2996     //'real' 'double' 'float'
2997     //'int' 'integer'
2998     String ident = "";
2999     if (token == TT_IDENTIFIER) {
3000       ident = identifier;
3001       String str = identifier.toLowerCase();
3002       getNextToken();
3003       for (int i = 0; i < PHP_TYPES.length; i++) {
3004         if (PHP_TYPES[i].equals(str)) {
3005           return;
3006         }
3007       }
3008     }
3009     throwSyntaxError("Expected type cast '( <type-name> )'; Got '" + ident + "'.");
3010   }
3011
3012   private void assignExpression() throws CoreException {
3013     castExpression();
3014     if (token == TT_ASSIGN) { // =
3015       getNextToken();
3016       logicalinclusiveorExpression();
3017     } else if (token == TT_DOTASSIGN) { // .=
3018       getNextToken();
3019       logicalinclusiveorExpression();
3020     } else if (token == TT_FOREACH) { // =>
3021       getNextToken();
3022       logicalinclusiveorExpression();
3023     } else if (token == TT_ADDTO) { // +=
3024       getNextToken();
3025       logicalinclusiveorExpression();
3026     } else if (token == TT_SUBTRACTFROM) { // -=
3027       getNextToken();
3028       logicalinclusiveorExpression();
3029     } else if (token == TT_TIMESBY) { // *=
3030       getNextToken();
3031       logicalinclusiveorExpression();
3032     } else if (token == TT_DIVIDEBY) { // *=
3033       getNextToken();
3034       logicalinclusiveorExpression();
3035     } else if (token == TT_MODASSIGN) { // %=
3036       getNextToken();
3037       logicalinclusiveorExpression();
3038     } else if (token == TT_ANDASSIGN) { // &=
3039       getNextToken();
3040       logicalinclusiveorExpression();
3041     } else if (token == TT_POWASSIGN) { // ^=
3042       getNextToken();
3043       logicalinclusiveorExpression();
3044     } else if (token == TT_LSHIFTASSIGN) { // <<=
3045       getNextToken();
3046       logicalinclusiveorExpression();
3047     } else if (token == TT_RSHIFTASSIGN) { // >>=
3048       getNextToken();
3049       logicalinclusiveorExpression();
3050     } else if (token == TT_TILDEASSIGN) { // ~=
3051       getNextToken();
3052       logicalinclusiveorExpression();
3053     }
3054   }
3055
3056   private void multiplicativeExpression() throws CoreException {
3057     do {
3058       assignExpression();
3059       if (token != TT_MULTIPLY && token != TT_DIV && token != TT_MOD) {
3060         return;
3061       }
3062       getNextToken();
3063     } while (true);
3064   }
3065
3066   private void concatenationExpression() throws CoreException {
3067     do {
3068       multiplicativeExpression();
3069       if (token != TT_DOT) {
3070         return;
3071       }
3072       getNextToken();
3073     } while (true);
3074   }
3075
3076   private void additiveExpression() throws CoreException {
3077     do {
3078       concatenationExpression();
3079       if (token != TT_ADD && token != TT_SUBTRACT) {
3080         return;
3081       }
3082       getNextToken();
3083     } while (true);
3084   }
3085
3086   private void shiftExpression() throws CoreException {
3087     do {
3088       additiveExpression();
3089       if (token != TT_LSHIFT && token != TT_RSHIFT) {
3090         return;
3091       }
3092       getNextToken();
3093     } while (true);
3094   }
3095
3096   private void relationalExpression() throws CoreException {
3097     do {
3098       shiftExpression();
3099       if (token != TT_LESS && token != TT_GREATER && token != TT_LESSEQUAL && token != TT_GREATEREQUAL) {
3100         return;
3101       }
3102       getNextToken();
3103     } while (true);
3104   }
3105
3106   private void identicalExpression() throws CoreException {
3107     do {
3108       relationalExpression();
3109       if (token != TT_EX_EQUAL && token != TT_EX_UNEQUAL) {
3110         return;
3111       }
3112       getNextToken();
3113     } while (true);
3114   }
3115
3116   private void equalityExpression() throws CoreException {
3117     do {
3118       identicalExpression();
3119       if (token != TT_EQUAL && token != TT_UNEQUAL) {
3120         return;
3121       }
3122       getNextToken();
3123     } while (true);
3124   }
3125
3126   private void ternaryExpression() throws CoreException {
3127     equalityExpression();
3128     if (token == TT_QUESTIONMARK) {
3129       getNextToken();
3130       expression();
3131       if (token == TT_DDOT) {
3132         getNextToken();
3133         expression();
3134       } else {
3135         throwSyntaxError("':' expected in ternary operator '? :'.");
3136       }
3137     }
3138   }
3139
3140   private void andExpression() throws CoreException {
3141     do {
3142       ternaryExpression();
3143       if (token != TT_AMPERSAND) {
3144         return;
3145       }
3146       getNextToken();
3147     } while (true);
3148   }
3149
3150   private void exclusiveorExpression() throws CoreException {
3151     do {
3152       andExpression();
3153       if (token != TT_POW) {
3154         return;
3155       }
3156       getNextToken();
3157     } while (true);
3158   }
3159
3160   private void inclusiveorExpression() throws CoreException {
3161     do {
3162       exclusiveorExpression();
3163       if (token != TT_LINE) {
3164         return;
3165       }
3166       getNextToken();
3167     } while (true);
3168   }
3169
3170   private void booleanandExpression() throws CoreException {
3171     do {
3172       inclusiveorExpression();
3173       if (token != TT_AND) {
3174         return;
3175       }
3176       getNextToken();
3177     } while (true);
3178   }
3179
3180   private void booleanorExpression() throws CoreException {
3181     do {
3182       booleanandExpression();
3183       if (token != TT_OR) {
3184         return;
3185       }
3186       getNextToken();
3187     } while (true);
3188   }
3189
3190   private void logicalandExpression() throws CoreException {
3191     do {
3192       booleanorExpression();
3193       if (token != TT_and) {
3194         return;
3195       }
3196       getNextToken();
3197     } while (true);
3198   }
3199
3200   private void logicalexclusiveorExpression() throws CoreException {
3201     do {
3202       logicalandExpression();
3203       if (token != TT_xor) {
3204         return;
3205       }
3206       getNextToken();
3207     } while (true);
3208   }
3209
3210   private void logicalinclusiveorExpression() throws CoreException {
3211     do {
3212       logicalexclusiveorExpression();
3213       if (token != TT_or) {
3214         return;
3215       }
3216       getNextToken();
3217     } while (true);
3218   }
3219
3220   //  public void assignmentExpression() {
3221   //    if (token == TT_VARIABLE) {
3222   //      getNextToken();
3223   //      if (token == TT_SET) {
3224   //        getNextToken();
3225   //        logicalinclusiveorExpression();
3226   //      }
3227   //    } else {
3228   //      logicalinclusiveorExpression();
3229   //    }
3230   //  }
3231
3232   private void variableList() throws CoreException {
3233     do {
3234       variable();
3235       if (token == TT_COMMA) {
3236         getNextToken();
3237       } else {
3238         break;
3239       }
3240     } while (true);
3241   }
3242
3243   private void variable() throws CoreException {
3244     if (token == TT_DOLLAROPEN) {
3245       getNextToken();
3246       expression();
3247       ;
3248       if (token != TT_LISTCLOSE) {
3249         throwSyntaxError("'}' expected after indirect variable token '${'.");
3250       }
3251       getNextToken();
3252     } else {
3253       if (token == TT_VARIABLE) {
3254         getNextToken();
3255         if (token == TT_PARTOPEN) {
3256           getNextToken();
3257           expression();
3258           if (token != TT_PARTCLOSE) {
3259             throwSyntaxError("']' expected in variable-list.");
3260           }
3261           getNextToken();
3262         } else if (token == TT_ASSIGN) {
3263           getNextToken();
3264           constant();
3265         }
3266       } else {
3267         throwSyntaxError("$-variable expected in variable-list.");
3268       }
3269     }
3270   }
3271
3272   private void constant() throws CoreException {
3273     String ident;
3274     switch (token) {
3275       case TT_ADD :
3276         getNextToken();
3277         switch (token) {
3278           case TT_DOUBLE_NUMBER :
3279             getNextToken();
3280             break;
3281           case TT_INT_NUMBER :
3282             getNextToken();
3283             break;
3284           default :
3285             throwSyntaxError("Constant expected after '+' presign.");
3286         }
3287         break;
3288       case TT_SUBTRACT :
3289         getNextToken();
3290         switch (token) {
3291           case TT_DOUBLE_NUMBER :
3292             getNextToken();
3293             break;
3294           case TT_INT_NUMBER :
3295             getNextToken();
3296             break;
3297           default :
3298             throwSyntaxError("Constant expected after '-' presign.");
3299         }
3300         break;
3301       case TT_null :
3302         getNextToken();
3303         break;
3304       case TT_false :
3305         getNextToken();
3306         break;
3307       case TT_true :
3308         getNextToken();
3309         break;
3310       case TT_IDENTIFIER :
3311         ident = identifier;
3312         getNextToken();
3313         if (token == TT_ARGOPEN) {
3314           getNextToken();
3315           if (token != TT_ARGCLOSE) {
3316             expressionList();
3317             if (token != TT_ARGCLOSE) {
3318               throwSyntaxError("')' expected after identifier '" + ident + "' in postfix-expression.");
3319             }
3320           }
3321           getNextToken();
3322         }
3323         break;
3324       case TT_STRING_CONSTANT :
3325         getNextToken();
3326         break;
3327       case TT_INTERPOLATED_STRING :
3328         getNextToken();
3329         break;
3330       case TT_DOUBLE_NUMBER :
3331         getNextToken();
3332         break;
3333       case TT_INT_NUMBER :
3334         getNextToken();
3335         break;
3336       default :
3337         throwSyntaxError("Constant expected.");
3338     }
3339   }
3340
3341   /**
3342    * Call the php parse command ( php -l -f &lt;filename&gt; )
3343    * and create markers according to the external parser output
3344    */
3345   public static void phpExternalParse(IFile file) {
3346     //IFile file = (IFile) resource;
3347     IPath path = file.getFullPath();
3348     IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
3349     String filename = file.getLocation().toString();
3350
3351     String[] arguments = { filename };
3352     MessageFormat form = new MessageFormat(store.getString(PHPeclipsePlugin.EXTERNAL_PARSER_PREF));
3353     String command = form.format(arguments);
3354
3355     String parserResult = PHPStartApacheAction.execute(command, "External parser: ");
3356
3357     try {
3358       // parse the buffer to find the errors and warnings
3359       createMarkers(parserResult, file);
3360     } catch (CoreException e) {
3361     }
3362   }
3363
3364   /**
3365    * Create markers according to the external parser output
3366    */
3367   private static void createMarkers(String output, IFile file) throws CoreException {
3368     // delete all markers
3369     file.deleteMarkers(IMarker.PROBLEM, false, 0);
3370
3371     int indx = 0;
3372     int brIndx = 0;
3373     boolean flag = true;
3374     while ((brIndx = output.indexOf("<br />", indx)) != -1) {
3375       // newer php error output (tested with 4.2.3)
3376       scanLine(output, file, indx, brIndx);
3377       indx = brIndx + 6;
3378       flag = false;
3379     }
3380     if (flag) {
3381       while ((brIndx = output.indexOf("<br>", indx)) != -1) {
3382         // older php error output (tested with 4.2.3)
3383         scanLine(output, file, indx, brIndx);
3384         indx = brIndx + 4;
3385       }
3386     }
3387   }
3388
3389   private static void scanLine(String output, IFile file, int indx, int brIndx) throws CoreException {
3390     String current;
3391     String outLineNumberString;
3392     StringBuffer lineNumberBuffer = new StringBuffer(10);
3393     char ch;
3394     current = output.substring(indx, brIndx);
3395
3396     if (current.indexOf(PARSE_WARNING_STRING) != -1 || current.indexOf(PARSE_ERROR_STRING) != -1) {
3397       int onLine = current.indexOf("on line <b>");
3398       if (onLine != -1) {
3399         lineNumberBuffer.delete(0, lineNumberBuffer.length());
3400         for (int i = onLine; i < current.length(); i++) {
3401           ch = current.charAt(i);
3402           if ('0' <= ch && '9' >= ch) {
3403             lineNumberBuffer.append(ch);
3404           }
3405         }
3406
3407         int lineNumber = Integer.parseInt(lineNumberBuffer.toString());
3408
3409         Hashtable attributes = new Hashtable();
3410
3411         current = current.replaceAll("\n", "");
3412         current = current.replaceAll("<b>", "");
3413         current = current.replaceAll("</b>", "");
3414         MarkerUtilities.setMessage(attributes, current);
3415
3416         if (current.indexOf(PARSE_ERROR_STRING) != -1)
3417           attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_ERROR));
3418         else if (current.indexOf(PARSE_WARNING_STRING) != -1)
3419           attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_WARNING));
3420         else
3421           attributes.put(IMarker.SEVERITY, new Integer(IMarker.SEVERITY_INFO));
3422         MarkerUtilities.setLineNumber(attributes, lineNumber);
3423         MarkerUtilities.createMarker(file, attributes, IMarker.PROBLEM);
3424       }
3425     }
3426   }
3427 }