X-Git-Url: http://secure.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/php/PHPPartitionScanner.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/php/PHPPartitionScanner.java index c15249b..2cb2eb9 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/php/PHPPartitionScanner.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/php/PHPPartitionScanner.java @@ -1,573 +1,504 @@ -/********************************************************************** -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 -**********************************************************************/ +/** + * 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 + * Created on 05.03.2003 + * + * @author Stefan Langer (musk) + * @version $Revision: 1.24 $ + */ package net.sourceforge.phpeclipse.phpeditor.php; import java.util.ArrayList; -import java.util.List; +import java.util.HashMap; +import java.util.Map; + +import net.sourceforge.phpdt.internal.ui.text.*; +import org.eclipse.jface.text.Assert; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITypedRegion; import org.eclipse.jface.text.rules.ICharacterScanner; -import org.eclipse.jface.text.rules.IPredicateRule; +import org.eclipse.jface.text.rules.IPartitionTokenScanner; import org.eclipse.jface.text.rules.IToken; -import org.eclipse.jface.text.rules.MultiLineRule; -import org.eclipse.jface.text.rules.RuleBasedPartitionScanner; import org.eclipse.jface.text.rules.Token; /** - * This scanner recognizes the JavaDoc comments and Java multi line comments. + * */ -public class PHPPartitionScanner extends RuleBasedPartitionScanner { +public class PHPPartitionScanner implements IPartitionTokenScanner { + private static final boolean DEBUG = false; - private final static String SKIP = "__skip"; //$NON-NLS-1$ - public final static String HTML_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"; //$NON-NLS-1$ - //public final static String HTML = "__html"; //$NON-NLS-1$ + private boolean fInString = false; + private boolean fInDoubString = false; + private IDocument fDocument = null; + private int fOffset = -1; + private String fContentType = IPHPPartitions.HTML; + private String fPrevContentType = IPHPPartitions.HTML; + private boolean partitionBorder = false; + private int fTokenOffset; + private int fEnd = -1; + private int fLength; + private int fCurrentLength; + private int fFileType; + private Map tokens = new HashMap(); - public final static IToken php = new Token(PHP); - //public final static IToken html = new Token(HTML); - public final static IToken comment = new Token(HTML_MULTILINE_COMMENT); + public PHPPartitionScanner() { + this(IPHPPartitions.PHP_FILE); + } + + public PHPPartitionScanner(int fileType) { + this.tokens.put(IPHPPartitions.PHP_PARTITIONING, new Token(IPHPPartitions.PHP_PARTITIONING)); + this.tokens.put(IPHPPartitions.PHP_STRING_DQ, new Token(IPHPPartitions.PHP_STRING_DQ)); + this.tokens.put( + IPHPPartitions.PHP_PHPDOC_COMMENT, + new Token(IPHPPartitions.PHP_PHPDOC_COMMENT)); + this.tokens.put(IPHPPartitions.HTML, new Token(IPHPPartitions.HTML)); + this.tokens.put( + IPHPPartitions.HTML_MULTILINE_COMMENT, + new Token(IPHPPartitions.HTML_MULTILINE_COMMENT)); - protected final static char[] php0EndSequence = { '<', '?' }; - protected final static char[] php1EndSequence = { '<', '?', 'p', 'h', 'p' }; - protected final static char[] php2EndSequence = { '<', '?', 'P', 'H', 'P' }; + this.tokens.put(IPHPPartitions.SMARTY, new Token(IPHPPartitions.SMARTY)); + this.tokens.put( + IPHPPartitions.SMARTY_MULTILINE_COMMENT, + new Token(IPHPPartitions.SMARTY_MULTILINE_COMMENT)); - private StringBuffer test; + this.tokens.put(IDocument.DEFAULT_CONTENT_TYPE, new Token(IDocument.DEFAULT_CONTENT_TYPE)); + fFileType = fileType; + } - public class PHPMultiLineRule extends MultiLineRule { + private IToken getToken(String type) { + fLength = fCurrentLength; + if (DEBUG) { - public PHPMultiLineRule(String startSequence, String endSequence, IToken token) { - super(startSequence, endSequence, token); + try { + if (fLength <= 0) { + int line = fDocument.getLineOfOffset(fOffset); + System.err.println("Error at " + line + " offset:" + String.valueOf(fOffset - fDocument.getLineOffset(line))); + } + } catch (BadLocationException e) { // should never happen + // TODO Write stacktrace to log + e.printStackTrace(); + } + } + Assert.isTrue(fLength > 0, "Partition length <= 0!"); + fCurrentLength = 0; + // String can never cross partition borders so reset string detection + fInString = false; + fInDoubString = false; + IToken token = (IToken) this.tokens.get(type); + Assert.isNotNull(token, "Token for type \"" + type + "\" not found!"); + if (DEBUG) { + System.out.println("Partition: fTokenOffset=" + fTokenOffset + " fContentType=" + type + " fLength=" + fLength); } + return token; + } - public PHPMultiLineRule(String startSequence, String endSequence, IToken token, char escapeCharacter) { - super(startSequence, endSequence, token, escapeCharacter); + /* (non-Javadoc) + * @see org.eclipse.jface.text.rules.IPartitionTokenScanner#setPartialRange(org.eclipse.jface.text.IDocument, int, int, java.lang.String, int) + */ + public void setPartialRange(IDocument document, int offset, int length, String contentType, int partitionOffset) { + if (DEBUG) { + System.out.println("*****"); + System.out.println("PartialRange: contentType=" + contentType + " partitionOffset=" + partitionOffset); } - protected boolean endSequenceDetected(ICharacterScanner scanner) { - int c; - int c2; - - boolean lineCommentMode = false; - boolean multiLineCommentMode = false; - boolean stringMode = false; - - char[][] delimiters = scanner.getLegalLineDelimiters(); - while ((c = scanner.read()) != ICharacterScanner.EOF) { - if (c == '#') { - // read until end of line - while ((c = scanner.read()) != ICharacterScanner.EOF) { - if (fEndSequence.length > 0 && c == fEndSequence[0]) { - // Check if the specified end sequence has been found. - if (sequenceDetected(scanner, fEndSequence, true)) - return true; - } else if (c == '\n') { - break; - } + try { + if (partitionOffset > -1) { + partitionBorder = false; + // because of strings we have to parse the whole partition + this.setRange(document, partitionOffset, offset - partitionOffset + length); + // sometimes we get a wrong partition so we retrieve the partition + // directly from the document + fContentType = fDocument.getContentType(partitionOffset); + } else + this.setRange(document, offset, length); + + } catch (BadLocationException e) { + // should never happen + // TODO print stack trace to log + // fall back just scan the whole document again + this.setRange(document, 0, fDocument.getLength()); + } + + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenLength() + */ + public int getTokenLength() { + return fLength; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.rules.ITokenScanner#getTokenOffset() + */ + public int getTokenOffset() { + return fTokenOffset; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken() + */ + public IToken nextToken() { + int c; + + // check if we are not allready at the end of the + // file + if ((c = read()) == ICharacterScanner.EOF) { + partitionBorder = false; + return Token.EOF; + } else + unread(); + + if (partitionBorder) { + fTokenOffset = fOffset; + partitionBorder = false; + } + + while ((c = read()) != ICharacterScanner.EOF) { + switch (c) { + case '<' : + if (!isInString(IPHPPartitions.PHP_PARTITIONING) + && fContentType != IPHPPartitions.PHP_PHPDOC_COMMENT + && checkPattern(new char[] { '?', 'p', 'h', 'p' }, true)) { + if (fContentType != IPHPPartitions.PHP_PARTITIONING && fCurrentLength > 5) { + unread(5); + IToken token = getToken(fContentType); + // save previouse contenttype + //TODO build stack for previouse contenttype + fPrevContentType = fContentType; + + fContentType = IPHPPartitions.PHP_PARTITIONING; + + return token; + } else + fContentType = IPHPPartitions.PHP_PARTITIONING; + + // remember offset of this partition + fTokenOffset = fOffset - 5; + fCurrentLength = 5; + } else if ( + !isInString(IPHPPartitions.PHP_PARTITIONING) + && fContentType != IPHPPartitions.PHP_PHPDOC_COMMENT + && checkPattern(new char[] { '?' }, false)) { + if (fContentType != IPHPPartitions.PHP_PARTITIONING && fCurrentLength > 2) { + unread(2); + IToken token = getToken(fContentType); + // save previouse contenttype + fPrevContentType = fContentType; + fContentType = IPHPPartitions.PHP_PARTITIONING; + return token; + } else + fContentType = IPHPPartitions.PHP_PARTITIONING; + // remember offset of this partition + fTokenOffset = fOffset - 2; + fCurrentLength = 2; + } else if ( + !isInString(IPHPPartitions.PHP_PARTITIONING) + && (fContentType != IPHPPartitions.PHP_PARTITIONING) // BUG #769044 + && (fContentType != IPHPPartitions.PHP_PHPDOC_COMMENT) // BUG #769044 + && checkPattern(new char[] { '!', '-', '-' })) { // return previouse partition + if (fContentType != IPHPPartitions.HTML_MULTILINE_COMMENT && fCurrentLength > 4) { + unread(4); + IToken token = getToken(fContentType); + fContentType = IPHPPartitions.HTML_MULTILINE_COMMENT; + return token; + } else + fContentType = IPHPPartitions.HTML_MULTILINE_COMMENT; + + fTokenOffset = fOffset - 4; + fCurrentLength = 4; + } + break; + case '?' : + if (!isInString(IPHPPartitions.PHP_PARTITIONING) && fContentType == IPHPPartitions.PHP_PARTITIONING) { + if ((c = read()) == '>') { + if (fPrevContentType != null) + fContentType = fPrevContentType; + else + fContentType = IPHPPartitions.HTML; + partitionBorder = true; + return getToken(IPHPPartitions.PHP_PARTITIONING); + } else if (c != ICharacterScanner.EOF) + unread(); } - continue; - } else if (c == '/' && (c = scanner.read()) != ICharacterScanner.EOF) { - if (c == '/') { - // read until end of line - while ((c = scanner.read()) != ICharacterScanner.EOF) { - if (fEndSequence.length > 0 && c == fEndSequence[0]) { - // Check if the specified end sequence has been found. - if (sequenceDetected(scanner, fEndSequence, true)) - return true; - } else if (c == '\n') { - break; + break; + case '-' : + if (!isInString(IPHPPartitions.PHP_PARTITIONING) + && fContentType == IPHPPartitions.HTML_MULTILINE_COMMENT + && checkPattern(new char[] { '-', '>' })) { + fContentType = IPHPPartitions.HTML; + partitionBorder = true; + return getToken(IPHPPartitions.HTML_MULTILINE_COMMENT); + } + break; + case '{' : // SMARTY code starts here ? + if (fFileType == IPHPPartitions.SMARTY_FILE) { + if ((c = read()) == '*') { + if (DEBUG) { + System.out.println( + "SMARTYDOC_TOKEN start " + + fTokenOffset + + " fContentType=" + + fContentType + + " fLength=" + + fLength + + " fOffset=" + + fOffset + + " fCurrentLength=" + + fCurrentLength); } - } - continue; - } else if (c == '*') { - // multi-line comment - while ((c = scanner.read()) != ICharacterScanner.EOF) { - if (c == '*' && (c = scanner.read()) != ICharacterScanner.EOF) { - if (c == '/') { - break; - } - scanner.unread(); + if (fContentType != IPHPPartitions.SMARTY_MULTILINE_COMMENT && fCurrentLength > 2) { + // SMARTY doc code starts here + unread(2); + IToken token = getToken(fContentType); + fContentType = IPHPPartitions.SMARTY_MULTILINE_COMMENT; + return token; + // } else if (fContentType == IPHPPartitionScannerConstants.HTML && fOffset == 2) { + // fContentType = IPHPPartitionScannerConstants.SMARTY_MULTILINE_COMMENT; + } else { // if (fContentType == IPHPPartitionScannerConstants.SMARTY_MULTILINE_COMMENT) { + fContentType = IPHPPartitions.SMARTY_MULTILINE_COMMENT; + fTokenOffset = fOffset - 2; + fCurrentLength = 2; } - } - - continue; - } else { - scanner.unread(); - } - } else if (c == '"') { - // string mode - while ((c = scanner.read()) != ICharacterScanner.EOF) { - if (c == '\\') { - c = scanner.read(); - } else if (c == '"') { break; } + if (DEBUG) { + System.out.println( + "SMARTY_TOKEN start " + + fTokenOffset + + " fContentType=" + + fContentType + + " fLength=" + + fLength + + " fOffset=" + + fOffset); + } + if (c != ICharacterScanner.EOF) { + unread(); + } + if (fContentType != IPHPPartitions.SMARTY && fCurrentLength > 1) { + unread(1); + IToken token = getToken(fContentType); + fContentType = IPHPPartitions.SMARTY; + return token; + // } else if (fContentType == IPHPPartitionScannerConstants.HTML && fOffset==1) { + // fContentType = IPHPPartitionScannerConstants.SMARTY; + } else { + fContentType = IPHPPartitions.SMARTY; + fTokenOffset = fOffset - 1; + fCurrentLength = 1; + } } - continue; - } else if (c == '\'') { - // string mode - while ((c = scanner.read()) != ICharacterScanner.EOF) { - if (c == '\\') { - c = scanner.read(); - } else if (c == '\'') { - break; + break; + case '}' : // SMARTY code ends here ? + if (fFileType == IPHPPartitions.SMARTY_FILE && fContentType == IPHPPartitions.SMARTY) { + if (DEBUG) { + System.out.println( + "SMARTY_TOKEN end " + + fTokenOffset + + " fContentType=" + + fContentType + + " fLength=" + + fLength + + " fOffset=" + + fOffset); } + fContentType = IPHPPartitions.HTML; + partitionBorder = true; + return getToken(IPHPPartitions.SMARTY); } - continue; - } + break; + case '/' : + if (!isInString(IPHPPartitions.PHP_PARTITIONING) && (c = read()) == '*') { // MULTINE COMMENT JAVASCRIPT, CSS, PHP + if (fContentType == IPHPPartitions.PHP_PARTITIONING && fCurrentLength > 2) { + unread(2); + IToken token = getToken(fContentType); + fContentType = IPHPPartitions.PHP_PHPDOC_COMMENT; + return token; + } else if (fContentType == IPHPPartitions.PHP_PHPDOC_COMMENT) { + fTokenOffset = fOffset - 2; + fCurrentLength = 2; + } - if (c == fEscapeCharacter) { - // Skip the escaped character. - scanner.read(); - } else if (fEndSequence.length > 0 && c == fEndSequence[0]) { - // Check if the specified end sequence has been found. - if (sequenceDetected(scanner, fEndSequence, true)) - return true; - } else if (fBreaksOnEOL) { - // Check for end of line since it can be used to terminate the pattern. - for (int i = 0; i < delimiters.length; i++) { - if (c == delimiters[i][0] && sequenceDetected(scanner, delimiters[i], false)) - return true; + } else if (!isInString(IPHPPartitions.PHP_PARTITIONING) && c != ICharacterScanner.EOF) + unread(); + break; + case '*' : + if (!isInString(IPHPPartitions.PHP_PARTITIONING) && (c = read()) == '/') { + if (fContentType == IPHPPartitions.PHP_PHPDOC_COMMENT) { + fContentType = IPHPPartitions.PHP_PARTITIONING; + partitionBorder = true; + return getToken(IPHPPartitions.PHP_PHPDOC_COMMENT); + } else if (fContentType == IPHPPartitions.CSS_MULTILINE_COMMENT) { + } else if (fContentType == IPHPPartitions.JS_MULTILINE_COMMENT) { + } + } else if (fFileType == IPHPPartitions.SMARTY_FILE && (c = read()) == '}') { + if (DEBUG) { + System.out.println( + "SMARTYDOC_TOKEN end " + + fTokenOffset + + " fContentType=" + + fContentType + + " fLength=" + + fLength + + " fOffset=" + + fOffset); + } + if (fContentType == IPHPPartitions.SMARTY_MULTILINE_COMMENT) { + fContentType = IPHPPartitions.HTML; + partitionBorder = true; + return getToken(IPHPPartitions.SMARTY_MULTILINE_COMMENT); + } + } else if (!isInString(IPHPPartitions.PHP_PARTITIONING) && c != ICharacterScanner.EOF) { + unread(); } - } - } - boolean phpMode = false; - if (c == ICharacterScanner.EOF) { - phpMode = true; + break; + case '\'' : + if (!fInDoubString) + fInString = !fInString; + break; + case '"' : + // toggle String mode + if (!fInString) + fInDoubString = !fInDoubString; + break; } - scanner.unread(); - return phpMode; + } // end of file reached but we have to return the + // last partition. + return getToken(fContentType); + } + /* (non-Javadoc) + * @see org.eclipse.jface.text.rules.ITokenScanner#setRange(org.eclipse.jface.text.IDocument, int, int) + */ + public void setRange(IDocument document, int offset, int length) { + if (DEBUG) { + System.out.println("SET RANGE: offset=" + offset + " length=" + length); } + + fDocument = document; + fOffset = offset; + fTokenOffset = offset; + fCurrentLength = 0; + fLength = 0; + fEnd = fOffset + length; + fInString = false; + fInDoubString = false; + fContentType = IPHPPartitions.HTML; + // String[] prev = getPartitionStack(offset); } - // public class HTMLMultiLineRule extends MultiLineRule { - // - // public HTMLMultiLineRule(String startSequence, String endSequence, IToken token) { - // super(startSequence, endSequence, token); - // } - // - // public HTMLMultiLineRule(String startSequence, String endSequence, IToken token, char escapeCharacter) { - // super(startSequence, endSequence, token, escapeCharacter); - // } - // - // protected boolean endSequenceDetected(ICharacterScanner scanner) { - // int c; - // - // char[][] delimiters = scanner.getLegalLineDelimiters(); - // while ((c = scanner.read()) != ICharacterScanner.EOF) { - // if (c == '<') { - // // scanner.unread(); - // if (sequenceDetected(scanner, php2EndSequence, true)) { - // // null is a legal value -// * @param token the token which will be returned on success -// * @param escapeCharacter any character following this one will be ignored -// * @param indicates whether the end of the line also termines the pattern -// */ -// public HTMLPatternRule(IToken token) { -// fToken = token; -// fEscapeCharacter = (char) 0; -// fBreaksOnEOL = false; -// } -// -// /** -// * Sets a column constraint for this rule. If set, the rule's token -// * will only be returned if the pattern is detected starting at the -// * specified column. If the column is smaller then 0, the column -// * constraint is considered removed. -// * -// * @param column the column in which the pattern starts -// */ -// public void setColumnConstraint(int column) { -// if (column < 0) -// column = UNDEFINED; -// fColumn = column; -// } -// -// /** -// * Evaluates this rules without considering any column constraints. -// * -// * @param scanner the character scanner to be used -// * @return the token resulting from this evaluation -// */ -// protected IToken doEvaluate(ICharacterScanner scanner) { -// return doEvaluate(scanner, false); -// } -// -// /** -// * Evaluates this rules without considering any column constraints. Resumes -// * detection, i.e. look sonly for the end sequence required by this rule if the -// * resume flag is set. -// * -// * @param scanner the character scanner to be used -// * @param resume true if detection should be resumed, false otherwise -// * @return the token resulting from this evaluation -// * @since 2.0 -// */ -// protected IToken doEvaluate(ICharacterScanner scanner, boolean resume) { -// -// if (resume) { -// -// if (endSequenceDetected(scanner)) -// return fToken; -// -// } else { -// -// int c = scanner.read(); -// // if (c == fStartSequence[0]) { -// // if (sequenceDetected(scanner, fStartSequence, false)) { -// if (endSequenceDetected(scanner)) -// return fToken; -// // } -// // } -// } -// -// scanner.unread(); -// return Token.UNDEFINED; -// } -// -// /* -// * @see IRule#evaluate -// */ -// public IToken evaluate(ICharacterScanner scanner) { -// return evaluate(scanner, false); -// } -// -// /** -// * Returns whether the end sequence was detected. As the pattern can be considered -// * ended by a line delimiter, the result of this method is true if the -// * rule breaks on the end of the line, or if the EOF character is read. -// * -// * @param scanner the character scanner to be used -// * @return true if the end sequence has been detected -// */ -// protected boolean endSequenceDetected(ICharacterScanner scanner) { -// int c; -// -// char[][] delimiters = scanner.getLegalLineDelimiters(); -// while ((c = scanner.read()) != ICharacterScanner.EOF) { -// if (c == '<') { -// // scanner.unread(); -// if (sequenceDetected(scanner, php2EndSequence, true)) { -// // true if the given sequence has been detected -// */ -// protected boolean sequenceDetected(ICharacterScanner scanner, char[] sequence, boolean eofAllowed) { -// for (int i = 1; i < sequence.length; i++) { -// int c = scanner.read(); -// if (c == ICharacterScanner.EOF && eofAllowed) { -// return true; -// } else if (c != sequence[i]) { -// // Non-matching character detected, rewind the scanner back to the start. -// scanner.unread(); -// for (int j = i - 1; j > 0; j--) -// scanner.unread(); -// return false; -// } -// } -// -// return true; -// } -// -// /* -// * @see IPredicateRule#evaluate(ICharacterScanner, boolean) -// * @since 2.0 -// */ -// public IToken evaluate(ICharacterScanner scanner, boolean resume) { -// if (fColumn == UNDEFINED) -// return doEvaluate(scanner, resume); -// -// int c = scanner.read(); -// scanner.unread(); -// // if (c == fStartSequence[0]) -// return (fColumn == scanner.getColumn() ? doEvaluate(scanner, resume) : Token.UNDEFINED); -// // else -// // return Token.UNDEFINED; -// } -// -// /* -// * @see IPredicateRule#getSuccessToken() -// * @since 2.0 -// */ -// public IToken getSuccessToken() { -// return fToken; -// } -// } - /** - * 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 == '/'); -// } -// }; + private int read() { + try { + if (fOffset < fEnd) { + fCurrentLength++; + return fDocument.getChar(fOffset++); + } + return ICharacterScanner.EOF; + } catch (BadLocationException e) { + // should never happen + // TODO write stacktrace to log + fOffset = fEnd; + return ICharacterScanner.EOF; + } + } - /** - * - */ -// 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; -// } -// }; + private void unread() { + --fOffset; + --fCurrentLength; + } + + private void unread(int num) { + fOffset -= num; + fCurrentLength -= num; + } + + private boolean checkPattern(char[] pattern) { + return checkPattern(pattern, false); + } /** - * Creates the partitioner and sets up the appropriate rules. + * Check if next character sequence read from document is equals to + * the provided pattern. Pattern is read from left to right until the + * first character read doesn't match. If this happens all read characters are + * unread. + * @param pattern The pattern to check. + * @return true if pattern is equals else returns false. */ - public PHPPartitionScanner() { - super(); - - // IToken php = new Token(PHP); - // IToken html = new Token(HTML); - // IToken comment = new Token(HTML_MULTILINE_COMMENT); + private boolean checkPattern(char[] pattern, boolean ignoreCase) { + int prevOffset = fOffset; + int prevLength = fCurrentLength; + for (int i = 0; i < pattern.length; i++) { + int c = read(); - List rules = new ArrayList(); + if (c == ICharacterScanner.EOF || !letterEquals(c, pattern[i], ignoreCase)) { + fOffset = prevOffset; + fCurrentLength = prevLength; + return false; + } + } - // Add rule for single line comments. - // rules.add(new EndOfLineRule("//", Token.UNDEFINED)); + return true; + } - // Add rule for strings and character constants. - // rules.add(new SingleLineRule("\"", "\"", Token.UNDEFINED, '\\')); - // rules.add(new SingleLineRule("'", "'", Token.UNDEFINED, '\\')); + private boolean letterEquals(int test, char letter, boolean ignoreCase) { + if (test == letter) + return true; + else if (ignoreCase && Character.isLowerCase(letter) && test == Character.toUpperCase(letter)) + return true; + else if (ignoreCase && Character.isUpperCase(letter) && test == Character.toLowerCase(letter)) + return true; - // Add special case word rule. - // rules.add(new WordPredicateRule(comment)); + return false; + } - // Add rules for multi-line comments and javadoc. - //rules.add(new MultiLineRule("/**", "*/", javaDoc)); - // rules.add(new HTMLMultiLineRule("<", "String and the specified + * contenttype is the current content type. + * Strings are delimited, mutual exclusive, by a " or by a '. + * + * @param contentType The contenttype to check. + * @return true if the current offset is in a string else + * returns false. + */ + private boolean isInString(String contentType) { + if (fContentType == contentType) + return (fInString || fInDoubString); + else + return false; + } - rules.add(new MultiLineRule("", comment)); - rules.add(new PHPMultiLineRule("", php)); - rules.add(new PHPMultiLineRule("", php)); - rules.add(new PHPMultiLineRule("", php)); - rules.add(new PHPMultiLineRule("", php)); - rules.add(new PHPMultiLineRule("", php)); - rules.add(new PHPMultiLineRule("", php)); + /** + * Returns the previouse partition stack for the given offset. + * + * @param offset The offset to return the previouse partitionstack for. + * + * @return The stack as a string array. + */ + private String[] getPartitionStack(int offset) { + ArrayList types = new ArrayList(); + int tmpOffset = 0; + try { + ITypedRegion region = fDocument.getPartition(offset); + tmpOffset = region.getOffset(); + while (tmpOffset - 1 > 0) { + region = fDocument.getPartition(tmpOffset - 1); + tmpOffset = region.getOffset(); + types.add(0, region.getType()); + } + } catch (BadLocationException e) { + if (DEBUG) { + e.printStackTrace(); + } + } - // rules.add(new HTMLPatternRule(html)); // "<", "