diff -r 000000000000 -r 818e61de6cd1 crashanalysercmd/PerfToolsSharedLibraries/Engine/SymBuildParsingLib/Token/SymTokenBalancerNodes.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/crashanalysercmd/PerfToolsSharedLibraries/Engine/SymBuildParsingLib/Token/SymTokenBalancerNodes.cs Thu Feb 11 15:50:58 2010 +0200 @@ -0,0 +1,619 @@ +/* +* Copyright (c) 2004-2008 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + +using System; +using System.Text; +using System.Collections; +using SymBuildParsingLib.Tree; +using SymBuildParsingLib.Token; +using SymBuildParsingLib.Common.Objects; +using SymbianTree; + +namespace SymBuildParsingLib.Token +{ + #region SymTokenBalancerDocument + public class SymTokenBalancerDocument : SymTokenDocument + { + #region Constructors & destructor + public SymTokenBalancerDocument() + { + } + #endregion + + #region Internal framework API + protected override void ExtractToContainer( SymNode aNode, SymTokenContainer aContainer ) + { + if ( aNode is SymTokenBalancerNodeEmittedElement ) + { + SymTokenBalancerNodeEmittedElement node = (SymTokenBalancerNodeEmittedElement) aNode; + node.AddToContainerIfEmittable( aContainer ); + } + } + + protected override void ExtractToDocument( SymNode aNode, SymTokenDocument aDocument ) + { + if ( aNode is SymTokenBalancerNodeEmittedElement ) + { + SymTokenBalancerNodeEmittedElement node = (SymTokenBalancerNodeEmittedElement) aNode; + node.AddToDocumentIfEmittable( aDocument ); + } + } + + protected override bool NodeIsExtractable( SymNode aNode ) + { + bool ret = false; + // + if ( aNode is SymTokenBalancerNodeEmittedElement ) + { + SymTokenBalancerNodeEmittedElement node = (SymTokenBalancerNodeEmittedElement) aNode; + ret = node.Emit; + } + // + return ret; + } + #endregion + } + #endregion + + #region SymTokenBalancerNode + public class SymTokenBalancerNode : SymNodeToken + { + #region Constructors & destructor + public SymTokenBalancerNode( SymToken aToken ) + : base( aToken ) + { + } + #endregion + } + #endregion + + #region SymTokenBalancerMarkerNode + public class SymTokenBalancerMarkerNode : SymNodeAddAsChild + { + #region Constructors & destructor + public SymTokenBalancerMarkerNode( SymTokenBalancerMatchCriteria aMatchCriteria ) + { + iMatchCriteria = aMatchCriteria; + } + #endregion + + #region Properties + public SymTokenBalancerMatchCriteria MatchCriteria + { + get { return iMatchCriteria; } + } + #endregion + + #region Data members + private readonly SymTokenBalancerMatchCriteria iMatchCriteria; + #endregion + } + #endregion + + #region SymTokenBalancerMarkerLevelNode + public class SymTokenBalancerMarkerLevelNode : SymTokenBalancerMarkerNode + { + #region Constructors & destructor + public SymTokenBalancerMarkerLevelNode( SymTokenBalancerMatchCriteria aMatchCriteria ) + : base( aMatchCriteria ) + { + } + #endregion + + #region From SymNode + public override void Replace( SymNode aReplacement ) + { + if ( HasPrevious && Previous is SymTokenBalancerNodeEmittedElement ) + { + Previous.Remove(); + } + if ( HasNext && Next is SymTokenBalancerNodeEmittedElement ) + { + Next.Remove(); + } + + base.Replace( aReplacement ); + } + #endregion + + #region API + public SymArgumentSubLevel AsArgumentSubLevel( bool aRecurse ) + { + SymArgumentSubLevel ret = new SymArgumentSubLevel( this ); + // + if ( aRecurse ) + { + foreach( SymNode child in ret ) + { + if ( child is SymTokenBalancerMarkerLevelNode ) + { + SymTokenBalancerMarkerLevelNode markerNode = (SymTokenBalancerMarkerLevelNode) child; + SymArgumentSubLevel subLevel = markerNode.AsArgumentSubLevel( aRecurse ); + ret.InsertChild( subLevel, markerNode ); + markerNode.Remove(); + } + } + } + // + return ret; + } + + public void ConvertEmittedElementsToRealTokenNodes( bool aRecurse ) + { + int i = ChildCount; + // + while( i > 0 ) + { + SymNode child = this[ --i ]; + // + if ( child is SymTokenBalancerNodeEmittedElement ) + { + SymTokenBalancerNodeEmittedElement emittedElement = (SymTokenBalancerNodeEmittedElement) child; + if ( emittedElement.Emit ) + { + SymNodeToken replacement = new SymNodeToken( emittedElement.Token ); + InsertChild( replacement, child ); + } + child.Remove(); + } + else if ( child is SymTokenBalancerMarkerLevelNode && aRecurse ) + { + SymTokenBalancerMarkerLevelNode childLevel = (SymTokenBalancerMarkerLevelNode) child; + childLevel.ConvertEmittedElementsToRealTokenNodes( aRecurse ); + } + } + } + + public int CountTokenByType( SymToken.TClass aClass ) + { + int count = 0; + // + foreach( SymNode n in this ) + { + if ( n is SymNodeToken ) + { + bool isSpecial = ( n is SymTokenBalancerNode ); + // + if ( isSpecial == false ) + { + SymToken t = ((SymNodeToken) n).Token; + // + if ( t.Class == aClass ) + { + ++count; + } + } + } + } + // + return count; + } + + public void Subsume() + { + System.Diagnostics.Debug.Assert( IsComplete ); + // + SymTokenBalancerNodeEmittedElement previous = EmittedElementPrevious; + SymTokenBalancerNodeEmittedElement next = EmittedElementNext; + + // Insert all my children as siblings of myself (i.e. make my parent's + // grandchildren its direct children - i.e. promote them up the tree + // by one level). + SymNode parent = Parent; + ArrayList parentsChildren = Parent.Children; + parent.InsertChildrenFrom( this /* my children */, previous.Previous /* move them before the opening bracket */); + + // Remove the opening bracket token + previous.Remove(); + + // Remove the closing bracket token. + next.Remove(); + + // Remove the level marker token, i.e myself + Remove(); + } + #endregion + + #region Properties + public bool CanBeSubsumed + { + get + { + bool canBeSubsumed = false; + // + if ( IsComplete ) + { + if ( AreLocalEmittedNodesDiametricallyOposite ) + { + bool isSimple = IsSimple; + // + if ( isSimple ) + { + // Deal with the case whereby we have something like this: ([SOMETHINGELSE]) + if ( ( Parent is SymTokenBalancerMarkerLevelNode) && ChildCountLevelNodes == 0 ) + { + // We don't have any child level nodes and our parent is a level (it always sound be in any case). + SymTokenBalancerMarkerLevelNode parent = (SymTokenBalancerMarkerLevelNode) Parent; + if ( parent.IsComplete ) + { + // Check whether the parent is a function. If it is, then we don't want to subsume the children. + bool isFunc = parent.IsFunction; + if ( isFunc == false ) + { + // The parent is complete, which means we can compare this level's open and closing tokens + // with the parents. + canBeSubsumed = ( parent.EmittedElementPrevious.Token.Equals( EmittedElementPrevious.Token ) && + parent.EmittedElementNext.Token.Equals( EmittedElementNext.Token ) ); + } + } + else + { + canBeSubsumed = true; + } + + } + else + { + canBeSubsumed = true; + } + } + else + { + // Check whether our children contains at least a single argument separator node. + // If it does, we can't allow it to be subsumed. + if ( ChildCountArgumentNodes == 0 ) + { + if ( Parent is SymTokenBalancerMarkerLevelNode ) + { + SymTokenBalancerMarkerLevelNode parent = (SymTokenBalancerMarkerLevelNode) Parent; + bool parentIsSimple = parent.IsSimple; + canBeSubsumed = parentIsSimple; + } + } + } + } + } + // + return canBeSubsumed; + } + } + + public bool IsFunction + { + get + { + #region Example + // + // [FUNC_NAME] [(] [*] [)] + // | + // [alpha_numeric_child] + // + #endregion + + bool bracketsAreCorrect = false; + bool hasFunctionName = false; + bool childIsValid = false; + // + if ( AreLocalEmittedNodesDiametricallyOposite ) + { + // Check that the previous node is a function name + if ( Previous.HasPrevious ) + { + SymNode previousPrevious = Previous.Previous; + if ( previousPrevious is SymNodeToken ) + { + SymNodeToken nodeToken = (SymNodeToken) previousPrevious; + hasFunctionName = (nodeToken.Token.Class == SymToken.TClass.EClassAlphaNumeric ); + } + } + + // Check that the brackets are ( and ) + bracketsAreCorrect = ( EmittedElementPrevious.Token.Value == "(" && EmittedElementNext.Token.Value == ")" ); + + // Check that the level node has but one child and that it + // is alphanumeric in nature. + if ( ChildCountByType( typeof(SymNodeToken) ) > 0 ) + { + foreach( SymNode child in this ) + { + if ( child is SymNodeToken ) + { + SymNodeToken tokenNode = (SymNodeToken) child; + // + if ( tokenNode.Token.Class == SymToken.TClass.EClassAlphaNumeric ) + { + childIsValid = true; + break; + } + } + } + } + } + + bool isFunction = (bracketsAreCorrect && hasFunctionName && childIsValid ); + return isFunction; + } + } + + public bool IsSimple + { + get + { + bool isSimple = false; + // + if ( IsFunction ) + { + isSimple = false; + } + else if ( ChildCountNonWhiteSpace == 1 ) + { + // My child is but a single node... + isSimple = true; + } + else if ( ChildCountWhiteSpace == ChildCount ) + { + // My children are just whitespace + isSimple = true; + } + else if ( ChildCountLevelNodes == 1 ) + { + int childCountLevelAndAssociatedEmittedNodes = ChildCountLevelAndAssociatedEmittedNodes; + int childCount = ChildCount; + int whiteSpaceCount = ChildCountWhiteSpace; + // + if ( (childCount - whiteSpaceCount) == childCountLevelAndAssociatedEmittedNodes ) + { + // Ignoring the whitespace nodes, all we had was a single level node plus its + // two associated emitted elements... + isSimple = true; + } + } + // + return isSimple; + } + } + + public bool IsComplete + { + get + { + bool complete = false; + + // Must have a next and a previous node. Next and previous must be + // emitted element nodes + if ( HasNext && HasPrevious ) + { + complete = ( Previous is SymTokenBalancerNodeEmittedElement && Next is SymTokenBalancerNodeEmittedElement ); + } + + return complete; + } + } + + public bool AreLocalEmittedNodesDiametricallyOposite + { + get + { + bool ret = false; + // + if ( IsComplete ) + { + SymTokenBalancerNodeEmittedElement previous = (SymTokenBalancerNodeEmittedElement) Previous; + SymTokenBalancerNodeEmittedElement next = (SymTokenBalancerNodeEmittedElement) Next; + // + if ( previous.MatchCriteria.DiametricToken.Equals( next.Token ) ) + { + // Paranoid + ret = ( next.MatchCriteria.DiametricToken.Equals( previous.Token ) ); + } + } + // + return ret; + } + } + + public SymNodeToken FunctionName + { + get + { + if ( IsFunction == false ) + { + throw new ArgumentException( "Level node is not a function node" ); + } + + System.Diagnostics.Debug.Assert( Previous.HasPrevious ); + System.Diagnostics.Debug.Assert( Previous.Previous is SymNodeToken ); + SymNodeToken functionNameToken = (SymNodeToken) Previous.Previous; + return functionNameToken; + } + } + + public SymTokenContainer ChildTokens + { + get + { + SymTokenContainer ret = new SymTokenContainer(); + // + foreach( SymNode c in this ) + { + if ( c is SymNodeToken ) + { + SymNodeToken t = (SymNodeToken) c; + ret.Append( t.Token ); + } + } + // + return ret; + } + } + + public int ChildCountWhiteSpace + { + get + { + return CountTokenByType( SymToken.TClass.EClassWhiteSpace ); + } + } + + public int ChildCountNonWhiteSpace + { + get + { + return ChildCount - ChildCountWhiteSpace; + } + } + + public int ChildCountLevelNodes + { + get + { + int count = ChildCountByType( typeof(SymTokenBalancerMarkerLevelNode) ); + return count; + } + } + + public int ChildCountLevelAndAssociatedEmittedNodes + { + get + { + int count = 0; + // + int index = 0; + object childLevelNodeObject = ChildByType( typeof(SymTokenBalancerMarkerLevelNode), ref index ); + while( childLevelNodeObject != null ) + { + // Count is incremented by one each time we find a level node + SymTokenBalancerMarkerLevelNode childLevelNode = (SymTokenBalancerMarkerLevelNode) childLevelNodeObject; + ++count; + + // It should always have a previous token. + System.Diagnostics.Debug.Assert( childLevelNode.HasPrevious ); + if ( childLevelNode.Previous is SymTokenBalancerNodeEmittedElement ) + { + ++count; + } + + // It may have a next node, assuming its complete... + if ( childLevelNode.HasNext ) + { + if ( childLevelNode.Next is SymTokenBalancerNodeEmittedElement ) + { + ++count; + } + } + + // Move to next child level node + ++index; + childLevelNodeObject = ChildByType( typeof(SymTokenBalancerMarkerLevelNode), ref index ); + } + // + return count; + } + } + + public int ChildCountArgumentNodes + { + get + { + int count = ChildCountByType( typeof(SymTokenBalancerMarkerArgumentNode) ); + return count; + } + } + + public SymTokenBalancerNodeEmittedElement EmittedElementPrevious + { + get + { + return (SymTokenBalancerNodeEmittedElement) Previous; + } + } + + public SymTokenBalancerNodeEmittedElement EmittedElementNext + { + get + { + return (SymTokenBalancerNodeEmittedElement) Next; + } + } + + #endregion + + #region Internal methods + #endregion + } + #endregion + + #region SymTokenBalancerMarkerArgumentNode + public class SymTokenBalancerMarkerArgumentNode : SymTokenBalancerMarkerNode + { + #region Constructors & destructor + public SymTokenBalancerMarkerArgumentNode( SymTokenBalancerMatchCriteria aMatchCriteria ) + : base( aMatchCriteria ) + { + } + #endregion + } + #endregion + + #region SymTokenBalancerNodeEmittedElement + public class SymTokenBalancerNodeEmittedElement : SymTokenBalancerMarkerNode + { + #region Constructors & destructor + public SymTokenBalancerNodeEmittedElement( SymToken aToken, SymTokenBalancerMatchCriteria aMatchCriteria ) + : base( aMatchCriteria ) + { + iToken = aToken; + } + #endregion + + #region API + public void AddToDocumentIfEmittable( SymDocument aDocument ) + { + if ( Emit ) + { + SymNodeToken node = new SymNodeToken( Token ); + aDocument.CurrentNode.Add( node ); + } + } + + public void AddToContainerIfEmittable( SymTokenContainer aContainer ) + { + if ( Emit ) + { + aContainer.Append( Token ); + } + } + #endregion + + #region Properties + public SymToken Token + { + get { return iToken; } + } + + public bool Emit + { + get { return MatchCriteria.Emit; } + } + #endregion + + #region Data members + private readonly SymToken iToken; + #endregion + } + #endregion +}