Integrated PHP help files; Fixed some bugs
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / phpeditor / php / PHPPartitionScanner.java
1 /**********************************************************************
2 Copyright (c) 2000, 2002 IBM Corp. 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://www.eclipse.org/legal/cpl-v10.html
7
8 Contributors:
9     IBM Corporation - Initial implementation
10     Klaus Hartlage - www.eclipseproject.de
11 **********************************************************************/
12 package net.sourceforge.phpeclipse.phpeditor.php;
13
14 import java.io.CharArrayWriter;
15 import java.util.ArrayList;
16 import java.util.List;
17
18 import org.eclipse.jface.text.rules.ICharacterScanner;
19 import org.eclipse.jface.text.rules.IPredicateRule;
20 import org.eclipse.jface.text.rules.IToken;
21 import org.eclipse.jface.text.rules.IWordDetector;
22 import org.eclipse.jface.text.rules.MultiLineRule;
23 import org.eclipse.jface.text.rules.RuleBasedPartitionScanner;
24 import org.eclipse.jface.text.rules.Token;
25 import org.eclipse.jface.text.rules.WordRule;
26
27 /**
28  * This scanner recognizes the JavaDoc comments and Java multi line comments.
29  */
30 public class PHPPartitionScanner extends RuleBasedPartitionScanner {
31
32   private final static String SKIP = "__skip"; //$NON-NLS-1$
33   public final static String JAVA_MULTILINE_COMMENT = "__html_multiline_comment"; //$NON-NLS-1$
34   //    public final static String JAVA_DOC= "__java_javadoc"; //$NON-NLS-1$
35   public final static String PHP = "__php";
36   private StringBuffer test;
37   public class PHPMultiLineRule extends MultiLineRule {
38
39     public PHPMultiLineRule(String startSequence, String endSequence, IToken token) {
40       super(startSequence, endSequence, token);
41     }
42
43     public PHPMultiLineRule(String startSequence, String endSequence, IToken token, char escapeCharacter) {
44       super(startSequence, endSequence, token, escapeCharacter);
45     }
46
47     protected boolean endSequenceDetected(ICharacterScanner scanner) {
48       int c;
49       int c2;
50
51       boolean lineCommentMode = false;
52       boolean multiLineCommentMode = false;
53       boolean stringMode = false;
54
55       char[][] delimiters = scanner.getLegalLineDelimiters();
56       while ((c = scanner.read()) != ICharacterScanner.EOF) {
57         if (lineCommentMode && (c == '\n')) {
58           lineCommentMode = false;
59           // read until end of line
60         } else if ((!stringMode) && (c == '#')) {
61           // read until end of line
62           lineCommentMode = true;
63           continue;
64         } else if ((!stringMode) && (!multiLineCommentMode) && (c == '/')) {
65           c2 = scanner.read();
66           if (c2 == '/') {
67             lineCommentMode = true;
68             continue;
69           } else if (c2 == '*') {
70             multiLineCommentMode = true;
71             continue;
72           } else {
73             scanner.unread();
74           }
75         } else if (c == '*' && multiLineCommentMode) {
76           c2 = scanner.read();
77           if (c2 == '/') {
78             multiLineCommentMode = false;
79             continue;
80           } else {
81             scanner.unread();
82           }
83         } else if (c == '\\' && stringMode) {
84           c2 = scanner.read();
85           if (c2 == '"') {
86             continue;
87           } else {
88             scanner.unread();
89           }
90         } else if ((!lineCommentMode) && (!multiLineCommentMode) && (c == '"')) {
91           if (stringMode) {
92             stringMode = false;
93           } else {
94             stringMode = true;
95           }
96           continue;
97         }
98         if (lineCommentMode || multiLineCommentMode || stringMode) {
99           continue;
100         }
101
102         if (c == fEscapeCharacter) {
103           // Skip the escaped character.
104           scanner.read();
105         } else if (fEndSequence.length > 0 && c == fEndSequence[0]) {
106           // Check if the specified end sequence has been found.
107           if (sequenceDetected(scanner, fEndSequence, true))
108             return true;
109         } else if (fBreaksOnEOL) {
110           // Check for end of line since it can be used to terminate the pattern.
111           for (int i = 0; i < delimiters.length; i++) {
112             if (c == delimiters[i][0] && sequenceDetected(scanner, delimiters[i], false))
113               return true;
114           }
115         }
116       }
117       scanner.unread();
118       return true;
119     }
120   }
121   /**
122    * Detector for empty comments.
123    */
124   static class EmptyCommentDetector implements IWordDetector {
125
126     /* (non-Javadoc)
127     * Method declared on IWordDetector
128         */
129     public boolean isWordStart(char c) {
130       return (c == '/');
131     }
132
133     /* (non-Javadoc)
134     * Method declared on IWordDetector
135         */
136     public boolean isWordPart(char c) {
137       return (c == '*' || c == '/');
138     }
139   };
140
141   /**
142    * 
143    */
144   static class WordPredicateRule extends WordRule implements IPredicateRule {
145
146     private IToken fSuccessToken;
147
148     public WordPredicateRule(IToken successToken) {
149       super(new EmptyCommentDetector());
150       fSuccessToken = successToken;
151       addWord("/**/", fSuccessToken);
152     }
153
154     /*
155      * @see org.eclipse.jface.text.rules.IPredicateRule#evaluate(ICharacterScanner, boolean)
156      */
157     public IToken evaluate(ICharacterScanner scanner, boolean resume) {
158       return super.evaluate(scanner);
159     }
160
161     /*
162      * @see org.eclipse.jface.text.rules.IPredicateRule#getSuccessToken()
163      */
164     public IToken getSuccessToken() {
165       return fSuccessToken;
166     }
167   };
168
169   /**
170    * Creates the partitioner and sets up the appropriate rules.
171    */
172   public PHPPartitionScanner() {
173     super();
174
175     //          IToken javaDoc= new Token(JAVA_DOC);
176     IToken comment = new Token(JAVA_MULTILINE_COMMENT);
177     IToken php = new Token(PHP);
178
179     List rules = new ArrayList();
180
181     // Add rule for single line comments.
182     //  rules.add(new EndOfLineRule("//", Token.UNDEFINED));
183
184     // Add rule for strings and character constants.
185     //          rules.add(new SingleLineRule("\"", "\"", Token.UNDEFINED, '\\'));
186     //  rules.add(new SingleLineRule("'", "'", Token.UNDEFINED, '\\')); 
187
188     // Add special case word rule.
189     rules.add(new WordPredicateRule(comment));
190
191     // Add rules for multi-line comments and javadoc.
192     //rules.add(new MultiLineRule("/**", "*/", javaDoc));
193     rules.add(new MultiLineRule("<!--", "-->", comment));
194     rules.add(new PHPMultiLineRule("<?\r", "?>", php));
195     rules.add(new PHPMultiLineRule("<?\n", "?>", php));
196     rules.add(new PHPMultiLineRule("<?\t", "?>", php));
197     rules.add(new PHPMultiLineRule("<? ", "?>", php));
198     rules.add(new PHPMultiLineRule("<?php", "?>", php));
199     rules.add(new PHPMultiLineRule("<?PHP", "?>", php));
200     //Add rule for processing instructions
201
202     IPredicateRule[] result = new IPredicateRule[rules.size()];
203     rules.toArray(result);
204     setPredicateRules(result);
205   }
206 }