blob: 7029f98cc7fc1e626fbdc2fc87f030abde696dfe [file] [log] [blame]
package org.codehaus.groovy.modules.pages;
/**
* Created by IntelliJ IDEA.
* Author: Troy Heninger
* Date: Jan 10, 2004
* Lexer for GroovyPages.
*/
class Scan implements Tokens {
private String text;
private int end1, begin1, end2, begin2, state = HTML, len, level;
private boolean str1, str2;
Scan(String text) {
Strip strip = new Strip(text);
strip.strip(0);
this.text = strip.toString();
len = this.text.length();
} // Scan()
private int found(int newState, int skip) {
begin2 = begin1;
end2 = --end1;
begin1 = end1 += skip;
int lastState = state;
state = newState;
return lastState;
} // found()
String getToken() {
return text.substring(begin2, end2);
} // getToken()
int nextToken() {
for (;;) {
int left = len - end1;
if (left == 0) {
end1++; // in order to include the last letter
return found(EOF, 0);
}
char c = text.charAt(end1++);
char c1 = left > 1 ? text.charAt(end1) : 0;
char c2 = left > 2 ? text.charAt(end1 + 1) : 0;
if (str1) {
if (c == '\\') end1++;
else if (c == '\'') str1 = false;
continue;
} else if (str2) {
if (c == '\\') end1++;
else if (c == '"') str2 = false;
continue;
} else if (level > 0 && (c == ')' || c == '}' || c == ']')) {
level--;
continue;
}
switch (state) {
case HTML:
if (c == '<' && left > 3) {
if (c1 == '%') {
if (c2 == '=') {
return found(JEXPR, 3);
} else if (c2 == '@') {
return found(JDIRECT, 3);
} else if (c2 == '!') {
return found(JDECLAR, 3);
} else if (c2 == '-' && left > 3 && text.charAt(end1 + 2) == '-') {
if (skipJComment()) continue;
}
return found(JSCRIPT, 2);
}
} else if (c == '$' && c1 == '{') {
return found(GEXPR, 2);
} else if (c == '%' && c1 == '{') {
if (c2 == '-' && left > 3 && text.charAt(end1 + 2) == '-') {
if (skipGComment()) continue;
}
return found(GSCRIPT, 2);
} else if (c == '!' && c1 == '{') {
return found(GDECLAR, 2);
} else if (c == '@' && c1 == '{') {
return found(GDIRECT, 2);
}
break;
case JEXPR:
case JSCRIPT:
case JDIRECT:
case JDECLAR:
if (c == '%' && c1 == '>') {
return found(HTML, 2);
}
break;
case GEXPR:
case GDIRECT:
if (c == '}' && !str1 && !str2 && level == 0) {
return found(HTML, 1);
}
break;
case GSCRIPT:
if (c == '}' && c1 == '%' && !str1 && !str2 && level == 0) {
return found(HTML, 2);
}
break;
case GDECLAR:
if (c == '}' && (c1 == '!' || c1 == '%') && !str1 && !str2 && level == 0) {
return found(HTML, 2);
}
break;
}
}
} // nextToken()
private boolean skipComment(char c3, char c4) {
int ix = end1 + 3;
for (int ixz = len - 4; ; ix++) {
if (ix >= ixz) return false;
if (text.charAt(ix) == '-' && text.charAt(ix + 1) == '-' && text.charAt(ix + 2) == c3
&& text.charAt(ix + 3) == c4) break;
}
text = text.substring(0, --end1) + text.substring(ix + 4);
len = text.length();
return true;
} // skipComment()
private boolean skipGComment() {
return skipComment('}', '%');
} // skipGComment()
private boolean skipJComment() {
return skipComment('%', '>');
} // skipJComment()
void reset() {
end1= begin1 = end2 = begin2 = level = 0;
state = HTML;
} // reset()
} // Scan