/* * * Copyright 2012 lexergen. * This file is part of lexergen. * * lexergen is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * lexergen is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with lexergen. If not, see <http://www.gnu.org/licenses/>. * * lexergen: * A tool to chunk source code into tokens for further processing in a compiler chain. * * Projectgroup: bi, bii * * Authors: Johannes Dahlke * * Module: Softwareprojekt Übersetzerbau 2012 * * Created: Apr. 2012 * Version: 1.0 * */ package de.fuberlin.bii.regextodfaconverter.directconverter.syntaxtree; import de.fuberlin.bii.regextodfaconverter.directconverter.lrparser.ItemAutomat; import de.fuberlin.bii.regextodfaconverter.directconverter.lrparser.ReduceEventHandler; import de.fuberlin.bii.regextodfaconverter.directconverter.lrparser.ShiftEventHandler; import de.fuberlin.bii.regextodfaconverter.directconverter.lrparser.grammar.ContextFreeGrammar; import de.fuberlin.bii.regextodfaconverter.directconverter.lrparser.grammar.EmptyString; import de.fuberlin.bii.regextodfaconverter.directconverter.lrparser.grammar.ProductionRule; import de.fuberlin.bii.regextodfaconverter.directconverter.lrparser.grammar.Symbol; import de.fuberlin.bii.regextodfaconverter.directconverter.lrparser.grammar.Terminal; import de.fuberlin.bii.regextodfaconverter.directconverter.syntaxtree.node.InnerNode; import de.fuberlin.bii.regextodfaconverter.directconverter.syntaxtree.node.Leaf; import de.fuberlin.bii.regextodfaconverter.directconverter.syntaxtree.node.NewNodeEventHandler; import de.fuberlin.bii.regextodfaconverter.directconverter.syntaxtree.node.NumberedTreeNode; import de.fuberlin.bii.regextodfaconverter.directconverter.syntaxtree.node.ScalableInnerNode; import de.fuberlin.bii.regextodfaconverter.directconverter.syntaxtree.node.TreeNode; import de.fuberlin.bii.utils.Notification; import de.fuberlin.bii.utils.Test; /** * Stellt einen abstrakten Syntaxbaum dar. * * @author Johannes Dahlke * */ @SuppressWarnings("rawtypes") public class AbstractSyntaxTree<ExpressionElement extends Symbol> extends ConcreteSyntaxTree<ExpressionElement> { private SyntaxDirectedDefinition sddTable; private AttributesMap rootAttributesMap; public AbstractSyntaxTree( ContextFreeGrammar grammar, SyntaxDirectedDefinition sddTable, ExpressionElement[] expression) throws Exception { this( grammar, sddTable, expression, null); } public AbstractSyntaxTree( ContextFreeGrammar grammar, final SyntaxDirectedDefinition sddTable, ExpressionElement[] expression, NewNodeEventHandler newNodeEventHandler) throws Exception { super( grammar, expression, newNodeEventHandler, false); this.sddTable = sddTable; this.buildTree(); } protected ReduceEventHandler getReduceEventHandler() { return new ReduceEventHandler() { public Object handle( Object sender, ProductionRule reduceRule, int sequenceNumber) throws Exception { // Notification.printDebugInfoMessage( "r: " + reduceRule); updateStackBySequenceNumber( sequenceNumber); // create the map contains attributes of this node AttributesMap thisAttributesMap = new AttributesMap(); rootAttributesMap = thisAttributesMap; // create new inner node InnerNode<AttributesMap> newInnerNode = new ScalableInnerNode<AttributesMap>( thisAttributesMap); // newInnerNode.setPrintHandler( getNodePrintHandler()); // get the semantic rules defined for given rule to reduce SemanticRules semanticRules = sddTable.get( reduceRule); // add childs to the new inner node int countOfReducedElements = reduceRule.getRightRuleSide().size(); // By the way, assemble the attributes of rule elements of right rule side representing by the nodes AttributesMap[] nodeAttributesMaps = new AttributesMap[countOfReducedElements+1]; nodeAttributesMaps[0] = thisAttributesMap; for ( int i = countOfReducedElements; i > 0; i--) { if ( reduceRule.getRightRuleSide().get( i-1) instanceof EmptyString) continue; // get child from stack TreeNode childNode = getNodeStack().pop().getTreeNode(); // insert child into parent node newInnerNode.insertChild( childNode, 0); // add attributes from end to front nodeAttributesMaps[i] = (AttributesMap) childNode.getValue(); } // apply all defined semantic rules if (Test.isAssigned( semanticRules)) { for ( SemanticRule semanticRule : semanticRules) { semanticRule.apply( nodeAttributesMaps); } } if ( Test.isAssigned( onNewNodeEvent)) onNewNodeEvent.doOnEvent( this, newInnerNode); // push the inner node onto stack NumberedTreeNode newNumberedNode = new NumberedTreeNode<AttributesMap>( newInnerNode, sequenceNumber); getNodeStack().push( newNumberedNode); snapshotCurrentStackWithSequenceNumber( sequenceNumber); return null; } }; } @Override protected ShiftEventHandler getShiftEventHandler() { return new ShiftEventHandler() { public Object handle( Object sender, Terminal shiftedTerminal, int sequenceNumber) throws Exception { // Notification.printDebugInfoMessage( "s: " + shiftedTerminal); updateStackBySequenceNumber( sequenceNumber); // create the map contains attributes of this node AttributesMap thisAttributesMap = new AttributesMap(); // create attribute value to pass the terminal thisAttributesMap.put( "value", shiftedTerminal.getSymbol()); // create new leaf node Leaf<AttributesMap> newLeaf = new Leaf<AttributesMap>( thisAttributesMap); if ( Test.isAssigned( onNewNodeEvent)) onNewNodeEvent.doOnEvent( this, newLeaf); NumberedTreeNode newNumberedLeaf = new NumberedTreeNode<AttributesMap>( newLeaf, sequenceNumber); getNodeStack().push( newNumberedLeaf); snapshotCurrentStackWithSequenceNumber( sequenceNumber); return null; } }; } /** * Liefert die Attributierungen des Wurzelknotens. * @return */ public AttributesMap getRootAttributesMap() { return rootAttributesMap; } }