mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
350 lines
8.6 KiB
350 lines
8.6 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1991 - 2000.
|
|
//
|
|
// File: State.cxx
|
|
//
|
|
// Contents: Finite automata state classes
|
|
//
|
|
// Classes:
|
|
//
|
|
// History: 01-21-92 KyleP Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include <pch.cxx>
|
|
#pragma hdrstop
|
|
|
|
#include <state.hxx>
|
|
|
|
#include "stateset.hxx"
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CNFAState::CNFAState, public
|
|
//
|
|
// Synopsis: Copy constructor
|
|
//
|
|
// Arguments: [src] -- Source
|
|
//
|
|
// History: 13-Jul-95 KyleP Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
CNFAState::CNFAState( CNFAState const & src )
|
|
: CFAState( src ),
|
|
_pmoveRest( 0 ),
|
|
_cmoveRest( src._cmoveRest ),
|
|
_cMove( src._cMove )
|
|
{
|
|
if ( _cmoveRest > 0 )
|
|
{
|
|
_pmoveRest = new CMove [_cmoveRest];
|
|
RtlCopyMemory( _pmoveRest, src._pmoveRest, _cmoveRest * sizeof(_pmoveRest[0]) );
|
|
}
|
|
|
|
RtlCopyMemory( _moveFirst, src._moveFirst, sizeof(_moveFirst) );
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CNFAState::Init, public
|
|
//
|
|
// Synopsis: Copy initializer
|
|
//
|
|
// Arguments: [src] -- Source
|
|
//
|
|
// History: 15-Jul-96 KyleP Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
void CNFAState::Init( CNFAState & src )
|
|
{
|
|
CFAState::Init( src.StateNumber() );
|
|
|
|
if ( src.IsFinal() )
|
|
MakeFinal();
|
|
|
|
_cMove = src._cMove;
|
|
RtlCopyMemory( _moveFirst, src._moveFirst, sizeof(_moveFirst) );
|
|
|
|
_cmoveRest = src._cmoveRest;
|
|
_pmoveRest = src._pmoveRest;
|
|
|
|
src._cMove = 0;
|
|
src._cmoveRest = 0;
|
|
src._pmoveRest = 0;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CNFAState::operator =, public
|
|
//
|
|
// Synopsis: Assignment operator
|
|
//
|
|
// Arguments: [src] -- Source
|
|
//
|
|
// History: 13-Jul-95 KyleP Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
inline void * operator new( size_t, CNFAState * pthis )
|
|
{
|
|
return pthis;
|
|
}
|
|
|
|
#if _MSC_VER >= 1200
|
|
inline void operator delete( void * p, CNFAState * pthis ) {}
|
|
#endif
|
|
|
|
CNFAState & CNFAState::operator =( CNFAState const & src )
|
|
{
|
|
CNFAState::~CNFAState();
|
|
|
|
new (this) CNFAState( src );
|
|
|
|
return *this;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CNFAState::AddTransition, public
|
|
//
|
|
// Synopsis: Add new state transition.
|
|
//
|
|
// Arguments: [symbol] -- On this symbol to...
|
|
// [StateNum] -- this state.
|
|
//
|
|
// History: 20-Jan-92 KyleP Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
void CNFAState::AddTransition( UINT symbol, UINT StateNum )
|
|
{
|
|
//
|
|
// First look for an exact match. If this transition exists
|
|
// then don't add it again.
|
|
//
|
|
|
|
for ( int i = CNFAState_cFirst-1; i >= 0; i--)
|
|
{
|
|
if ( _moveFirst[i]._symbol == symbol &&
|
|
_moveFirst[i]._iState == StateNum )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( _cMove > CNFAState_cFirst )
|
|
{
|
|
for ( int i = _cMove - CNFAState_cFirst - 1; i >= 0; i--)
|
|
{
|
|
if ( _pmoveRest[i]._symbol == symbol &&
|
|
_pmoveRest[i]._iState == StateNum )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// New transition. Add it.
|
|
//
|
|
|
|
if ( _cMove < CNFAState_cFirst )
|
|
{
|
|
//
|
|
// Fits in the first (object based) set of moves.
|
|
//
|
|
|
|
_moveFirst[_cMove] = CMove( symbol, StateNum );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Overflow set of moves.
|
|
//
|
|
|
|
if ( _cMove - CNFAState_cFirst >= _cmoveRest )
|
|
{
|
|
vqDebugOut(( DEB_ITRACE,
|
|
"Growing NFA State transition array.\n" ));
|
|
CMove * oldpmoveRest = _pmoveRest;
|
|
UINT oldcmoveRest = _cmoveRest;
|
|
|
|
_cmoveRest = (_cmoveRest == 0) ? 2 : _cmoveRest + 5;
|
|
|
|
_pmoveRest = (CMove *) new char [ _cmoveRest * sizeof( CMove ) ];
|
|
|
|
memcpy( _pmoveRest, oldpmoveRest, oldcmoveRest * sizeof( CMove ) );
|
|
delete oldpmoveRest;
|
|
}
|
|
|
|
_pmoveRest[_cMove - CNFAState_cFirst] = CMove( symbol, StateNum );
|
|
}
|
|
|
|
++_cMove;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CNFAState::RemoveTransition, public
|
|
//
|
|
// Synopsis: Removes a transition.
|
|
//
|
|
// Arguments: [symbol] -- On this symbol to...
|
|
// [StateNum] -- this state.
|
|
//
|
|
// History: 20-Jan-92 KyleP Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
void CNFAState::RemoveTransition( UINT symbol, UINT StateNum )
|
|
{
|
|
//
|
|
// Find the transition
|
|
//
|
|
|
|
for ( int i = CNFAState_cFirst-1; i >= 0; i--)
|
|
{
|
|
if ( _moveFirst[i]._symbol == symbol &&
|
|
_moveFirst[i]._iState == StateNum )
|
|
{
|
|
//
|
|
// Move the last transition to this place.
|
|
//
|
|
|
|
if ( _cMove > CNFAState_cFirst )
|
|
{
|
|
_moveFirst[i] = _pmoveRest[_cMove - CNFAState_cFirst - 1];
|
|
}
|
|
else
|
|
{
|
|
_moveFirst[i] = _moveFirst[ _cMove - 1 ];
|
|
}
|
|
|
|
_cMove--;
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( _cMove > CNFAState_cFirst )
|
|
{
|
|
for ( int i = _cMove - CNFAState_cFirst - 1; i >= 0; i--)
|
|
{
|
|
if ( _pmoveRest[i]._symbol == symbol &&
|
|
_pmoveRest[i]._iState == StateNum )
|
|
{
|
|
_pmoveRest[i] = _pmoveRest[ _cMove - CNFAState_cFirst - 1 ];
|
|
|
|
_cMove--;
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CNFAState::Move, public
|
|
//
|
|
// Effects: Adds to [ss] the set of states that can be reached from
|
|
// this state on [symbol].
|
|
//
|
|
// Arguments: [ss] -- Output state set.
|
|
// [symbol] -- Input symbol.
|
|
//
|
|
// History: 20-Jan-92 KyleP Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
void CNFAState::Move( CStateSet & ss, UINT symbol )
|
|
{
|
|
for ( int i = (_cMove <= CNFAState_cFirst) ? _cMove-1 : CNFAState_cFirst-1;
|
|
i >= 0;
|
|
i--)
|
|
{
|
|
if ( _moveFirst[i]._symbol == symbol ||
|
|
( _moveFirst[i]._symbol == symAny &&
|
|
symbol != symEpsilon ))
|
|
{
|
|
ss.Add( _moveFirst[i]._iState );
|
|
}
|
|
}
|
|
|
|
for ( i = _cMove - CNFAState_cFirst - 1; i >= 0; i-- )
|
|
{
|
|
if ( _pmoveRest[i]._symbol == symbol ||
|
|
( _pmoveRest[i]._symbol == symAny &&
|
|
symbol != symEpsilon &&
|
|
symbol != symDot ))
|
|
{
|
|
ss.Add( _pmoveRest[i]._iState );
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Debug methods
|
|
//
|
|
|
|
#if (CIDBG == 1)
|
|
|
|
void CFAState::Display()
|
|
{
|
|
vqDebugOut(( DEB_REGEX,
|
|
"State: %u, Final = %c", _iState, _fFinal ? 'T' : 'F' ));
|
|
}
|
|
|
|
void CNFAState::Display()
|
|
{
|
|
CFAState::Display();
|
|
vqDebugOut(( DEB_REGEX | DEB_NOCOMPNAME, " -- %u transitions\n", _cMove ));
|
|
|
|
for ( int i = (_cMove <= CNFAState_cFirst) ? _cMove-1 : CNFAState_cFirst-1;
|
|
i >= 0;
|
|
i--)
|
|
{
|
|
if ( _moveFirst[i]._symbol == symEpsilon)
|
|
{
|
|
vqDebugOut(( DEB_REGEX | DEB_NOCOMPNAME, "\tEpsilon " ));
|
|
}
|
|
else if ( _moveFirst[i]._symbol == symAny )
|
|
{
|
|
vqDebugOut(( DEB_REGEX | DEB_NOCOMPNAME, "\tAny " ));
|
|
}
|
|
else
|
|
{
|
|
vqDebugOut(( DEB_REGEX | DEB_NOCOMPNAME,
|
|
"\t%u ", _moveFirst[i]._symbol ));
|
|
}
|
|
|
|
vqDebugOut(( DEB_REGEX | DEB_NOCOMPNAME,
|
|
"--> %u\n", _moveFirst[i]._iState ));
|
|
}
|
|
|
|
for ( i = _cMove - CNFAState_cFirst - 1; i >= 0; i-- )
|
|
{
|
|
if ( _pmoveRest[i]._symbol == symEpsilon)
|
|
{
|
|
vqDebugOut(( DEB_REGEX | DEB_NOCOMPNAME, "\tEpsilon " ));
|
|
}
|
|
else if ( _pmoveRest[i]._symbol == symAny )
|
|
{
|
|
vqDebugOut(( DEB_REGEX | DEB_NOCOMPNAME, "\tAny " ));
|
|
}
|
|
else
|
|
{
|
|
vqDebugOut(( DEB_REGEX | DEB_NOCOMPNAME,
|
|
"\t%u ", _pmoveRest[i]._symbol ));
|
|
}
|
|
|
|
vqDebugOut(( DEB_REGEX | DEB_NOCOMPNAME,
|
|
"--> %u\n", _pmoveRest[i]._iState ));
|
|
}
|
|
}
|
|
|
|
#endif // (CIDBG == 1)
|