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)
{
// 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
* 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;
if( (tok = (TFIELD_T) in->NextTok()) != T_LEFT )
in->Expecting( T_LEFT );
in->NeedLEFT(); // begin (name ...)
if( (tok = (TFIELD_T) in->NextTok()) != T_name )
in->Expecting( T_name );
if( (tok = (TFIELD_T) in->NextTok()) != T_SYMBOL && tok!=T_STRING )
in->Expecting( _("field's name") );
in->NeedSYMBOLorNUMBER();
m_Name = CONV_FROM_UTF8( in->CurText() );
if( (tok = (TFIELD_T) in->NextTok()) != T_RIGHT )
in->Expecting( T_RIGHT );
in->NeedRIGHT(); // end (name ...)
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 )
tok = (TFIELD_T) in->NextTok();
switch( tok )
{
case T_value:
if( (tok = (TFIELD_T) in->NextTok()) != T_SYMBOL && tok!=T_STRING )
in->Expecting( _("field's value") );
in->NeedSYMBOLorNUMBER();
m_Value = CONV_FROM_UTF8( in->CurText() );
if( (tok = (TFIELD_T) in->NextTok()) != T_RIGHT )
in->Expecting( T_RIGHT );
in->NeedRIGHT();
break;
case T_visible:
@ -86,7 +80,7 @@ void TEMPLATE_FIELDNAME::Parse( DSNLEXER* in ) throw( IOError )
break;
default:
in->Unexpected( CONV_FROM_UTF8( in->CurText() ) );
in->Expecting( wxT( "value|visible" ) );
break;
}
}

View File

@ -208,10 +208,9 @@ public:
return old;
}
/**
* 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
* 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
@ -221,6 +220,13 @@ public:
*/
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
@ -264,6 +270,42 @@ public:
*/
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
* 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 )
{
wxString errText = CONV_FROM_UTF8( text );
lexer->Expecting( errText );
}
void SPECCTRA_DB::unexpected( DSN_T aTok ) throw( IOError )
{
lexer->Unexpected( aTok );
}
void SPECCTRA_DB::unexpected( const char* text ) throw( IOError )
{
@ -576,47 +567,6 @@ DSN_T SPECCTRA_DB::nextTok()
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 )
{
DSN_T tok;

View File

@ -4039,15 +4039,16 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
*/
DSN_T nextTok();
/**
* Function isSymbol
* 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
* 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
@ -4055,7 +4056,10 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
* If it is not, an IOError is thrown.
* @throw IOError, if the next token is not a T_LEFT
*/
void needLEFT() throw( IOError );
void needLEFT() throw( IOError )
{
lexer->NeedLEFT();
}
/**
* Function needRIGHT
@ -4063,7 +4067,10 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
* If it is not, an IOError is thrown.
* @throw IOError, if the next token is not a T_RIGHT
*/
void needRIGHT() throw( IOError );
void needRIGHT() throw( IOError )
{
lexer->NeedRIGHT();
}
/**
* Function needSYMBOL
@ -4073,7 +4080,10 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
* @return DSN_T - the actual token read in.
* @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
@ -4083,7 +4093,10 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
* @return DSN_T - the actual token read in.
* @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
@ -4127,9 +4140,15 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
* @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.
*/
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 unexpected( DSN_T aTok ) throw( IOError );
void unexpected( const char* text ) throw( IOError );
void doPCB( PCB* growth ) throw(IOError);