2 * Copyright 2004-2005 the original author or authors.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org
.codehaus
.groovy
.grails
.web
.pages
;
19 * NOTE: Based on work done by on the GSP standalone project (https://gsp.dev.java.net/)
21 * Lexer for GroovyPagesServlet.
23 * @author Troy Heninger
24 * @author Graeme Rocher
29 class Scan
implements Tokens
{
31 private int end1
, begin1
, end2
, begin2
, state
= HTML
, len
, level
;
32 private boolean str1
, str2
;
33 private String lastNamespace
;
34 private int exprBracketCount
= 0;
37 Strip strip
= new Strip(text
);
39 this.text
= strip
.toString();
40 len
= this.text
.length();
41 this.lastNamespace
= null;
44 private int found(int newState
, int skip
) {
47 begin1
= end1
+= skip
;
48 int lastState
= state
;
53 private int foundStartOrEndTag(int newState
, int skip
, String namespace
) {
56 begin1
= end1
+= skip
;
57 int lastState
= state
;
59 lastNamespace
= namespace
;
64 return text
.substring(begin2
, end2
);
67 String
getNamespace() {
73 int left
= len
- end1
;
75 end1
++; // in order to include the last letter
78 char c
= text
.charAt(end1
++);
79 char c1
= left
> 1 ? text
.charAt(end1
) : 0;
80 char c2
= left
> 2 ? text
.charAt(end1
+ 1) : 0;
81 char c3
= left
> 3 ? text
.charAt(end1
+ 2) : 0;
83 StringBuffer chars
= new StringBuffer()
87 String startTag
= chars
.toString();
94 if (c
== '\\') end1
++;
95 else if (c
== '\'') str1
= false;
98 if (c
== '\\') end1
++;
99 else if (c
== '"') str2
= false;
101 } else if (level
> 0 && (c
== ')' || c
== '}' || c
== ']')) {
108 if (c
== '<' && left
> 3) {
111 return found(JEXPR
, 3);
112 } else if (c2
== '@') {
113 return found(JDIRECT
, 3);
114 } else if (c2
== '!') {
115 return found(JDECLAR
, 3);
116 } else if (c2
== '-' && left
> 3 && text
.charAt(end1
+ 2) == '-') {
117 if (skipJComment()) continue;
119 return found(JSCRIPT
, 2);
122 boolean bStartTag
= true;
123 int fromIndex
= end1
; // we are expecting a start tag.
126 fromIndex
= end1
+ 1; // well it should be an end tag.
129 int foundColonIdx
= text
.indexOf(":", fromIndex
);
130 if (foundColonIdx
> -1) {
131 String tagNameSpace
= text
.substring(fromIndex
,foundColonIdx
);
132 if (tagNameSpace
.matches("^\\p{Alpha}\\w*$")) {
134 return foundStartOrEndTag(GSTART_TAG
,tagNameSpace
.length() + 2,tagNameSpace
);
137 return foundStartOrEndTag(GEND_TAG
,tagNameSpace
.length() + 3,tagNameSpace
);
142 } else if (c
== '$' && c1
== '{') {
143 return found(GEXPR
, 2);
144 } else if (c
== '%' && c1
== '{') {
145 if (c2
== '-' && left
> 3 && text
.charAt(end1
+ 2) == '-') {
146 if (skipGComment()) continue;
148 return found(GSCRIPT
, 2);
149 } else if (c
== '!' && c1
== '{') {
150 return found(GDECLAR
, 2);
151 } else if (c
== '@' && c1
== '{') {
152 return found(GDIRECT
, 2);
159 if (c
== '%' && c1
== '>') {
160 return found(HTML
, 2);
164 if(c
== '$' && c1
== '{') {
165 return found(GTAG_EXPR
, 2);
168 return found(HTML
,1);
170 else if(c
== '/' && c1
== '>') {
171 return found(GEND_TAG
,1);
176 return found(HTML
,1);
180 if(c
== '{') exprBracketCount
++;
182 if(exprBracketCount
>0) {
186 return found(GSTART_TAG
,1);
192 if (c
== '}' && !str1
&& !str2
&& level
== 0) {
193 return found(HTML
, 1);
197 if (c
== '}' && c1
== '%' && !str1
&& !str2
&& level
== 0) {
198 return found(HTML
, 2);
202 if (c
== '}' && (c1
== '!' || c1
== '%') && !str1
&& !str2
&& level
== 0) {
203 return found(HTML
, 2);
210 private boolean skipComment(char c3
, char c4
) {
212 for (int ixz
= len
- 4; ; ix
++) {
213 if (ix
>= ixz
) return false;
214 if (text
.charAt(ix
) == '-' && text
.charAt(ix
+ 1) == '-' && text
.charAt(ix
+ 2) == c3
215 && text
.charAt(ix
+ 3) == c4
) break;
217 text
= text
.substring(0, --end1
) + text
.substring(ix
+ 4);
222 private boolean skipGComment() {
223 return skipComment('}', '%');
226 private boolean skipJComment() {
227 return skipComment('%', '>');
231 end1
= begin1
= end2
= begin2
= level
= 0;
233 lastNamespace
= null;