fixed bug #1037094 (foreach)
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / phpeditor / php / PHPPartitionScanner.java
1 /**********************************************************************
2  Copyright (c) 2002  Widespace, OU  and others.
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://solareclipse.sourceforge.net/legal/cpl-v10.html
7
8  Contributors:
9  Igor Malinin - initial contribution
10
11  $Id: PHPPartitionScanner.java,v 1.25 2004-09-02 18:32:34 jsurfer Exp $
12  **********************************************************************/
13 package net.sourceforge.phpeclipse.phpeditor.php;
14
15 import java.util.HashMap;
16 import java.util.Map;
17
18 import net.sourceforge.phpeclipse.ui.text.rules.AbstractPartitioner;
19
20 import org.eclipse.core.internal.indexing.AbstractPagePolicy;
21 import org.eclipse.jface.text.Assert;
22 import org.eclipse.jface.text.BadLocationException;
23 import org.eclipse.jface.text.IDocument;
24 import org.eclipse.jface.text.rules.ICharacterScanner;
25 import org.eclipse.jface.text.rules.IPartitionTokenScanner;
26 import org.eclipse.jface.text.rules.IToken;
27 import org.eclipse.jface.text.rules.Token;
28
29 /**
30  * 
31  * 
32  * @author Igor Malinin
33  */
34 public class PHPPartitionScanner implements IPartitionTokenScanner {
35   //    public static final String JSP_DIRECTIVE = "__jsp_directive";
36   //    public static final String JSP_COMMENT = "__jsp_comment";
37   //// public static final String JSP_TAG = "__jsp_tag";
38   //    public static final String JSP_DECLARATION = "__jsp_declaration";
39   public static final String PHP_SCRIPTING_AREA = "__php_scripting_area ";
40
41   //    public static final String JSP_EXPRESSION = "__jsp_expression";
42
43   public static final int STATE_DEFAULT = 0;
44
45   //    public static final int STATE_TAG = 1;
46   //    public static final int STATE_SCRIPT = 2;
47
48   private IDocument document;
49
50   private int begin;
51
52   private int end;
53
54   private int offset;
55
56   private int length;
57
58   private int position;
59
60   private int state;
61
62   private Map tokens = new HashMap();
63
64   public PHPPartitionScanner() {
65   }
66
67   /*
68    * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken()
69    */
70   public IToken nextToken() {
71     offset += length;
72
73     /*
74      * switch (state) { case STATE_TAG: return nextTagToken(); }
75      */
76
77     switch (read()) {
78     case ICharacterScanner.EOF:
79       state = STATE_DEFAULT;
80       return getToken(null);
81
82     case '<':
83       switch (read()) {
84       case ICharacterScanner.EOF:
85         state = STATE_DEFAULT;
86         return getToken(null);
87
88       case '?': // <%SCRIPLET <%@DIRECTIVE <%!DECLARATION <%=EXPRESSION <%--COMMENT
89         int ch = read();
90         //                                               if (Character.isWhitespace((char)ch)) {
91         //                                                 return nextJSPToken(PHP_SCRIPTING_AREA);
92         //                                               }
93         switch (ch) {
94         case ICharacterScanner.EOF:
95           state = STATE_DEFAULT;
96           return getToken(PHP_SCRIPTING_AREA);
97
98         //                                                      case '-': // <%- <%--COMMENT
99         //                                                              switch (read()) {
100         //                                                                      case ICharacterScanner.EOF:
101         //                                                                      case '-': // <%--
102         //                                                                              return nextCommentToken();
103         //                                                              }
104         //
105         //                                                              break;
106         }
107
108         return scanUntilPHPEndToken(PHP_SCRIPTING_AREA);
109       }
110
111       unread();
112     }
113
114     loop: while (true) {
115       switch (read()) {
116       case ICharacterScanner.EOF:
117         state = STATE_DEFAULT;
118         return getToken(null);
119
120       case '<':
121         switch (read()) {
122         case ICharacterScanner.EOF:
123           state = STATE_DEFAULT;
124           return getToken(null);
125
126         case '?':
127           unread();
128           break;
129
130         case '<':
131           unread();
132
133         default:
134           continue loop;
135         }
136
137         unread();
138
139         state = STATE_DEFAULT;
140         return getToken(null);
141       }
142     }
143   }
144
145   private IToken scanUntilPHPEndToken(String token) {
146     int ch = read();
147     while (true) {
148       switch (ch) {
149       case ICharacterScanner.EOF:
150         state = STATE_DEFAULT;
151         return getToken(token);
152       case '"': // double quoted string
153         // read until end of double quoted string
154         readUntilEscaped('"');
155         break;
156       case '\'': // single quoted string
157         // read until end of single quoted string
158         readUntilEscaped('\'');
159         break;
160       case '/': // comment start?
161         ch = read();
162         switch (ch) {
163         case ICharacterScanner.EOF:
164           break;
165         case '/':
166           // read until end of line
167           readSingleLine();
168           break;
169         case '*':
170           // read until end of comment
171           readMultiLineComment();
172           break;
173         default:
174           continue;
175         }
176         break;
177       case '#': // line comment
178         // read until end of line
179         readSingleLine();
180         break;
181       case '?':
182         ch = read();
183         switch (ch) {
184         case ICharacterScanner.EOF:
185         case '>':
186           state = STATE_DEFAULT;
187           return getToken(token);
188
189         case '?':
190           continue;
191         }
192       }
193
194       ch = read();
195     }
196   }
197
198   //    private IToken nextCommentToken() {
199   //            int ch = read();
200   //            loop: while (true) {
201   //                    switch (ch) {
202   //                            case ICharacterScanner.EOF:
203   //                                    break loop;
204   //
205   //                            case '-': // - --%>
206   //                                    ch = read();
207   //                                    switch (ch) {
208   //                                            case ICharacterScanner.EOF:
209   //                                                    break loop;
210   //
211   //                                            case '-': // -- --%>
212   //                                                    ch = read();
213   //                                                    switch (ch) {
214   //                                                            case ICharacterScanner.EOF:
215   //                                                                    break loop;
216   //
217   //                                                            case '%': // --% --%>
218   //                                                                    ch = read();
219   //                                                                    switch (ch) {
220   //                                                                            case ICharacterScanner.EOF:
221   //                                                                            case '>':
222   //                                                                                    break loop;
223   //                                                                    }
224   //
225   //                                                                    continue loop;
226   //
227   //                                                            case '-': // --- ---%>
228   //                                                                    unread();
229   //                                                                    continue loop;
230   //                                                    }
231   //
232   //                                                    ch = read();
233   //                                                    continue loop;
234   //                                    }
235   //                    }
236   //
237   //                    ch = read();
238   //            }
239   //
240   //            return getToken(JSP_COMMENT);
241   //    }
242
243   private IToken getToken(String type) {
244     length = position - offset;
245
246     if (length == 0) {
247       return Token.EOF;
248     }
249
250     if (type == null) {
251       return Token.UNDEFINED;
252     }
253
254     IToken token = (IToken) tokens.get(type);
255     if (token == null) {
256       token = new Token(type);
257       tokens.put(type, token);
258     }
259
260     return token;
261   }
262
263   private int read() {
264     if (position >= end) {
265       return ICharacterScanner.EOF;
266     }
267
268     try {
269       return document.getChar(position++);
270     } catch (BadLocationException e) {
271       --position;
272       return ICharacterScanner.EOF;
273     }
274   }
275
276   private void readUntilEscaped(char ch) {
277     if (position >= end) {
278       return;
279     }
280     try {
281       while (true) {
282         if (document.getChar(position++) == ch) {
283           if (position < 2 || document.getChar(position - 2) != '\\') {
284             break;
285           }
286         }
287       }
288     } catch (BadLocationException e) {
289       --position;
290       return;
291     }
292   }
293
294   private void readSingleLine() {
295     if (position >= end) {
296       return;
297     }
298     try {
299       while (document.getChar(position++) != '\n') {
300
301       }
302     } catch (BadLocationException e) {
303       --position;
304       return;
305     }
306   }
307
308   private void readMultiLineComment() {
309     if (position >= end) {
310       return;
311     }
312     try {
313       char ch;
314       while (true) {
315         ch = document.getChar(position++);
316         if (ch == '*') {
317           if (document.getChar(position) == '/') {
318             position++;
319             break;
320           }
321         }
322       }
323     } catch (BadLocationException e) {
324       --position;
325       return;
326     }
327   }
328
329   private void unread() {
330     --position;
331   }
332
333   /*
334    * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenOffset()
335    */
336   public int getTokenOffset() {
337     if (AbstractPartitioner.DEBUG) {
338       Assert.isTrue(offset >= 0, Integer.toString(offset));
339     }
340     return offset;
341   }
342
343   /*
344    * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenLength()
345    */
346   public int getTokenLength() {
347     return length;
348   }
349
350   /*
351    * @see org.eclipse.jface.text.rules.ITokenScanner#setRange(IDocument, int, int)
352    */
353   public void setRange(IDocument document, int offset, int length) {
354     this.document = document;
355     this.begin = offset;
356     this.end = offset + length;
357
358     this.offset = offset;
359     this.position = offset;
360     this.length = 0;
361   }
362
363   /*
364    * @see org.eclipse.jface.text.rules.IPartitionTokenScanner
365    */
366   public void setPartialRange(IDocument document, int offset, int length, String contentType, int partitionOffset) {
367     state = STATE_DEFAULT;
368     //    if (partitionOffset > -1) {
369     //          int delta= offset - partitionOffset;
370     //          if (delta > 0) {
371     //                  this.setRange(document, partitionOffset, length + delta);
372     //                  return;
373     //          }
374     //  }
375     setRange(document, partitionOffset, length);
376   }
377
378   //    private boolean isContinuationPartition(IDocument document, int offset) {
379   //            try {
380   //                    String type = document.getContentType(offset - 1);
381   //
382   //                    if (type != IDocument.DEFAULT_CONTENT_TYPE) {
383   //                            return true;
384   //                    }
385   //            } catch (BadLocationException e) {}
386   //
387   //            return false;
388   //    }
389 }