/******************************************************************************* * Copyright (c) 2006, 2015 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 java.util.List; 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 List<String> reservedWords = new ArrayList<>(); { reservedWords.add("#"); reservedWords.add("A"); reservedWords.add("a"); reservedWords.add("n"); } /* * ...and their corresponding regular expressions */ private static List<String> 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 = 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; } }