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..5d25697 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,453 @@ /********************************************************************** -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.33 2005-10-10 19:56:02 axelcl Exp $ + **********************************************************************/ 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.compiler.parser.Scanner; +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.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. + * + * + * @author Igor Malinin */ -public class PHPPartitionScanner extends RuleBasedPartitionScanner { - - 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$ - - 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); - - protected final static char[] php0EndSequence = { '<', '?' }; - protected final static char[] php1EndSequence = { '<', '?', 'p', 'h', 'p' }; - protected final static char[] php2EndSequence = { '<', '?', 'P', 'H', 'P' }; - - private StringBuffer test; - - public class PHPMultiLineRule extends MultiLineRule { - - public PHPMultiLineRule(String startSequence, String endSequence, IToken token) { - super(startSequence, endSequence, token); - } - - public PHPMultiLineRule(String startSequence, String endSequence, IToken token, char escapeCharacter) { - super(startSequence, endSequence, token, escapeCharacter); - } - - 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; - } - } - 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; - } - } - 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(); - } - } - - continue; - } else { - scanner.unread(); - } - } else if (c == '"') { - // string mode - while ((c = scanner.read()) != ICharacterScanner.EOF) { - if (c == '\\') { - c = scanner.read(); - } else if (c == '"') { - break; - } - } - continue; - } else if (c == '\'') { - // string mode - while ((c = scanner.read()) != ICharacterScanner.EOF) { - if (c == '\\') { - c = scanner.read(); - } else if (c == '\'') { - break; - } - } - continue; - } - - 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; - } - } - } - boolean phpMode = false; - if (c == ICharacterScanner.EOF) { - phpMode = true; - } - scanner.unread(); - return phpMode; - } - } - - // 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 == '/'); -// } -// }; - - /** - * - */ -// 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 php = new Token(PHP); - // IToken html = new Token(HTML); - // IToken comment = new Token(HTML_MULTILINE_COMMENT); - - 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 HTMLMultiLineRule("<", "", 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)); - - // rules.add(new HTMLPatternRule(html)); // "<", "': + // state = STATE_DEFAULT; + return getToken(token); + + case '?': + continue; + default: + continue; + } + } + + ch = read(); + } + } + + private IToken getToken(String type) { + length = position - offset; + + if (length == 0) { + return Token.EOF; + } + + // if (length<0) { + // try { + // System.out.println("Length<0:"+document.get(offset,5)+""+length); + // } catch (BadLocationException e) { + // e.printStackTrace(); + // } + // } + + 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 + try { + char ch; + while (true) { + if (position >= end) { + return false; + } + ch = document.getChar(position++); + if (ch == '\\') { + if (position >= end) { + return false; + } + 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 + try { + char ch; + while (true) { + if (position >= end) { + return false; + } + ch = document.getChar(position++); + if (ch == '\\') { + if (position >= end) { + return false; + } + ch = document.getChar(position++); // ignore escaped character + } else if (ch == '\'') { + return true; + } + } + } catch (BadLocationException e) { + --position; + } + return false; + } + + private boolean readUntilEscapedHEREDOC() { + // search until heredoc ends + try { + char ch; + StringBuffer buf = new StringBuffer(); + char[] heredocIdent; + if (position >= end) { + return false; + } + ch = document.getChar(position++); + if (!Scanner.isPHPIdentifierStart(ch)) { + return false; + } + while (Scanner.isPHPIdentifierPart(ch)) { + buf.append(ch); + if (position >= end) { + return false; + } + ch = document.getChar(position++); + } + heredocIdent = buf.toString().toCharArray(); + while (true) { + if (position >= end) { + return false; + } + ch = document.getChar(position++); + if (ch == '\n') { // heredoc could end after a newline + int pos = 0; + while (true) { + if (position >= end) { + return false; + } + if (pos == heredocIdent.length) { + return true; + } + ch = document.getChar(position++); // ignore escaped character + if (ch != heredocIdent[pos]) { + break; + } + pos++; + } + } + } + } catch (BadLocationException e) { + --position; + } + return false; + } + + private boolean readSingleLine() { + try { + do { + if (position >= end) { + return false; + } + } while (document.getChar(position++) != '\n'); + return true; + } catch (BadLocationException e) { + --position; + } + return false; + } + + private boolean readMultiLineComment() { + try { + char ch; + while (true) { + if (position >= end) { + return false; + } + ch = document.getChar(position++); + if (ch == '*') { + if (position >= end) { + return false; + } + if (document.getChar(position) == '/') { + position++; + return true; + } + } + } + } catch (BadLocationException e) { + --position; + } + return false; + } + + 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) { + 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