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