crashanalysercmd/PerfToolsSharedLibraries/Engine/SymBuildParsingLib/Parser/Framework/Parser/SymParserBase.cs
changeset 0 818e61de6cd1
equal deleted inserted replaced
-1:000000000000 0:818e61de6cd1
       
     1 #define SHOW_TOKENS/*
       
     2 * Copyright (c) 2004-2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 using System;
       
    19 using System.Collections;
       
    20 using System.Threading;
       
    21 using System.Reflection;
       
    22 using SymBuildParsingLib.Tree;
       
    23 using SymBuildParsingLib.Utils;
       
    24 using SymBuildParsingLib.Grouper;
       
    25 using SymBuildParsingLib.Lexer;
       
    26 using SymBuildParsingLib.Token;
       
    27 using SymBuildParsingLib.Parser.Framework.Workers;
       
    28 using SymBuildParsingLib.Parser.Framework.Document;
       
    29 using SymbianTree;
       
    30 
       
    31 namespace SymBuildParsingLib.Parser.Framework.Parser
       
    32 {
       
    33 	public abstract class SymParserBase
       
    34 	{
       
    35 		#region Event enumerations
       
    36 		public enum TEvent
       
    37 		{
       
    38 			EEventStaringLexing = 0,
       
    39 			EEventStaringGrouping,
       
    40 			EEventParsingComplete
       
    41 		};
       
    42 		#endregion
       
    43 
       
    44 		#region Observer interface
       
    45 		public delegate void ParserObserver( SymParserBase aParser, TEvent aEvent );
       
    46 		#endregion
       
    47 
       
    48 		#region Events
       
    49 		public event ParserObserver ParserObservers;
       
    50 		#endregion
       
    51 
       
    52 		#region Constructors and destructor
       
    53 		public SymParserBase( SymParserDocument aDocument )
       
    54 		{
       
    55 			// Store the document and initialise the document's 
       
    56 			// parser reference
       
    57 			iDocument = aDocument;
       
    58 			iDocument.Context.Parser = this;
       
    59 
       
    60 			// The lexer reads the tokens from the stream and performs minimal
       
    61 			// (very basic) grouping.
       
    62 			iLexer = new SymLexer( iDocument.Context.FileName );
       
    63 
       
    64 			// We observe the lexer in order to know when all the input data
       
    65 			// has been consumed from the source file.
       
    66 			iLexer.LexerObservers += new SymLexer.LexerObserver( HandleLexerEvent );
       
    67 
       
    68 			// The grouper performs more sophisticated grouping based upon
       
    69 			// simple C++/C rules. It observes the lexer for tokens.
       
    70 			iGrouper = new SymGrouper( iLexer );
       
    71 
       
    72 			// We observe the grouper in order to obtain the grouped tokens
       
    73 			// which we will parse to form the tree.
       
    74 			iGrouper.GrouperObservers += new SymGrouper.GrouperObserver( HandleGrouperEvent );
       
    75 
       
    76 			// Create the thread for the parser
       
    77 			iWorkerThread = new Thread( new System.Threading.ThreadStart( BuildParserTree ) );
       
    78 			PrepareWorkerThread();
       
    79 
       
    80 			// Create any initial required workers
       
    81 			PrepareInitialWorkers();
       
    82 		}
       
    83 		#endregion
       
    84 
       
    85 		#region API
       
    86 		public void Parse()
       
    87 		{
       
    88 			// Starting the lexer will implicitly start the grouper
       
    89 			// as the grouper is already awaiting the lexer's output
       
    90 			// tokens. Tokens will arrive into the iGroupedTokens data
       
    91 			// member. This call is asynchronous.
       
    92 			iLexer.Lex();
       
    93 		}
       
    94 		#endregion
       
    95 
       
    96 		#region Clone API
       
    97 		public SymParserBase CarbonCopy( object[] aArguments )
       
    98 		{
       
    99 			// NB. Should use object.Clone with custom IClonable charactersitics?
       
   100 			System.Type type = this.GetType();
       
   101 			object objectInstance = Activator.CreateInstance( type, aArguments );
       
   102 			//
       
   103 			if	( !(objectInstance is SymParserBase) )
       
   104 			{
       
   105 				throw new Exception( "Unexpected object type during Carbon Copy operation" );
       
   106 			}
       
   107 			//
       
   108 			SymParserBase parser = (SymParserBase) objectInstance;
       
   109 			return parser;
       
   110 		}
       
   111 		#endregion
       
   112 
       
   113 		#region Abstract API
       
   114 		protected virtual void PrepareInitialWorkers()
       
   115 		{
       
   116 		}
       
   117 
       
   118 		protected virtual void HandleParserToken( SymToken aToken )
       
   119 		{
       
   120 			// Try to dish the token out to the workers. Give
       
   121 			// the token to the highest priority worker initially.
       
   122 			// Keep trying to offer it until one of the workers
       
   123 			// consumes it.
       
   124 			int count = iWorkers.Count;
       
   125 			for( int i=0; i<count; i++ )
       
   126 			{
       
   127 				SymParserWorker worker = (SymParserWorker) iWorkers[ i ];
       
   128 				SymParserWorker.TTokenConsumptionType consumptionType = worker.OfferToken( aToken );
       
   129 				//
       
   130 				if	( consumptionType == SymParserWorker.TTokenConsumptionType.ETokenConsumed )
       
   131 				{
       
   132 					break;
       
   133 				}
       
   134 			}
       
   135 		}
       
   136 		#endregion
       
   137 
       
   138 		#region Abstract properties
       
   139 		protected abstract string ParserName { get; }
       
   140 		#endregion
       
   141 
       
   142 		#region Properties
       
   143 		public string FileName
       
   144 		{
       
   145 			get { return iLexer.FileName; }
       
   146 		}
       
   147 
       
   148 		public SymParserDocument Document
       
   149 		{
       
   150 			get { return iDocument; }
       
   151 		}
       
   152 		#endregion
       
   153 
       
   154 		#region Worker related
       
   155 		public int WorkerCount
       
   156 		{
       
   157 			get { return iWorkers.Count; }
       
   158 		}
       
   159 
       
   160 		public void QueueWorker( SymParserWorker aWorker )
       
   161 		{
       
   162 			// Insert into sorted order
       
   163 			int count = iWorkers.Count;
       
   164 			for( int i=0; i<count; i++ )
       
   165 			{
       
   166 				SymParserWorker worker = (SymParserWorker) iWorkers[ i ];
       
   167 				int existingPriority = worker.Priority;
       
   168 				//
       
   169 				if	( aWorker.Priority >= existingPriority )
       
   170 				{
       
   171 					iWorkers.Insert( i, aWorker );
       
   172 					return;
       
   173 				}
       
   174 			}
       
   175 
       
   176 			// First entry - just append it...
       
   177 			iWorkers.Add( aWorker );
       
   178 		}
       
   179 		#endregion
       
   180 
       
   181 		#region Internal Properties
       
   182 		protected SymTokenContainer GroupedTokens
       
   183 		{
       
   184 			get { return iGroupedTokens; }
       
   185 		}
       
   186 		#endregion
       
   187 
       
   188 		#region Internal methods
       
   189 		private void BuildParserTree()
       
   190 		{
       
   191 			// Pull a token from the source buffer
       
   192 			do
       
   193 			{
       
   194 				int tokenCount = 0;
       
   195 				//
       
   196 				do
       
   197 				{
       
   198 					SymToken token = null;
       
   199 
       
   200 					// Try to get the head token (if there is one)
       
   201 					lock( iGroupedTokens )
       
   202 					{
       
   203 						tokenCount = iGroupedTokens.Count;
       
   204 						if	( tokenCount > 0 )
       
   205 						{
       
   206 							token = iGroupedTokens.PopHead();
       
   207 						}
       
   208 					}
       
   209 
       
   210 					// Then process it
       
   211 					if	( token != null )
       
   212 					{
       
   213 #if SHOW_TOKENS
       
   214 						System.Diagnostics.Debug.WriteLine( "BuildParserTree() - next token is: [" + token.Value + "]");
       
   215 #endif
       
   216 						HandleParserToken( token );
       
   217 					}
       
   218 				} 
       
   219 				while ( tokenCount > 0 );
       
   220 
       
   221 				// We've processed all the tokens we had so far... put us to sleep
       
   222 				//System.Diagnostics.Debug.WriteLine( "Parser.BuildParserTree() - no more tokens - waiting on semaphore..." );
       
   223 				iSemaphore.Wait();
       
   224 				//System.Diagnostics.Debug.WriteLine( "Parser.BuildParserTree() - AWAKE!" );
       
   225 			}
       
   226 			while( true );
       
   227 
       
   228 		}
       
   229 
       
   230 		private void PrepareWorkerThread()
       
   231 		{
       
   232 			System.Random randomNumberGen = new Random( System.Environment.TickCount );
       
   233 			int uniquePostfix = randomNumberGen.Next();
       
   234 			//
       
   235 			string workerThreadName = ParserName + uniquePostfix.ToString("d8");
       
   236 			iWorkerThread.Name = workerThreadName;
       
   237 			iWorkerThread.IsBackground = true;
       
   238 			iWorkerThread.Start();
       
   239 		}
       
   240 		private void ReportEvent( TEvent aEvent )
       
   241 		{
       
   242 			if	( ParserObservers != null )
       
   243 			{
       
   244 				ParserObservers( this, aEvent );
       
   245 			}
       
   246 		}
       
   247 		private void NewGroupedTokenArrived( SymToken aToken )
       
   248 		{
       
   249 			lock( this )
       
   250 			{
       
   251 				iGroupedTokens.Append( aToken );
       
   252 				//
       
   253 				if	( iSemaphore.Count == 0 )
       
   254 				{
       
   255 					iSemaphore.Signal();
       
   256 				}
       
   257 			}
       
   258 		}
       
   259 		#endregion
       
   260 
       
   261 		#region Event handlers
       
   262 		private void HandleLexerEvent( SymLexer aLexer, SymLexer.TEvent aEvent, SymToken aToken )
       
   263 		{
       
   264 			switch( aEvent )
       
   265 			{
       
   266 				case SymLexer.TEvent.EEventLexingStarted: 
       
   267 					ReportEvent( TEvent.EEventStaringLexing );
       
   268 					break;
       
   269 				case SymLexer.TEvent.EEventLexingNewLine: 
       
   270 					break;
       
   271 				case SymLexer.TEvent.EEventLexingComplete: 
       
   272 					break;
       
   273 				default:
       
   274 					break;
       
   275 			}
       
   276 		}
       
   277 
       
   278 		private void HandleGrouperEvent( SymGrouper aGrouper, SymGrouper.TEvent aEvent, SymToken aGroupedToken )
       
   279 		{
       
   280 			switch( aEvent )
       
   281 			{
       
   282 				case SymGrouper.TEvent.EEventGroupingStarted: 
       
   283 					ReportEvent( TEvent.EEventStaringGrouping );
       
   284 					break;
       
   285 				case SymGrouper.TEvent.EEventGroupingPaused:
       
   286 					break;
       
   287 				case SymGrouper.TEvent.EEventGroupingComplete: 
       
   288 					ReportEvent( TEvent.EEventParsingComplete );
       
   289 					break;
       
   290 				case SymGrouper.TEvent.EEventGroupingTokenReady:
       
   291 					NewGroupedTokenArrived( aGroupedToken );
       
   292 					break;
       
   293 				default:
       
   294 					break;
       
   295 			}
       
   296 		}
       
   297 		#endregion
       
   298 
       
   299 		#region Data members
       
   300 		private readonly Thread iWorkerThread;
       
   301 		private readonly SymGrouper iGrouper;
       
   302 		private readonly SymLexer iLexer;
       
   303 		private readonly SymParserDocument iDocument;
       
   304 		private SymTokenContainer iGroupedTokens = new SymTokenContainer();
       
   305 		private ArrayList iWorkers = new ArrayList( 4 );
       
   306 		private SymSemaphore iSemaphore = new SymSemaphore( 0, 1 );
       
   307 		#endregion
       
   308 	}
       
   309 }