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