blob: d9c61b4961fb8eb653772f1e45b5d0adc63aaedc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 The Pampered Chef and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* The Pampered Chef - initial API and implementation
******************************************************************************/
package org.eclipse.jface.examples.databinding.mask.internal;
import java.util.ArrayList;
import org.eclipse.jface.examples.databinding.mask.EditMaskParseException;
/**
* Lexical analyzer and token for an input mask. Since input masks have exactly
* one token type, we use the same class to be the recognizer and the token
* itself.
*
* @since 3.3
*/
public class EditMaskLexerAndToken {
/*
* First the literals that represent the types of characters
*/
private static ArrayList reservedWords = new ArrayList();{
reservedWords.add("#");
reservedWords.add("A");
reservedWords.add("a");
reservedWords.add("n");
}
/*
* ...and their corresponding regular expressions
*/
private static ArrayList inputRegexes = new ArrayList();{
inputRegexes.add("^[0-9]$");
inputRegexes.add("^[A-Z]$");
inputRegexes.add("^[a-zA-Z]$");
inputRegexes.add("^[0-9a-zA-Z]$");
}
private String charRegex = null; // A regex for matching input characters or null
private String literal = null; // The literal character if charRegex is null
private boolean readOnly;
private String input = null; // The user's input
private boolean recognizeReservedWord(String inputMask, int position) {
String input = inputMask.substring(position, position+1);
for (int reservedWord = 0; reservedWord < reservedWords.size(); reservedWord++) {
if (input.equals(reservedWords.get(reservedWord))) {
charRegex = (String) inputRegexes.get(reservedWord);
literal = null;
input = null;
readOnly = false;
return true;
}
}
return false;
}
private boolean recognizeBackslashLiteral(String inputMask, int position) throws EditMaskParseException {
String input = inputMask.substring(position, position+1);
if (input.equals("\\")) {
try {
input = inputMask.substring(position+1, position+2);
charRegex = null;
this.input = input;
literal = input;
readOnly = true;
return true;
} catch (Throwable t) {
throw new EditMaskParseException("Found a \\ without a character after it: " + inputMask);
}
}
return false;
}
private boolean recognizeLiteral(String inputMask, int position) {
literal = inputMask.substring(position, position+1);
this.input = literal;
charRegex = null;
readOnly = true;
return true;
}
/**
* Initializes itself based on characters in edit mask starting at position;
* returns number of chars consumed
*
* @param inputMask The entire edit mask
* @param position The position to begin parsing
* @return The number of characters consumed
* @throws EditMaskParseException If it encountered a syntax error during the parse
*/
public int initializeEditMask(String inputMask, int position) throws EditMaskParseException {
clear();
if (recognizeReservedWord(inputMask, position)) {
return 1;
}
if (recognizeBackslashLiteral(inputMask, position)) {
return 2;
}
if (!recognizeLiteral(inputMask, position)) {
throw new EditMaskParseException("Should never see this error in this implementation!");
}
readOnly = true;
return 1;
}
/**
* ignores invalid input; stores valid input
* @param inputCharacter
* @return
*/
public boolean accept(String inputCharacter) {
if (readOnly) {
return false;
}
if (literal != null) {
return false;
}
if (!canAcceptMoreCharacters()) {
return false;
}
if (inputCharacter.matches(charRegex)) {
this.input = inputCharacter;
return true;
}
return false;
}
/**
* @return Returns the characters it has accepted. In the current implementation,
* this is exactly one character. Once quantifiers are implemented, this could
* be many characters. If no characters have been accepted, returns null.
*/
public String getInput() {
return input;
}
/**
* Clear any accepted input
*/
public void clear() {
if (!isReadOnly())
input = null;
}
/**
* @return true if it's a literal; false if it's a placeholder
*/
public boolean isReadOnly() {
return readOnly;
}
/**
* @return true if it is a literal or if it has accepted the minimum
* required number of characters
*/
public boolean isComplete() {
if (input != null) {
return true;
}
return false;
}
/**
* @return A position may be complete and yet able to accept more characters if
* the position includes optional characters via a quantifier of some type.
* Not implemented right now.
*/
public boolean canAcceptMoreCharacters() {
return !isComplete();
}
/**
* @return the minimum number of characters this RegexLexer must accept
* in order to be complete. Because we don't yet support quantifiers, this
* is currently always 1.
*/
public int getMinimumLength() {
return 1;
}
}