From 8971bf75467f9f672af318b6157ba6e852dd2846 Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Sun, 29 Apr 2012 21:57:48 -0500 Subject: [PATCH] Add tools/parser_gen.cpp which is the beginnings of an s-expression parser generation tool. For now, it is just an s-expression beautifier using our "non-specctra mode" version of s-expressions. --- .bzrignore | 2 + CMakeLists.txt | 2 +- common/dsnlexer.cpp | 36 ++--- pcbnew/specctra.h | 2 +- polygon/PolyLine.cpp | 2 - tools/CMakeLists.txt | 71 +++++++++- tools/class_painter.h | 172 +++++++++++++++++++++++ tools/container_test.cpp | 23 +++- tools/parser_gen.cpp | 290 +++++++++++++++++++++++++++++++++++++++ 9 files changed, 574 insertions(+), 26 deletions(-) create mode 100644 tools/class_painter.h create mode 100644 tools/parser_gen.cpp diff --git a/.bzrignore b/.bzrignore index af2e593557..c981d28c7f 100644 --- a/.bzrignore +++ b/.bzrignore @@ -21,6 +21,8 @@ common/pcb_plot_params_keywords.cpp include/pcb_plot_params_lexer.h pcbnew/specctra_keywords.cpp pcbnew/specctra_lexer.h +pcb_calculator/pcb_calculator_datafile_keywords.cpp +pcb_calculator/pcb_calculator_datafile_lexer.h new/html new/sch_lib_table_keywords.cpp new/sch_lib_table_lexer.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 38a555006e..d89804dab9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -268,7 +268,7 @@ add_subdirectory(polygon/kbool/src) add_subdirectory(potrace) add_subdirectory(bitmap2component) add_subdirectory(pcb_calculator) -#add_subdirectory(tools) +add_subdirectory(tools) #add_subdirectory(new) diff --git a/common/dsnlexer.cpp b/common/dsnlexer.cpp index da08358b05..cfa298427d 100644 --- a/common/dsnlexer.cpp +++ b/common/dsnlexer.cpp @@ -51,7 +51,9 @@ static int compare( const void* a1, const void* a2 ) void DSNLEXER::init() { - curTok = DSN_NONE; + curTok = DSN_NONE; + prevTok = DSN_NONE; + stringDelimiter = '"'; specctraMode = false; @@ -433,6 +435,22 @@ L_read: if( cur >= limit ) goto L_read; + if( *cur == '(' ) + { + curText = *cur; + curTok = DSN_LEFT; + head = cur+1; + goto exit; + } + + if( *cur == ')' ) + { + curText = *cur; + curTok = DSN_RIGHT; + head = cur+1; + goto exit; + } + // switching the string_quote character if( prevTok == DSN_STRING_QUOTE ) { @@ -462,22 +480,6 @@ L_read: goto exit; } - if( *cur == '(' ) - { - curText = *cur; - curTok = DSN_LEFT; - head = cur+1; - goto exit; - } - - if( *cur == ')' ) - { - curText = *cur; - curTok = DSN_RIGHT; - head = cur+1; - goto exit; - } - /* get the dash out of a which is embedded for example like: U2-14 or "U2"-"14" This is detectable by a non-space immediately preceeding the dash. diff --git a/pcbnew/specctra.h b/pcbnew/specctra.h index 2b10267737..3c02596148 100644 --- a/pcbnew/specctra.h +++ b/pcbnew/specctra.h @@ -45,7 +45,7 @@ class BOARD; class TRACK; class SEGVIA; class NETCLASS; - +class MODULE; typedef DSN::T DSN_T; using namespace DSN; diff --git a/polygon/PolyLine.cpp b/polygon/PolyLine.cpp index 113bd0eba4..d7459a788e 100644 --- a/polygon/PolyLine.cpp +++ b/polygon/PolyLine.cpp @@ -339,8 +339,6 @@ int CPolyLine::MakeKboolPoly( int aStart_contour, int aEnd_contour, std::vector< for( int ic = ic_st; ic<=ic_end; ic++ ) { int style = side_style[ic]; - int x1 = corner[ic].x; - int y1 = corner[ic].y; int x2, y2; if( ic < ic_end ) { diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 2c80eb2c77..3a1bd2524b 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,6 +1,73 @@ -add_executable( container_test EXCLUDE_FROM_ALL container_test.cpp ) -target_link_libraries( container_test common polygon bitmaps ${wxWidgets_LIBRARIES} ) +if( 0 ) + + project(kicad-tools) + + cmake_minimum_required( VERSION 2.8 FATAL_ERROR ) + + set( PROJECT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../ ) + + # message( "PROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}" ) + + # Path to local CMake modules. + set( CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules ) + + include( CheckFindPackageResult ) + + ########################## + # Find wxWidgets library # + ########################## + # Here you can define what libraries of wxWidgets you need for your + # application. You can figure out what libraries you need here; + # http://www.wxwidgets.org/manuals/2.8/wx_librarieslist.html + + # On Apple only wxwidgets 2.9 or higher doesn't need to find aui part of base + if(APPLE) + find_package(wxWidgets COMPONENTS gl adv html core net base xml QUIET) + else(APPLE) + find_package(wxWidgets COMPONENTS gl aui adv html core net base xml QUIET) + endif(APPLE) + check_find_package_result(wxWidgets_FOUND "wxWidgets") + # Include wxWidgets macros. + include(${wxWidgets_USE_FILE}) + + # make config.h + include( PerformFeatureChecks ) + perform_feature_checks() + + +endif() + +include_directories( + ${PROJECT_SOURCE_DIR}/include + ${PROJECT_SOURCE_DIR}/pcbnew + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_BINARY_DIR} + ) + + +add_executable( container_test + EXCLUDE_FROM_ALL + container_test.cpp + ) +target_link_libraries( container_test + common + polygon + bitmaps + ${wxWidgets_LIBRARIES} + ) + + +add_executable( parser_gen + EXCLUDE_FROM_ALL + parser_gen.cpp + ../common/richio.cpp + ../common/dsnlexer.cpp + ) +target_link_libraries( parser_gen + ${wxWidgets_LIBRARIES} + ) + diff --git a/tools/class_painter.h b/tools/class_painter.h new file mode 100644 index 0000000000..ee201c1c50 --- /dev/null +++ b/tools/class_painter.h @@ -0,0 +1,172 @@ + + +#if defined(PCBNEW) + +class BOARD; +class TRACK; +class ZONE_CONTAINER; + +//: + +#elif defined(EESCHEMA) + +class SCH_SHEET; +//: + +#endif + + +/** + * Class PAINTER + * contains all the knowledge about how to draw any graphical object onto + * any particular output device. + * This knowledge is held outside the individual graphical objects so that + * alternative output devices may be used, and so that the graphical objects + * themselves to not contain drawing routines. Drawing routines in the objects + * cause problems with usages of the objects as simple container objects in + * DLL/DSOs. + */ +class PAINTER +{ +public: + + + /** + * Constructor PAINTER( wxDC& ) + * initializes this object for painting on any of the polymorphic + * wxDC derivatives. + * + * @param aDC is a reference to a polymorphic wx device context on which + * to draw. It can be any of the wxDC derivatives. + * No ownership is given to this PAINTER of aDC. + */ + PAINTER( wxDC& aDC ) : + m_dc( aDC ), + m_highlight( false ), + m_grayed( false ) + { + } + + + +#if defined(PCBNEW) + + void Draw( const BOARD_ITEM* ); + +#elif defined(EESCHEMA) + + void Draw( const SCH_ITEM* ); + +#endif + + +private: + + wxDC& m_dc; + + // drawing state information. + bool m_highlite; + bool m_grayed; + + +#if defined(PCBNEW) + + void draw( const TRACK* ); + void draw( const MODULE* ); + void draw( const EDGE_MODULE* ); + // : + +#elif defined(EESCHEMA) + void draw( const SCH_WIRE* ); + // : + +#endif +} + + +#if defined(PCBNEW) + +void PAINTER::Draw( const BOARD_ITEM* aItem ) +{ + // the "cast" applied in here clarifies which overloaded draw() is called + + switch( aItem->Type() ) + { + case PCB_MODULE_T: + draw( (MODULE*) aItem ); + break; + + case PCB_PAD_T: + draw( (D_PAD*) aItem ); + break; + + case PCB_LINE_T: + draw( (TEXTE_PCB*) aItem ); + break; + + case PCB_TEXT_T: + draw( (TEXTE_PCB*) aItem ); + break; + + case PCB_MODULE_TEXT_T: + draw( (TEXTE_PCB*) aItem ); + break; + + case PCB_MODULE_EDGE_T: + draw( (EDGE_MODULE*) aItem ); + break; + + case PCB_TRACE_T: + draw( (TRACKE*) aItem ); + break; + + case PCB_VIA_T: + draw( (VIA*) aItem ); + break; + + case PCB_ZONE_T: + draw( (SEGZONE*) aItem ); + break; + + case PCB_MARKER_T: + draw( (MARKER_PCB*) aItem ); + break; + + case PCB_DIMENSION_T: + draw( (DIMENSION*) aItem ); + break; + + case PCB_TARGET_T: + draw( (TARGET*) aItem ); + break; + + + case PCB_ZONE_AREA_T: + draw( (ZONE_CONTAINER*) aItem ); + break; + + /* not used + case PCB_ITEM_LIST_T: + draw( (BOARD_ITEM_LIST*) aItem ); + break; + */ + + default: + ; // nothing + } +} + +#elif defined(EESCHEMA) + +void PAINTER::Draw( const SCH_ITEM* aItem ) +{ + // the "cast" applied in here clarifies which overloaded draw() is called + + switch( aItem->Type() ) + { + //: + } +} + + +#endif \ No newline at end of file diff --git a/tools/container_test.cpp b/tools/container_test.cpp index f817325522..3b65dad7c4 100644 --- a/tools/container_test.cpp +++ b/tools/container_test.cpp @@ -13,6 +13,23 @@ //typedef std::deque EDA_ITEMV; typedef boost::ptr_vector EDA_ITEMV; +class MY_ITEM : public EDA_ITEM +{ +public: + + MY_ITEM( KICAD_T id ) : + EDA_ITEM( id ) + {} + + +#if defined(DEBUG) + void Show( int nestLevel, std::ostream& os ) const + { + ShowDummy( os ); + } +#endif +}; + void heap_warm_up(); @@ -37,7 +54,7 @@ int main( int argc, char** argv ) for( int i=0; i + * Copyright (C) 2012 KiCad Developers, see CHANGELOG.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 + */ + + +// This is wanting to be an s-expression C++ parser generator. Feed it a sample +// file and maybe someday it will generate a C++ file which uses DSNLEXER to +// parse the described grammar OK. + +// Until then, it is a non-specctra mode s-expression beautifier. + + +#include +#include +#include +#include +#include + + +// http://sexpr.sourceforge.net/ see comments about graphviz +// http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx + +#define D(x) x +//#define D(x) + + +/** + * Class ELEM + */ +class ELEM +{ +protected: + int token; + std::string text; + + typedef boost::ptr_vector ELEMS; + typedef ELEMS::const_iterator ELEMS_CITER; + typedef ELEMS::iterator ELEMS_ITER; + + ELEMS kids; ///< ELEM pointers + +public: + + // there are two constructors, one for a list, one for an atom + + /// List constructor + ELEM( int aToken ) : + token( aToken ), + text( "" ) + { + // D( printf( "ELEM%p: list\n", this ); ) + } + + /// Atom constructor + ELEM( const std::string& aText, int aToken ) : + token( aToken ), + text( aText ) + { + // D( printf( "ELEM%p: '%s'\n", this, text.c_str() ); ) + } + + int Token() const { return token; } + + const char* Text() { return text.c_str(); } + + + /** + * Function Format + * writes this object as ASCII out to an OUTPUTFORMATTER + * @param out The formatter to write to. + * @param nestLevel A multiple of the number of spaces to preceed the output with. + * @throw IO_ERROR if a system error writing the output, such as a full disk. + */ + void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel = 0, int aControlBits = 0 ); + +#define CTL_OMIT_NL (1<<0) + + /** + * Function Length + * returns the number of ELEMs in this ELEM. + * @return int - the count of children + */ + int Length() const + { + return kids.size(); + } + + void Append( ELEM* aElem ) + { + kids.push_back( aElem ); + } + + ELEM* Replace( int aIndex, ELEM* aElem ) + { + ELEMS::auto_type ret = kids.replace( aIndex, aElem ); + return ret.release(); + } + + ELEM* Remove( int aIndex ) + { + ELEMS::auto_type ret = kids.release( kids.begin()+aIndex ); + return ret.release(); + } + + void Insert( int aIndex, ELEM* aElem ) + { + kids.insert( kids.begin()+aIndex, aElem ); + } + + ELEM* At( int aIndex ) const + { + const ELEM& ref = kids.at( aIndex ); + return (ELEM*) &ref; + } + + ELEM* operator[]( int aIndex ) const + { + return At( aIndex ); + } + + void Delete( int aIndex ) + { + kids.erase( kids.begin()+aIndex ); + } +}; + + +void ELEM::Format( OUTPUTFORMATTER* out, int nestLevel, int ctl ) +{ + if( token == DSN_LEFT ) // this is a list + { + out->Print( nestLevel, "(" ); + + const int count = Length(); + for( int i=0; i 0 ) + out->Print( 0, " " ); + + if( next && next->token == DSN_LEFT ) + { + cur->Format( out, nestLevel+1, 0 ); + } + else + { + cur->Format( out, nestLevel+1, CTL_OMIT_NL ); + } + } + + out->Print( 0, ")%s", ctl & CTL_OMIT_NL ? "" : "\n" ); + } + else // this is an atom + { + const char* s = out->Quotes( text ).c_str(); + out->Print( 0, "%s%s", s, ctl & CTL_OMIT_NL ? "" : "\n" ); + } +} + +ELEM* Scan( DSNLEXER* lex ); +ELEM* ScanList( DSNLEXER* lex ); +ELEM* ScanAtom( DSNLEXER* lex ); + + +void usage() +{ + fprintf( stderr, "Usage: parser_gen \n" ); + exit( 1 ); +} + + +static KEYWORD empty_keywords[] = {}; + + +ELEM* Scan( DSNLEXER* lex ) +{ + ELEM* elem = NULL; + int tok = lex->CurTok(); + + // conditionally read first token. + if( tok == DSN_NONE ) + tok = lex->NextTok(); + + if( tok == DSN_EOF ) + { + lex->Unexpected( DSN_EOF ); + } + + if( tok == DSN_LEFT ) + { + elem = ScanList( lex ); + } + else + { + elem = ScanAtom( lex ); + } + + return elem; +} + + +/** + * Function ScanList + * reads and returns a sexpList from the input stream. + */ +ELEM* ScanList( DSNLEXER* lex ) +{ + int tok; + ELEM* list = NULL; + + assert( lex->CurTok() == DSN_LEFT ); + + list = new ELEM( DSN_LEFT ); + + while( ( tok = lex->NextTok() ) != DSN_RIGHT ) + { + if( tok == DSN_EOF ) + lex->Unexpected( DSN_EOF ); + + ELEM* elem = Scan( lex ); + list->Append( elem ); + } + + return list; +} + + +ELEM* ScanAtom( DSNLEXER* lex ) +{ + return new ELEM( lex->CurText(), lex->CurTok() ); +} + + +int main( int argc, char** argv ) +{ + if( argc != 2 ) + { + usage(); + } + + FILE* fp = fopen( argv[1], "rt" ); + if( !fp ) + { + fprintf( stderr, "Unable to open '%s'\n", argv[1] ); + usage(); + } + + DSNLEXER lexer( empty_keywords, 0, fp, wxString( FROM_UTF8( argv[1] ) ) ); + + try + { + ELEM* elem = Scan( &lexer ); + + if( elem ) + { + STRING_FORMATTER sf; + + elem->Format( &sf, 0 ); + + printf( "%s", sf.GetString().c_str() ); + } + } + catch( IO_ERROR ioe ) + { + fprintf( stderr, "%s\n", TO_UTF8( ioe.errorText ) ); + } +} +