KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > freemarker > eclipse > editors > FreemarkerTools


1 /*
2  * Copyright (c) 2003 The Visigoth Software Society. All rights
3  * reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in
14  * the documentation and/or other materials provided with the
15  * distribution.
16  *
17  * 3. The end-user documentation included with the redistribution, if
18  * any, must include the following acknowledgement:
19  * "This product includes software developed by the
20  * Visigoth Software Society (http://www.visigoths.org/)."
21  * Alternately, this acknowledgement may appear in the software
22  * itself, if and wherever such third-party acknowledgements
23  * normally appear.
24  *
25  * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names
26  * of the project contributors may be used to endorse or promote
27  * products derived from this software without prior written
28  * permission. For written permission, please contact
29  * visigoths@visigoths.org.
30  *
31  * 5. Products derived from this software may not be called
32  * "FreeMarker" or "Visigoth" nor may "FreeMarker" or "Visigoth"
33  * appear in their names without prior written permission of the
34  * Visigoth Software Society.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Visigoth Software Society. For more
52  * information on the Visigoth Software Society, please see
53  * http://www.visigoths.org/
54  */

55
56 package freemarker.eclipse.editors;
57
58 import org.eclipse.jface.text.rules.ICharacterScanner;
59
60 /**
61  * A class containing utility methods. In particular, this class
62  * contains metods for performing the lexical analysis needed for
63  * correct syntax highlighting.
64  *
65  * @author <a HREF="mailto:stephan@chaquotay.net">Stephan Mueller</a>
66  * @author <a HREF="mailto:per&#64;percederberg.net">Per Cederberg</a>
67  * @version $Id: FreemarkerTools.java,v 1.3 2004/03/03 21:55:43 stephanmueller Exp $
68  */

69 public class FreemarkerTools {
70
71     /**
72      * The FreeMarker comment start character sequence.
73      */

74     private static final char[] COMMENT_START = "<#--".toCharArray();
75
76     /**
77      * The FreeMarker comment end character sequence.
78      */

79     private static final char[] COMMENT_END = "-->".toCharArray();
80
81     /**
82      * The XML comment start character sequence.
83      */

84     private static final char[] XML_COMMENT_START = "<!--".toCharArray();
85
86     /**
87      * The XML comment end character sequence.
88      */

89     private static final char[] XML_COMMENT_END = "-->".toCharArray();
90
91     /**
92      * Checks for a FreeMarker comment start. If a matching character
93      * sequence was detected, it will be read. If no match was found
94      * starting at the first character returned by the scanner, false
95      * will be returned and any characters read will be unread
96      * (leaving the scanner in the original state).
97      *
98      * @param scanner the character scanner
99      *
100      * @return true if a comment start was read, or
101      * false otherwise
102      */

103     public static boolean readCommentStart(ICharacterScanner scanner) {
104         return readSequence(scanner, COMMENT_START);
105     }
106     
107     /**
108      * Reads characters until a FreeMarker comment end is found.
109      *
110      * @param scanner the character scanner
111      */

112     public static void readCommentEnd(ICharacterScanner scanner) {
113         int c;
114
115         do {
116             c = scanner.read();
117             if (c == '-') {
118                 scanner.unread();
119                 if (readSequence(scanner, COMMENT_END)) {
120                     break;
121                 } else {
122                     c = scanner.read();
123                 }
124             }
125         } while (c != ICharacterScanner.EOF);
126     }
127
128     /**
129      * Checks for a FreeMarker directive start. If a matching
130      * character sequence was detected, it will be read. If no match
131      * was found starting at the first character returned by the
132      * scanner, false will be returned and any characters read will
133      * be unread (leaving the scanner in the original state).
134      *
135      * @param scanner the character scanner
136      *
137      * @return true if a directive start was read, or
138      * false otherwise
139      */

140     public static boolean readDirectiveStart(ICharacterScanner scanner) {
141         int c;
142
143         c = scanner.read();
144         if (c != '<') {
145             scanner.unread();
146             return false;
147         }
148         c = scanner.read();
149         if (c != '#' && c != '@' && c != '/') {
150             scanner.unread();
151             scanner.unread();
152             return false;
153         }
154         if (c == '/') {
155             c = scanner.read();
156             if (c != '#' && c != '@') {
157                 scanner.unread();
158                 scanner.unread();
159                 scanner.unread();
160                 return false;
161             }
162         }
163         return true;
164     }
165
166     /**
167      * Reads characters until a FreeMarker directive end is found.
168      * This method attempts to detect and handle '>' characters used
169      * inside parenthesized expressions, as well as quoted strings
170      * and FreeMarker comments.
171      *
172      * @param scanner the character scanner
173      */

174     public static void readDirectiveEnd(ICharacterScanner scanner) {
175         int parens = 0;
176         int c;
177
178         do {
179             c = scanner.read();
180             if (c == '<') {
181                 scanner.unread();
182                 if (readCommentStart(scanner)) {
183                     readCommentEnd(scanner);
184                 } else {
185                     c = scanner.read();
186                 }
187             } else if (c == '"') {
188                 readQuoteEnd(scanner);
189             } else if (c == '(') {
190                 parens++;
191             } else if (c == ')') {
192                 parens--;
193             }
194         } while (c != ICharacterScanner.EOF
195               && (c != '>' || parens > 0));
196     }
197
198     /**
199      * Checks for a FreeMarker interpolation start. If a matching
200      * character sequence was detected, it will be read. If no match
201      * was found starting at the first character returned by the
202      * scanner, false will be returned and any characters read will
203      * be unread (leaving the scanner in the original state).
204      *
205      * @param scanner the character scanner
206      *
207      * @return true if an interpolation start was read, or
208      * false otherwise
209      */

210     public static boolean readInterpolationStart(ICharacterScanner scanner) {
211         int c;
212
213         c = scanner.read();
214         if (c != '$' && c != '#') {
215             scanner.unread();
216             return false;
217         }
218         c = scanner.read();
219         if (c != '{') {
220             scanner.unread();
221             scanner.unread();
222             return false;
223         }
224         return true;
225     }
226
227     /**
228      * Reads characters until a FreeMarker comment end is found. This
229      * method attempts to detect and handle quoted strings and hash
230      * literals inside the interpolation.
231      *
232      * @param scanner the character scanner
233      */

234     public static void readInterpolationEnd(ICharacterScanner scanner) {
235         int c;
236
237         do {
238             c = scanner.read();
239             if (c == '"') {
240                 readQuoteEnd(scanner);
241             } else if (c == '{') {
242                 readHashEnd(scanner);
243             }
244         } while (c != ICharacterScanner.EOF && c != '}');
245     }
246
247     /**
248      * Checks for a literal hash start. If a matching character
249      * sequence was detected, it will be read. If no match was found
250      * starting at the first character returned by the scanner, false
251      * will be returned and any characters read will be unread
252      * (leaving the scanner in the original state).
253      *
254      * @param scanner the character scanner
255      *
256      * @return true if a literal hash start was read, or
257      * false otherwise
258      */

259     public static boolean readHashStart(ICharacterScanner scanner) {
260         if (scanner.read() != '{') {
261             scanner.unread();
262             return false;
263         } else {
264             return true;
265         }
266     }
267     
268     /**
269      * Reads characters until a literal hash end is found.
270      *
271      * @param scanner the character scanner
272      */

273     public static void readHashEnd(ICharacterScanner scanner) {
274         int c;
275
276         do {
277             c = scanner.read();
278             if (c == '"') {
279                 readQuoteEnd(scanner);
280             } else if (c == '{') {
281                 readHashEnd(scanner);
282             }
283             
284         } while (c != ICharacterScanner.EOF && c != '}');
285     }
286
287     /**
288      * Checks for a quoted string start. If a matching character
289      * sequence was detected, it will be read. If no match was found
290      * starting at the first character returned by the scanner, false
291      * will be returned and any characters read will be unread
292      * (leaving the scanner in the original state).
293      *
294      * @param scanner the character scanner
295      *
296      * @return true if a quoted string start was read, or
297      * false otherwise
298      */

299     public static boolean readQuoteStart(ICharacterScanner scanner) {
300         if (scanner.read() != '"') {
301             scanner.unread();
302             return false;
303         } else {
304             return true;
305         }
306     }
307
308     /**
309      * Reads characters until a quote end is found. This method
310      * attempts to detect and handle character escapes inside the
311      * quoted string.
312      *
313      * @param scanner the character scanner
314      */

315     public static void readQuoteEnd(ICharacterScanner scanner) {
316         int c;
317
318         do {
319             c = scanner.read();
320             if (c == '\\') {
321                 scanner.read();
322             }
323         } while (c != ICharacterScanner.EOF && c != '"');
324     }
325
326     /**
327      * Checks for an XML comment start. If a matching character
328      * sequence was detected, it will be read. If no match was found
329      * starting at the first character returned by the scanner, false
330      * will be returned and any characters read will be unread
331      * (leaving the scanner in the original state).
332      *
333      * @param scanner the character scanner
334      *
335      * @return true if an XML comment start was read, or
336      * false otherwise
337      */

338     public static boolean readXmlCommentStart(ICharacterScanner scanner) {
339         return readSequence(scanner, XML_COMMENT_START);
340     }
341     
342     /**
343      * Reads characters until an XML comment end is found. This
344      * method attempts to detect and handle FreeMarker comments,
345      * directives and interpolations inside the XML comment.
346      *
347      * @param scanner the character scanner
348      */

349     public static void readXmlCommentEnd(ICharacterScanner scanner) {
350         int c;
351
352         do {
353             c = scanner.read();
354             if (c == '$' || c == '#') {
355                 scanner.unread();
356                 if (readInterpolationStart(scanner)) {
357                     readInterpolationEnd(scanner);
358                 } else {
359                     c = scanner.read();
360                 }
361             } else if (c == '<') {
362                 scanner.unread();
363                 if (readCommentStart(scanner)) {
364                     readCommentEnd(scanner);
365                 } else if (readDirectiveStart(scanner)) {
366                     readDirectiveEnd(scanner);
367                 } else {
368                     c = scanner.read();
369                 }
370             } else if (c == '-') {
371                 scanner.unread();
372                 if (readSequence(scanner, XML_COMMENT_END)) {
373                     break;
374                 } else {
375                     c = scanner.read();
376                 }
377             }
378         } while (c != ICharacterScanner.EOF);
379     }
380
381     /**
382      * Checks for an XML tag start. If a matching character sequence
383      * was detected, it will be read. If no match was found starting
384      * at the first character returned by the scanner, false will be
385      * returned and any characters read will be unread (leaving the
386      * scanner in the original state).
387      *
388      * @param scanner the character scanner
389      *
390      * @return true if an XML tag start was read, or
391      * false otherwise
392      */

393     public static boolean readXmlTagStart(ICharacterScanner scanner) {
394         if (scanner.read() != '<') {
395             scanner.unread();
396             return false;
397         } else {
398             return true;
399         }
400     }
401
402     /**
403      * Reads characters until an XML tag end is found. This method
404      * attempts to detect and handle FreeMarker comments, directives
405      * and interpolations inside the tag.
406      *
407      * @param scanner the character scanner
408      */

409     public static void readXmlTagEnd(ICharacterScanner scanner) {
410         int c;
411         
412         do {
413             c = scanner.read();
414             if (c == '$' || c == '#') {
415                 scanner.unread();
416                 if (readInterpolationStart(scanner)) {
417                     readInterpolationEnd(scanner);
418                 } else {
419                     c = scanner.read();
420                 }
421             } else if (c == '<') {
422                 scanner.unread();
423                 if (readCommentStart(scanner)) {
424                     readCommentEnd(scanner);
425                 } else if (readDirectiveStart(scanner)) {
426                     readDirectiveEnd(scanner);
427                 } else {
428                     c = scanner.read();
429                 }
430             }
431         } while (c != ICharacterScanner.EOF && c != '>');
432     }
433     
434     /**
435      * Checks for a character sequence. If a matching sequence was
436      * detected, it will be read. If no match was found starting at
437      * the first character returned by the scanner, false will be
438      * returned and any characters read will be unread (leaving the
439      * scanner in the original state).
440      *
441      * @param scanner the character scanner
442      *
443      * @return true if a character sequence was read, or
444      * false otherwise
445      */

446     private static boolean readSequence(ICharacterScanner scanner,
447                                         char[] chars) {
448
449         int pos = 0;
450         int c;
451         
452         do {
453             c = scanner.read();
454             if (chars[pos] != c) {
455                 while (pos-- >= 0) {
456                     scanner.unread();
457                 }
458                 return false;
459             }
460             pos++;
461         } while (pos < chars.length);
462
463         return true;
464     }
465 }
466
Popular Tags