factor some pioneering code into a the stable building block class DSNLEXER, generalize expected valued for name and value within the template field parser.

This commit is contained in:
Dick Hollenbeck 2010-06-18 11:00:16 -05:00
parent 1ff2b5596f
commit 0361ad6a55
5 changed files with 124 additions and 74 deletions

View File

@ -192,6 +192,18 @@ wxString DSNLEXER::GetTokenString( int aTok )
} }
bool DSNLEXER::IsSymbol( int aTok )
{
// This is static and not inline to reduce code space.
// if aTok is >= 0, then it is a coincidental match to a keyword.
return aTok==DSN_SYMBOL
|| aTok==DSN_STRING
|| aTok>=0
;
}
void DSNLEXER::ThrowIOError( wxString aText, int charOffset ) throw (IOError) void DSNLEXER::ThrowIOError( wxString aText, int charOffset ) throw (IOError)
{ {
// append to aText, do not overwrite // append to aText, do not overwrite
@ -235,6 +247,39 @@ void DSNLEXER::Unexpected( const wxString& text ) throw( IOError )
} }
void DSNLEXER::NeedLEFT() throw( IOError )
{
int tok = NextTok();
if( tok != DSN_LEFT )
Expecting( DSN_LEFT );
}
void DSNLEXER::NeedRIGHT() throw( IOError )
{
int tok = NextTok();
if( tok != DSN_RIGHT )
Expecting( DSN_RIGHT );
}
int DSNLEXER::NeedSYMBOL() throw( IOError )
{
int tok = NextTok();
if( !IsSymbol( tok ) )
Expecting( DSN_SYMBOL );
return tok;
}
int DSNLEXER::NeedSYMBOLorNUMBER() throw( IOError )
{
int tok = NextTok();
if( !IsSymbol( tok ) && tok!=DSN_NUMBER )
Expecting( _("symbol|number") );
return tok;
}
/** /**
* Function isspace * Function isspace
* strips the upper bits of the int to ensure the value passed to ::isspace() is * strips the upper bits of the int to ensure the value passed to ::isspace() is

View File

@ -50,35 +50,29 @@ void TEMPLATE_FIELDNAME::Parse( DSNLEXER* in ) throw( IOError )
{ {
TFIELD_T tok; TFIELD_T tok;
if( (tok = (TFIELD_T) in->NextTok()) != T_LEFT ) in->NeedLEFT(); // begin (name ...)
in->Expecting( T_LEFT );
if( (tok = (TFIELD_T) in->NextTok()) != T_name ) if( (tok = (TFIELD_T) in->NextTok()) != T_name )
in->Expecting( T_name ); in->Expecting( T_name );
if( (tok = (TFIELD_T) in->NextTok()) != T_SYMBOL && tok!=T_STRING ) in->NeedSYMBOLorNUMBER();
in->Expecting( _("field's name") );
m_Name = CONV_FROM_UTF8( in->CurText() ); m_Name = CONV_FROM_UTF8( in->CurText() );
if( (tok = (TFIELD_T) in->NextTok()) != T_RIGHT ) in->NeedRIGHT(); // end (name ...)
in->Expecting( T_RIGHT );
while( (tok = (TFIELD_T) in->NextTok() ) != T_RIGHT && tok != T_EOF ) while( (tok = (TFIELD_T) in->NextTok() ) != T_RIGHT && tok != T_EOF )
{ {
// "visible" has no '(' prefix, "value" does, so T_LEFT is optional.
if( tok == T_LEFT ) if( tok == T_LEFT )
tok = (TFIELD_T) in->NextTok(); tok = (TFIELD_T) in->NextTok();
switch( tok ) switch( tok )
{ {
case T_value: case T_value:
if( (tok = (TFIELD_T) in->NextTok()) != T_SYMBOL && tok!=T_STRING ) in->NeedSYMBOLorNUMBER();
in->Expecting( _("field's value") );
m_Value = CONV_FROM_UTF8( in->CurText() ); m_Value = CONV_FROM_UTF8( in->CurText() );
in->NeedRIGHT();
if( (tok = (TFIELD_T) in->NextTok()) != T_RIGHT )
in->Expecting( T_RIGHT );
break; break;
case T_visible: case T_visible:
@ -86,7 +80,7 @@ void TEMPLATE_FIELDNAME::Parse( DSNLEXER* in ) throw( IOError )
break; break;
default: default:
in->Unexpected( CONV_FROM_UTF8( in->CurText() ) ); in->Expecting( wxT( "value|visible" ) );
break; break;
} }
} }

View File

@ -208,10 +208,9 @@ public:
return old; return old;
} }
/** /**
* Function NextTok * Function NextTok
* returns the next token found in the input file or T_EOF when reaching * returns the next token found in the input file or DSN_EOF when reaching
* the end of file. Users should wrap this function to return an enum * the end of file. Users should wrap this function to return an enum
* to aid in grammar debugging while running under a debugger, but leave * to aid in grammar debugging while running under a debugger, but leave
* this lower level function returning an int (so the enum does not collide * this lower level function returning an int (so the enum does not collide
@ -221,6 +220,13 @@ public:
*/ */
int NextTok() throw (IOError); int NextTok() throw (IOError);
/**
* Function IsSymbol
* tests a token to see if it is a symbol. This means it cannot be a
* special delimiter character such as DSN_LEFT, DSN_RIGHT, DSN_QUOTE, etc. It may
* however, coincidentally match a keyword and still be a symbol.
*/
static bool IsSymbol( int aTok );
/** /**
* Function ThrowIOError * Function ThrowIOError
@ -264,6 +270,42 @@ public:
*/ */
void Unexpected( const wxString& aErrorMsg ) throw( IOError ); void Unexpected( const wxString& aErrorMsg ) throw( IOError );
/**
* Function NeedLEFT
* calls NextTok() and then verifies that the token read in is a DSN_LEFT.
* If it is not, an IOError is thrown.
* @throw IOError, if the next token is not a DSN_LEFT
*/
void NeedLEFT() throw( IOError );
/**
* Function NeedRIGHT
* calls NextTok() and then verifies that the token read in is a DSN_RIGHT.
* If it is not, an IOError is thrown.
* @throw IOError, if the next token is not a DSN_RIGHT
*/
void NeedRIGHT() throw( IOError );
/**
* Function NeedSYMBOL
* calls NextTok() and then verifies that the token read in
* satisfies bool IsSymbol().
* If not, an IOError is thrown.
* @return int - the actual token read in.
* @throw IOError, if the next token does not satisfy IsSymbol()
*/
int NeedSYMBOL() throw( IOError );
/**
* Function NeedSYMBOLorNUMBER
* calls NextTok() and then verifies that the token read in
* satisfies bool IsSymbol() or tok==DSN_NUMBER.
* If not, an IOError is thrown.
* @return int - the actual token read in.
* @throw IOError, if the next token does not satisfy the above test
*/
int NeedSYMBOLorNUMBER() throw( IOError );
/** /**
* Function GetTokenText * Function GetTokenText
* returns the C string representation of a DSN_T value. * returns the C string representation of a DSN_T value.

View File

@ -547,21 +547,12 @@ void SPECCTRA_DB::ThrowIOError( const wxChar* fmt, ... ) throw( IOError )
} }
void SPECCTRA_DB::expecting( DSN_T aTok ) throw( IOError )
{
lexer->Expecting( aTok );
}
void SPECCTRA_DB::expecting( const char* text ) throw( IOError ) void SPECCTRA_DB::expecting( const char* text ) throw( IOError )
{ {
wxString errText = CONV_FROM_UTF8( text ); wxString errText = CONV_FROM_UTF8( text );
lexer->Expecting( errText ); lexer->Expecting( errText );
} }
void SPECCTRA_DB::unexpected( DSN_T aTok ) throw( IOError )
{
lexer->Unexpected( aTok );
}
void SPECCTRA_DB::unexpected( const char* text ) throw( IOError ) void SPECCTRA_DB::unexpected( const char* text ) throw( IOError )
{ {
@ -576,47 +567,6 @@ DSN_T SPECCTRA_DB::nextTok()
return ret; return ret;
} }
bool SPECCTRA_DB::isSymbol( DSN_T aTok )
{
// if aTok is >= 0, then it might be a coincidental match to a keyword.
return aTok==T_SYMBOL
|| aTok==T_STRING
|| aTok>=0
;
}
void SPECCTRA_DB::needLEFT() throw( IOError )
{
DSN_T tok = nextTok();
if( tok != T_LEFT )
expecting( T_LEFT );
}
void SPECCTRA_DB::needRIGHT() throw( IOError )
{
DSN_T tok = nextTok();
if( tok != T_RIGHT )
expecting( T_RIGHT );
}
DSN_T SPECCTRA_DB::needSYMBOL() throw( IOError )
{
DSN_T tok = nextTok();
if( !isSymbol( tok ) )
expecting( T_SYMBOL );
return tok;
}
DSN_T SPECCTRA_DB::needSYMBOLorNUMBER() throw( IOError )
{
DSN_T tok = nextTok();
if( !isSymbol( tok ) && tok!=T_NUMBER )
expecting( "symbol|number" );
return tok;
}
void SPECCTRA_DB::readCOMPnPIN( std::string* component_id, std::string* pin_id ) throw( IOError ) void SPECCTRA_DB::readCOMPnPIN( std::string* component_id, std::string* pin_id ) throw( IOError )
{ {
DSN_T tok; DSN_T tok;

View File

@ -4039,15 +4039,16 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
*/ */
DSN_T nextTok(); DSN_T nextTok();
/** /**
* Function isSymbol * Function isSymbol
* tests a token to see if it is a symbol. This means it cannot be a * tests a token to see if it is a symbol. This means it cannot be a
* special delimiter character such as T_LEFT, T_RIGHT, T_QUOTE, etc. It may * special delimiter character such as T_LEFT, T_RIGHT, T_QUOTE, etc. It may
* however, coincidentally match a keyword and still be a symbol. * however, coincidentally match a keyword and still be a symbol.
*/ */
static bool isSymbol( DSN_T aTok ); static bool isSymbol( DSN_T aTok )
{
return DSNLEXER::IsSymbol( aTok );
}
/** /**
* Function needLEFT * Function needLEFT
@ -4055,7 +4056,10 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
* If it is not, an IOError is thrown. * If it is not, an IOError is thrown.
* @throw IOError, if the next token is not a T_LEFT * @throw IOError, if the next token is not a T_LEFT
*/ */
void needLEFT() throw( IOError ); void needLEFT() throw( IOError )
{
lexer->NeedLEFT();
}
/** /**
* Function needRIGHT * Function needRIGHT
@ -4063,7 +4067,10 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
* If it is not, an IOError is thrown. * If it is not, an IOError is thrown.
* @throw IOError, if the next token is not a T_RIGHT * @throw IOError, if the next token is not a T_RIGHT
*/ */
void needRIGHT() throw( IOError ); void needRIGHT() throw( IOError )
{
lexer->NeedRIGHT();
}
/** /**
* Function needSYMBOL * Function needSYMBOL
@ -4073,7 +4080,10 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
* @return DSN_T - the actual token read in. * @return DSN_T - the actual token read in.
* @throw IOError, if the next token does not satisfy isSymbol() * @throw IOError, if the next token does not satisfy isSymbol()
*/ */
DSN_T needSYMBOL() throw( IOError ); DSN_T needSYMBOL() throw( IOError )
{
return (DSN_T) lexer->NeedSYMBOL();
}
/** /**
* Function needSYMBOLorNUMBER * Function needSYMBOLorNUMBER
@ -4083,7 +4093,10 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
* @return DSN_T - the actual token read in. * @return DSN_T - the actual token read in.
* @throw IOError, if the next token does not satisfy the above test * @throw IOError, if the next token does not satisfy the above test
*/ */
DSN_T needSYMBOLorNUMBER() throw( IOError ); DSN_T needSYMBOLorNUMBER() throw( IOError )
{
return (DSN_T) lexer->NeedSYMBOLorNUMBER();
}
/** /**
* Function readCOMPnPIN * Function readCOMPnPIN
@ -4127,9 +4140,15 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
* @param int is the token type which was expected at the current input location. * @param int is the token type which was expected at the current input location.
* @throw IOError with the location within the input file of the problem. * @throw IOError with the location within the input file of the problem.
*/ */
void expecting( DSN_T aTok ) throw( IOError ); void expecting( DSN_T aTok ) throw( IOError )
{
lexer->Expecting( aTok );
}
void unexpected( DSN_T aTok ) throw( IOError )
{
lexer->Unexpected( aTok );
}
void expecting( const char* text ) throw( IOError ); void expecting( const char* text ) throw( IOError );
void unexpected( DSN_T aTok ) throw( IOError );
void unexpected( const char* text ) throw( IOError ); void unexpected( const char* text ) throw( IOError );
void doPCB( PCB* growth ) throw(IOError); void doPCB( PCB* growth ) throw(IOError);