crashanalysercmd/PerfToolsSharedLibraries/Engine/SymBuildParsingLib/Lexer/SymLexer.cs
changeset 0 818e61de6cd1
equal deleted inserted replaced
-1:000000000000 0:818e61de6cd1
       
     1 /*
       
     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.Text;
       
    20 using System.Threading;
       
    21 using System.Collections;
       
    22 using SymBuildParsingLib.Token;
       
    23 using SymBuildParsingLib.Lexer;
       
    24 using SymBuildParsingLib.Utils;
       
    25 
       
    26 namespace SymBuildParsingLib.Lexer
       
    27 {
       
    28 	public class SymLexer : ISymLexerPositionObserver
       
    29 	{
       
    30 		#region Enumerations
       
    31 		public enum TEvent
       
    32 		{
       
    33 			EEventLexingStarted = 0,
       
    34 			EEventLexingNewLine,
       
    35 			EEventLexingToken,
       
    36 			EEventLexingComplete
       
    37 		};
       
    38 		#endregion
       
    39 
       
    40 		#region Observer interface
       
    41 		public delegate void LexerObserver( SymLexer aLexer, TEvent aEvent, SymToken aToken );
       
    42 		#endregion
       
    43 
       
    44 		#region Events
       
    45 		public event LexerObserver LexerObservers;
       
    46 		#endregion
       
    47 
       
    48 		#region Constructors & destructor
       
    49 		public SymLexer( string aFileName )
       
    50 		{
       
    51 			iStream = new SymStream( aFileName );
       
    52 			//
       
    53 			PrepareDefaultWorkers();
       
    54 		}
       
    55 		#endregion
       
    56 
       
    57 		#region API
       
    58 		public void Lex()
       
    59 		{
       
    60 			StartWorkerThread();
       
    61 		}
       
    62 
       
    63 		internal void RegisterWorker( SymLexerWorker aWorker )
       
    64 		{
       
    65 			iWorkers.Add( aWorker );
       
    66 		}
       
    67 
       
    68 		internal void FlushToken( SymToken aToken )
       
    69 		{
       
    70 			ReportEvent( TEvent.EEventLexingToken, aToken );
       
    71 		}
       
    72 		#endregion
       
    73 
       
    74 		#region Properties
       
    75 		public string FileName
       
    76 		{
       
    77 			get { return iStream.FileName; }
       
    78 		}
       
    79 
       
    80 		internal SymStream Stream
       
    81 		{
       
    82 			get { return iStream; }
       
    83 		}
       
    84 
       
    85 		internal SymTextPosition CurrentPosition
       
    86 		{
       
    87 			get { return iPositionProvider.CurrentPosition; }
       
    88 		}
       
    89 		#endregion
       
    90 
       
    91 		#region Internal threading related
       
    92 		private void DoLexing()
       
    93 		{
       
    94 			ReportEvent( TEvent.EEventLexingStarted, SymToken.NullToken() );
       
    95 
       
    96 			while( !Stream.EOF )
       
    97 			{
       
    98 				char character = Stream.ReadChar();
       
    99 				ProcessCharacter( character );
       
   100 			}
       
   101 
       
   102 			ReportEvent( TEvent.EEventLexingComplete, SymToken.NullToken() );
       
   103 		}
       
   104 
       
   105 		private void StartWorkerThread()
       
   106 		{
       
   107 			lock( this )
       
   108 			{
       
   109 				if	( iWorkerThread == null )
       
   110 				{
       
   111 					ThreadStart threadStart = new ThreadStart( DoLexing );
       
   112 					iWorkerThread = new Thread( threadStart );
       
   113 					iWorkerThread.Name = "SymLexerWorkerThread";
       
   114 					iWorkerThread.IsBackground = true;
       
   115 					iWorkerThread.Priority = ThreadPriority.BelowNormal;
       
   116 					iWorkerThread.Start();
       
   117 				}
       
   118 			}
       
   119 		}
       
   120 		#endregion
       
   121 
       
   122 		#region Internal methods
       
   123 		private void PrepareDefaultWorkers()
       
   124 		{
       
   125 			SymLexerWorkerLine workerLine = new SymLexerWorkerLine( this );
       
   126 			RegisterWorker( workerLine);
       
   127 			iPositionProvider = workerLine;
       
   128 			//
       
   129 			SymLexerWorkerWord workerWord = new SymLexerWorkerWord( this );
       
   130 			RegisterWorker( workerWord );
       
   131 		}
       
   132 
       
   133 		private void ProcessCharacter( char aCharacter )
       
   134 		{
       
   135 			int count = iWorkers.Count;
       
   136 			//
       
   137 			for( int i=0; i<count; i++ )
       
   138 			{
       
   139 				SymLexerWorker worker = (SymLexerWorker) iWorkers[ i ];
       
   140 				bool consumed = worker.ProcessCharacter( aCharacter );
       
   141 				//
       
   142 				if	( consumed )
       
   143 				{
       
   144 					break;
       
   145 				}
       
   146 			}
       
   147 		}
       
   148 
       
   149 		private void ReportEvent( TEvent aEvent, SymToken aToken )
       
   150 		{
       
   151 			if	( LexerObservers != null )
       
   152 			{
       
   153 				LexerObservers( this, aEvent, aToken );
       
   154 			}
       
   155 		}
       
   156 		#endregion
       
   157 
       
   158 		#region ISymLexerPositionObserver Members
       
   159 		public void HandleEndOfLineDetected( SymTextPosition aEOLPosition )
       
   160 		{
       
   161 			// Report to children
       
   162 			int count = iWorkers.Count;
       
   163 			for( int i=0; i<count; i++ )
       
   164 			{
       
   165 				SymLexerWorker worker = (SymLexerWorker) iWorkers[ i ];
       
   166 				worker.StartedNewLine( aEOLPosition );
       
   167 			}
       
   168 
       
   169 			// Add a token for the new line - do this after reporting the
       
   170 			// event to the children so that they can flush any data
       
   171 			// they have before we append the new line.
       
   172 			SymToken token = new SymToken( "", SymToken.TClass.EClassNewLine, aEOLPosition );
       
   173 			FlushToken( token );
       
   174 
       
   175 			// Report new line event
       
   176 			ReportEvent( TEvent.EEventLexingNewLine, token );
       
   177 		}
       
   178 		#endregion
       
   179 
       
   180 		#region Data members
       
   181 		private SymStream iStream;
       
   182 		private Thread iWorkerThread;
       
   183 		private ISymLexerPositionProvider iPositionProvider;
       
   184 		private ArrayList iWorkers = new ArrayList( 4 );
       
   185 		#endregion
       
   186 	}
       
   187 }