/**********************************************************************
-Copyright (c) 2000, 2002 IBM Corp. and others.
-All rights reserved. This program and the accompanying materials
-are made available under the terms of the Common Public License v1.0
-which accompanies this distribution, and is available at
-http://www.eclipse.org/legal/cpl-v10.html
-
-Contributors:
- IBM Corporation - Initial implementation
- Klaus Hartlage - www.eclipseproject.de
-**********************************************************************/
+ Copyright (c) 2002 Widespace, OU and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://solareclipse.sourceforge.net/legal/cpl-v10.html
+
+ Contributors:
+ Igor Malinin - initial contribution
+
+ $Id: PHPPartitionScanner.java,v 1.27 2005-05-06 00:57:28 stefanbjarni Exp $
+ **********************************************************************/
package net.sourceforge.phpeclipse.phpeditor.php;
-import java.util.ArrayList;
-import java.util.List;
-import org.eclipse.jface.text.rules.EndOfLineRule;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.sourceforge.phpeclipse.ui.text.rules.AbstractPartitioner;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.rules.ICharacterScanner;
-import org.eclipse.jface.text.rules.IPredicateRule;
-import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IPartitionTokenScanner;
import org.eclipse.jface.text.rules.IToken;
-import org.eclipse.jface.text.rules.IWordDetector;
-import org.eclipse.jface.text.rules.MultiLineRule;
-import org.eclipse.jface.text.rules.RuleBasedPartitionScanner;
-import org.eclipse.jface.text.rules.RuleBasedScanner;
-import org.eclipse.jface.text.rules.SingleLineRule;
import org.eclipse.jface.text.rules.Token;
-import org.eclipse.jface.text.rules.WordRule;
/**
- * This scanner recognizes the JavaDoc comments and Java multi line comments.
+ *
+ *
+ * @author Igor Malinin
*/
-public class PHPPartitionScanner extends RuleBasedPartitionScanner {
-
- private final static String SKIP= "__skip"; //$NON-NLS-1$
- public final static String JAVA_MULTILINE_COMMENT= "__html_multiline_comment"; //$NON-NLS-1$
-// public final static String JAVA_DOC= "__java_javadoc"; //$NON-NLS-1$
- public final static String PHP= "__php";
- /**
- * Detector for empty comments.
- */
- static class EmptyCommentDetector implements IWordDetector {
-
- /* (non-Javadoc)
- * Method declared on IWordDetector
- */
- public boolean isWordStart(char c) {
- return (c == '/');
- }
-
- /* (non-Javadoc)
- * Method declared on IWordDetector
- */
- public boolean isWordPart(char c) {
- return (c == '*' || c == '/');
- }
- };
-
- /**
- *
- */
- static class WordPredicateRule extends WordRule implements IPredicateRule {
-
- private IToken fSuccessToken;
-
- public WordPredicateRule(IToken successToken) {
- super(new EmptyCommentDetector());
- fSuccessToken= successToken;
- addWord("/**/", fSuccessToken);
- }
-
- /*
- * @see org.eclipse.jface.text.rules.IPredicateRule#evaluate(ICharacterScanner, boolean)
- */
- public IToken evaluate(ICharacterScanner scanner, boolean resume) {
- return super.evaluate(scanner);
- }
-
- /*
- * @see org.eclipse.jface.text.rules.IPredicateRule#getSuccessToken()
- */
- public IToken getSuccessToken() {
- return fSuccessToken;
- }
- };
-
- /**
- * Creates the partitioner and sets up the appropriate rules.
- */
- public PHPPartitionScanner() {
- super();
-
-// IToken javaDoc= new Token(JAVA_DOC);
- IToken comment= new Token(JAVA_MULTILINE_COMMENT);
- IToken php = new Token(PHP);
-
- List rules= new ArrayList();
-
- // Add rule for single line comments.
- // rules.add(new EndOfLineRule("//", Token.UNDEFINED));
-
- // Add rule for strings and character constants.
- // rules.add(new SingleLineRule("\"", "\"", Token.UNDEFINED, '\\'));
- // rules.add(new SingleLineRule("'", "'", Token.UNDEFINED, '\\'));
-
- // Add special case word rule.
- rules.add(new WordPredicateRule(comment));
-
- // Add rules for multi-line comments and javadoc.
- //rules.add(new MultiLineRule("/**", "*/", javaDoc));
- rules.add(new MultiLineRule("<!--", "-->", comment));
- rules.add(new MultiLineRule("<? ", "?>", php));
- rules.add(new MultiLineRule("<?php", "?>", php));
- rules.add(new MultiLineRule("<?PHP", "?>", php));
- //Add rule for processing instructions
-
-
- IPredicateRule[] result= new IPredicateRule[rules.size()];
- rules.toArray(result);
- setPredicateRules(result);
- }
-}
+public class PHPPartitionScanner implements IPartitionTokenScanner {
+ // public static final String JSP_DIRECTIVE = "__jsp_directive";
+ // public static final String JSP_COMMENT = "__jsp_comment";
+ //// public static final String JSP_TAG = "__jsp_tag";
+ // public static final String JSP_DECLARATION = "__jsp_declaration";
+ public static final String PHP_SCRIPTING_AREA = "__php_scripting_area ";
+
+ // public static final String JSP_EXPRESSION = "__jsp_expression";
+
+ public static final int STATE_DEFAULT = 0;
+
+ // public static final int STATE_TAG = 1;
+ // public static final int STATE_SCRIPT = 2;
+
+ private IDocument document;
+
+ private int begin;
+
+ private int end;
+
+ private int offset;
+
+ private int length;
+
+ private int position;
+
+ private int state;
+
+ private Map tokens = new HashMap();
+
+ public PHPPartitionScanner() {
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken()
+ */
+ public IToken nextToken() {
+ offset += length;
+
+ /*
+ * switch (state) { case STATE_TAG: return nextTagToken(); }
+ */
+
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ state = STATE_DEFAULT;
+ return getToken(null);
+
+ case '<':
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ state = STATE_DEFAULT;
+ return getToken(null);
+
+ case '?': // <%SCRIPLET <%@DIRECTIVE <%!DECLARATION <%=EXPRESSION <%--COMMENT
+ int ch = read();
+ // if (Character.isWhitespace((char)ch)) {
+ // return nextJSPToken(PHP_SCRIPTING_AREA);
+ // }
+ switch (ch) {
+ case ICharacterScanner.EOF:
+ state = STATE_DEFAULT;
+ return getToken(PHP_SCRIPTING_AREA);
+
+ // case '-': // <%- <%--COMMENT
+ // switch (read()) {
+ // case ICharacterScanner.EOF:
+ // case '-': // <%--
+ // return nextCommentToken();
+ // }
+ //
+ // break;
+ }
+
+ return scanUntilPHPEndToken(PHP_SCRIPTING_AREA);
+ }
+
+ unread();
+ }
+
+ loop: while (true) {
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ state = STATE_DEFAULT;
+ return getToken(null);
+
+ case '<':
+ switch (read()) {
+ case ICharacterScanner.EOF:
+ state = STATE_DEFAULT;
+ return getToken(null);
+
+ case '?':
+ unread();
+ break;
+
+ case '<':
+ unread();
+
+ default:
+ continue loop;
+ }
+
+ unread();
+
+ state = STATE_DEFAULT;
+ return getToken(null);
+ }
+ }
+ }
+
+ private IToken scanUntilPHPEndToken(String token) {
+ int ch = read();
+ while (true) {
+ switch (ch) {
+ case ICharacterScanner.EOF:
+ state = STATE_DEFAULT;
+ return getToken(token);
+ case '"': // double quoted string
+ // read until end of double quoted string
+ if (!readUntilEscapedDQ()) {
+ state = STATE_DEFAULT;
+ return getToken(token);
+ }
+ break;
+ case '\'': // single quoted string
+ // read until end of single quoted string
+ if (!readUntilEscapedSQ()) {
+ state = STATE_DEFAULT;
+ return getToken(token);
+ }
+ break;
+ case '/': // comment start?
+ ch = read();
+ switch (ch) {
+ case ICharacterScanner.EOF:
+ break;
+ case '/':
+ // read until end of line
+ readSingleLine();
+ break;
+ case '*':
+ // read until end of comment
+ readMultiLineComment();
+ break;
+ default:
+ continue;
+ }
+ break;
+ case '#': // line comment
+ // read until end of line
+ readSingleLine();
+ break;
+ case '?':
+ ch = read();
+ switch (ch) {
+ case ICharacterScanner.EOF:
+ case '>':
+ state = STATE_DEFAULT;
+ return getToken(token);
+
+ case '?':
+ continue;
+ }
+ }
+
+ ch = read();
+ }
+ }
+
+ // private IToken nextCommentToken() {
+ // int ch = read();
+ // loop: while (true) {
+ // switch (ch) {
+ // case ICharacterScanner.EOF:
+ // break loop;
+ //
+ // case '-': // - --%>
+ // ch = read();
+ // switch (ch) {
+ // case ICharacterScanner.EOF:
+ // break loop;
+ //
+ // case '-': // -- --%>
+ // ch = read();
+ // switch (ch) {
+ // case ICharacterScanner.EOF:
+ // break loop;
+ //
+ // case '%': // --% --%>
+ // ch = read();
+ // switch (ch) {
+ // case ICharacterScanner.EOF:
+ // case '>':
+ // break loop;
+ // }
+ //
+ // continue loop;
+ //
+ // case '-': // --- ---%>
+ // unread();
+ // continue loop;
+ // }
+ //
+ // ch = read();
+ // continue loop;
+ // }
+ // }
+ //
+ // ch = read();
+ // }
+ //
+ // return getToken(JSP_COMMENT);
+ // }
+
+ private IToken getToken(String type) {
+ length = position - offset;
+
+ if (length == 0) {
+ return Token.EOF;
+ }
+
+ if (type == null) {
+ return Token.UNDEFINED;
+ }
+
+ IToken token = (IToken) tokens.get(type);
+ if (token == null) {
+ token = new Token(type);
+ tokens.put(type, token);
+ }
+
+ return token;
+ }
+
+ private int read() {
+ if (position >= end) {
+ return ICharacterScanner.EOF;
+ }
+
+ try {
+ return document.getChar(position++);
+ } catch (BadLocationException e) {
+ --position;
+ return ICharacterScanner.EOF;
+ }
+ }
+
+ private boolean readUntilEscapedDQ() {
+ // search last double quoted character
+ if (position >= end) {
+ return false;
+ }
+ try {
+ char ch;
+ while (true) {
+ ch = document.getChar(position++);
+ if (ch == '\\') {
+ ch = document.getChar(position++); // ignore escaped character
+ } else if (ch == '"') {
+ return true;
+ }
+ }
+ } catch (BadLocationException e) {
+ --position;
+ }
+ return false;
+ }
+
+ private boolean readUntilEscapedSQ() {
+ // search last single quoted character
+ if (position >= end) {
+ return false;
+ }
+ try {
+ char ch;
+ while (true) {
+ ch = document.getChar(position++);
+ if (ch == '\\') {
+ ch = document.getChar(position++); // ignore escaped character
+ } else if (ch == '\'') {
+ return true;
+ }
+ }
+ } catch (BadLocationException e) {
+ --position;
+ }
+ return false;
+ }
+
+ private void readSingleLine() {
+ if (position >= end) {
+ return;
+ }
+ try {
+ while (document.getChar(position++) != '\n') {
+
+ }
+ } catch (BadLocationException e) {
+ --position;
+ return;
+ }
+ }
+
+ private void readMultiLineComment() {
+ if (position >= end) {
+ return;
+ }
+ try {
+ char ch;
+ while (true) {
+ ch = document.getChar(position++);
+ if (ch == '*') {
+ if (document.getChar(position) == '/') {
+ position++;
+ break;
+ }
+ }
+ }
+ } catch (BadLocationException e) {
+ --position;
+ return;
+ }
+ }
+
+ private void unread() {
+ --position;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenOffset()
+ */
+ public int getTokenOffset() {
+ if (AbstractPartitioner.DEBUG) {
+ Assert.isTrue(offset >= 0, Integer.toString(offset));
+ }
+ return offset;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenLength()
+ */
+ public int getTokenLength() {
+ return length;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.ITokenScanner#setRange(IDocument, int, int)
+ */
+ public void setRange(IDocument document, int offset, int length) {
+ this.document = document;
+ this.begin = offset;
+ this.end = offset + length;
+
+ this.offset = offset;
+ this.position = offset;
+ this.length = 0;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.IPartitionTokenScanner
+ */
+ public void setPartialRange(IDocument document, int offset, int length, String contentType, int partitionOffset) {
+ state = STATE_DEFAULT;
+ // if (partitionOffset > -1) {
+ // int delta= offset - partitionOffset;
+ // if (delta > 0) {
+ // this.setRange(document, partitionOffset, length + delta);
+ // return;
+ // }
+ // }
+ setRange(document, partitionOffset, length);
+ }
+
+ // private boolean isContinuationPartition(IDocument document, int offset) {
+ // try {
+ // String type = document.getContentType(offset - 1);
+ //
+ // if (type != IDocument.DEFAULT_CONTENT_TYPE) {
+ // return true;
+ // }
+ // } catch (BadLocationException e) {}
+ //
+ // return false;
+ // }
+}
\ No newline at end of file