diff -r 000000000000 -r 818e61de6cd1 crashanalysercmd/PerfToolsSharedLibraries/Engine/SymBuildParsingLib/Parser/Framework/Utils/SymFunctionParser.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/crashanalysercmd/PerfToolsSharedLibraries/Engine/SymBuildParsingLib/Parser/Framework/Utils/SymFunctionParser.cs Thu Feb 11 15:50:58 2010 +0200 @@ -0,0 +1,290 @@ +/* +* 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.Token; +using SymBuildParsingLib.Tree; +using SymBuildParsingLib.Common.Objects; +using SymbianTree; + +namespace SymBuildParsingLib.Parser.Framework.Utils +{ + public class SymFunctionParser : SymTokenBalancer + { + #region Observer interface + public delegate void ArgumentAvailable( SymArgument aArgument, SymToken aDelimitingToken ); + #endregion + + #region Events + public event ArgumentAvailable EventArgumentAvailableHandler; + #endregion + + #region Constructors & destructor + public SymFunctionParser() + { + } + #endregion + + #region API + public virtual void RegisterFunctionParserTokens() + { + // Base class registration + RegisterBalancerTokens(); + + // These are the important tokens relating to function arguments + SymToken bracketTokenOpening = new SymToken( "(", SymToken.TClass.EClassSymbol, SymToken.TType.ETypeUnidentified ); + SymToken bracketTokenClosing = new SymToken( ")", SymToken.TClass.EClassSymbol, SymToken.TType.ETypeUnidentified ); + SymToken squareBracketTokenOpening = new SymToken( "[", SymToken.TClass.EClassSymbol, SymToken.TType.ETypeUnidentified ); + SymToken squareBracketTokenClosing = new SymToken( "]", SymToken.TClass.EClassSymbol, SymToken.TType.ETypeUnidentified ); + SymToken templateBracketTokenOpening = new SymToken( "<", SymToken.TClass.EClassSymbol, SymToken.TType.ETypeUnidentified ); + SymToken templateBracketTokenClosing = new SymToken( ">", SymToken.TClass.EClassSymbol, SymToken.TType.ETypeUnidentified ); + + // We want to track levels for square brackets and template arguments in order to ensure we balance correctly. + // We don't want to remove any redundancy here as these may have special meaning. + RegisterOpeningToken( squareBracketTokenOpening, squareBracketTokenClosing, true, true, TLevelExpectations.ELevelExpectationsAboveLevelNumber, 0, TAssociatedBehaviour.EBehaviourNone ); + RegisterClosingToken( squareBracketTokenClosing, squareBracketTokenOpening, true, true, TLevelExpectations.ELevelExpectationsAboveLevelNumber, 0, TAssociatedBehaviour.EBehaviourNone ); + RegisterOpeningToken( templateBracketTokenOpening, templateBracketTokenClosing, true, true, TLevelExpectations.ELevelExpectationsAboveLevelNumber, 0, TAssociatedBehaviour.EBehaviourNone ); + RegisterClosingToken( templateBracketTokenClosing, templateBracketTokenOpening, true, true, TLevelExpectations.ELevelExpectationsAboveLevelNumber, 0, TAssociatedBehaviour.EBehaviourNone ); + + // Define our argument separation token(s). + TAssociatedBehaviour flags = TAssociatedBehaviour.EBehaviourNone; + flags |= TAssociatedBehaviour.EBehaviourCreateSubTree; + flags |= TAssociatedBehaviour.EBehaviourRemoveReduntantBracketing; + // + SymToken commaDelimiterToken = new SymToken( ",", SymToken.TClass.EClassSymbol, SymToken.TType.ETypeUnidentified ); + RegisterArgumentSeparatorToken( commaDelimiterToken, new SymTokenBalancerMatchCriteria( SymToken.NullToken(), false, true, TLevelExpectations.ELevelExpectationsAtLevel, 1, flags ) ); + RegisterArgumentSeparatorToken( commaDelimiterToken, new SymTokenBalancerMatchCriteria( SymToken.NullToken(), true, true, TLevelExpectations.ELevelExpectationsAboveLevelNumber, 1, TAssociatedBehaviour.EBehaviourNone ) ); + } + + public virtual SymArgument MakeArgument() + { + SymNode levelNodeToObtainArgumentsFrom = CurrentNode; + + // Try to work out whether we have a leve node at the current + // scope which should be preferred t + object levelNodeObject = levelNodeToObtainArgumentsFrom.ChildByType( typeof(SymTokenBalancerMarkerLevelNode) ); + if ( levelNodeObject != null ) + { + levelNodeToObtainArgumentsFrom = (SymNode) levelNodeObject; + } + + return MakeArgument( levelNodeToObtainArgumentsFrom ); + } + + public virtual SymArgument MakeArgument( SymNode aLevelToMakeArgumentsFrom ) + { + SymArgument argument = new SymArgument(); + + // Convert (recursively) any emitted elements to real tokens + if ( aLevelToMakeArgumentsFrom is SymTokenBalancerMarkerLevelNode ) + { + SymTokenBalancerMarkerLevelNode levelNode = (SymTokenBalancerMarkerLevelNode) aLevelToMakeArgumentsFrom; + levelNode.ConvertEmittedElementsToRealTokenNodes( true /*recurse*/ ); + } + + // Now actually obtain the argument tokens + int count = aLevelToMakeArgumentsFrom.ChildCount; + int i = 0; + // + while( i < count ) + { + SymNode n = aLevelToMakeArgumentsFrom[ 0 ]; + + // We always remove any other nodes, irrespective of their type. + // This is to ensure that the document tree does not get cluttered + // with redundant argument token info. + n.Remove(); + + // Now we decide what to do... + if ( n is SymTokenBalancerMarkerArgumentNode ) + { + // We've reached the argument itself. This is the + // signal to stop processing. We remove the argument node + // since its not relevant to the production of the tree. + break; + } + else if ( n is SymTokenBalancerMarkerLevelNode ) + { + // Create a new sub-argument node and copy over the + // children. + SymTokenBalancerMarkerLevelNode levelNode = (SymTokenBalancerMarkerLevelNode) n; + SymArgumentSubLevel subLevel = levelNode.AsArgumentSubLevel( true ); + argument.CurrentNode.Add( subLevel ); + } + else if ( n is SymTokenBalancerNodeEmittedElement ) + { + System.Diagnostics.Debug.Assert( false ); // shouldn't get here anymore! + } + else if ( n is SymNodeToken ) + { + // Node is implicitly removed since it transfers + // from one tree to another. + argument.CurrentNode.Add( n ); + } + + count = aLevelToMakeArgumentsFrom.ChildCount; + } + // + SymTokenUtils.RemoveWhiteSpace( argument, true ); + return argument; + } + + public string MakeFunctionName() + { + StringBuilder name = new StringBuilder(); + + // Pull out all the level one tokens from the balancer. These form + // the function/define name. + foreach( SymNode n in DocumentTree ) + { + if ( n is SymTokenBalancerMarkerNode ) + { + // Not part of the name + break; + } + else if ( n is SymTokenBalancerNodeEmittedElement ) + { + // Not part of the name - also, this is indicator to stop iterating! + break; + } + else if ( n is SymNodeToken ) + { + SymNodeToken tokenNode = (SymNodeToken) n; + name.Append( tokenNode.Token.Value ); + } + } + + return name.ToString(); + } + #endregion + + #region API - registration + public void RegisterArgumentSeparatorToken( SymToken aToken, SymTokenBalancerMatchCriteria aCriteria ) + { + SymToken copy = new SymToken( aToken ); + copy.Tag = aCriteria; + // + if ( IsTokenExactMatch( copy, iArgumentSeparators ) == false ) + { + iArgumentSeparators.Append( copy ); + } + } + #endregion + + #region From SymTokenBalancer + public override bool OfferToken( SymToken aToken ) + { + bool consumed = false; + int currentLevelNumber = CurrentLevelNumber; + + // Check for bracket matches + SymTokenBalancerMatchCriteria tokenExtendedInfo; + if ( IsArgumentSeparatorMatch( aToken, out tokenExtendedInfo, currentLevelNumber ) ) + { + ArgumentStarted( aToken, tokenExtendedInfo ); + consumed = true; + } + + // If it wasn't an arg token or it was, but it wasn't at the + // correct (expected) level, then give it to the base class + // to handle. + if ( consumed == false ) + { + consumed = base.OfferToken( aToken ); + } + // + return consumed; + } + #endregion + + #region Notification framework + protected virtual void NotifyArgumentAvailable( SymArgument aArgument, SymToken aDelimitingToken ) + { + if ( EventArgumentAvailableHandler != null ) + { + EventArgumentAvailableHandler( aArgument, aDelimitingToken ); + } + } + #endregion + + #region New internal framework + protected virtual void ArgumentStarted( SymToken aToken, SymTokenBalancerMatchCriteria aCriteria ) + { + System.Diagnostics.Debug.Write( aToken.Value ); + + int currentLevelNumber = CurrentLevelNumber; + + // Perform any base class end level behaviour + PerformEndLevelBehaviour( CurrentNode, aCriteria ); + + // Add the emit node (the rest of the code will work out whether it needs to quote it when the final + // tree is formed). + SymTokenBalancerNodeEmittedElement argEmitElement = new SymTokenBalancerNodeEmittedElement( aToken, aCriteria ); + DocumentTree.CurrentNode.Add( argEmitElement ); + + // Always add the argument node + SymTokenBalancerMarkerArgumentNode argNode = new SymTokenBalancerMarkerArgumentNode( aCriteria ); + DocumentTree.CurrentNode.Add( argNode ); + + if ( aCriteria.IsAssociatedBehaviourCreateSubTree ) + { + // Make a new argument definition based upon the tokens we have in + // the main document tree. + SymArgument argument = MakeArgument( DocumentTree.CurrentNode ); + + // Then notify the observer + NotifyArgumentAvailable( argument, aToken ); + } + } + #endregion + + #region Internal utility methods + protected bool IsArgumentSeparatorMatch( SymToken aToken, out SymTokenBalancerMatchCriteria aCriteria, int aLevelNumber ) + { + aCriteria = null; + bool matchFound = false; + // + int index = iArgumentSeparators.IndexOf( aToken ); + while( index >= 0 && matchFound == false ) + { + SymToken token = iArgumentSeparators[ index ]; + System.Diagnostics.Debug.Assert ( token.Tag != null && token.Tag is SymTokenBalancerMatchCriteria ); + SymTokenBalancerMatchCriteria criteria = (SymTokenBalancerMatchCriteria) token.Tag; + + if ( criteria.Matches( aLevelNumber ) ) + { + aCriteria = criteria; + matchFound = true; + } + else + { + index = iArgumentSeparators.IndexOf( aToken, index+1 ); + } + } + + return matchFound; + } + + #endregion + + #region Data members + private SymTokenContainer iArgumentSeparators = new SymTokenContainer(); + #endregion + } +}