/** * 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.parsing.matcher; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import com.aptana.ide.lexer.DynamicEnumerationMap; import com.aptana.ide.lexer.IEnumerationMap; import com.aptana.ide.lexer.Lexeme; import com.aptana.ide.parsing.nodes.IParseNode; import com.aptana.ide.parsing.nodes.ParseFragment; import com.aptana.ide.parsing.nodes.ParseNodeBase; import com.aptana.xml.INode; import com.aptana.xml.NodeBase; /** * @author Kevin Lindsey */ public abstract class AbstractLexemeMatcher extends NodeBase implements ILexemeMatcher { private String _node; private ParseFragment _childNodes; private Map<String,String> _attributes; /** * result */ protected IParseNode result; /** * AbstractLexemeMatcher */ public AbstractLexemeMatcher() { this.addChildTypes(); } /** * accept * * @param lexemes * @param startingIndex * @param endingIndex */ protected void accept(Lexeme[] lexemes, int startingIndex, int endingIndex) { if (this._node != null && this._node.length() > 0) { // get starting lexeme Lexeme startingLexeme = lexemes[startingIndex]; // use lexeme's language for node's language String language = startingLexeme.getLanguage(); // calculate the node type index from the node type (name) int type = this.getOwningParser().getNodeTypeIndex(this._node); // create the parse node IParseNode node = new ParseNodeBase(this._node, type, language, startingLexeme); // set the display name node.setName(this._node.toLowerCase()); // include the ending lexeme, if there is one if (startingIndex <= endingIndex - 1) { Lexeme endingLexeme = lexemes[endingIndex - 1]; node.includeLexemeInRange(endingLexeme); } // save the result for potential future appendChild operations from this node's // ancestors this.result = node; // add any accumulated child nodes to the result, if we have any if (this._childNodes != null) { this.result.appendChild(this._childNodes); } } else { // no node definition, so pass along any accumulated nodes from this node's // descendants this.result = this._childNodes; } // add any accumulated attributes if (this.result != null && this._attributes != null && this._attributes.size() > 0) { Set<Map.Entry<String,String>> entries = this._attributes.entrySet(); Iterator<Map.Entry<String,String>> entryIterator = entries.iterator(); while (entryIterator.hasNext()) { Map.Entry<String,String> entry = entryIterator.next(); this.result.setAttribute(entry.getKey(), entry.getValue()); } } } /** * addAttribute * * @param name * @param value */ protected void addAttribute(String name, String value) { if (name != null && name.length() > 0 && value != null && value.length() > 0) { if (this._attributes == null) { this._attributes = new HashMap<String,String>(); } this._attributes.put(name, value); // make sure we have a parse tree fragment that the attribute can ride on if (this._childNodes == null) { this._childNodes = new ParseFragment(); } } } /** * addChildNode * * @param childParseNode */ protected void addChildParseNode(IParseNode childParseNode) { if (childParseNode != null) { if (this._childNodes == null) { this._childNodes = new ParseFragment(); } this._childNodes.appendChild(childParseNode); } } /** * addChildTypes */ public abstract void addChildTypes(); /** * addTypesToMap * * @param indexMap */ protected void addTypesToMap(IEnumerationMap indexMap) { if (indexMap instanceof DynamicEnumerationMap) { DynamicEnumerationMap map = (DynamicEnumerationMap) indexMap; if (this._node != null && this._node.length() > 0) { map.getIntValue(this._node); } for (int i = 0; i < this.getChildCount(); i++) { INode child = this.getChild(i); if (child instanceof AbstractLexemeMatcher) { ((AbstractLexemeMatcher) child).addTypesToMap(indexMap); } } } } /** * reset */ protected void reset() { this._childNodes = null; if (this._attributes != null) { this._attributes.clear(); } this.result = null; } /** * getNode * * @return String */ public String getNode() { return this._node; } /** * getOwningParser * * @return ParserElement */ public ParserMatcher getOwningParser() { ParserMatcher result = null; INode current = this; while (current != null) { if (current instanceof ParserMatcher) { result = (ParserMatcher) current; break; } else { current = current.getParent(); } } return result; } /** * @see com.aptana.ide.parsing.matcher.ILexemeMatcher#getParseResults() */ public IParseNode getParseResults() { return this.result; } /** * setNode * * @param node */ public void setNode(String node) { this._node = node; } }