1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.jface.text.rules;
15 
16 
17 import org.eclipse.core.runtime.Assert;
18 
19 
20 
21 /**
22  * A specific single line rule which stipulates that the start
23  * and end sequence occur within a single word, as defined by a word detector.
24  *
25  * @see IWordDetector
26  */
27 public class WordPatternRule extends SingleLineRule {
28 
29 	/** The word detector used by this rule */
30 	protected IWordDetector fDetector;
31 	/** The internal buffer used for pattern detection */
32 	private StringBuilder fBuffer= new StringBuilder();
33 
34 	/**
35 	 * Creates a rule for the given starting and ending word
36 	 * pattern which, if detected, will return the specified token.
37 	 * A word detector is used to identify words.
38 	 *
39 	 * @param detector the word detector to be used
40 	 * @param startSequence the start sequence of the word pattern
41 	 * @param endSequence the end sequence of the word pattern
42 	 * @param token the token to be returned on success
43 	 */
WordPatternRule(IWordDetector detector, String startSequence, String endSequence, IToken token)44 	public WordPatternRule(IWordDetector detector, String startSequence, String endSequence, IToken token) {
45 		this(detector, startSequence, endSequence, token, (char)0);
46 	}
47 
48 	/**
49 	/**
50 	 * Creates a rule for the given starting and ending word
51 	 * pattern which, if detected, will return the specified token.
52 	 * A word detector is used to identify words.
53 	 * Any character which follows the given escapeCharacter will be ignored.
54 	 *
55 	 * @param detector the word detector to be used
56 	 * @param startSequence the start sequence of the word pattern
57 	 * @param endSequence the end sequence of the word pattern
58 	 * @param token the token to be returned on success
59 	 * @param escapeCharacter the escape character
60 	 */
WordPatternRule(IWordDetector detector, String startSequence, String endSequence, IToken token, char escapeCharacter)61 	public WordPatternRule(IWordDetector detector, String startSequence, String endSequence, IToken token, char escapeCharacter) {
62 		super(startSequence, endSequence, token, escapeCharacter);
63 		Assert.isNotNull(detector);
64 		fDetector= detector;
65 	}
66 
67 	/**
68 	 * Returns whether the end sequence was detected.
69 	 * The rule acquires the rest of the word, using the
70 	 * provided word detector, and tests to determine if
71 	 * it ends with the end sequence.
72 	 *
73 	 * @param scanner the scanner to be used
74 	 * @return <code>true</code> if the word ends on the given end sequence
75 	 */
76 	@Override
endSequenceDetected(ICharacterScanner scanner)77 	protected boolean endSequenceDetected(ICharacterScanner scanner) {
78 		fBuffer.setLength(0);
79 		int c= scanner.read();
80 		while (fDetector.isWordPart((char) c)) {
81 			fBuffer.append((char) c);
82 			c= scanner.read();
83 		}
84 		scanner.unread();
85 
86 		if (fBuffer.length() >= fEndSequence.length) {
87 			for (int i=fEndSequence.length - 1, j= fBuffer.length() - 1; i >= 0; i--, j--) {
88 				if (fEndSequence[i] != fBuffer.charAt(j)) {
89 					unreadBuffer(scanner);
90 					return false;
91 				}
92 			}
93 			return true;
94 		}
95 
96 		unreadBuffer(scanner);
97 		return false;
98 	}
99 
100 	/**
101 	 * Returns the characters in the buffer to the scanner.
102 	 * Note that the rule must also return the characters
103 	 * read in as part of the start sequence expect the first one.
104 	 *
105 	 * @param scanner the scanner to be used
106 	 */
unreadBuffer(ICharacterScanner scanner)107 	protected void unreadBuffer(ICharacterScanner scanner) {
108 		fBuffer.insert(0, fStartSequence);
109 		for (int i= fBuffer.length() - 1; i > 0; i--)
110 			scanner.unread();
111 	}
112 }
113