/*****************************************************************************
* This file is part of Rinzo
*
* Author: Claudio Cancinos
* WWW: https://sourceforge.net/projects/editorxml
* Copyright (C): 2008, Claudio Cancinos
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; If not, see <http://www.gnu.org/licenses/>
****************************************************************************/
package ar.com.tadp.xml.rinzo.core.partitioner;
import java.util.Stack;
import org.eclipse.jface.text.rules.ICharacterScanner;
import org.eclipse.jface.text.rules.IPredicateRule;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.Token;
/**
*
* @author ccancinos
*/
public class XMLRule2 implements IPredicateRule {
private static final int STATE_UNDEFINED = 0;
private static final int STATE_TEXT = 1;
private static final int STATE_SCAN_TAG = 2;
private static final int STATE_TAG = 3;
private static final int STATE_INCOMPLETE_TAG = 4;
private static final int STATE_END_TAG = 5;
private static final int STATE_EMPTY_TAG = 6;
private static final int STATE_DECL_OR_COMMENT = 7;
private static final int STATE_SCAN_DECLARATION = 8;
private static final int STATE_DECLARATION = 9;
private static final int STATE_SCAN_COMMENT = 10;
private static final int STATE_COMMENT_ABOUTTOEND = 11;
private static final int STATE_COMMENT = 12;
private static final int STATE_SCAN_PI = 13;
private static final int STATE_PI = 14;
private static final int STATE_ATTRIBUTE_STRING = 15;
private static final int STATE_SCAN_CDATA = 16;
private static final int STATE_CDATA = 17;
private static final int STATE_CDATA_ABOUTTOEND = 18;
private int state;
private Stack<Integer> stateStack;
public XMLRule2() {
stateStack = new Stack<Integer>();
}
public IToken getSuccessToken() {
switch(state) {
case STATE_TAG:
return XMLPartitionScanner.TOKEN_XML_TAG;
case STATE_END_TAG:
return XMLPartitionScanner.TOKEN_XML_ENDTAG;
case STATE_INCOMPLETE_TAG:
return XMLPartitionScanner.TOKEN_XML_INCOMPLETETAG;
case STATE_EMPTY_TAG:
return XMLPartitionScanner.TOKEN_XML_EMPTYTAG;
case STATE_TEXT:
return XMLPartitionScanner.TOKEN_XML_TEXT;
case STATE_COMMENT:
return XMLPartitionScanner.TOKEN_XML_COMMENT;
case STATE_DECLARATION:
return XMLPartitionScanner.TOKEN_XML_DECLARATION;
case STATE_PI:
return XMLPartitionScanner.TOKEN_XML_PI;
case STATE_CDATA:
return XMLPartitionScanner.TOKEN_XML_CDATA; //yo lo agregue
case STATE_SCAN_TAG:
case STATE_DECL_OR_COMMENT:
case STATE_SCAN_DECLARATION:
case STATE_SCAN_COMMENT:
case STATE_COMMENT_ABOUTTOEND:
case STATE_SCAN_CDATA:
case STATE_CDATA_ABOUTTOEND:
case STATE_SCAN_PI:
default:
return Token.EOF;
}
}
public IToken evaluate(ICharacterScanner scanner, boolean resume) {
return evaluate(scanner);
}
private void switchState(int newState) {
state = newState;
}
private void pushState() {
stateStack.push(Integer.valueOf(state));
}
private void popState() {
Integer i = stateStack.pop();
state = i.intValue();
}
public IToken evaluate(ICharacterScanner scanner) {
boolean done = false;
switchState(0);
int previous = -1;
int character = -1;
while(!done) {
previous = character;
character = scanner.read();
if(character == -1)
done = true;
else
switch(state) {
case STATE_UNDEFINED:
done = handleUndefined(scanner, character, previous);
break;
case STATE_TEXT:
done = handleText(scanner, character, previous);
break;
case STATE_SCAN_TAG:
done = handleScanTag(scanner, character, previous);
break;
case STATE_TAG:
done = handleTag(scanner, character, previous);
break;
case STATE_INCOMPLETE_TAG:
done = handleTagIncomplete(scanner, character, previous);
break;
case STATE_EMPTY_TAG:
done = handleEmptyTag(scanner, character, previous);
break;
case STATE_END_TAG:
done = handleEndTag(scanner, character, previous);
break;
case STATE_DECL_OR_COMMENT:
done = handleDeclOrComment(scanner, character, previous);
break;
case STATE_SCAN_COMMENT:
done = handleScanComment(scanner, character, previous);
break;
case STATE_SCAN_DECLARATION:
done = handleScanDeclaration(scanner, character, previous);
break;
case STATE_COMMENT_ABOUTTOEND:
done = handleCommentAboutToEnd(scanner, character, previous);
break;
case STATE_COMMENT:
done = handleComment(scanner, character, previous);
break;
case STATE_SCAN_PI:
done = handlePI(scanner, character, previous);
break;
case STATE_ATTRIBUTE_STRING:
done = handleAttributeString(scanner, character, previous);
break;
case STATE_SCAN_CDATA:
done = handleScanCdata(scanner, character, previous);
break;
case STATE_CDATA:
done = handleAttributeCdata(scanner, character, previous);
break;
case STATE_CDATA_ABOUTTOEND:
done = handleCdataAboutToEnd(scanner, character, previous);
break;
case STATE_DECLARATION:
case STATE_PI:
default:
System.out.println("Unexpected error.");
break;
}
}
return getSuccessToken();
}
private boolean handleCdataAboutToEnd(ICharacterScanner scanner,int character, int previous) {
if(previous == ']' && character == '>') {
switchState(STATE_CDATA);
return false;
}
if(previous == ']' && character != '>') {
switchState(STATE_SCAN_CDATA);
return false;
}
else {
return false;
}
}
private boolean handleAttributeCdata(ICharacterScanner scanner, int character, int previous) {
scanner.unread();
return true;
}
private boolean handleAttributeString(ICharacterScanner scanner, int character, int previous) {
if(character == '"' || character == '\'')
popState();
else
if(character == '>')
popState();
return false;
}
private boolean handleComment(ICharacterScanner scanner, int character, int previous) {
return true;
}
private boolean handlePI(ICharacterScanner scanner, int character, int previous) {
if(previous == '?' && character == '>') {
switchState(STATE_PI);
return true;
} else {
return false;
}
}
private boolean handleScanDeclaration(ICharacterScanner scanner, int character, int previous) {
if(character == '>') {
switchState(STATE_DECLARATION);
return true;
} else {
return false;
}
}
private boolean handleCommentAboutToEnd(ICharacterScanner scanner, int character, int previous) {
if(previous == '-' && character == '>') {
switchState(STATE_COMMENT);
return true;
} else {
return false;
}
}
private boolean handleScanComment(ICharacterScanner scanner, int character, int previous) {
if(previous == '-' && character == '-') {
switchState(STATE_COMMENT_ABOUTTOEND);
return false;
} else {
return false;
}
}
private boolean handleScanCdata(ICharacterScanner scanner, int character, int previous) {
if(previous == ']' && character == ']') {
switchState(STATE_CDATA_ABOUTTOEND);
return false;
} else {
return false;
}
}
private boolean handleDeclOrComment(ICharacterScanner scanner, int character, int previous) {
if(previous == '!' && character == '['){
return false;
}
if(previous == '[' && character == 'C') {
switchState(STATE_SCAN_CDATA);
return false;
}
if(previous == '!' && character == '-')
return false;
if(previous == '-' && character == '-') {
switchState(STATE_SCAN_COMMENT);
return false;
} else {
switchState(STATE_SCAN_DECLARATION);
return false;
}
}
private boolean handleEmptyTag(ICharacterScanner scanner, int character, int previous) {
return character == '>';
}
private boolean handleEndTag(ICharacterScanner scanner, int character, int previous) {
return character == '>';
}
private boolean handleTagIncomplete(ICharacterScanner scanner, int character, int previous) {
return true;
}
private boolean handleTag(ICharacterScanner scanner, int character, int previous) {
return true;
}
private boolean handleScanTag(ICharacterScanner scanner, int character, int previous) {
if(character == '<') {
switchState(STATE_INCOMPLETE_TAG);
scanner.unread();
return true;
}
if(character == '"' || character == '\'') {
pushState();
switchState(STATE_ATTRIBUTE_STRING);
return false;
}
if(character == '/')
if(previous == '<') {
switchState(STATE_END_TAG);
return false;
} else {
switchState(STATE_EMPTY_TAG);
return false;
}
if(character == '>') {
switchState(STATE_TAG);
return true;
}
if(previous == '<' && character == '?') {
switchState(STATE_SCAN_PI);
return false;
}
if(previous == '<' && character == '!') {
switchState(STATE_DECL_OR_COMMENT);
return false;
} else {
return false;
}
}
private boolean handleText(ICharacterScanner scanner, int character, int previous) {
if(character == '<') {
scanner.unread();
return true;
} else {
return false;
}
}
private boolean handleUndefined(ICharacterScanner scanner, int character, int previous) {
if(character == '<') {
switchState(STATE_SCAN_TAG);
} else {
switchState(STATE_TEXT);
}
return false;
}
}