--- /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
+ }
+}