From bdbd28a9f47ba711611ac82fc6aa18eea4fdb27a Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Mon, 27 Dec 2010 15:22:12 -0600 Subject: [PATCH 1/2] complete initial version of LIB_TABLE::Parse() --- CMakeModules/TokenList2DsnLexer.cmake | 20 ++-- common/dsnlexer.cpp | 18 ++-- include/dsnlexer.h | 16 +-- include/richio.h | 2 +- new/CMakeLists.txt | 16 ++- new/sch_dir_lib_source.h | 6 +- new/sch_lib.cpp | 45 ++++++++ new/sch_lib.h | 22 +--- new/sch_lib_table.cpp | 150 +++++++++++++++++++++++++- new/sch_lib_table.h | 66 +++++++----- new/sch_lib_table.keywords | 1 + 11 files changed, 282 insertions(+), 80 deletions(-) create mode 100644 new/sch_lib.cpp diff --git a/CMakeModules/TokenList2DsnLexer.cmake b/CMakeModules/TokenList2DsnLexer.cmake index 2aa7508c7e..f89d009244 100644 --- a/CMakeModules/TokenList2DsnLexer.cmake +++ b/CMakeModules/TokenList2DsnLexer.cmake @@ -144,9 +144,6 @@ set( sourceFileHeader * your DSN lexer. */ -//#include \"fctsys.h\" -//#include \"macros.h\" - #include \"${result}_lexer.h\" namespace DSN { @@ -228,13 +225,13 @@ class ${RESULT}_LEXER : public DSNLEXER public: /** * Constructor ${RESULT}_LEXER - * @param aClipboartTxt is std::string (8 bit) text possibly from the - * clipboard that you want to parse. + * @param aSExpression is (utf8) text possibly from the clipboard that you want to parse. + * @param aSource is a description of the origin of @a aSExpression, such as a filename. + * If left empty, then _("clipboard") is used. */ - ${RESULT}_LEXER( const std::string& aClipboardTxt ) : - DSNLEXER( aClipboardTxt, - DSN::${result}_keywords, - DSN::${result}_keyword_count ) + ${RESULT}_LEXER( const std::string& aSExpression, const wxString& aSource = wxEmptyString ) : + DSNLEXER( DSN::${result}_keywords, DSN::${result}_keyword_count, + aSExpression, aSource ) { } @@ -248,9 +245,8 @@ public: * @param aFilename is the name of the opened file, needed for error reporting. */ ${RESULT}_LEXER( FILE* aFile, const wxString& aFilename ) : - DSNLEXER( aFile, aFilename, - DSN::${result}_keywords, - DSN::${result}_keyword_count ) + DSNLEXER( DSN::${result}_keywords, DSN::${result}_keyword_count, + aFile, aFilename ) { } diff --git a/common/dsnlexer.cpp b/common/dsnlexer.cpp index ba4e6a3bac..39791d0b03 100644 --- a/common/dsnlexer.cpp +++ b/common/dsnlexer.cpp @@ -32,8 +32,8 @@ #include "dsnlexer.h" -#include "fctsys.h" -#include "pcbnew.h" +//#include "fctsys.h" +//#include "pcbnew.h" //#define STANDALONE 1 // enable this for stand alone testing. @@ -60,8 +60,8 @@ void DSNLEXER::init() } -DSNLEXER::DSNLEXER( FILE* aFile, const wxString& aFilename, - const KEYWORD* aKeywordTable, unsigned aKeywordCount ) : +DSNLEXER::DSNLEXER( const KEYWORD* aKeywordTable, unsigned aKeywordCount, + FILE* aFile, const wxString& aFilename ) : keywords( aKeywordTable ), keywordCount( aKeywordCount ) { @@ -71,12 +71,13 @@ DSNLEXER::DSNLEXER( FILE* aFile, const wxString& aFilename, } -DSNLEXER::DSNLEXER( const std::string& aClipboardTxt, - const KEYWORD* aKeywordTable, unsigned aKeywordCount ) : +DSNLEXER::DSNLEXER( const KEYWORD* aKeywordTable, unsigned aKeywordCount, + const std::string& aClipboardTxt, const wxString& aSource ) : keywords( aKeywordTable ), keywordCount( aKeywordCount ) { - STRING_LINE_READER* stringReader = new STRING_LINE_READER( aClipboardTxt, _( "clipboard" ) ); + STRING_LINE_READER* stringReader = new STRING_LINE_READER( aClipboardTxt, aSource.IsEmpty() ? + wxString( _( "clipboard" ) ) : aSource ); PushReader( stringReader ); init(); } @@ -206,7 +207,7 @@ wxString DSNLEXER::GetTokenString( int aTok ) { wxString ret; - ret << wxT("'") << CONV_FROM_UTF8( GetTokenText(aTok) ) << wxT("'"); + ret << wxT("'") << wxConvertMB2WX( GetTokenText(aTok) ) << wxT("'"); return ret; } @@ -300,6 +301,7 @@ int DSNLEXER::NeedSYMBOLorNUMBER() throw( IO_ERROR ) return tok; } + /** * Function isspace * strips the upper bits of the int to ensure the value passed to ::isspace() is diff --git a/include/dsnlexer.h b/include/dsnlexer.h index 457ec97d0f..e1900bd31d 100644 --- a/include/dsnlexer.h +++ b/include/dsnlexer.h @@ -22,8 +22,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef _DSNLEXER_H -#define _DSNLEXER_H +#ifndef DSNLEXER_H_ +#define DSNLEXER_H_ #include #include @@ -162,12 +162,14 @@ public: * @param aKeywordTable is an array of KEYWORDS holding \a aKeywordCount. This * token table need not contain the lexer separators such as '(' ')', etc. * @param aKeywordTable is the count of tokens in aKeywordTable. + * @param aFile is an open file, which will be closed when this is destructed. + * @param aFileName is the name of the file */ - DSNLEXER( FILE* aFile, const wxString& aFilename, - const KEYWORD* aKeywordTable, unsigned aKeywordCount ); + DSNLEXER( const KEYWORD* aKeywordTable, unsigned aKeywordCount, + FILE* aFile, const wxString& aFileName ); - DSNLEXER( const std::string& aClipboardTxt, - const KEYWORD* aKeywordTable, unsigned aKeywordCount ); + DSNLEXER( const KEYWORD* aKeywordTable, unsigned aKeywordCount, + const std::string& aClipboardTxt, const wxString& aSource = wxEmptyString ); ~DSNLEXER() { @@ -418,4 +420,4 @@ public: } }; -#endif // _DSNLEXER_H +#endif // DSNLEXER_H_ diff --git a/include/richio.h b/include/richio.h index 84be5e25fa..8892a2bc8a 100644 --- a/include/richio.h +++ b/include/richio.h @@ -196,7 +196,7 @@ public: * The last line does not necessarily need a trailing '\n'. * * @param aSource describes the source of aString for error reporting purposes - * can be anything meaninful, such as wxT( "cliboard" ). + * can be anything meaninful, such as wxT( "clipboard" ). */ STRING_LINE_READER( const std::string& aString, const wxString& aSource ) : LINE_READER( LINE_READER_LINE_DEFAULT_MAX ), diff --git a/new/CMakeLists.txt b/new/CMakeLists.txt index fe3ea262f9..b6eedc64e4 100644 --- a/new/CMakeLists.txt +++ b/new/CMakeLists.txt @@ -60,14 +60,22 @@ endif() include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) -add_executable( test_dir_lib_source sch_dir_lib_source.cpp ) +add_executable( test_dir_lib_source + sch_dir_lib_source.cpp + ) target_link_libraries( test_dir_lib_source ${wxWidgets_LIBRARIES} ) -add_executable( test_lib_table sch_lib_table.cpp sch_lib_table_keywords.cpp ) -target_link_libraries( test_lib_table ${wxWidgets_LIBRARIES} ) +add_executable( test_sch_lib_table + sch_lib_table.cpp + sch_lib_table_keywords.cpp + sch_lib.cpp + ${PROJECT_SOURCE_DIR}/common/richio.cpp + ${PROJECT_SOURCE_DIR}/common/dsnlexer.cpp + ) +target_link_libraries( test_sch_lib_table ${wxWidgets_LIBRARIES} ) add_executable( test_sch_part sch_part.cpp ) -target_link_libraries( test_lib_table ${wxWidgets_LIBRARIES} ) +target_link_libraries( test_sch_part ${wxWidgets_LIBRARIES} ) make_lexer( diff --git a/new/sch_dir_lib_source.h b/new/sch_dir_lib_source.h index 7e2cc91800..e12f72113a 100644 --- a/new/sch_dir_lib_source.h +++ b/new/sch_dir_lib_source.h @@ -151,14 +151,14 @@ public: * tree, otherwise only a single version of each part is recognized, namely the * one without the ".revN[N..]" trailer. */ - DIR_LIB_SOURCE( const STRING& aDirectoryPath, const STRING& aOptions = StrEmpty ) + DIR_LIB_SOURCE( const STRING& aDirectoryPath, const STRING& aOptions = "" ) throw( IO_ERROR ); ~DIR_LIB_SOURCE(); //----------------------------------- - void ReadPart( STRING* aResult, const STRING& aPartName, const STRING& aRev = StrEmpty ) + void ReadPart( STRING* aResult, const STRING& aPartName, const STRING& aRev = "" ) throw( IO_ERROR ); void ReadParts( STRINGS* aResults, const STRINGS& aPartNames ) @@ -166,7 +166,7 @@ public: void GetCategories( STRINGS* aResults ) throw( IO_ERROR ); - void GetCategoricalPartNames( STRINGS* aResults, const STRING& aCategory = StrEmpty ) + void GetCategoricalPartNames( STRINGS* aResults, const STRING& aCategory = "" ) throw( IO_ERROR ); void GetRevisions( STRINGS* aResults, const STRING& aPartName ) throw( IO_ERROR ) diff --git a/new/sch_lib.cpp b/new/sch_lib.cpp new file mode 100644 index 0000000000..9a5f423da7 --- /dev/null +++ b/new/sch_lib.cpp @@ -0,0 +1,45 @@ +/* + * This program source code file is part of KICAD, a free EDA CAD application. + * + * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2010 Kicad Developers, see change_log.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + + + +using namespace SCH; + + +LIB::LIB( const STRING& aLogicalLibrary, LIB_SOURCE* aSource, LIB_SINK* aSink ) : + name( aLogicalLibrary ), + source( aSource ), + sink( aSink ) +{ +} + + +LIB::~LIB() +{ + delete source; + delete sink; +} + diff --git a/new/sch_lib.h b/new/sch_lib.h index 84157c4476..fe907e0118 100644 --- a/new/sch_lib.h +++ b/new/sch_lib.h @@ -207,7 +207,7 @@ protected: */ class LIB { - friend class LIBS; ///< the LIB factory is LIBS::GetLibrary() + friend class LIB_TABLE; ///< the LIB factory is LIB_TABLE protected: // constructor is not public, called from LIBS only. @@ -224,21 +224,11 @@ protected: // constructor is not public, called from LIBS only. * @param aSink is an open LIB_SINK whose ownership is given over * to this LIB, and it is normally NULL. */ - LIB( const STRING& aLogicalLibrary, LIB_SOURCE* aSource, LIB_SINK* aSink=NULL ) : - name( aLogicalLibrary ), - source( aSource ), - sink( aSink ) - { - } + LIB( const STRING& aLogicalLibrary, LIB_SOURCE* aSource, LIB_SINK* aSink = NULL ); public: - ~LIB() - { - delete source; - delete sink; - } - + ~LIB(); /** * Function HasSink @@ -294,9 +284,9 @@ public: * saves the part to non-volatile storage and returns the next new revision * name in the sequence established by the LIB_SINK. */ - virtual STRING WritePart( PART* aPart ) throw( IO_ERROR ); + STRING WritePart( PART* aPart ) throw( IO_ERROR ); - virtual void SetPartBody( PART* aPart, const STRING& aSExpression ) throw( IO_ERROR ); + void SetPartBody( PART* aPart, const STRING& aSExpression ) throw( IO_ERROR ); /** * Function GetRevisions @@ -346,6 +336,4 @@ protected: } // namespace SCH -const STRING StrEmpty = ""; - #endif // SCH_LIB_H_ diff --git a/new/sch_lib_table.cpp b/new/sch_lib_table.cpp index 085814f9e9..f0d34d536c 100644 --- a/new/sch_lib_table.cpp +++ b/new/sch_lib_table.cpp @@ -22,10 +22,158 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include +#include +#include + +using namespace std; +using namespace SCH; + + +LIB_TABLE::LIB_TABLE( LIB_TABLE* aFallBackTable ) +{ + if( aFallBackTable ) + { + const ROWS& t = aFallBackTable->rows; + + for( ROWS_CITER it = t.begin(); it != t.end(); ++it ) + { + // our rows are empty, expect no collisions here + auto_ptr row( new ROW( *it ) ); + + row->owner = this; + rows.insert( row.release() ); + } + } +} + + +void LIB_TABLE::Parse( SCH_LIB_TABLE_LEXER* in ) throw( IO_ERROR ) +{ + /* grammar: + + (lib_table + (lib (logical "LOGICAL")(type "TYPE")(full_uri "FULL_URI")(options "OPTIONS")) + (lib (logical "LOGICAL")(type "TYPE")(full_uri "FULL_URI")(options "OPTIONS")) + (lib (logical "LOGICAL")(type "TYPE")(full_uri "FULL_URI")(options "OPTIONS")) + ) + + note: "(lib_table" has already been read in. + */ + + ELT_T tok; + + while( (tok = in->NextTok() ) != T_RIGHT && tok != T_EOF ) + { + // (lib (logical "LOGICAL")(type "TYPE")(full_uri "FULL_URI")(options "OPTIONS")) + + if( tok != T_LEFT ) + in->Expecting( T_LEFT ); + + if( ( tok = in->NextTok() ) != T_lib ) + in->Expecting( T_lib ); + + in->NeedLEFT(); + + if( ( tok = in->NextTok() ) != T_logical ) + in->Expecting( T_logical ); + + in->NeedSYMBOLorNUMBER(); + + auto_ptr row( new ROW( this ) ); + + row->SetLogicalName( in->CurText() ); + + in->NeedRIGHT(); + in->NeedLEFT(); + + if( ( tok = in->NextTok() ) != T_type ) + in->Expecting( T_type ); + + in->NeedSYMBOLorNUMBER(); + + // verify that type is one of: {dir, schematic, subversion, http} + if( strcmp( in->CurText(), "dir" ) && + strcmp( in->CurText(), "schematic" ) && + strcmp( in->CurText(), "subversion" ) && + strcmp( in->CurText(), "http" ) ) + { + in->Expecting( wxT( "dir|schematic|subversion|http" ) ); + } + + row->SetType( in->CurText() ); + + in->NeedRIGHT(); + in->NeedLEFT(); + + if( ( tok = in->NextTok() ) != T_full_uri ) + in->Expecting( T_full_uri ); + + in->NeedSYMBOLorNUMBER(); + + row->SetFullURI( in->CurText() ); + + in->NeedRIGHT(); + in->NeedLEFT(); + + if( ( tok = in->NextTok() ) != T_options ) + in->Expecting( T_options ); + + in->NeedSYMBOLorNUMBER(); + + row->SetOptions( in->CurText() ); + + in->NeedRIGHT(); + in->NeedRIGHT(); // teriminate the (lib..) + + rows.insert( row.release() ); + } + return; +} + + +#if 1 int main( int argc, char** argv ) { + // the null string is not really a legal DSN token since any double quotes + // as assumed to be a single quote. To pass an empty string, we pass " " + // to (options " ") + SCH_LIB_TABLE_LEXER slr( + "(lib_table \n" + " (lib (logical meparts) (type dir) (full_uri /tmp/eeschema-lib) (options \" \"))\n" + " (lib (logical old-project) (type schematic)(full_uri /tmp/old-schematic.sch) (options \" \"))\n" + " (lib (logical www) (type http) (full_uri http://kicad.org/libs) (options \" \"))\n", + + wxT( "inline text" ) // source + ); + + LIB_TABLE lib_table; + + // read the "( lib_table" pair of tokens + + try + { + slr.NextTok(); + slr.NextTok(); + + lib_table.Parse( &slr ); + } + + catch( std::exception& ex ) + { + printf( "std::exception\n" ); + } + + catch( IO_ERROR ioe ) + { + printf( "caught\n" ); + printf( "exception: %s\n", (const char*) wxConvertWX2MB( ioe.errorText ) ); + } + + lib_table.Show(); + return 0; } + +#endif diff --git a/new/sch_lib_table.h b/new/sch_lib_table.h index 80683ee669..f2bc59fed8 100644 --- a/new/sch_lib_table.h +++ b/new/sch_lib_table.h @@ -29,12 +29,10 @@ #include #include +class SCH_LIB_TABLE_LEXER; // outside namespace SCH, since make_lexer() Functions.cmake can't do namespace namespace SCH { -class LIB_TABLE_LEXER; - - /** * Class LIB_TABLE * holds LIB_TABLE::ROW records, and can be searched in a very high speed @@ -52,6 +50,8 @@ public: */ class ROW { + friend class LIB_TABLE; + public: bool operator<( const ROW& other ) const @@ -101,9 +101,18 @@ public: delete lib; } +#if defined(DEBUG) + void Show() const + { + printf( "(lib (logical \"%s\")(type \"%s\")(full_uri \"%s\")(options \"%s\"))\n", + logicalName.c_str(), libType.c_str(), fullURI.c_str(), options.c_str() ); + } +#endif + protected: - ROW() : + ROW( LIB_TABLE* aOwner ) : + owner( aOwner ), lib( 0 ) {} @@ -145,37 +154,28 @@ public: } private: - STRING logicalName; - STRING libType; - STRING fullURI; - STRING options; + LIB_TABLE* owner; + STRING logicalName; + STRING libType; + STRING fullURI; + STRING options; - LIB* lib; + LIB* lib; }; /** * Constructor LIB_TABLE * builds a library table from an s-expression form of the library table. - * @param aLibraryTable is an s-expression form of all the rows in a library - * table fragment. These rows take presedence over rows in @a aFallBackTable. * @param aFallBackTable is another LIB_TABLE which is searched only when - * a record is not found in this table. + * a record is not found in this table. No ownership is taken of aFallBackTable. */ - LIB_TABLE( const STRING& aLibraryTable, LIB_TABLE* aFallBackTable = NULL ) - throw( PARSE_ERROR ) - { - // s-expression is chosen so we can read a table fragment from either - // a schematic or a disk file, for schematic resident or - // personal table, respectively. - } + LIB_TABLE( LIB_TABLE* aFallBackTable = NULL ); - -protected: /** * Function Parse - * fills this object from information in the input stream \a aSpec, which - * is a DSN_LEXER customized for the grammar needed to describe instances of this object. + * fills this object from information in the input stream \a aLexer, which + * is a DSNLEXER customized for the grammar needed to describe instances of this object. * The entire textual element spec is
* (lib_table (logical _yourfieldname_)(value _yourvalue_) visible)) * @@ -183,21 +183,33 @@ protected: * (lib_table * (lib (logical "LOGICAL")(type "TYPE")(fullURI "FULL_URI")(options "OPTIONS")) * (lib (logical "LOGICAL")(type "TYPE")(fullURI "FULL_URI")(options "OPTIONS")) - (lib (logical "LOGICAL")(type "TYPE")(fullURI "FULL_URI")(options "OPTIONS")) + * (lib (logical "LOGICAL")(type "TYPE")(fullURI "FULL_URI")(options "OPTIONS")) * * - * When this function is called, the input token stream given by \a aSpec + * When this function is called, the input token stream given by \a aLexer * is assumed to be positioned at the '^' in the following example, i.e. just after the * identifying keyword and before the content specifying stuff.
* (lib_table ^ (....) ) * * @param aSpec is the input token stream of keywords and symbols. */ - void Parse( LIB_TABLE_LEXER* aLexer ) throw( PARSE_ERROR ); + void Parse( SCH_LIB_TABLE_LEXER* aLexer ) throw( IO_ERROR ); -private: +#if defined(DEBUG) + void Show() const + { + printf("(lib_table\n" ); + for( ROWS_CITER it = rows.begin(); it != rows.end(); ++it ) + it->Show(); + printf(")\n" ); + } +#endif typedef boost::ptr_set ROWS; + typedef ROWS::iterator ROWS_ITER; + typedef ROWS::const_iterator ROWS_CITER; + +private: ROWS rows; }; diff --git a/new/sch_lib_table.keywords b/new/sch_lib_table.keywords index 003abdebeb..df56bba7f1 100644 --- a/new/sch_lib_table.keywords +++ b/new/sch_lib_table.keywords @@ -3,3 +3,4 @@ logical type full_uri options +lib From 5b5db5557de534cc41a11f4e722443760790d201 Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Mon, 27 Dec 2010 15:27:52 -0600 Subject: [PATCH 2/2] change order of constructor args of DSNLEXER::DSNLEXER() --- pcbnew/specctra.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pcbnew/specctra.cpp b/pcbnew/specctra.cpp index f041e32677..cae5c4854a 100644 --- a/pcbnew/specctra.cpp +++ b/pcbnew/specctra.cpp @@ -687,7 +687,7 @@ void SPECCTRA_DB::LoadPCB( const wxString& filename ) throw( IO_ERROR ) delete lexer; lexer = 0; - lexer = new DSNLEXER( fp, filename, SPECCTRA_DB::keywords, SPECCTRA_DB::keywordCount ); + lexer = new DSNLEXER( SPECCTRA_DB::keywords, SPECCTRA_DB::keywordCount, fp, filename ); if( nextTok() != T_LEFT ) expecting( T_LEFT ); @@ -714,9 +714,8 @@ void SPECCTRA_DB::LoadSESSION( const wxString& filename ) throw( IO_ERROR ) } delete lexer; - lexer = 0; - lexer = new DSNLEXER( fp, filename, SPECCTRA_DB::keywords, SPECCTRA_DB::keywordCount ); + lexer = new DSNLEXER( SPECCTRA_DB::keywords, SPECCTRA_DB::keywordCount, fp, filename ); if( nextTok() != T_LEFT ) expecting( T_LEFT );