/** * This file Copyright (c) 2005-2008 Aptana, Inc. This program is * dual-licensed under both the Aptana Public License and the GNU General * Public license. You may elect to use one or the other of these licenses. * * This program is distributed in the hope that it will be useful, but * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or * NONINFRINGEMENT. Redistribution, except as permitted by whichever of * the GPL or APL you select, is prohibited. * * 1. For the GPL license (GPL), you can redistribute and/or modify this * program under the terms of the GNU General Public License, * Version 3, as published by the Free Software Foundation. You should * have received a copy of the GNU General Public License, Version 3 along * with this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Aptana provides a special exception to allow redistribution of this file * with certain other free and open source software ("FOSS") code and certain additional terms * pursuant to Section 7 of the GPL. You may view the exception and these * terms on the web at http://www.aptana.com/legal/gpl/. * * 2. For the Aptana Public License (APL), this program and the * accompanying materials are made available under the terms of the APL * v1.0 which accompanies this distribution, and is available at * http://www.aptana.com/legal/apl/. * * You may view the GPL, Aptana's exception and additional terms, and the * APL in the file titled license.html at the root of the corresponding * plugin containing this source file. * * Any modifications to this file must keep this entire header intact. */ package com.aptana.ide.lexer; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; /** * @author Kevin Lindsey */ public class TokenList implements ITokenList { private static final String[] NO_STRINGS = new String[0]; private String _language; private List<IToken> _tokens; private int[] _ignoreSet; private String _currentGroupName; private IEnumerationMap _categories; private IEnumerationMap _types; private Map<String,Integer> _groups; private Map<Integer,String> _groupByIndex; private boolean _isSealed; /** * TokenList * * @param language */ public TokenList(String language) { this(); this._language = language; this._currentGroupName = ""; //$NON-NLS-1$ } /** * TokenList */ public TokenList() { this._tokens = new ArrayList<IToken>(); this._groups = new HashMap<String,Integer>(); this._groupByIndex = new HashMap<Integer,String>(); } /** * getCategoryMap * * @return IEnumerationMap or null */ public IEnumerationMap getCategoryMap() { return this._categories; } /** * setCategoryMap * * @param map */ public void setCategoryMap(IEnumerationMap map) { this._categories = map; } /** * getTypeMap * * @return IEnumerationMap or null */ public IEnumerationMap getTypeMap() { return this._types; } /** * setTypeMap * * @param map */ public void setTypeMap(IEnumerationMap map) { this._types = map; } /** * getTokenCategoriesByName * * @return String[] */ public String[] getTokenCategoriesByName() { String[] result = NO_STRINGS; if (this._categories != null) { result = this._categories.getNames(); } return result; } /** * getTokenTypesByName * * @return String[] */ public String[] getTokenTypesByName() { String[] result = NO_STRINGS; if (this._types != null) { result = this._types.getNames(); } return result; } /** * Get the lexer group for the associated index * * @param index * The index of the lexer group to look up * @return The name of the lexer group at the specified index */ public String getGroup(int index) { String result = ""; //$NON-NLS-1$ if (this._groupByIndex.containsKey(index)) { result = this._groupByIndex.get(index); } return result; } /** * Get the number of lexer groups used in this list * * @return The lexer group count */ protected int getGroupCount() { return this._groups.size(); } /** * getGroupIndex * * @param groupName * @return int */ protected int getGroupIndex(String groupName) { int result = -1; if (this._groups.containsKey(groupName)) { result = this._groups.get(groupName); } return result; } /** * setGroupIndex * * @param groupName * @param index */ protected void setGroupIndex(String groupName, int index) { this._groups.put(groupName, index); this._groupByIndex.put(index, groupName); } /** * @see com.aptana.ide.lexer.ITokenList#seal() */ public void seal() throws LexerException { this.setSealed(); // seal all tokens for (int i = 0; i < this._tokens.size(); i++) { IToken token = this.get(i); token.seal(); } } /** * setSealed */ protected void setSealed() { this._isSealed = true; } /** * @see com.aptana.ide.lexer.ITokenList#get(int) */ public IToken get(int index) { return this._tokens.get(index); } /** * @see com.aptana.ide.lexer.ITokenList#getCurrentGroup() */ public String getCurrentGroup() { return this._currentGroupName; } /** * @see com.aptana.ide.lexer.ITokenList#setCurrentGroup(java.lang.String) */ public void setCurrentGroup(String groupName) throws LexerException { this._currentGroupName = groupName; } /** * @see com.aptana.ide.lexer.ITokenList#setCurrentGroup(int) */ public void setCurrentGroup(int index) { String groupName = this._groupByIndex.get(index); if (groupName != null) { this._currentGroupName = groupName; } } /** * @see com.aptana.ide.lexer.ITokenList#getGroupNames() */ public String[] getGroupNames() { Set<String> keys = this._groups.keySet(); return keys.toArray(new String[keys.size()]); } /** * @see com.aptana.ide.lexer.ITokenList#getIgnoreSet() */ public int[] getIgnoreSet() { return this._ignoreSet; } /** * @see com.aptana.ide.lexer.ITokenList#setIgnoreSet(int[]) */ public void setIgnoreSet(int[] set) { if (set != null) { Arrays.sort(set); } this._ignoreSet = set; } /** * @see com.aptana.ide.lexer.ITokenList#getLanguage() */ public String getLanguage() { return this._language; } /** * Set this list's language type * * @param language * The language type this list represents */ protected void setLanguage(String language) { this._language = language; } /** * internalAdd * * @param token */ protected void internalAdd(IToken token) { this._tokens.add(token); } /** * add * * @param category * @param type * @param displayName * @return token index */ public int add(String category, String type, String displayName) { IToken token = this.createToken(); token.setCategory(category); token.setType(type); token.setDisplayName(displayName); return this.add(token); } /** * add * * @param category * @param type * @param displayName * @param group * @return token index */ public int add(String category, String type, String displayName, String group) { IToken token = this.createToken(); token.setCategory(category); token.setType(type); token.setDisplayName(displayName); token.setLexerGroup(group); token.setNewLexerGroup(group); return this.add(token); } /** * add * * @param category * @param type * @param displayName * @param group * @param newGroup * @return token index */ public int add(String category, String type, String displayName, String group, String newGroup) { IToken token = this.createToken(); token.setCategory(category); token.setType(type); token.setDisplayName(displayName); token.setLexerGroup(group); token.setNewLexerGroup(newGroup); return this.add(token); } /** * @see com.aptana.ide.lexer.ITokenList#add(com.aptana.ide.lexer.IToken) */ public int add(IToken token) { String category = token.getCategory(); String type = token.getType(); String lexerGroup = token.getLexerGroup(); String newLexerGroup = token.getNewLexerGroup(); // set token's category index int categoryIndex = this._categories.getIntValue(category); if (categoryIndex == -1) { String message = MessageFormat.format(Messages.TokenList_Category_Not_Defined, new Object[] { category }); throw new IllegalArgumentException(message); } token.setCategoryIndex(categoryIndex); // set token's type index int typeIndex = this._types.getIntValue(type); if (typeIndex == -1) { String message = MessageFormat.format(Messages.TokenList_Type_Not_Defined, new Object[] { type }); throw new IllegalArgumentException(message); } token.setTypeIndex(typeIndex); // determine token's lexer group index if (this._groups.containsKey(lexerGroup)) { int groupIndex = this._groups.get(lexerGroup).intValue(); token.setLexerGroupIndex(groupIndex); } else { int groupIndex = this._groups.size(); this.setGroupIndex(lexerGroup, groupIndex); token.setLexerGroupIndex(groupIndex); } // determine token's new lexer group index if (this._groups.containsKey(newLexerGroup)) { int newGroupIndex = this._groups.get(newLexerGroup).intValue(); token.setNewLexerGroupIndex(newGroupIndex); } else { int newGroupIndex = this._groups.size(); this.setGroupIndex(newLexerGroup, newGroupIndex); token.setNewLexerGroupIndex(newGroupIndex); } // add token to our list this.internalAdd(token); // set index token.setIndex(this._tokens.size() - 1); // return new token index return token.getIndex(); } /** * @see com.aptana.ide.lexer.ITokenList#size() */ public int size() { return this._tokens.size(); } /** * @see com.aptana.ide.lexer.ITokenList#isSealed() */ public boolean isSealed() { return this._isSealed; } /** * @see com.aptana.ide.lexer.ITokenList#createToken() */ public IToken createToken() { return new Token(this); } /** * @see com.aptana.ide.lexer.ITokenList#hasGroup() */ public boolean hasGroup(String groupName) { Set<String> keys = this._groups.keySet(); return keys.contains(groupName); } }