more specctra work
This commit is contained in:
parent
1afb0498aa
commit
0d3fd5d17f
112
pcbnew/dsn.cpp
112
pcbnew/dsn.cpp
|
@ -156,6 +156,7 @@ const static KEYWORD tokens[] = {
|
||||||
TOKDEF(host_cad),
|
TOKDEF(host_cad),
|
||||||
TOKDEF(host_version),
|
TOKDEF(host_version),
|
||||||
TOKDEF(image),
|
TOKDEF(image),
|
||||||
|
TOKDEF(image_conductor),
|
||||||
TOKDEF(image_image),
|
TOKDEF(image_image),
|
||||||
TOKDEF(image_image_spacing),
|
TOKDEF(image_image_spacing),
|
||||||
TOKDEF(image_outline_clearance),
|
TOKDEF(image_outline_clearance),
|
||||||
|
@ -464,6 +465,25 @@ int LINE_READER::ReadLine() throw (IOError)
|
||||||
//-----<LEXER>-------------------------------------------------------------
|
//-----<LEXER>-------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
LEXER::LEXER( FILE* aFile, const wxString& aFilename ) :
|
||||||
|
reader( aFile, 4096 )
|
||||||
|
{
|
||||||
|
curTok = T_END;
|
||||||
|
stringDelimiter = '"';
|
||||||
|
filename = aFilename;
|
||||||
|
|
||||||
|
space_in_quoted_tokens = false;
|
||||||
|
|
||||||
|
// "start" should never change until we change the reader. The DSN
|
||||||
|
// format spec supports an include file mechanism but we can add that later
|
||||||
|
// using a std::stack to hold a stack of LINE_READERs to track nesting.
|
||||||
|
start = (char*) reader;
|
||||||
|
|
||||||
|
limit = start;
|
||||||
|
next = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int LEXER::findToken( const std::string& tok )
|
int LEXER::findToken( const std::string& tok )
|
||||||
{
|
{
|
||||||
// convert to lower case once, this should be faster than using strcasecmp()
|
// convert to lower case once, this should be faster than using strcasecmp()
|
||||||
|
@ -486,15 +506,69 @@ int LEXER::findToken( const std::string& tok )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString LEXER::GetTokenText( DSN_T aTok )
|
||||||
|
{
|
||||||
|
wxString ret;
|
||||||
|
|
||||||
|
if( aTok < 0 )
|
||||||
|
{
|
||||||
|
switch( aTok )
|
||||||
|
{
|
||||||
|
case T_QUOTE_DEF:
|
||||||
|
ret << _("'quoted text delimiter'");
|
||||||
|
break;
|
||||||
|
case T_DASH:
|
||||||
|
ret << wxT( "'-'" );
|
||||||
|
break;
|
||||||
|
case T_SYMBOL:
|
||||||
|
ret << _("'symbol'");
|
||||||
|
break;
|
||||||
|
case T_NUMBER:
|
||||||
|
ret << _("'number'");
|
||||||
|
break;
|
||||||
|
case T_RIGHT:
|
||||||
|
ret << wxT( "')'" );
|
||||||
|
break;
|
||||||
|
case T_LEFT:
|
||||||
|
ret << wxT( "'('" );
|
||||||
|
break;
|
||||||
|
case T_STRING:
|
||||||
|
ret << _("\"quoted string\"");
|
||||||
|
break;
|
||||||
|
case T_EOF:
|
||||||
|
ret << _("'end of file'");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret << wxT("'") << CONV_FROM_UTF8( tokens[aTok].name ) << wxT("'");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LEXER::ThrowIOError( wxString aText, int charOffset ) throw (IOError)
|
||||||
|
{
|
||||||
|
aText << wxT(" ") << _("in file") << wxT(" \"") << filename
|
||||||
|
<< wxT("\" ") << _("on line") << wxT(" ") << reader.LineNumber()
|
||||||
|
<< wxT(" ") << _("at offset") << wxT(" ") << charOffset;
|
||||||
|
|
||||||
|
throw IOError( aText );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DSN_T LEXER::NextTok() throw (IOError)
|
DSN_T LEXER::NextTok() throw (IOError)
|
||||||
{
|
{
|
||||||
char* head;
|
char* cur = next;
|
||||||
char* cur;
|
char* head = cur;
|
||||||
|
|
||||||
lastTok = curTok;
|
lastTok = curTok;
|
||||||
|
|
||||||
cur = next;
|
|
||||||
|
|
||||||
if( curTok != T_EOF )
|
if( curTok != T_EOF )
|
||||||
{
|
{
|
||||||
if( cur >= limit )
|
if( cur >= limit )
|
||||||
|
@ -520,15 +594,27 @@ L_read:
|
||||||
// switching the string_quote character
|
// switching the string_quote character
|
||||||
if( lastTok == T_string_quote )
|
if( lastTok == T_string_quote )
|
||||||
{
|
{
|
||||||
|
static const wxString errtxt( _("String delimiter must be a single character of ', \", or $"));
|
||||||
|
|
||||||
|
char cc = *cur;
|
||||||
|
switch( cc )
|
||||||
|
{
|
||||||
|
case '\'':
|
||||||
|
case '$':
|
||||||
|
case '"':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ThrowIOError( errtxt, CurOffset() );
|
||||||
|
}
|
||||||
|
|
||||||
curText.clear();
|
curText.clear();
|
||||||
curText += *cur;
|
curText += cc;
|
||||||
|
|
||||||
head = cur+1;
|
head = cur+1;
|
||||||
|
|
||||||
if( head<limit && *head!=')' && *head!='(' && !isspace(*head) )
|
if( head<limit && *head!=')' && *head!='(' && !isspace(*head) )
|
||||||
{
|
{
|
||||||
wxString errtxt(_("String delimiter char must be a single char") );
|
ThrowIOError( errtxt, CurOffset() );
|
||||||
ThrowIOError( errtxt, cur-start+1 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
curTok = T_QUOTE_DEF;
|
curTok = T_QUOTE_DEF;
|
||||||
|
@ -578,17 +664,17 @@ L_read:
|
||||||
// a quoted string
|
// a quoted string
|
||||||
else if( *cur == stringDelimiter )
|
else if( *cur == stringDelimiter )
|
||||||
{
|
{
|
||||||
++cur; // skip over the leading "
|
++cur; // skip over the leading delimiter: ",', or $
|
||||||
|
|
||||||
head = cur;
|
head = cur;
|
||||||
|
|
||||||
while( head<limit && *head!=stringDelimiter )
|
while( head<limit && !isStringTerminator( *head ) )
|
||||||
++head;
|
++head;
|
||||||
|
|
||||||
if( head >= limit )
|
if( head >= limit )
|
||||||
{
|
{
|
||||||
wxString errtxt(_("Un-terminated delimited string") );
|
wxString errtxt(_("Un-terminated delimited string") );
|
||||||
ThrowIOError( errtxt, cur-start+1 );
|
ThrowIOError( errtxt, CurOffset() );
|
||||||
}
|
}
|
||||||
|
|
||||||
curText.clear();
|
curText.clear();
|
||||||
|
@ -628,7 +714,9 @@ L_read:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exit: // single point of exit
|
exit: // single point of exit
|
||||||
|
|
||||||
|
curOffset = cur - start;
|
||||||
|
|
||||||
next = head;
|
next = head;
|
||||||
|
|
||||||
|
@ -640,7 +728,7 @@ exit: // single point of exit
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(STANDALONE)
|
#if 0 && defined(STANDALONE)
|
||||||
|
|
||||||
// stand alone testing
|
// stand alone testing
|
||||||
|
|
||||||
|
|
72
pcbnew/dsn.h
72
pcbnew/dsn.h
|
@ -42,11 +42,10 @@ namespace DSN {
|
||||||
enum DSN_T {
|
enum DSN_T {
|
||||||
|
|
||||||
// the first few are special (the uppercase ones)
|
// the first few are special (the uppercase ones)
|
||||||
T_QUOTE_DEF = -9,
|
T_QUOTE_DEF = -8,
|
||||||
T_DASH = -8,
|
T_DASH = -7,
|
||||||
T_SYMBOL = -7,
|
T_SYMBOL = -6,
|
||||||
T_NUMBER = -6,
|
T_NUMBER = -5,
|
||||||
T_NONE = -5, // not a token
|
|
||||||
T_RIGHT = -4, // right bracket, ')'
|
T_RIGHT = -4, // right bracket, ')'
|
||||||
T_LEFT = -3, // left bracket, '('
|
T_LEFT = -3, // left bracket, '('
|
||||||
T_STRING = -2, // a quoted string, stripped of the quotes
|
T_STRING = -2, // a quoted string, stripped of the quotes
|
||||||
|
@ -157,6 +156,7 @@ enum DSN_T {
|
||||||
T_host_cad,
|
T_host_cad,
|
||||||
T_host_version,
|
T_host_version,
|
||||||
T_image,
|
T_image,
|
||||||
|
T_image_conductor,
|
||||||
T_image_image,
|
T_image_image,
|
||||||
T_image_image_spacing,
|
T_image_image_spacing,
|
||||||
T_image_outline_clearance,
|
T_image_outline_clearance,
|
||||||
|
@ -513,8 +513,11 @@ class LEXER
|
||||||
|
|
||||||
LINE_READER reader;
|
LINE_READER reader;
|
||||||
int stringDelimiter;
|
int stringDelimiter;
|
||||||
|
bool space_in_quoted_tokens; ///< blank spaces within quoted strings
|
||||||
|
|
||||||
wxString filename;
|
wxString filename;
|
||||||
int lastTok; ///< curTok from previous NextTok() call.
|
int lastTok; ///< curTok from previous NextTok() call.
|
||||||
|
int curOffset; ///< offset within current line of the current token
|
||||||
|
|
||||||
DSN_T curTok; ///< the current token obtained on last NextTok()
|
DSN_T curTok; ///< the current token obtained on last NextTok()
|
||||||
std::string curText; ///< the text of the current token
|
std::string curText; ///< the text of the current token
|
||||||
|
@ -543,23 +546,21 @@ class LEXER
|
||||||
*/
|
*/
|
||||||
int findToken( const std::string& tok );
|
int findToken( const std::string& tok );
|
||||||
|
|
||||||
|
bool isStringTerminator( char cc )
|
||||||
|
{
|
||||||
|
if( !space_in_quoted_tokens && cc==' ' )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if( cc == stringDelimiter )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LEXER( FILE* aFile, const wxString& aFilename ) :
|
LEXER( FILE* aFile, const wxString& aFilename );
|
||||||
reader( aFile, 4096 )
|
|
||||||
{
|
|
||||||
curTok = T_NONE;
|
|
||||||
stringDelimiter = '"';
|
|
||||||
filename = aFilename;
|
|
||||||
|
|
||||||
// "start" should never change until we change the reader. The DSN
|
|
||||||
// format spec supports an include file mechanism but we can add that later
|
|
||||||
// using a std::stack to hold a stack of LINE_READERs to track nesting.
|
|
||||||
start = (char*) reader;
|
|
||||||
|
|
||||||
limit = start;
|
|
||||||
next = start;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function SetStringDelimiter
|
* Function SetStringDelimiter
|
||||||
|
@ -575,6 +576,19 @@ public:
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function SetSpaceInQuotedTokens
|
||||||
|
* changes the setting controlling whether a space in a quoted string is
|
||||||
|
* a terminator
|
||||||
|
*/
|
||||||
|
bool SetSpaceInQuotedTokens( bool val )
|
||||||
|
{
|
||||||
|
bool old = space_in_quoted_tokens;
|
||||||
|
space_in_quoted_tokens = val;
|
||||||
|
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 T_EOF when reaching
|
||||||
|
@ -590,14 +604,10 @@ public:
|
||||||
* encapsulates the formatting of an error message which contains the exact
|
* encapsulates the formatting of an error message which contains the exact
|
||||||
* location within the input file of a lexical error.
|
* location within the input file of a lexical error.
|
||||||
*/
|
*/
|
||||||
void ThrowIOError( wxString aText, int charOffset ) throw (IOError)
|
void ThrowIOError( wxString aText, int charOffset ) throw (IOError);
|
||||||
{
|
|
||||||
aText << wxT(" ") << _("in file") << wxT(" \"") << filename
|
|
||||||
<< wxT("\" ") << _("on line") << wxT(" ") << reader.LineNumber()
|
|
||||||
<< wxT(" ") << _("at offset") << wxT(" ") << charOffset;
|
|
||||||
|
|
||||||
throw IOError( aText );
|
|
||||||
}
|
wxString GetTokenText( DSN_T aTok );
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -619,6 +629,16 @@ public:
|
||||||
return curTok;
|
return curTok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function CurOffset
|
||||||
|
* returns the char offset within the current line, using a 1 based index.
|
||||||
|
* @return int - a one based index into the current line.
|
||||||
|
*/
|
||||||
|
int CurOffset()
|
||||||
|
{
|
||||||
|
return curOffset + 1;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
#include <boost/ptr_container/ptr_vector.hpp>
|
#include <boost/ptr_container/ptr_vector.hpp>
|
||||||
|
|
||||||
|
#include <wx/ffile.h>
|
||||||
#include "fctsys.h"
|
#include "fctsys.h"
|
||||||
#include "pcbstruct.h"
|
#include "pcbstruct.h"
|
||||||
|
|
||||||
|
@ -43,7 +43,6 @@ namespace DSN {
|
||||||
* is a base class for any DSN element. It is not a parent node so it
|
* is a base class for any DSN element. It is not a parent node so it
|
||||||
* cannot contain other elements but it can be extended to hold fields
|
* cannot contain other elements but it can be extended to hold fields
|
||||||
* for any DSN element which contains no other elements, only fields.
|
* for any DSN element which contains no other elements, only fields.
|
||||||
*/
|
|
||||||
class ELEM
|
class ELEM
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
@ -58,26 +57,24 @@ public:
|
||||||
|
|
||||||
virtual ~ELEM()
|
virtual ~ELEM()
|
||||||
{
|
{
|
||||||
printf("~ELEM(%p %d)\n", this, Type() );
|
// printf("~ELEM(%p %d)\n", this, Type() );
|
||||||
}
|
}
|
||||||
|
|
||||||
DSN_T Type() { return type; }
|
|
||||||
|
|
||||||
virtual void Test()
|
|
||||||
{
|
|
||||||
printf("virtual Test()\n" );
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class PARENT
|
* Class ELEM
|
||||||
* is a base class holder for any DSN element. It can contain other
|
* is a holder for any DSN element. It can contain other
|
||||||
* elements, including elements derived from this class.
|
* elements, including elements derived from this class.
|
||||||
*/
|
*/
|
||||||
class PARENT : public ELEM
|
class ELEM
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
|
DSN_T type;
|
||||||
|
|
||||||
// see http://www.boost.org/libs/ptr_container/doc/ptr_sequence_adapter.html
|
// see http://www.boost.org/libs/ptr_container/doc/ptr_sequence_adapter.html
|
||||||
typedef boost::ptr_vector<ELEM> ELEM_ARRAY;
|
typedef boost::ptr_vector<ELEM> ELEM_ARRAY;
|
||||||
|
|
||||||
|
@ -86,18 +83,53 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PARENT( DSN_T aType ) :
|
ELEM( DSN_T aType ) :
|
||||||
ELEM( aType )
|
type( aType )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~PARENT()
|
virtual ~ELEM()
|
||||||
{
|
{
|
||||||
printf("~PARENT(%p %d)\n", this, Type() );
|
// printf("~ELEM(%p %d)\n", this, Type() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DSN_T Type() { return type; }
|
||||||
|
|
||||||
//-----< list operations >--------------------------------------------
|
//-----< list operations >--------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function FindElem
|
||||||
|
* finds a particular instance number of a given type of ELEM.
|
||||||
|
* @param aType The type of ELEM to find
|
||||||
|
* @param instanceNum The instance number of to find: 0 for first, 1 for second, etc.
|
||||||
|
* @return int - The index into the kids array or -1 if not found.
|
||||||
|
*/
|
||||||
|
int FindElem( DSN_T aType, int instanceNum )
|
||||||
|
{
|
||||||
|
int repeats=0;
|
||||||
|
for( unsigned i=0; i<kids.size(); ++i )
|
||||||
|
{
|
||||||
|
if( kids[i].Type() == aType )
|
||||||
|
{
|
||||||
|
if( repeats == instanceNum )
|
||||||
|
return i;
|
||||||
|
++repeats;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Length
|
||||||
|
* returns the number ELEMs in this ELEM.
|
||||||
|
* @return int - the count of children
|
||||||
|
*/
|
||||||
|
int Length() const
|
||||||
|
{
|
||||||
|
return kids.size();
|
||||||
|
}
|
||||||
|
|
||||||
void Append( ELEM* aElem )
|
void Append( ELEM* aElem )
|
||||||
{
|
{
|
||||||
kids.push_back( aElem );
|
kids.push_back( aElem );
|
||||||
|
@ -115,6 +147,7 @@ public:
|
||||||
return ret.release();
|
return ret.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
ELEM& operator[]( int aIndex )
|
ELEM& operator[]( int aIndex )
|
||||||
{
|
{
|
||||||
return kids[aIndex];
|
return kids[aIndex];
|
||||||
|
@ -124,14 +157,17 @@ public:
|
||||||
{
|
{
|
||||||
return kids[aIndex];
|
return kids[aIndex];
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
void Insert( int aIndex, ELEM* aElem )
|
void Insert( int aIndex, ELEM* aElem )
|
||||||
{
|
{
|
||||||
kids.insert( kids.begin()+aIndex, aElem );
|
kids.insert( kids.begin()+aIndex, aElem );
|
||||||
}
|
}
|
||||||
|
|
||||||
ELEM* At( int aIndex )
|
ELEM* operator[]( int aIndex )
|
||||||
{
|
{
|
||||||
|
// we have varying sized object and are using polymorphism, so we
|
||||||
|
// must return a pointer not a reference.
|
||||||
return &kids[aIndex];
|
return &kids[aIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,20 +175,20 @@ public:
|
||||||
{
|
{
|
||||||
kids.erase( kids.begin()+aIndex );
|
kids.erase( kids.begin()+aIndex );
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class SPECCTRA_DB
|
* Class SPECCTRA_DB
|
||||||
* holds a DSN data tree, usually coming from a DSN file.
|
* holds a DSN data tree, usually coming from a DSN file.
|
||||||
*/
|
*/
|
||||||
class SPECCTRA_DB
|
class SPECCTRA_DB
|
||||||
{
|
{
|
||||||
FILE* fp;
|
LEXER* lexer;
|
||||||
|
|
||||||
|
ELEM* tree;
|
||||||
|
|
||||||
|
FILE* fp;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -164,15 +200,49 @@ class SPECCTRA_DB
|
||||||
*/
|
*/
|
||||||
void print( const char* fmt, ... );
|
void print( const char* fmt, ... );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function nextTok
|
||||||
|
* returns the next token from the lexer.
|
||||||
|
*/
|
||||||
|
DSN_T nextTok();
|
||||||
|
|
||||||
|
void expecting( DSN_T ) throw( IOError );
|
||||||
|
void expecting( const wxChar* text ) throw( IOError );
|
||||||
|
|
||||||
|
void doPCB( ELEM* growth ) throw(IOError);
|
||||||
|
void doPARSER( ELEM* growth ) throw(IOError);
|
||||||
|
void doRESOLUTION( ELEM* growth ) throw(IOError);
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
SPECCTRA_DB( FILE* aFile ) :
|
SPECCTRA_DB()
|
||||||
fp( aFile )
|
|
||||||
{
|
{
|
||||||
|
lexer = 0;
|
||||||
|
tree = 0;
|
||||||
|
fp = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~SPECCTRA_DB()
|
||||||
|
{
|
||||||
|
delete lexer;
|
||||||
|
delete tree;
|
||||||
|
|
||||||
|
if( fp )
|
||||||
|
fclose( fp );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Load
|
||||||
|
* is a recursive descent parser for a DSN file.
|
||||||
|
* @param filename The name of the dsn file to load.
|
||||||
|
* @throw IOError if there is a lexer or parser error.
|
||||||
|
*/
|
||||||
|
void Load( const wxString& filename ) throw( IOError );
|
||||||
|
|
||||||
|
void ThrowIOError( const wxChar* fmt, ... ) throw( IOError );
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function Export
|
* Function Export
|
||||||
|
@ -180,10 +250,261 @@ public:
|
||||||
* @param aBoard The BOARD to save.
|
* @param aBoard The BOARD to save.
|
||||||
*/
|
*/
|
||||||
void Export( BOARD* aBoard );
|
void Export( BOARD* aBoard );
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void SPECCTRA_DB::ThrowIOError( const wxChar* fmt, ... ) throw( IOError )
|
||||||
|
{
|
||||||
|
wxString errText;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start( args, fmt );
|
||||||
|
errText.PrintfV( fmt, args );
|
||||||
|
va_end( args );
|
||||||
|
|
||||||
|
throw IOError( errText );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SPECCTRA_DB::expecting( DSN_T aTok ) throw( IOError )
|
||||||
|
{
|
||||||
|
wxString errText( _("Expecting") );
|
||||||
|
|
||||||
|
errText << wxT(" ") << lexer->GetTokenText( aTok );
|
||||||
|
|
||||||
|
lexer->ThrowIOError( errText, lexer->CurOffset() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPECCTRA_DB::expecting( const wxChar* text ) throw( IOError )
|
||||||
|
{
|
||||||
|
wxString errText( _("Expecting") );
|
||||||
|
|
||||||
|
errText << wxT(" '") << text << wxT("'");
|
||||||
|
|
||||||
|
lexer->ThrowIOError( errText, lexer->CurOffset() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DSN_T SPECCTRA_DB::nextTok()
|
||||||
|
{
|
||||||
|
return lexer->NextTok();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SPECCTRA_DB::Load( const wxString& filename ) throw( IOError )
|
||||||
|
{
|
||||||
|
wxFFile file( filename.c_str() );
|
||||||
|
|
||||||
|
if( !file.IsOpened() )
|
||||||
|
{
|
||||||
|
ThrowIOError( _("Unable to open file \"%s\""), filename.GetData() );
|
||||||
|
}
|
||||||
|
|
||||||
|
delete lexer;
|
||||||
|
lexer = 0;
|
||||||
|
|
||||||
|
lexer = new LEXER( file.fp(), filename );
|
||||||
|
|
||||||
|
if( nextTok() != T_LEFT )
|
||||||
|
expecting( T_LEFT );
|
||||||
|
|
||||||
|
if( nextTok() != T_pcb )
|
||||||
|
expecting( T_pcb );
|
||||||
|
|
||||||
|
tree = new ELEM( T_pcb );
|
||||||
|
|
||||||
|
doPCB( tree );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SPECCTRA_DB::doPCB( ELEM* growth ) throw( IOError )
|
||||||
|
{
|
||||||
|
ELEM* child;
|
||||||
|
DSN_T tok = nextTok();
|
||||||
|
|
||||||
|
switch( tok )
|
||||||
|
{
|
||||||
|
case T_SYMBOL:
|
||||||
|
case T_STRING:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
expecting( T_STRING );
|
||||||
|
}
|
||||||
|
|
||||||
|
while( (tok = nextTok()) != T_EOF )
|
||||||
|
{
|
||||||
|
if( tok != T_LEFT )
|
||||||
|
expecting( T_LEFT );
|
||||||
|
|
||||||
|
tok = nextTok();
|
||||||
|
switch( tok )
|
||||||
|
{
|
||||||
|
case T_parser:
|
||||||
|
child = new ELEM( T_parser );
|
||||||
|
growth->Append( child );
|
||||||
|
doPARSER( child );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_unit:
|
||||||
|
child = new ELEM( T_unit );
|
||||||
|
growth->Append( child );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_resolution:
|
||||||
|
child = new ELEM( T_resolution );
|
||||||
|
growth->Append( child );
|
||||||
|
doRESOLUTION( child );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_structure:
|
||||||
|
case T_placement:
|
||||||
|
case T_library:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
expecting( wxT("parser, unit, resolution, or structure") );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SPECCTRA_DB::doPARSER( ELEM* growth ) throw( IOError )
|
||||||
|
{
|
||||||
|
DSN_T tok;
|
||||||
|
|
||||||
|
while( (tok = nextTok()) != T_RIGHT )
|
||||||
|
{
|
||||||
|
if( tok != T_LEFT )
|
||||||
|
expecting( T_LEFT );
|
||||||
|
|
||||||
|
tok = nextTok();
|
||||||
|
switch( tok )
|
||||||
|
{
|
||||||
|
case T_string_quote:
|
||||||
|
tok = nextTok();
|
||||||
|
if( tok != T_QUOTE_DEF )
|
||||||
|
expecting( T_QUOTE_DEF );
|
||||||
|
lexer->SetStringDelimiter( (unsigned char) *lexer->CurText() );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_space_in_quoted_tokens:
|
||||||
|
tok = nextTok();
|
||||||
|
if( tok!=T_on && tok!=T_off )
|
||||||
|
expecting( _("on or off") );
|
||||||
|
lexer->SetSpaceInQuotedTokens( tok==T_on );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_host_cad:
|
||||||
|
tok = nextTok();
|
||||||
|
if( tok!=T_STRING && tok!=T_SYMBOL )
|
||||||
|
expecting( T_SYMBOL );
|
||||||
|
// @todo
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_host_version:
|
||||||
|
tok = nextTok();
|
||||||
|
if( tok!=T_STRING && tok!=T_SYMBOL )
|
||||||
|
expecting( T_SYMBOL );
|
||||||
|
// @todo
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_constant:
|
||||||
|
tok = nextTok();
|
||||||
|
if( tok!=T_STRING && tok!=T_SYMBOL )
|
||||||
|
expecting( T_SYMBOL );
|
||||||
|
tok = nextTok();
|
||||||
|
if( tok!=T_STRING && tok!=T_SYMBOL )
|
||||||
|
expecting( T_SYMBOL );
|
||||||
|
// @todo
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_write_resolution: // [(writee_resolution {<character> <positive_integer >})]
|
||||||
|
while( (tok = nextTok()) != T_RIGHT )
|
||||||
|
{
|
||||||
|
if( tok!=T_SYMBOL )
|
||||||
|
expecting( T_SYMBOL );
|
||||||
|
tok = nextTok();
|
||||||
|
if( tok!=T_NUMBER )
|
||||||
|
expecting( T_NUMBER );
|
||||||
|
// @todo
|
||||||
|
}
|
||||||
|
continue; // we ate the T_RIGHT
|
||||||
|
|
||||||
|
case T_routes_include: // [(routes_include {[testpoint | guides | image_conductor]})]
|
||||||
|
while( (tok = nextTok()) != T_RIGHT )
|
||||||
|
{
|
||||||
|
switch( tok )
|
||||||
|
{
|
||||||
|
case T_testpoint:
|
||||||
|
case T_guide:
|
||||||
|
case T_image_conductor:
|
||||||
|
// @todo
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
expecting( _("testpoint, guides, or image_conductor") );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue; // we ate the T_RIGHT
|
||||||
|
|
||||||
|
case T_wires_include: // [(wires_include testpoint)]
|
||||||
|
tok = nextTok();
|
||||||
|
if( tok != T_testpoint )
|
||||||
|
expecting( T_testpoint );
|
||||||
|
// @todo
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_case_sensitive:
|
||||||
|
tok = nextTok();
|
||||||
|
if( tok!=T_on && tok!=T_off )
|
||||||
|
expecting( _("on or off") );
|
||||||
|
// @todo
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_via_rotate_first: // [(via_rotate_first [on | off])]
|
||||||
|
tok = nextTok();
|
||||||
|
if( tok!=T_on && tok!=T_off )
|
||||||
|
expecting( _("on or off") );
|
||||||
|
// @todo
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
default:
|
||||||
|
expecting( wxT("parser_descriptor contents") );
|
||||||
|
}
|
||||||
|
|
||||||
|
tok = nextTok();
|
||||||
|
if( tok != T_RIGHT )
|
||||||
|
expecting( T_RIGHT );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPECCTRA_DB::doRESOLUTION( ELEM* growth ) throw(IOError)
|
||||||
|
{
|
||||||
|
DSN_T tok = nextTok();
|
||||||
|
|
||||||
|
switch( tok )
|
||||||
|
{
|
||||||
|
case T_inch:
|
||||||
|
case T_mil:
|
||||||
|
case T_cm:
|
||||||
|
case T_mm:
|
||||||
|
case T_um:
|
||||||
|
// @todo
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
expecting( wxT("inch, mil, cm, mm, or um") );
|
||||||
|
}
|
||||||
|
|
||||||
|
tok = nextTok();
|
||||||
|
if( tok != T_NUMBER )
|
||||||
|
expecting( T_NUMBER );
|
||||||
|
|
||||||
|
tok = nextTok();
|
||||||
|
if( tok != T_RIGHT )
|
||||||
|
expecting( T_RIGHT );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SPECCTRA_DB::print( const char* fmt, ... )
|
void SPECCTRA_DB::print( const char* fmt, ... )
|
||||||
{
|
{
|
||||||
|
@ -210,15 +531,36 @@ using namespace DSN;
|
||||||
|
|
||||||
int main( int argc, char** argv )
|
int main( int argc, char** argv )
|
||||||
{
|
{
|
||||||
PARENT parent( T_pcb );
|
#if 0
|
||||||
|
ELEM parent( T_pcb );
|
||||||
|
|
||||||
PARENT* child = new PARENT( T_absolute );
|
ELEM* child = new ELEM( T_absolute );
|
||||||
|
|
||||||
parent.Append( child );
|
parent.Append( child );
|
||||||
|
|
||||||
parent.At(0)->Test();
|
parent[0]->Test();
|
||||||
|
|
||||||
child->Append( new ELEM( T_absolute ) );
|
child->Append( new ELEM( T_absolute ) );
|
||||||
|
#else
|
||||||
|
|
||||||
|
wxString filename( wxT("/tmp/fpcroute/Sample_1sided/demo_1sided.dsn") );
|
||||||
|
// wxString filename( wxT("/tmp/testdesigns/test.dsn") );
|
||||||
|
|
||||||
|
SPECCTRA_DB db;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
db.Load( filename );
|
||||||
|
}
|
||||||
|
catch( IOError ioe )
|
||||||
|
{
|
||||||
|
printf( "%s\n", CONV_TO_UTF8(ioe.errorText) );
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("loaded OK\n");
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue