* Added the basic structure to the Sweet parser in sch_part.cpp.
  * Got inheritence working off of the 'extends' keyword and PART::inherit()
  * Tossed the units support out of sweet.keywords, since we agreed to go dimensionless.
++richio:
  * Added the problemInputLine support to PARSE_ERROR, so UI can show the
    offending line of bytes.  Yes bytes, not even guaranteed to be characters.
This commit is contained in:
Dick Hollenbeck 2011-01-01 16:56:07 -06:00
parent e7d5770f42
commit 84ed5f501d
13 changed files with 381 additions and 76 deletions

View File

@ -4,6 +4,17 @@ KiCad ChangeLog 2010
Please add newer entries at the top, list the date and your name with Please add newer entries at the top, list the date and your name with
email address. email address.
2011-Jan-1 UPDATE Dick Hollenbeck <dick@softplc.com>
================================================================================
++new:
* Added the basic structure to the Sweet parser in sch_part.cpp.
* Got inheritence working off of the 'extends' keyword and PART::inherit()
* Tossed the units support out of sweet.keywords, since we agreed to go dimensionless.
++richio:
* Added the problemInputLine support to PARSE_ERROR, so UI can show the
offending line of bytes. Yes bytes, not even guaranteed to be characters.
2010-dec-31 UPDATE Wayne Stambaugh <stambaughw@verizon.net> 2010-dec-31 UPDATE Wayne Stambaugh <stambaughw@verizon.net>
================================================================================ ================================================================================
++all ++all

View File

@ -231,7 +231,7 @@ wxString DSNLEXER::GetTokenString( int aTok )
{ {
wxString ret; wxString ret;
ret << wxT("'") << wxConvertMB2WX( GetTokenText(aTok) ) << wxT("'"); ret << wxT("'") << wxString::FromUTF8( GetTokenText(aTok) ) << wxT("'");
return ret; return ret;
} }
@ -249,24 +249,11 @@ bool DSNLEXER::IsSymbol( int aTok )
} }
void DSNLEXER::ThrowIOError( wxString aText, int charOffset ) throw( IO_ERROR )
{
// @todo convert this to THROW_PARSE_ERROR()
// append to aText, do not overwrite
aText << wxT(" ") << _("in") << wxT(" \"") << CurSource()
<< wxT("\" ") << _("on line") << wxT(" ") << reader->LineNumber()
<< wxT(" ") << _("at offset") << wxT(" ") << charOffset;
THROW_IO_ERROR( aText );
}
void DSNLEXER::Expecting( int aTok ) throw( IO_ERROR ) void DSNLEXER::Expecting( int aTok ) throw( IO_ERROR )
{ {
wxString errText( _("Expecting") ); wxString errText( _("Expecting") );
errText << wxT(" ") << GetTokenString( aTok ); errText << wxT(" ") << GetTokenString( aTok );
ThrowIOError( errText, CurOffset() ); THROW_PARSE_ERROR( errText, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
} }
@ -274,7 +261,7 @@ void DSNLEXER::Expecting( const wxString& text ) throw( IO_ERROR )
{ {
wxString errText( _("Expecting") ); wxString errText( _("Expecting") );
errText << wxT(" '") << text << wxT("'"); errText << wxT(" '") << text << wxT("'");
ThrowIOError( errText, CurOffset() ); THROW_PARSE_ERROR( errText, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
} }
@ -282,15 +269,22 @@ void DSNLEXER::Unexpected( int aTok ) throw( IO_ERROR )
{ {
wxString errText( _("Unexpected") ); wxString errText( _("Unexpected") );
errText << wxT(" ") << GetTokenString( aTok ); errText << wxT(" ") << GetTokenString( aTok );
ThrowIOError( errText, CurOffset() ); THROW_PARSE_ERROR( errText, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
} }
void DSNLEXER::Duplicate( int aTok ) throw( IO_ERROR )
{
wxString errText;
errText.Printf( _("%s is a duplicate"), GetTokenString( aTok ).GetData() );
THROW_PARSE_ERROR( errText, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
}
void DSNLEXER::Unexpected( const wxString& text ) throw( IO_ERROR ) void DSNLEXER::Unexpected( const wxString& text ) throw( IO_ERROR )
{ {
wxString errText( _("Unexpected") ); wxString errText( _("Unexpected") );
errText << wxT(" '") << text << wxT("'"); errText << wxT(" '") << text << wxT("'");
ThrowIOError( errText, CurOffset() ); THROW_PARSE_ERROR( errText, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
} }
@ -408,7 +402,7 @@ L_read:
case '"': case '"':
break; break;
default: default:
ThrowIOError( errtxt, CurOffset() ); THROW_PARSE_ERROR( errtxt, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
} }
curText = cc; curText = cc;
@ -417,7 +411,7 @@ L_read:
if( head<limit && *head!=')' && *head!='(' && !isSpace(*head) ) if( head<limit && *head!=')' && *head!='(' && !isSpace(*head) )
{ {
ThrowIOError( errtxt, CurOffset() ); THROW_PARSE_ERROR( errtxt, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
} }
curTok = DSN_QUOTE_DEF; curTok = DSN_QUOTE_DEF;
@ -514,7 +508,7 @@ L_read:
} }
wxString errtxt(_("Un-terminated delimited string") ); wxString errtxt(_("Un-terminated delimited string") );
ThrowIOError( errtxt, CurOffset() ); THROW_PARSE_ERROR( errtxt, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
#else // old code, did not understand nested quotes #else // old code, did not understand nested quotes
++cur; // skip over the leading delimiter: ",', or $ ++cur; // skip over the leading delimiter: ",', or $
@ -527,7 +521,7 @@ L_read:
if( head >= limit ) if( head >= limit )
{ {
wxString errtxt(_("Un-terminated delimited string") ); wxString errtxt(_("Un-terminated delimited string") );
ThrowIOError( errtxt, CurOffset() ); THROW_PARSE_ERROR( errtxt, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
} }
curText.clear(); curText.clear();

View File

@ -330,13 +330,6 @@ public:
*/ */
static bool IsSymbol( int aTok ); static bool IsSymbol( int aTok );
/**
* Function ThrowIOError
* encapsulates the formatting of an error message which contains the exact
* location within the input file of something the caller is rejecting.
*/
void ThrowIOError( wxString aText, int charOffset ) throw( IO_ERROR );
/** /**
* Function Expecting * Function Expecting
* throws an IO_ERROR exception with an input file specific error message. * throws an IO_ERROR exception with an input file specific error message.
@ -363,6 +356,16 @@ public:
*/ */
void Unexpected( int aTok ) throw( IO_ERROR ); void Unexpected( int aTok ) throw( IO_ERROR );
/**
* Function Duplicate
* throws an IO_ERROR exception with a message saying specifically that aTok
* is a duplicate of one already seen in current context.
* @param aTok is the token/keyword type which was not expected at the
* current input location.
* @throw IO_ERROR with the location within the input file of the problem.
*/
void Duplicate( int aTok ) throw( IO_ERROR );
/** /**
* Function Unexpected * Function Unexpected
* throws an IO_ERROR exception with an input file specific error message. * throws an IO_ERROR exception with an input file specific error message.
@ -411,6 +414,16 @@ public:
return curText.c_str(); return curText.c_str();
} }
/**
* Function FromUTF8
* returns the current token text as a wxString, assuming that the input
* byte stream is UTF8 encoded.
*/
wxString FromUTF8()
{
return wxString::FromUTF8( curText.c_str() );
}
/** /**
* Function CurLineNumber * Function CurLineNumber
* returns the current line number within my LINE_READER * returns the current line number within my LINE_READER
@ -420,6 +433,16 @@ public:
return reader->LineNumber(); return reader->LineNumber();
} }
/**
* Function CurLine
* returns the current line of text, from which the CurText() would return
* its token.
*/
const char* CurLine()
{
return (const char*)(*reader);
}
/** /**
* Function CurFilename * Function CurFilename
* returns the current LINE_READER source. * returns the current LINE_READER source.
@ -433,7 +456,7 @@ public:
/** /**
* Function CurOffset * Function CurOffset
* returns the char offset within the current line, using a 1 based index. * returns the byte offset within the current line, using a 1 based index.
* @return int - a one based index into the current line. * @return int - a one based index into the current line.
*/ */
int CurOffset() int CurOffset()

View File

@ -46,8 +46,8 @@
*/ */
#define IO_FORMAT _( "IO_ERROR: '%s'\n from %s : %s" ) #define IO_FORMAT _( "IO_ERROR: %s\n from %s : %s" )
#define PARSE_FORMAT _( "PARSE_ERROR: '%s' in input/source '%s', line %d, offset %d\n from %s : %s" ) #define PARSE_FORMAT _( "PARSE_ERROR: %s in input/source \"%s\", line %d, offset %d\n from %s : %s" )
// references: // references:
// http://stackoverflow.com/questions/2670816/how-can-i-use-the-compile-time-constant-line-in-a-string // http://stackoverflow.com/questions/2670816/how-can-i-use-the-compile-time-constant-line-in-a-string
@ -123,12 +123,11 @@ struct IO_ERROR // : std::exception
}; };
#define THROW_PARSE_ERROR( msg, input, line, offset ) throw PARSE_ERROR( __FILE__, __LOC__, msg, input, line, offset )
/** /**
* Class PARSE_ERROR * Class PARSE_ERROR
* contains a filename or source description, a line number, a character offset, * contains a filename or source description, a problem input line, a line number,
* and an error message. * a byte offset, and an error message which contains the the caller's report and his
* call site information: CPP source file, function, and line number.
* @author Dick Hollenbeck * @author Dick Hollenbeck
*/ */
struct PARSE_ERROR : public IO_ERROR struct PARSE_ERROR : public IO_ERROR
@ -138,24 +137,36 @@ struct PARSE_ERROR : public IO_ERROR
int lineNumber; ///< at which line number, 1 based index. int lineNumber; ///< at which line number, 1 based index.
int byteIndex; ///< at which character position within the line, 1 based index int byteIndex; ///< at which character position within the line, 1 based index
/// problem line of input [say, from a LINE_READER].
/// this is brought up in original byte format rather than wxString form, incase
/// there was a problem with the encoding, in which case converting to wxString is
/// not reliable in this context.
std::string inputLine;
/**
* Constructor
* which is normally called via the macro THROW_PARSE_ERROR so that
* __FILE__ and __LOC__ can be captured from the call site.
*/
PARSE_ERROR( const char* aThrowersFile, const char* aThrowersLoc, PARSE_ERROR( const char* aThrowersFile, const char* aThrowersLoc,
const wxString& aMsg, const wxString& aSource, const wxString& aMsg, const wxString& aSource,
const char* aInputLine,
int aLineNumber, int aByteIndex ) : int aLineNumber, int aByteIndex ) :
IO_ERROR() IO_ERROR()
{ {
init( aThrowersFile, aThrowersLoc, aMsg, aSource, aLineNumber, aByteIndex ); init( aThrowersFile, aThrowersLoc, aMsg, aSource, aInputLine, aLineNumber, aByteIndex );
} }
void init( const char* aThrowersFile, const char* aThrowersLoc, void init( const char* aThrowersFile, const char* aThrowersLoc,
const wxString& aMsg, const wxString& aSource, const wxString& aMsg, const wxString& aSource,
const char* aInputLine,
int aLineNumber, int aByteIndex ) int aLineNumber, int aByteIndex )
{ {
// save line and offset in binary for Sweet text editor, which will catch exceptions // save inpuLine, lineNumber, and offset for UI (.e.g. Sweet text editor)
inputLine = aInputLine;
lineNumber = aLineNumber; lineNumber = aLineNumber;
byteIndex = aByteIndex; byteIndex = aByteIndex;
// #define PARSE_FORMAT _( "PARSE_ERROR: %s in source %s, line %d, offset %d\nfrom cpp:%s func:%s" )
errorText.Printf( PARSE_FORMAT, aMsg.GetData(), aSource.GetData(), errorText.Printf( PARSE_FORMAT, aMsg.GetData(), aSource.GetData(),
aLineNumber, aByteIndex, aLineNumber, aByteIndex,
wxString::FromUTF8( aThrowersFile ).GetData(), wxString::FromUTF8( aThrowersFile ).GetData(),
@ -165,6 +176,11 @@ struct PARSE_ERROR : public IO_ERROR
~PARSE_ERROR() throw ( /*none*/ ){} ~PARSE_ERROR() throw ( /*none*/ ){}
}; };
#define THROW_PARSE_ERROR( aMsg, aSource, aInputLine, aLineNumber, aByteIndex ) \
throw PARSE_ERROR( __FILE__, __LOC__, aMsg, aSource, aInputLine, aLineNumber, aByteIndex )
/** @} exception_types */ /** @} exception_types */

View File

@ -16,8 +16,7 @@ for C in ${CATEGORIES}; do
for P in ${PARTS}; do for P in ${PARTS}; do
for R in ${REVS}; do for R in ${REVS}; do
echo "#$R: (part $C/$P)" > $BASEDIR/$C/$P.part.$R (part $C/$P/$R extends $P/$R (value 22)(footprint SM0805)) > $BASEDIR/$C/$P.part.$R
done done
done done
done done

View File

@ -413,6 +413,12 @@ int main( int argc, char** argv )
lib_table.Test(); lib_table.Test();
} }
catch( PARSE_ERROR& ioe ) // most derived class first
{
printf( "%s\n", (const char*) ioe.errorText.ToUTF8() );
printf( "%s", ioe.inputLine.c_str() ); // rare not to have \n at end
printf( "%*s^\n", ioe.byteIndex-1, " " );
}
catch( IO_ERROR& ioe ) catch( IO_ERROR& ioe )
{ {
printf( "%s\n", (const char*) ioe.errorText.ToUTF8() ); printf( "%s\n", (const char*) ioe.errorText.ToUTF8() );

View File

@ -187,6 +187,7 @@ LPID::LPID( const STRING& aLPID ) throw( PARSE_ERROR )
THROW_PARSE_ERROR( THROW_PARSE_ERROR(
_( "Illegal character found in LPID string" ), _( "Illegal character found in LPID string" ),
wxConvertMB2WX( aLPID.c_str() ), wxConvertMB2WX( aLPID.c_str() ),
aLPID.c_str(),
0, 0,
offset offset
); );

View File

@ -59,7 +59,7 @@ class LPID // aka GUID
{ {
public: public:
LPID(); LPID() {}
/** /**
* Constructor LPID * Constructor LPID

View File

@ -21,21 +21,258 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include <wx/wx.h> // _()
#include <sch_part.h> #include <sch_part.h>
#include <sweet_lexer.h> #include <sweet_lexer.h>
#include <wx/wx.h> // _() #include <sch_lpid.h>
#include <sch_lib_table.h>
using namespace SCH; using namespace SCH;
void PART::Parse( SWEET_LEXER* aLexer, LIB_TABLE* aTable ) throw( PARSE_ERROR ) //-----<temporary home for PART sub objects, move after stable>------------------
{
// Wayne's world, if he still wants it.
//-----</temporary home for PART sub objects, move after stable>-----------------
/**
* Class PART_PARSER
* is a localized/hidden PART Parser. You get here through the public interface
* PART::Parse(). Advantages of private class declaration in this situation:
* 1) keeps all the recursive parsing helper functions out of the main public PART
* header file and so should speed up compilation.
* 2) Allows use of cost-less Java like inline functions, since nobody knows about
* them but this source file. Most are only used once and called from one place.
* <p>
* All the functions in this class throw PARSE_ERROR. If SWEET_LEXER throws, it
* may be an IO_ERROR, propogated from here also. The throws() statements are left off
* to keep the noise level down.
*/
class PART_PARSER
{
SWEET_LEXER* in;
LIB_TABLE* libs;
int contains;
public:
PART_PARSER( PART* aPart, SWEET_LEXER* aLexer, LIB_TABLE* aTable ) :
in( aLexer ),
libs( aTable ),
contains( 0 )
{
parsePart( aPart );
} }
/// @param me = ja mir, the object getting stuffed, from its perspective
void parsePart( PART* me )
{
PART_T tok;
if( (tok = in->NextTok()) == T_LEFT )
tok = in->NextTok();
// a token "( part .." i.e. class PART
// Be flexible regarding the starting point of the stream.
// Caller may not have read the first two tokens out of the
// stream: T_LEFT and T_part, so ignore them if seen here.
// The 1st two tokens T_LEFT and T_part are then optional in the grammar.
if( tok == T_part )
{
in->NeedSYMBOLorNUMBER(); // read in part NAME_HINT, and toss
tok = in->NextTok();
}
// extends must be _first_ thing, if it is present at all, after NAME_HINT
if( tok == T_extends )
{
PART* base;
int offset;
if( contains & PB(EXTENDS) )
in->Duplicate( tok );
in->NeedSYMBOLorNUMBER();
me->setExtends( new LPID() );
offset = me->extends->Parse( in->CurText() );
if( offset > -1 ) // -1 is success
THROW_PARSE_ERROR( _("invalid extends LPID"),
in->CurSource(),
in->CurLine(),
in->CurLineNumber(),
in->CurOffset() + offset );
// we could be going in circles here, recursively, @todo add a max counter or stack chain
base = libs->LookupPart( *me->extends, me->Owner() );
me->inherit( *base );
contains |= PB(EXTENDS);
tok = in->NextTok();
}
for( ; tok!=T_RIGHT && tok!=T_EOF; tok = in->NextTok() )
{
if( tok == T_LEFT )
tok = in->NextTok();
switch( tok )
{
default:
// describe what we expect at this level
in->Expecting( wxT(
"anchor|value|footprint|model|keywords|alternates\n"
"|property\n"
" |property_del\n"
"|pin\n"
" |pin_merge|pin_swap|pin_renum|pin_rename|route_pin_swap\n"
"|polyline|line|rectangle|circle|arc|bezier|text"
)
);
break;
case T_anchor:
if( contains & PB(ANCHOR) )
in->Duplicate( tok );
contains |= PB(ANCHOR);
break;
/*
case T_value:
if( contains & PB(VALUE) )
in->Duplicate( tok );
contains |= PB(VALUE);
in->NeedSYMBOLorNUMBER();
// me->value = in->CurText();
in->NeedRIGHT();
break;
case T_footprint:
break;
case T_model:
break;
case T_keywords:
break;
case T_alternates:
break;
case T_property:
break;
case T_property_del:
break;
case T_pin:
break;
case T_pin_merge:
break;
case T_pin_swap:
break;
case T_pin_renum:
break;
case T_pin_rename:
break;
case T_route_pin_swap:
break;
case T_polyline:
break;
case T_line:
break;
case T_rectangle:
break;
case T_circle:
break;
case T_arc:
break;
case T_bezier:
break;
case T_text:
break;
*/
// Not sure about reference in a PART, comes in at COMPONENT object.
// It is maybe just a hint here or a prefix.
case T_reference:
if( contains & PB(REFERENCE) )
in->Duplicate( tok );
contains |= PB(REFERENCE);
break;
}
}
}
void parseAt( PART* me )
{
}
};
PART::PART( LIB* aOwner, const STRING& aPartName, const STRING& aRevision ) :
owner( aOwner ),
contains( 0 ),
partName( aPartName ),
revision( aRevision ),
extends( 0 )
{}
PART::~PART()
{
delete extends;
}
void PART::setExtends( LPID* aLPID )
{
delete extends;
extends = aLPID;
}
void PART::inherit( const PART& other )
{
contains = other.contains;
setExtends( other.extends ? new LPID( *other.extends ) : 0 );
body = other.body;
}
PART& PART::operator=( const PART& other )
{
owner = other.owner;
partName = other.partName;
revision = other.revision;
// maintain inherit() as a partial assignment operator.
inherit( other );
return *this;
}
void PART::Parse( SWEET_LEXER* aLexer, LIB_TABLE* aTable ) throw( IO_ERROR )
{
PART_PARSER( this, aLexer, aTable );
}
#if 0 && defined(DEBUG) #if 0 && defined(DEBUG)

View File

@ -28,9 +28,13 @@
#include <sch_lib.h> #include <sch_lib.h>
class SWEET_LEXER; class SWEET_LEXER;
class PART_PARSER;
namespace SCH { namespace SCH {
class LPID;
/** /**
* Enum PartBit * Enum PartBit
* is a set of bit positions that can be used to create flag bits within * is a set of bit positions that can be used to create flag bits within
@ -39,9 +43,16 @@ namespace SCH {
*/ */
enum PartBit enum PartBit
{ {
BODY, ///< body has been read in.
PARSED, ///< have parsed this part already, otherwise 'body' text must be parsed PARSED, ///< have parsed this part already, otherwise 'body' text must be parsed
EXTENDS, ///< saw and "extends" keyword, inheriting from another PART EXTENDS, ///< saw and "extends" keyword, inheriting from another PART
VALUE,
ANCHOR,
REFERENCE,
FOOTPRINT,
DATASHEET,
MODEL,
KEYWORDS,
}; };
/// Function PB /// Function PB
@ -63,34 +74,40 @@ static inline const int PB( PartBit oneBitOnly )
*/ */
class PART class PART
{ {
/// LIB class has great license to modify what's in here, nobody else does. friend class LIB; // is the owner of all PARTS, afterall
/// Modification is done through the LIB so it can track the state of the friend class ::PART_PARSER;
/// PART and take action as needed. Actually most of the modification will
/// be done by PARTS_LIST, a class derived from LIB.
friend class LIB;
/// a private constructor, only a LIB can instantiate a PART.
PART( LIB* aOwner, const STRING& aPartName, const STRING& aRevision ) :
owner( aOwner ),
contains( 0 ),
partName( aPartName ),
revision( aRevision )
{}
protected: // not likely to have C++ descendants, but protected none-the-less. protected: // not likely to have C++ descendants, but protected none-the-less.
/// a protected constructor, only a LIB can instantiate a PART.
PART( LIB* aOwner, const STRING& aPartName, const STRING& aRevision );
/**
* Function inherit
* is a specialized assignment function that copies a specific subset, enough
* to fulfill the requirements of the Sweet s-expression language.
*/
void inherit( const PART& aBasePart );
//PART( LIB* aOwner );
LIB* owner; ///< which LIB am I a part of (pun if you want) LIB* owner; ///< which LIB am I a part of (pun if you want)
int contains; ///< has bits from Enum PartParts int contains; ///< has bits from Enum PartParts
STRING extends; ///< LPID of base part
STRING partName; ///< example "passives/R", immutable. STRING partName; ///< example "passives/R", immutable.
STRING revision; // @todo need a single search key, this won't do. STRING revision; // @todo need a single search key, this won't do.
LPID* extends; ///< of base part, NULL if none, otherwise I own it.
/// encapsulate the old version deletion, take ownership of @a aLPID
void setExtends( LPID* aLPID );
/// s-expression text for the part, initially empty, and read in as this part /// s-expression text for the part, initially empty, and read in as this part
/// actually becomes cached in RAM. /// actually becomes cached in RAM.
STRING body; STRING body;
// 3 separate lists for speed: // 3 separate lists for speed:
/// A property list. /// A property list.
@ -105,16 +122,13 @@ protected: // not likely to have C++ descendants, but protected none-the-le
/// Alternate body forms. /// Alternate body forms.
//ALTERNATES alternates; //ALTERNATES alternates;
// lots of other stuff, like the mandatory properties. // lots of other stuff, like the mandatory properties, but no units, since we went with dimensionless
public: public:
/** ~PART();
* Function Inherit
* is a specialized assignment function that copies a specific subset, enough PART& operator=( const PART& other );
* to fulfill the requirements of the Sweet s-expression language.
*/
void Inherit( const PART& aBasePart );
/** /**
* Function Owner * Function Owner
@ -122,6 +136,7 @@ public:
*/ */
LIB* Owner() { return owner; } LIB* Owner() { return owner; }
/** /**
* Function Parse * Function Parse
* translates a Sweet string into a binary form that is represented * translates a Sweet string into a binary form that is represented
@ -133,7 +148,7 @@ public:
* @param aLibTable is the LIB_TABLE view that is in effect for inheritance, * @param aLibTable is the LIB_TABLE view that is in effect for inheritance,
* and comes from the big containing SCHEMATIC object. * and comes from the big containing SCHEMATIC object.
*/ */
void Parse( SWEET_LEXER* aLexer, LIB_TABLE* aTable ) throw( PARSE_ERROR ); void Parse( SWEET_LEXER* aLexer, LIB_TABLE* aTable ) throw( IO_ERROR );
/* /*
void SetBody( const STR_UTF& aSExpression ) void SetBody( const STR_UTF& aSExpression )

View File

@ -25,6 +25,7 @@ keywords
length length
line line
line_width line_width
model
name name
none none
number number
@ -38,6 +39,7 @@ pin_del
pin_merge pin_merge
pin_rename pin_rename
pin_renum pin_renum
pin_swap
polyline polyline
pos pos
power_in power_in
@ -58,5 +60,6 @@ tristate
unconnected unconnected
units units
unspecified unspecified
value
visible visible
xy xy

View File

@ -111,7 +111,7 @@ void WinEDA_PcbFrame::ExportToSpecctra( wxCommandEvent& event )
// if an exception is thrown by FromBOARD or ExportPCB(), then // if an exception is thrown by FromBOARD or ExportPCB(), then
// ~SPECCTRA_DB() will close the file. // ~SPECCTRA_DB() will close the file.
} }
catch( IO_ERROR ioe ) catch( IO_ERROR& ioe )
{ {
ok = false; ok = false;

View File

@ -96,7 +96,7 @@ void WinEDA_PcbFrame::ImportSpecctraSession( wxCommandEvent& event )
db.LoadSESSION( fullFileName ); db.LoadSESSION( fullFileName );
db.FromSESSION( GetBoard() ); db.FromSESSION( GetBoard() );
} }
catch( IO_ERROR ioe ) catch( IO_ERROR& ioe )
{ {
SetLocaleTo_Default( ); // revert to the current locale SetLocaleTo_Default( ); // revert to the current locale