/* ***** BEGIN LICENSE BLOCK ***** * Version: GPL 3 * * This program is Copyright (C) 2007-2008 Aptana, Inc. All Rights Reserved * This program is licensed under the GNU General Public license, version 3 (GPL). * * 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 the GPL, * is prohibited. * * You can redistribute and/or modify this program under the terms of the GPL, * 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 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/. * * You may view the GPL, and Aptana's exception and additional terms in the file * titled license-jaxer.html in the main distribution folder of this program. * * Any modifications to this file must keep this entire header intact. * * ***** END LICENSE BLOCK ***** */ package com.aptana.ide.editor.css.parsing; import java.util.ArrayList; import java.util.List; import com.aptana.ide.editor.css.parsing.nodes.CSSCharSetNode; import com.aptana.ide.editor.css.parsing.nodes.CSSDeclarationNode; import com.aptana.ide.editor.css.parsing.nodes.CSSExprNode; import com.aptana.ide.editor.css.parsing.nodes.CSSImportNode; import com.aptana.ide.editor.css.parsing.nodes.CSSListNode; import com.aptana.ide.editor.css.parsing.nodes.CSSMediaNode; import com.aptana.ide.editor.css.parsing.nodes.CSSMediumNode; import com.aptana.ide.editor.css.parsing.nodes.CSSPageNode; import com.aptana.ide.editor.css.parsing.nodes.CSSParseNode; import com.aptana.ide.editor.css.parsing.nodes.CSSParseNodeTypes; import com.aptana.ide.editor.css.parsing.nodes.CSSRuleSetNode; import com.aptana.ide.editor.css.parsing.nodes.CSSSelectorNode; import com.aptana.ide.editor.css.parsing.nodes.CSSSimpleSelectorNode; import com.aptana.ide.editor.css.parsing.nodes.CSSTermNode; import com.aptana.ide.editor.css.parsing.nodes.CSSTextNode; import com.aptana.ide.editors.unified.parsing.UnifiedReductionHandler; import com.aptana.ide.lexer.Lexeme; import com.aptana.ide.parsing.IParseState; import com.aptana.ide.parsing.bnf.IReductionContext; import com.aptana.ide.parsing.nodes.IParseNode; import com.aptana.ide.parsing.nodes.ParseFragment; /** * @author Kevin Lindsey */ public class CSSASTHandler extends UnifiedReductionHandler<CSSParseNode> { private List<CSSParseNode> _statements; /** * CSSASTHandler * * @param parseState */ public CSSASTHandler() { super(); this._statements = new ArrayList<CSSParseNode>(); } /** * @see com.aptana.ide.parsing.bnf.IReductionHandler#afterParse(com.aptana.ide.parsing.IParseState, com.aptana.ide.parsing.nodes.IParseNode) */ public void afterParse(IParseState parseState, IParseNode parentNode) { if (parentNode != null) { for (CSSParseNode node : this._statements) { parentNode.appendChild(node); } } this._statements.clear(); super.afterParse(parseState, parentNode); } /** * @param context * @param primitive * @return */ private CSSTermNode createTermNode(IReductionContext context, Lexeme primitive) { CSSTermNode result = (CSSTermNode) this.createNode(CSSParseNodeTypes.TERM, primitive); result.setAttribute("value", primitive.getText()); //$NON-NLS-1$ return result; } /** * onAddAttributeSelector * * @param context * @return */ public Object onAddAttributeSelector(IReductionContext context) { Object[] nodes = context.getNodes(); CSSTextNode component = (CSSTextNode) nodes[1]; ParseFragment fragment = (ParseFragment) nodes[0]; fragment.appendChild(component); return fragment; } /** * onAddDeclaration * * @param context * @return */ public Object onAddDeclaration(IReductionContext context) { Object[] nodes = context.getNodes(); CSSListNode declarations = (CSSListNode) nodes[0]; CSSDeclarationNode declaration = (CSSDeclarationNode) nodes[2]; declarations.appendChild(declaration); return declarations; } /** * onAddEmptyDeclaration * * @param context * @return */ public Object onAddEmptyDeclaration(IReductionContext context) { Object[] nodes = context.getNodes(); CSSListNode declarations = (CSSListNode) nodes[0]; declarations.appendChild(CSSParseNode.Empty); return declarations; } /** * onAddFunctionExpression * * @param context * @return */ public Object onAddFunctionExpression(IReductionContext context) { Object[] nodes = context.getNodes(); CSSTermNode function = (CSSTermNode) nodes[1]; function.setAttribute("joining-operator", " "); //$NON-NLS-1$ //$NON-NLS-2$ CSSExprNode expression = (CSSExprNode) nodes[0]; expression.appendChild(function); return expression; } /** * onAddList * * @param context * @return */ public Object onAddList(IReductionContext context) { Object[] nodes = context.getNodes(); CSSListNode list = (CSSListNode) nodes[0]; Lexeme identifier = (Lexeme) nodes[2]; CSSTextNode medium = (CSSTextNode) this.createNode(CSSParseNodeTypes.TEXT, identifier); list.appendChild(medium); return list; } /** * onAddPrimitiveExpression * * @param context * @return */ public Object onAddPrimitiveExpression(IReductionContext context) { Object[] nodes = context.getNodes(); Lexeme primitive = (Lexeme) nodes[1]; CSSTermNode term = this.createTermNode(context, primitive); term.setAttribute("joining-operator", " "); //$NON-NLS-1$ //$NON-NLS-2$ CSSExprNode expression = (CSSExprNode) nodes[0]; expression.appendChild(term); return expression; } /** * onAddSelector * * @param context * @return */ public Object onAddSelector(IReductionContext context) { Object[] nodes = context.getNodes(); CSSListNode selectors = (CSSListNode) nodes[0]; CSSSelectorNode selector = (CSSSelectorNode) nodes[2]; selectors.appendChild(selector); return selectors; } /** * onAddSeparatorFunctionExpression * * @param context * @return */ public Object onAddSeparatorFunctionExpression(IReductionContext context) { Object[] nodes = context.getNodes(); Lexeme separator = (Lexeme) nodes[1]; CSSTermNode function = (CSSTermNode) nodes[2]; function.setAttribute("joining-operator", separator.getText()); //$NON-NLS-1$ CSSExprNode expression = (CSSExprNode) nodes[0]; expression.appendChild(function); return expression; } /** * onAddSeparatorPrimitiveExpression * * @param context * @return */ public Object onAddSeparatorPrimitiveExpression(IReductionContext context) { Object[] nodes = context.getNodes(); Lexeme separator = (Lexeme) nodes[1]; Lexeme primitive = (Lexeme) nodes[2]; CSSTermNode term = this.createTermNode(context, primitive); term.setAttribute("joining-operator", separator.getText()); //$NON-NLS-1$ CSSExprNode expression = (CSSExprNode) nodes[0]; expression.appendChild(term); return expression; } /** * onAddSimpleCombinedSelector * * @param context * @return */ public Object onAddSimpleCombinedSelector(IReductionContext context) { Object[] nodes = context.getNodes(); Lexeme combinator = (Lexeme) nodes[1]; CSSTextNode combinatorNode = (CSSTextNode) this.createNode(CSSParseNodeTypes.TEXT, combinator); CSSSimpleSelectorNode simpleSelector = (CSSSimpleSelectorNode) nodes[2]; simpleSelector.appendChild(combinatorNode); CSSSelectorNode selector = (CSSSelectorNode) nodes[0]; selector.appendChild(simpleSelector); return selector; } /** * onAddSimpleSelector * * @param context * @return */ public Object onAddSimpleSelector(IReductionContext context) { Object[] nodes = context.getNodes(); CSSSimpleSelectorNode simpleSelector = (CSSSimpleSelectorNode) nodes[1]; simpleSelector.appendChild(CSSParseNode.Empty); CSSSelectorNode selector = (CSSSelectorNode) nodes[0]; selector.appendChild(simpleSelector); return selector; } /** * onAddStatement * * @param context * @return */ public Object onAddStatement(IReductionContext context) { Object[] nodes = context.getNodes(); CSSParseNode statement = (CSSParseNode) nodes[1]; this._statements.add(statement); return this._statements; } /** * onAttributeExistsSelector * * @param context * @return */ public Object onAttributeExistsSelector(IReductionContext context) { Object[] nodes = context.getNodes(); Lexeme lbracket = (Lexeme) nodes[0]; Lexeme name = (Lexeme) nodes[1]; Lexeme rbracket = (Lexeme) nodes[2]; String text = "[" + name.getText() + "]"; //$NON-NLS-1$ //$NON-NLS-2$ CSSTextNode result = (CSSTextNode) this.createNode(CSSParseNodeTypes.TEXT, lbracket); result.setText(text); result.includeLexemeInRange(rbracket); return result; } /** * onAttributeSelector * * @param context * @return */ public Object onAttributeSelector(IReductionContext context) { Lexeme selector = (Lexeme) context.getNode(0); CSSTextNode result = (CSSTextNode) this.createNode(CSSParseNodeTypes.TEXT, selector); result.setText(selector.getText()); return result; } /** * onTAttributesSelectors * * @param context * @return */ public Object onAttributeSelectors(IReductionContext context) { ParseFragment attributeSelectors = (ParseFragment) context.getNode(0); CSSListNode components = (CSSListNode) this.createNode(CSSParseNodeTypes.LIST, null); components.setListName("components"); //$NON-NLS-1$ components.appendChild(attributeSelectors); CSSSimpleSelectorNode result = (CSSSimpleSelectorNode) this.createNode( CSSParseNodeTypes.SIMPLE_SELECTOR, attributeSelectors.getStartingLexeme() ); result.appendChild(components); return result; } /** * onAttributeValueExistsSelector * * @param context * @return */ public Object onAttributeValueExistsSelector(IReductionContext context) { Object[] nodes = context.getNodes(); Lexeme lbracket = (Lexeme) nodes[0]; Lexeme name = (Lexeme) nodes[1]; Lexeme operator = (Lexeme) nodes[2]; Lexeme test = (Lexeme) nodes[3]; Lexeme rbracket = (Lexeme) nodes[4]; StringBuilder buffer = new StringBuilder(); buffer.append("["); //$NON-NLS-1$ buffer.append(name.getText()); buffer.append(operator.getText()); buffer.append(test.getText()); buffer.append("]"); //$NON-NLS-1$ CSSTextNode result = (CSSTextNode) this.createNode(CSSParseNodeTypes.TEXT, lbracket); result.setText(buffer.toString()); result.includeLexemeInRange(rbracket); return result; } /** * onStart * * @param action * @param nodes * @return */ public Object onAtWord(IReductionContext context) { Object[] nodes = context.getNodes(); Lexeme atLexeme = (Lexeme) nodes[0]; CSSParseNode result = this.createNode(CSSParseNodeTypes.AT_RULE, atLexeme); return result; } /** * onCharSet * * @param context * @return */ public Object onCharSet(IReductionContext context) { Object[] objects = context.getNodes(); Lexeme keyword = (Lexeme) objects[0]; Lexeme name = (Lexeme) objects[1]; Lexeme semicolon = (Lexeme) objects[2]; CSSTextNode nameNode = (CSSTextNode) this.createNode(CSSParseNodeTypes.TEXT, name); CSSCharSetNode result = (CSSCharSetNode) this.createNode(CSSParseNodeTypes.CHAR_SET, keyword); result.appendChild(nameNode); result.includeLexemeInRange(semicolon); return result; } /** * onDeclaration * * @param context * @return */ public Object onDeclaration(IReductionContext context) { Object[] nodes = context.getNodes(); Lexeme identifier = (Lexeme) nodes[0]; CSSExprNode expression = (CSSExprNode) nodes[2]; // if (identifier.typeIndex == CSSTokenTypes.IDENTIFIER) // { // context.getParser().changeTokenType(CSSTokenTypes.PROPERTY); // } CSSDeclarationNode result = (CSSDeclarationNode) this.createNode(CSSParseNodeTypes.DECLARATION, identifier); result.setAttribute("name", identifier.getText()); //$NON-NLS-1$ result.appendChild(expression); return result; } /** * onEmptyDeclaration * * @param context * @return */ public Object onEmptyDeclaration(IReductionContext context) { CSSListNode result = (CSSListNode) this.createNode(CSSParseNodeTypes.LIST, null); result.appendChild(CSSParseNode.Empty); result.setListName("properties"); //$NON-NLS-1$ result.setDelimiter("\n"); //$NON-NLS-1$ return result; } /** * onFirstAttributeSelector * * @param context * @return */ public Object onFirstAttributeSelector(IReductionContext context) { CSSTextNode component = (CSSTextNode) context.getNode(0); ParseFragment result = new ParseFragment(); result.appendChild(component); return result; } /** * onFirstDeclaration * * @param context * @return */ public Object onFirstDeclaration(IReductionContext context) { CSSDeclarationNode declaration = (CSSDeclarationNode) context.getNode(0); CSSListNode result = (CSSListNode) this.createNode(CSSParseNodeTypes.LIST, null); result.appendChild(declaration); result.setListName("properties"); //$NON-NLS-1$ result.setDelimiter("\n"); //$NON-NLS-1$ return result; } /** * onFirstExpression * * @param context * @return */ public Object onFirstExpression(IReductionContext context) { CSSTermNode term = (CSSTermNode) context.getNode(0); CSSExprNode result = (CSSExprNode) this.createNode(CSSParseNodeTypes.EXPR, term.getStartingLexeme()); result.appendChild(term); return result; } /** * onFirstList * * @param context * @return */ public Object onFirstList(IReductionContext context) { Lexeme identifier = (Lexeme) context.getNode(0); CSSListNode list = (CSSListNode) this.createNode(CSSParseNodeTypes.LIST, identifier); CSSTextNode medium = (CSSTextNode) this.createNode(CSSParseNodeTypes.TEXT, identifier); list.setDelimiter(", "); //$NON-NLS-1$ list.appendChild(medium); return list; } /** * onFirstSelector * * @param context * @return */ public Object onFirstSelector(IReductionContext context) { CSSSelectorNode selector = (CSSSelectorNode) context.getNode(0); CSSListNode result = (CSSListNode) this.createNode(CSSParseNodeTypes.LIST, selector.getStartingLexeme()); result.appendChild(selector); result.setListName("selectors"); //$NON-NLS-1$ return result; } /** * onFirstSelector * * @param context * @return */ public Object onFirstSimpleSelector(IReductionContext context) { CSSSimpleSelectorNode selector = (CSSSimpleSelectorNode) context.getNode(0); selector.appendChild(CSSParseNode.Empty); CSSSelectorNode result = (CSSSelectorNode) this.createNode(CSSParseNodeTypes.SELECTOR, selector.getStartingLexeme()); result.appendChild(selector); return result; } /** * onFirstStatement * * @param context * @return */ public Object onFirstStatement(IReductionContext context) { CSSParseNode statement = (CSSParseNode) context.getNode(0); this._statements.add(statement); return this._statements; } /** * onFunction * * @param context * @return */ public Object onFunction(IReductionContext context) { Object[] nodes = context.getNodes(); Lexeme keyword = (Lexeme) nodes[0]; CSSExprNode args = (CSSExprNode) nodes[1]; Lexeme rcurly = (Lexeme) nodes[2]; CSSTermNode result = createTermNode(context, keyword); result.appendChild(args); result.includeLexemeInRange(rcurly); return result; } /** * onImport * * @param action * @param nodes * @return */ public Object onImport(IReductionContext context) { Object[] nodes = context.getNodes(); Lexeme importLexeme = (Lexeme) nodes[0]; Lexeme nameLexeme = (Lexeme) nodes[1]; Lexeme semicolon = (Lexeme) nodes[2]; CSSImportNode result = (CSSImportNode) this.createNode(CSSParseNodeTypes.IMPORT, importLexeme); result.setAttribute("name", nameLexeme.getText()); //$NON-NLS-1$ result.includeLexemeInRange(semicolon); return result; } /** * onImportantDeclaration * * @param context * @return */ public Object onImportantDeclaration(IReductionContext context) { Object[] nodes = context.getNodes(); Lexeme identifier = (Lexeme) nodes[0]; CSSExprNode expression = (CSSExprNode) nodes[2]; Lexeme important = (Lexeme) nodes[3]; // if (identifier.typeIndex == CSSTokenTypes.IDENTIFIER) // { // context.getParser().changeTokenType(CSSTokenTypes.PROPERTY); // } CSSDeclarationNode result = (CSSDeclarationNode) this.createNode(CSSParseNodeTypes.DECLARATION, identifier); result.setAttribute("name", identifier.getText()); //$NON-NLS-1$ result.setAttribute("status", important.getText()); //$NON-NLS-1$ result.appendChild(expression); result.includeLexemeInRange(important); return result; } /** * onImportList * * @param action * @param nodes * @return */ public Object onImportList(IReductionContext context) { Object[] nodes = context.getNodes(); Lexeme importLexeme = (Lexeme) nodes[0]; Lexeme nameLexeme = (Lexeme) nodes[1]; CSSListNode list = (CSSListNode) nodes[2]; Lexeme semicolon = (Lexeme) nodes[3]; CSSImportNode result = (CSSImportNode) this.createNode(CSSParseNodeTypes.IMPORT, importLexeme); result.setAttribute("name", nameLexeme.getText()); //$NON-NLS-1$ result.appendChild(list); result.includeLexemeInRange(semicolon); return result; } /** * onMedia * * @param context * @return */ public Object onMedia(IReductionContext context) { Object[] nodes = context.getNodes(); Lexeme keyword = (Lexeme) nodes[0]; Lexeme identifier = (Lexeme) nodes[1]; Lexeme rcurly = (Lexeme) nodes[3]; // create media container and set its delimiter type CSSListNode media = (CSSListNode) this.createNode(CSSParseNodeTypes.LIST, null); media.setDelimiter(", "); //$NON-NLS-1$ // create first medium and add to media list CSSMediumNode medium = (CSSMediumNode) this.createNode(CSSParseNodeTypes.MEDIUM, identifier); media.appendChild(medium); // create resulting media parse node, add children, and update its range CSSMediaNode result = (CSSMediaNode) this.createNode(CSSParseNodeTypes.MEDIA, keyword); result.includeLexemeInRange(rcurly); result.appendChild(media); result.appendChild(CSSParseNode.Empty); return result; } /** * onPage * * @param context * @return */ public Object onPage(IReductionContext context) { Object[] nodes = context.getNodes(); Lexeme keyword = (Lexeme) nodes[0]; Lexeme rcurly = (Lexeme) nodes[2]; CSSListNode declarations = (CSSListNode) this.createNode(CSSParseNodeTypes.LIST, null); declarations.setDelimiter("\n"); //$NON-NLS-1$ CSSPageNode result = (CSSPageNode) this.createNode(CSSParseNodeTypes.PAGE, keyword); result.appendChild(declarations); result.includeLexemeInRange(rcurly); return result; } /** * onPageDeclaration * * @param context * @return */ public Object onPageDeclaration(IReductionContext context) { Object[] nodes = context.getNodes(); Lexeme keyword = (Lexeme) nodes[0]; CSSListNode declarations = (CSSListNode) nodes[2]; Lexeme rcurly = (Lexeme) nodes[3]; CSSPageNode result = (CSSPageNode) this.createNode(CSSParseNodeTypes.PAGE, keyword); result.appendChild(declarations); result.includeLexemeInRange(rcurly); return result; } /** * onPlusMinusTerm * * @param context * @return */ public Object onPlusMinusTerm(IReductionContext context) { Object[] nodes = context.getNodes(); Lexeme plusMinus = (Lexeme) nodes[0]; Lexeme primitive = (Lexeme) nodes[1]; CSSTermNode result = (CSSTermNode) this.createNode(CSSParseNodeTypes.TERM, plusMinus); result.setAttribute("operator", plusMinus.getText()); //$NON-NLS-1$ result.setAttribute("value", primitive.getText()); //$NON-NLS-1$ return result; } /** * onPseudoPage * * @param context * @return */ public Object onPseudoPage(IReductionContext context) { Object[] nodes = context.getNodes(); Lexeme keyword = (Lexeme) nodes[0]; Lexeme identifier = (Lexeme) nodes[2]; Lexeme rcurly = (Lexeme) nodes[4]; CSSListNode declarations = (CSSListNode) this.createNode(CSSParseNodeTypes.LIST, null); declarations.setDelimiter("\n"); //$NON-NLS-1$ CSSPageNode result = (CSSPageNode) this.createNode(CSSParseNodeTypes.PAGE, keyword); result.setAttribute("name", identifier.getText()); //$NON-NLS-1$ result.appendChild(declarations); result.includeLexemeInRange(rcurly); return result; } /** * onPseudoSelector * * @param context * @return */ public Object onPseudoSelector(IReductionContext context) { Object[] nodes = context.getNodes(); Lexeme colon = (Lexeme) nodes[0]; Lexeme name = (Lexeme) nodes[1]; CSSTextNode result = (CSSTextNode) this.createNode(CSSParseNodeTypes.TEXT, colon); result.setText(Messages.CSSASTHandler_29 + name.getText()); result.includeLexemeInRange(name); return result; } /** * onPseudoSelectorFunction * * @param context * @return */ public Object onPseudoSelectorFunction(IReductionContext context) { Object[] nodes = context.getNodes(); Lexeme colon = (Lexeme) nodes[0]; CSSTermNode function = (CSSTermNode) nodes[1]; int startingIndex = this.lexemes.getLexemeIndex(function.getStartingLexeme()); int endingIndex = this.lexemes.getLexemeIndex(function.getEndingLexeme()); StringBuilder buffer = new StringBuilder(); buffer.append(Messages.CSSASTHandler_30); for (int i = startingIndex; i <= endingIndex; i++) { buffer.append(this.lexemes.get(i).getText()); } CSSTextNode result = (CSSTextNode) this.createNode(CSSParseNodeTypes.TEXT, colon); result.setText(buffer.toString()); result.includeLexemeInRange(function.getEndingLexeme()); return result; } /** * onRule * * @param context * @return */ public Object onRule(IReductionContext context) { Object[] nodes = context.getNodes(); CSSListNode selectors = (CSSListNode) nodes[0]; Lexeme rcurly = (Lexeme) nodes[2]; CSSListNode declarations = (CSSListNode) this.createNode(CSSParseNodeTypes.LIST, null); declarations.setListName(Messages.CSSASTHandler_31); CSSRuleSetNode result = (CSSRuleSetNode) this.createNode(CSSParseNodeTypes.RULE_SET, selectors.getStartingLexeme()); result.appendChild(selectors); result.appendChild(declarations); result.includeLexemeInRange(rcurly); return result; } /** * onRuleDeclarations * * @param context * @return */ public Object onRuleDeclarations(IReductionContext context) { Object[] nodes = context.getNodes(); CSSListNode selectors = (CSSListNode) nodes[0]; CSSListNode declarations = (CSSListNode) nodes[2]; Lexeme rcurly = (Lexeme) nodes[3]; CSSRuleSetNode result = (CSSRuleSetNode) this.createNode(CSSParseNodeTypes.RULE_SET, selectors.getStartingLexeme()); result.appendChild(selectors); result.appendChild(declarations); result.includeLexemeInRange(rcurly); return result; } /** * onTerm * * @param context * @return */ public Object onTerm(IReductionContext context) { Lexeme primitive = (Lexeme) context.getNode(0); CSSTermNode result = createTermNode(context, primitive); return result; } /** * onTypeAndAttributesSelectors * * @param context * @return */ public Object onTypeAndAttributeSelectors(IReductionContext context) { Object[] nodes = context.getNodes(); Lexeme selector = (Lexeme) nodes[0]; ParseFragment attributeSelectors = (ParseFragment) nodes[1]; CSSTextNode component = (CSSTextNode) this.createNode(CSSParseNodeTypes.TEXT, selector); CSSListNode components = (CSSListNode) this.createNode(CSSParseNodeTypes.LIST, null); components.setListName(Messages.CSSASTHandler_32); components.appendChild(component); components.appendChild(attributeSelectors); CSSSimpleSelectorNode result = (CSSSimpleSelectorNode) this.createNode( CSSParseNodeTypes.SIMPLE_SELECTOR, selector ); result.appendChild(components); return result; } /** * onTypeOrUniversalSelector * * @param context * @return */ public Object onTypeOrUniversalSelector(IReductionContext context) { Lexeme selector = (Lexeme) context.getNode(0); CSSTextNode component = (CSSTextNode) this.createNode(CSSParseNodeTypes.TEXT, selector); CSSListNode components = (CSSListNode) this.createNode(CSSParseNodeTypes.LIST, null); components.setListName(Messages.CSSASTHandler_33); components.appendChild(component); CSSSimpleSelectorNode result = (CSSSimpleSelectorNode) this.createNode( CSSParseNodeTypes.SIMPLE_SELECTOR, selector ); result.appendChild(components); return result; } /** * @see com.aptana.ide.parsing.bnf.IReductionHandler#reduce(com.aptana.ide.parsing.bnf.IReductionContext) */ public void reduce(IReductionContext context) { String actionName = context.getAction(); Object result = null; // collect the matching rule's items from the stack Object[] nodes = this.pop(context.getNodeCount()); // store the matching items within the reduction context for the handler method's use context.setNodes(nodes); if (actionName != null && actionName.length() > 0) { CSSHandlerAction action = CSSHandlerAction.get(actionName); if (action == null) { throw new IllegalArgumentException(Messages.CSSASTHandler_34 + actionName); } switch (action) { case ADD_ATTRIBUTE_SELECTOR: result = this.onAddAttributeSelector(context); break; case ADD_DECLARATION: result = this.onAddDeclaration(context); break; case ADD_EMPTY_DECLARATION: result = this.onAddEmptyDeclaration(context); break; case ADD_FUNCTION_EXPRESSION: result = this.onAddFunctionExpression(context); break; case ADD_LIST: result = this.onAddList(context); break; case ADD_PRIMITIVE_EXPRESSION: result = this.onAddPrimitiveExpression(context); break; case ADD_SELECTOR: result = this.onAddSelector(context); break; case ADD_SEPARATOR_PRIMITIVE_EXPRESSION: result = this.onAddSeparatorPrimitiveExpression(context); break; case ADD_SEPARATOR_FUNCTION_EXPRESSION: result = this.onAddSeparatorFunctionExpression(context); break; case ADD_SIMPLE_SELECTOR: result = this.onAddSimpleSelector(context); break; case ADD_SIMPLE_COMBINED_SELECTOR: result = this.onAddSimpleCombinedSelector(context); break; case ADD_STATEMENT: result = this.onAddStatement(context); break; case ATTRIBUTE_EXISTS_SELECTOR: result = this.onAttributeExistsSelector(context); break; case ATTRIBUTE_SELECTOR: result = this.onAttributeSelector(context); break; case ATTRIBUTE_SELECTORS: result = this.onAttributeSelectors(context); break; case ATTRIBUTE_VALUE_EXISTS_SELECTOR: result = this.onAttributeValueExistsSelector(context); break; case AT_WORD: result = this.onAtWord(context); break; case CHARSET: result = this.onCharSet(context); break; case DECLARATION: result = this.onDeclaration(context); break; case EMPTY_DECLARATION: result = this.onEmptyDeclaration(context); break; case FIRST_ATTRIBUTE_SELECTOR: result = this.onFirstAttributeSelector(context); break; case FIRST_LIST: result = this.onFirstList(context); break; case FIRST_DECLARATION: result = this.onFirstDeclaration(context); break; case FIRST_EXPRESSION: result = this.onFirstExpression(context); break; case FIRST_SELECTOR: result = this.onFirstSelector(context); break; case FIRST_SIMPLE_SELECTOR: result = this.onFirstSimpleSelector(context); break; case FIRST_STATEMENT: result = this.onFirstStatement(context); break; case FUNCTION: result = this.onFunction(context); break; case IMPORT: result = this.onImport(context); break; case IMPORTANT_DECLARATION: result = this.onImportantDeclaration(context); break; case IMPORT_LIST: result = this.onImportList(context); break; case MEDIA: result = this.onMedia(context); break; case PAGE: result = this.onPage(context); break; case PAGE_DECLARATION: result = this.onPageDeclaration(context); break; case PLUS_MINUS_TERM: result = this.onPlusMinusTerm(context); break; case PSEUDO_PAGE: result = this.onPseudoPage(context); break; case PSEUDO_SELECTOR: result = this.onPseudoSelector(context); break; case PSEUDO_SELECTOR_FUNCTION: result = this.onPseudoSelectorFunction(context); break; case RULE: result = this.onRule(context); break; case RULE_DECLARATIONS: result = this.onRuleDeclarations(context); break; case TERM: result = this.onTerm(context); break; case TYPE_OR_UNIVERSAL_SELECTOR: result = this.onTypeOrUniversalSelector(context); break; case TYPE_AND_ATTRIBUTE_SELECTORS: result = this.onTypeAndAttributeSelectors(context); break; default: throw new IllegalArgumentException(Messages.CSSASTHandler_35 + actionName); } } else { // We should always have nodes, but let's be safe just in case if (nodes.length > 0) { result = nodes[0]; } } // push the results onto our stack this.push(result); } }