crashanalysercmd/PerfToolsSharedLibraries/Engine/SymBuildParsingLib/Parser/Framework/Parser/SymParserBase.cs
changeset 0 818e61de6cd1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crashanalysercmd/PerfToolsSharedLibraries/Engine/SymBuildParsingLib/Parser/Framework/Parser/SymParserBase.cs	Thu Feb 11 15:50:58 2010 +0200
@@ -0,0 +1,309 @@
+#define SHOW_TOKENS/*
+* 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.Collections;
+using System.Threading;
+using System.Reflection;
+using SymBuildParsingLib.Tree;
+using SymBuildParsingLib.Utils;
+using SymBuildParsingLib.Grouper;
+using SymBuildParsingLib.Lexer;
+using SymBuildParsingLib.Token;
+using SymBuildParsingLib.Parser.Framework.Workers;
+using SymBuildParsingLib.Parser.Framework.Document;
+using SymbianTree;
+
+namespace SymBuildParsingLib.Parser.Framework.Parser
+{
+	public abstract class SymParserBase
+	{
+		#region Event enumerations
+		public enum TEvent
+		{
+			EEventStaringLexing = 0,
+			EEventStaringGrouping,
+			EEventParsingComplete
+		};
+		#endregion
+
+		#region Observer interface
+		public delegate void ParserObserver( SymParserBase aParser, TEvent aEvent );
+		#endregion
+
+		#region Events
+		public event ParserObserver ParserObservers;
+		#endregion
+
+		#region Constructors and destructor
+		public SymParserBase( SymParserDocument aDocument )
+		{
+			// Store the document and initialise the document's 
+			// parser reference
+			iDocument = aDocument;
+			iDocument.Context.Parser = this;
+
+			// The lexer reads the tokens from the stream and performs minimal
+			// (very basic) grouping.
+			iLexer = new SymLexer( iDocument.Context.FileName );
+
+			// We observe the lexer in order to know when all the input data
+			// has been consumed from the source file.
+			iLexer.LexerObservers += new SymLexer.LexerObserver( HandleLexerEvent );
+
+			// The grouper performs more sophisticated grouping based upon
+			// simple C++/C rules. It observes the lexer for tokens.
+			iGrouper = new SymGrouper( iLexer );
+
+			// We observe the grouper in order to obtain the grouped tokens
+			// which we will parse to form the tree.
+			iGrouper.GrouperObservers += new SymGrouper.GrouperObserver( HandleGrouperEvent );
+
+			// Create the thread for the parser
+			iWorkerThread = new Thread( new System.Threading.ThreadStart( BuildParserTree ) );
+			PrepareWorkerThread();
+
+			// Create any initial required workers
+			PrepareInitialWorkers();
+		}
+		#endregion
+
+		#region API
+		public void Parse()
+		{
+			// Starting the lexer will implicitly start the grouper
+			// as the grouper is already awaiting the lexer's output
+			// tokens. Tokens will arrive into the iGroupedTokens data
+			// member. This call is asynchronous.
+			iLexer.Lex();
+		}
+		#endregion
+
+		#region Clone API
+		public SymParserBase CarbonCopy( object[] aArguments )
+		{
+			// NB. Should use object.Clone with custom IClonable charactersitics?
+			System.Type type = this.GetType();
+			object objectInstance = Activator.CreateInstance( type, aArguments );
+			//
+			if	( !(objectInstance is SymParserBase) )
+			{
+				throw new Exception( "Unexpected object type during Carbon Copy operation" );
+			}
+			//
+			SymParserBase parser = (SymParserBase) objectInstance;
+			return parser;
+		}
+		#endregion
+
+		#region Abstract API
+		protected virtual void PrepareInitialWorkers()
+		{
+		}
+
+		protected virtual void HandleParserToken( SymToken aToken )
+		{
+			// Try to dish the token out to the workers. Give
+			// the token to the highest priority worker initially.
+			// Keep trying to offer it until one of the workers
+			// consumes it.
+			int count = iWorkers.Count;
+			for( int i=0; i<count; i++ )
+			{
+				SymParserWorker worker = (SymParserWorker) iWorkers[ i ];
+				SymParserWorker.TTokenConsumptionType consumptionType = worker.OfferToken( aToken );
+				//
+				if	( consumptionType == SymParserWorker.TTokenConsumptionType.ETokenConsumed )
+				{
+					break;
+				}
+			}
+		}
+		#endregion
+
+		#region Abstract properties
+		protected abstract string ParserName { get; }
+		#endregion
+
+		#region Properties
+		public string FileName
+		{
+			get { return iLexer.FileName; }
+		}
+
+		public SymParserDocument Document
+		{
+			get { return iDocument; }
+		}
+		#endregion
+
+		#region Worker related
+		public int WorkerCount
+		{
+			get { return iWorkers.Count; }
+		}
+
+		public void QueueWorker( SymParserWorker aWorker )
+		{
+			// Insert into sorted order
+			int count = iWorkers.Count;
+			for( int i=0; i<count; i++ )
+			{
+				SymParserWorker worker = (SymParserWorker) iWorkers[ i ];
+				int existingPriority = worker.Priority;
+				//
+				if	( aWorker.Priority >= existingPriority )
+				{
+					iWorkers.Insert( i, aWorker );
+					return;
+				}
+			}
+
+			// First entry - just append it...
+			iWorkers.Add( aWorker );
+		}
+		#endregion
+
+		#region Internal Properties
+		protected SymTokenContainer GroupedTokens
+		{
+			get { return iGroupedTokens; }
+		}
+		#endregion
+
+		#region Internal methods
+		private void BuildParserTree()
+		{
+			// Pull a token from the source buffer
+			do
+			{
+				int tokenCount = 0;
+				//
+				do
+				{
+					SymToken token = null;
+
+					// Try to get the head token (if there is one)
+					lock( iGroupedTokens )
+					{
+						tokenCount = iGroupedTokens.Count;
+						if	( tokenCount > 0 )
+						{
+							token = iGroupedTokens.PopHead();
+						}
+					}
+
+					// Then process it
+					if	( token != null )
+					{
+#if SHOW_TOKENS
+						System.Diagnostics.Debug.WriteLine( "BuildParserTree() - next token is: [" + token.Value + "]");
+#endif
+						HandleParserToken( token );
+					}
+				} 
+				while ( tokenCount > 0 );
+
+				// We've processed all the tokens we had so far... put us to sleep
+				//System.Diagnostics.Debug.WriteLine( "Parser.BuildParserTree() - no more tokens - waiting on semaphore..." );
+				iSemaphore.Wait();
+				//System.Diagnostics.Debug.WriteLine( "Parser.BuildParserTree() - AWAKE!" );
+			}
+			while( true );
+
+		}
+
+		private void PrepareWorkerThread()
+		{
+			System.Random randomNumberGen = new Random( System.Environment.TickCount );
+			int uniquePostfix = randomNumberGen.Next();
+			//
+			string workerThreadName = ParserName + uniquePostfix.ToString("d8");
+			iWorkerThread.Name = workerThreadName;
+			iWorkerThread.IsBackground = true;
+			iWorkerThread.Start();
+		}
+		private void ReportEvent( TEvent aEvent )
+		{
+			if	( ParserObservers != null )
+			{
+				ParserObservers( this, aEvent );
+			}
+		}
+		private void NewGroupedTokenArrived( SymToken aToken )
+		{
+			lock( this )
+			{
+				iGroupedTokens.Append( aToken );
+				//
+				if	( iSemaphore.Count == 0 )
+				{
+					iSemaphore.Signal();
+				}
+			}
+		}
+		#endregion
+
+		#region Event handlers
+		private void HandleLexerEvent( SymLexer aLexer, SymLexer.TEvent aEvent, SymToken aToken )
+		{
+			switch( aEvent )
+			{
+				case SymLexer.TEvent.EEventLexingStarted: 
+					ReportEvent( TEvent.EEventStaringLexing );
+					break;
+				case SymLexer.TEvent.EEventLexingNewLine: 
+					break;
+				case SymLexer.TEvent.EEventLexingComplete: 
+					break;
+				default:
+					break;
+			}
+		}
+
+		private void HandleGrouperEvent( SymGrouper aGrouper, SymGrouper.TEvent aEvent, SymToken aGroupedToken )
+		{
+			switch( aEvent )
+			{
+				case SymGrouper.TEvent.EEventGroupingStarted: 
+					ReportEvent( TEvent.EEventStaringGrouping );
+					break;
+				case SymGrouper.TEvent.EEventGroupingPaused:
+					break;
+				case SymGrouper.TEvent.EEventGroupingComplete: 
+					ReportEvent( TEvent.EEventParsingComplete );
+					break;
+				case SymGrouper.TEvent.EEventGroupingTokenReady:
+					NewGroupedTokenArrived( aGroupedToken );
+					break;
+				default:
+					break;
+			}
+		}
+		#endregion
+
+		#region Data members
+		private readonly Thread iWorkerThread;
+		private readonly SymGrouper iGrouper;
+		private readonly SymLexer iLexer;
+		private readonly SymParserDocument iDocument;
+		private SymTokenContainer iGroupedTokens = new SymTokenContainer();
+		private ArrayList iWorkers = new ArrayList( 4 );
+		private SymSemaphore iSemaphore = new SymSemaphore( 0, 1 );
+		#endregion
+	}
+}