Commit 2f211c6b authored by Dick Hollenbeck's avatar Dick Hollenbeck
Browse files

++all:

  * TokenList2DsnLexer.cmake now wraps each token enum in its own namespace. It
    also no longer setup of the "using" directive in the header file, which was
    bad behavior.  C++ enum values will have name collisions unless the enums
    themselves are different namespaces.
++new:
  * Sweet library is now a DSO/DLL.
  * Brought in SWIG to do a wrap of the Sweet DSO/DLL for unit testing
    and scripting.  The SWIG DSO/DLLs are built separate from the Sweet DSO/DLL
    and are also optional.
parent e7a75e0e
Loading
Loading
Loading
Loading
+13 −0
Original line number Original line Diff line number Diff line
@@ -4,6 +4,19 @@ 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-17 UPDATE Dick Hollenbeck <dick@softplc.com>
================================================================================
++all:
  * TokenList2DsnLexer.cmake now wraps each token enum in its own namespace. It
    also no longer setup of the "using" directive in the header file, which was
    bad behavior.  C++ enum values will have name collisions unless the enums
    themselves are different namespaces.
++new:
  * Sweet library is now a DSO/DLL.
  * Brought in SWIG to do a wrap of the Sweet DSO/DLL for unit testing
    and scripting.  The SWIG DSO/DLLs are built separate from the Sweet DSO/DLL
    and are also optional.

2011-Jan-1 UPDATE Dick Hollenbeck <dick@softplc.com>
2011-Jan-1 UPDATE Dick Hollenbeck <dick@softplc.com>
================================================================================
================================================================================
++new:
++new:
+75 −76
Original line number Original line Diff line number Diff line
@@ -38,7 +38,11 @@
#
#
# Invocation Parameters are:  enum, inputFile, outCppFile, outHeaderFile
# Invocation Parameters are:  enum, inputFile, outCppFile, outHeaderFile
#
#
#     enum       - Required, name of the enum to generate.
#     enum       - Required, namespace in which the enum T will be placed.
#                  Keep it short because from outside the class you want a short enum name
#                  like enum::T.   Enums are contained in their own namespace to avoid
#                  collisions on enum value names, a problem with C++ unless the enum
#                  itself is in a separate namespace.
#
#
#     inputFile  - Required, name of the token list file, or "*.keywords" file.
#     inputFile  - Required, name of the token list file, or "*.keywords" file.
#                  Choose the basefilename carefully, it decides the class name
#                  Choose the basefilename carefully, it decides the class name
@@ -52,23 +56,8 @@
#                  *.h lexfer file.  If not defined, the output path is the same
#                  *.h lexfer file.  If not defined, the output path is the same
#                  path as the token list file path, with a file name of *_lexer.h
#                  path as the token list file path, with a file name of *_lexer.h
#
#
# Example Usage from within a CMakeLists.txt file is shown below.  CMake itself
# Use the max_lexer() CMake function from functions.cmake for invocation convenience.
# is invoked as a child process to execute this script and parameters are passed on

# the command line, which is formulated as the "COMMAND" sequence below:
#
# add_custom_command(
#     OUTPUT  ${CMAKE_BINARY_DIR}/cmp_library_lexer.h
#             ${CMAKE_BINARY_DIR}/cmp_library_keywords.cpp
#     COMMAND ${CMAKE_COMMAND}
#             -Denum=YOURTOK_T
#             -DinputFile=${CMAKE_CURRENT_SOURCE_DIR}/cmp_library.keywords
#             -DoutCppFile=${CMAKE_CURRENT_SOURCE_DIR}/cmp_library_keywords.cpp
#             -DoutHeaderFile=${CMAKE_CURRENT_SOURCE_DIR}/cmp_library_lexer.h
#             -P ${CMAKE_MODULE_PATH}/TokenList2DsnLexer.cmake
#     DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/cmp_library.keywords
#     COMMENT "creating ${CMAKE_CURRENT_SOURCE_DIR}/cmp_library_{lexer.h,keywords.cpp}
#         from ${CMAKE_CURRENT_SOURCE_DIR}/cmp_library.keywords"
# )


#message( STATUS "TokenList2DsnLexer.cmake" )    # indicate we are running
#message( STATUS "TokenList2DsnLexer.cmake" )    # indicate we are running


@@ -90,6 +79,9 @@ get_filename_component( outputPath "${inputFile}" PATH )
get_filename_component( result "${inputFile}" NAME_WE )
get_filename_component( result "${inputFile}" NAME_WE )
string( TOUPPER "${result}" RESULT )
string( TOUPPER "${result}" RESULT )


set( LEXERCLASS "${RESULT}_LEXER" )
set( PARSERCLASS "${RESULT}_PARSER" )

#message( "enum:'${enum}' result:'${result}' outputPath:'${outputPath}' inputFile:'${inputFile}'" )
#message( "enum:'${enum}' result:'${result}' outputPath:'${outputPath}' inputFile:'${inputFile}'" )


if( NOT DEFINED outCppFile )
if( NOT DEFINED outCppFile )
@@ -101,7 +93,7 @@ if( NOT DEFINED outHeaderFile )
endif()
endif()


# Create tag for generating header file.
# Create tag for generating header file.
set( headerTag "_${RESULT}_H_" )
set( headerTag "${LEXERCLASS}_H_" )


set( includeFileHeader
set( includeFileHeader
"
"
@@ -114,10 +106,23 @@ set( includeFileHeader


#include \"dsnlexer.h\"
#include \"dsnlexer.h\"


namespace DSN {
/**

 * C++ does not put enum _values_ in separate namespaces unless the enum itself
enum ${enum} {
 * is in a separate namespace.  All the token enums must be in separate namespaces

 * otherwise the C++ compiler will eventually complain if it sees more than one
 * DSNLEXER in the same compilation unit, say by mutliple header file inclusion.
 * Plus this also enables re-use of the same enum name T.  A typedef can always be used
 * to clarify which enum T is in play should that ever be a problem.  This is
 * unlikely since Parse() functions will usually only be exposed to one header
 * file like this one.  But if there is a problem, then use:
 *   typedef ${enum}::T T;
 * within that problem area.
 */
namespace ${enum}
{
    /// enum T contains all this lexer's tokens.
    enum T
    {
        // these first few are negative special ones for syntax, and are
        // these first few are negative special ones for syntax, and are
        // inherited from DSNLEXER.
        // inherited from DSNLEXER.
        T_NONE          = DSN_NONE,
        T_NONE          = DSN_NONE,
@@ -127,14 +132,15 @@ enum ${enum} {
        T_DASH          = DSN_DASH,
        T_DASH          = DSN_DASH,
        T_SYMBOL        = DSN_SYMBOL,
        T_SYMBOL        = DSN_SYMBOL,
        T_NUMBER        = DSN_NUMBER,
        T_NUMBER        = DSN_NUMBER,
    T_RIGHT = DSN_RIGHT,    // right bracket, ')'
        T_RIGHT         = DSN_RIGHT,        // right bracket: ')'
    T_LEFT = DSN_LEFT,      // left bracket, '('
        T_LEFT          = DSN_LEFT,         // left bracket:  '('
        T_STRING        = DSN_STRING,       // a quoted string, stripped of the quotes
        T_STRING        = DSN_STRING,       // a quoted string, stripped of the quotes
        T_EOF           = DSN_EOF,          // special case for end of file
        T_EOF           = DSN_EOF,          // special case for end of file


"
"
)
)



set( sourceFileHeader
set( sourceFileHeader
"
"
/* Do not modify this file it was automatically generated by the
/* Do not modify this file it was automatically generated by the
@@ -146,11 +152,11 @@ set( sourceFileHeader


#include \"${result}_lexer.h\"
#include \"${result}_lexer.h\"


namespace DSN {
using namespace ${enum};


#define TOKDEF(x)    { #x, T_##x }
#define TOKDEF(x)    { #x, T_##x }


const KEYWORD ${result}_keywords[] = {
const KEYWORD ${LEXERCLASS}::keywords[] = {
"
"
)
)


@@ -212,34 +218,30 @@ endforeach( token ${tokens} )


file( APPEND "${outHeaderFile}"
file( APPEND "${outHeaderFile}"
"    };
"    };

}   // namespace ${enum}
extern const KEYWORD  ${result}_keywords[];
extern const unsigned ${result}_keyword_count;

}   // End namespace DSN

using namespace DSN;    // enum ${enum} is in this namespace




/**
/**
 * Classs ${RESULT}_LEXER
 * Class ${LEXERCLASS}
 * is an automatically generated class using the TokenList2DnsLexer.cmake
 * is an automatically generated class using the TokenList2DnsLexer.cmake
 * technology, based on keywords provided by file:
 * technology, based on keywords provided by file:
 *    ${inputFile}
 *    ${inputFile}
 */
 */
class ${RESULT}_LEXER : public DSNLEXER
class ${LEXERCLASS} : public DSNLEXER
{
{
public:
    /// Auto generated lexer keywords table and length:
    static const KEYWORD  keywords[];
    static const unsigned keyword_count;


public:
    /**
    /**
     * Constructor ( const std::string&, const wxString& )
     * Constructor ( const std::string&, const wxString& )
     * @param aSExpression is (utf8) 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.
     * @param aSource is a description of the origin of @a aSExpression, such as a filename.
     *   If left empty, then _("clipboard") is used.
     *   If left empty, then _("clipboard") is used.
     */
     */
    ${RESULT}_LEXER( const std::string& aSExpression, const wxString& aSource = wxEmptyString ) :
    ${LEXERCLASS}( const std::string& aSExpression, const wxString& aSource = wxEmptyString ) :
        DSNLEXER( DSN::${result}_keywords, DSN::${result}_keyword_count,
        DSNLEXER( keywords, keyword_count, aSExpression, aSource )
                  aSExpression, aSource )
    {
    {
    }
    }


@@ -252,9 +254,8 @@ public:
     * @param aFile is a FILE already opened for reading.
     * @param aFile is a FILE already opened for reading.
     * @param aFilename is the name of the opened file, needed for error reporting.
     * @param aFilename is the name of the opened file, needed for error reporting.
     */
     */
    ${RESULT}_LEXER( FILE* aFile, const wxString& aFilename ) :
    ${LEXERCLASS}( FILE* aFile, const wxString& aFilename ) :
        DSNLEXER( DSN::${result}_keywords, DSN::${result}_keyword_count,
        DSNLEXER( keywords, keyword_count, aFile, aFilename )
                  aFile, aFilename )
    {
    {
    }
    }


@@ -269,9 +270,8 @@ public:
     * @param aLineReader is any subclassed instance of LINE_READER, such as
     * @param aLineReader is any subclassed instance of LINE_READER, such as
     *  STRING_LINE_READER or FILE_LINE_READER.  No ownership is taken of aLineReader.
     *  STRING_LINE_READER or FILE_LINE_READER.  No ownership is taken of aLineReader.
     */
     */
    ${RESULT}_LEXER( LINE_READER* aLineReader ) :
    ${LEXERCLASS}( LINE_READER* aLineReader ) :
        DSNLEXER( DSN::${result}_keywords, DSN::${result}_keyword_count,
        DSNLEXER( keywords, keyword_count, aLineReader )
                  aLineReader )
    {
    {
    }
    }


@@ -282,12 +282,12 @@ public:
     * to aid in grammar debugging while running under a debugger, but leave
     * 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
     * this lower level function returning an int (so the enum does not collide
     * with another usage).
     * with another usage).
     * @return ${enum} - the type of token found next.
     * @return ${enum}::T - the type of token found next.
     * @throw IO_ERROR - only if the LINE_READER throws it.
     * @throw IO_ERROR - only if the LINE_READER throws it.
     */
     */
    ${enum} NextTok() throw( IO_ERROR )
    ${enum}::T NextTok() throw( IO_ERROR )
    {
    {
        return (${enum}) DSNLEXER::NextTok();
        return (${enum}::T) DSNLEXER::NextTok();
    }
    }


    /**
    /**
@@ -298,9 +298,9 @@ public:
     * @return int - the actual token read in.
     * @return int - the actual token read in.
     * @throw IO_ERROR, if the next token does not satisfy IsSymbol()
     * @throw IO_ERROR, if the next token does not satisfy IsSymbol()
     */
     */
    ${enum} NeedSYMBOL() throw( IO_ERROR )
    ${enum}::T NeedSYMBOL() throw( IO_ERROR )
    {
    {
        return (${enum}) DSNLEXER::NeedSYMBOL();
        return (${enum}::T) DSNLEXER::NeedSYMBOL();
    }
    }


    /**
    /**
@@ -311,37 +311,37 @@ public:
     * @return int - the actual token read in.
     * @return int - the actual token read in.
     * @throw IO_ERROR, if the next token does not satisfy the above test
     * @throw IO_ERROR, if the next token does not satisfy the above test
     */
     */
    ${enum} NeedSYMBOLorNUMBER() throw( IO_ERROR )
    ${enum}::T NeedSYMBOLorNUMBER() throw( IO_ERROR )
    {
    {
        return (${enum}) DSNLEXER::NeedSYMBOLorNUMBER();
        return (${enum}::T) DSNLEXER::NeedSYMBOLorNUMBER();
    }
    }


    /**
    /**
     * Function CurTok
     * Function CurTok
     * returns whatever NextTok() returned the last time it was called.
     * returns whatever NextTok() returned the last time it was called.
     */
     */
    ${enum} CurTok()
    ${enum}::T CurTok()
    {
    {
        return (${enum}) DSNLEXER::CurTok();
        return (${enum}::T) DSNLEXER::CurTok();
    }
    }


    /**
    /**
     * Function PrevTok
     * Function PrevTok
     * returns whatever NextTok() returned the 2nd to last time it was called.
     * returns whatever NextTok() returned the 2nd to last time it was called.
     */
     */
    ${enum} PrevTok()
    ${enum}::T PrevTok()
    {
    {
        return (${enum}) DSNLEXER::PrevTok();
        return (${enum}::T) DSNLEXER::PrevTok();
    }
    }
};
};


// example usage
// example usage


/**
/**
 * Class ${RESULT}_PARSER
 * Class ${LEXCLASS}_PARSER
 * holds data and functions pertinent to parsing a S-expression file .
 * holds data and functions pertinent to parsing a S-expression file .
 *
 *
class ${RESULT}_PARSER : public ${RESULT}_LEXER
class ${PARSERCLASS} : public ${LEXERCLASS}
{
{


};
};
@@ -354,8 +354,7 @@ class ${RESULT}_PARSER : public ${RESULT}_LEXER
file( APPEND "${outCppFile}"
file( APPEND "${outCppFile}"
"};
"};


const unsigned ${result}_keyword_count = unsigned( sizeof( ${result}_keywords )/sizeof( ${result}_keywords[0] ) );
const unsigned ${LEXERCLASS}::keyword_count = unsigned( sizeof( ${LEXERCLASS}::keywords )/sizeof( ${LEXERCLASS}::keywords[0] ) );


}   // End namespace DSN
"
"
)
)
+4 −4
Original line number Original line Diff line number Diff line
@@ -5,8 +5,7 @@
#include "fctsys.h"
#include "fctsys.h"
#include "macros.h"
#include "macros.h"


using namespace DSN;    // enum TFIELD_T is in this namespace
using namespace TFIELD_T;



wxString TEMPLATE_FIELDNAME::GetDefaultFieldName( int aFieldNdx )
wxString TEMPLATE_FIELDNAME::GetDefaultFieldName( int aFieldNdx )
{
{
@@ -48,7 +47,7 @@ void TEMPLATE_FIELDNAME::Format( OUTPUTFORMATTER* out, int nestLevel ) const thr


void TEMPLATE_FIELDNAME::Parse( TEMPLATE_FIELDNAMES_LEXER* in ) throw( IO_ERROR )
void TEMPLATE_FIELDNAME::Parse( TEMPLATE_FIELDNAMES_LEXER* in ) throw( IO_ERROR )
{
{
    TFIELD_T    tok;
    T    tok;


    in->NeedLEFT();     // begin (name ...)
    in->NeedLEFT();     // begin (name ...)


@@ -97,9 +96,10 @@ void TEMPLATES::Format( OUTPUTFORMATTER* out, int nestLevel ) const throw( IO_ER
    out->Print( 0, ")\n" );
    out->Print( 0, ")\n" );
}
}



void TEMPLATES::Parse( TEMPLATE_FIELDNAMES_LEXER* in ) throw( IO_ERROR )
void TEMPLATES::Parse( TEMPLATE_FIELDNAMES_LEXER* in ) throw( IO_ERROR )
{
{
    TFIELD_T        tok;
    T  tok;


    while( (tok = in->NextTok() ) != T_RIGHT && tok != T_EOF )
    while( (tok = in->NextTok() ) != T_RIGHT && tok != T_EOF )
    {
    {
+56 −29
Original line number Original line Diff line number Diff line
@@ -60,7 +60,7 @@ endif()


include_directories( ${CMAKE_CURRENT_SOURCE_DIR} )
include_directories( ${CMAKE_CURRENT_SOURCE_DIR} )


#=====<on standby until unit testing infrastructure>============================
#=====<on standby for possible C++ unit testing>================================
if( false )
if( false )


    add_executable( test_dir_lib_source
    add_executable( test_dir_lib_source
@@ -78,33 +78,60 @@ target_link_libraries( test_lpid ${wxWidgets_LIBRARIES} )


endif( false )
endif( false )


#=====</on standby until unit testing infrastructure>===========================
#=====</on standby for possible C++ unit testing>===============================


add_executable( test_sch_lib_table

make_lexer(
    ${CMAKE_CURRENT_SOURCE_DIR}/sch_lib_table.keywords
    ${CMAKE_CURRENT_SOURCE_DIR}/sch_lib_table_lexer.h
    ${CMAKE_CURRENT_SOURCE_DIR}/sch_lib_table_keywords.cpp
    LT
    )

make_lexer(
    ${CMAKE_CURRENT_SOURCE_DIR}/sweet.keywords
    ${CMAKE_CURRENT_SOURCE_DIR}/sweet_lexer.h
    ${CMAKE_CURRENT_SOURCE_DIR}/sweet_keywords.cpp
    PR
    )

add_library( sweet SHARED
    sch_lib_table.cpp
    sch_lib_table.cpp
    sch_lib_table_keywords.cpp
    sch_lib_table_keywords.cpp
    sch_lib.cpp
    sch_lib.cpp
    sch_lpid.cpp
    sch_lpid.cpp
    filter_reader.cpp
    sch_dir_lib_source.cpp
    sch_dir_lib_source.cpp
    sch_part.cpp
    sch_part.cpp
    sweet_keywords.cpp
    sweet_keywords.cpp
    ${PROJECT_SOURCE_DIR}/common/richio.cpp
    ${PROJECT_SOURCE_DIR}/common/richio.cpp
    ${PROJECT_SOURCE_DIR}/common/dsnlexer.cpp
    ${PROJECT_SOURCE_DIR}/common/dsnlexer.cpp
    )
    )
target_link_libraries( test_sch_lib_table ${wxWidgets_LIBRARIES} )
target_link_libraries( sweet ${wxWidgets_LIBRARIES} )




make_lexer(
#=====<USE_SWIG>============================================================
    ${CMAKE_CURRENT_SOURCE_DIR}/sch_lib_table.keywords
# if you want a Python scripting layer on top for unit testing or driving.
    ${CMAKE_CURRENT_SOURCE_DIR}/sch_lib_table_lexer.h
# reference: http://www.swig.org/Doc1.3/Introduction.html#Introduction_build_system
    ${CMAKE_CURRENT_SOURCE_DIR}/sch_lib_table_keywords.cpp

    ELT_T
option( USE_SWIG "Use SWIG to build a python scripting interface (default ON)." ON)
    )
if( USE_SWIG )

    find_package( SWIG REQUIRED )
    include( ${SWIG_USE_FILE} )

    # first install "python-dev" linux package for this:
    find_package( PythonLibs )
    include_directories( ${PYTHON_INCLUDE_PATH} )

    set( CMAKE_SWIG_FLAGS "" )

    set_source_files_properties( sweet.i PROPERTIES CPLUSPLUS ON )
    #set_source_files_properties( sweet.i PROPERTIES SWIG_FLAGS "-includeall" )

    swig_add_module( sweet python sweet.i )
    swig_link_libraries( sweet ${PYTHON_LIBRARIES} sweet )

    # @todo need a separate interface for each DSNLEXER

endif()
make_lexer(
    ${CMAKE_CURRENT_SOURCE_DIR}/sweet.keywords
    ${CMAKE_CURRENT_SOURCE_DIR}/sweet_lexer.h
    ${CMAKE_CURRENT_SOURCE_DIR}/sweet_keywords.cpp
    PART_T
    )
+3 −2
Original line number Original line Diff line number Diff line
@@ -30,6 +30,7 @@
#include <sch_lib_table.h>
#include <sch_lib_table.h>
#include <sch_dir_lib_source.h>
#include <sch_dir_lib_source.h>



//using namespace std;    // screws up Doxygen
//using namespace std;    // screws up Doxygen
using namespace SCH;
using namespace SCH;


@@ -55,7 +56,7 @@ void LIB_TABLE::Parse( SCH_LIB_TABLE_LEXER* in ) throw( IO_ERROR )
         note: "(lib_table" has already been read in.
         note: "(lib_table" has already been read in.
    */
    */


    ELT_T   tok;
    T tok;


    while( ( tok = in->NextTok() ) != T_RIGHT )
    while( ( tok = in->NextTok() ) != T_RIGHT )
    {
    {
@@ -339,7 +340,7 @@ bool LIB_TABLE::InsertRow( std::auto_ptr<ROW>& aRow, bool doReplace )
}
}




#if 1 && defined(DEBUG)
#if 0 && defined(DEBUG)


// build this with a Debug CMAKE_BUILD_TYPE
// build this with a Debug CMAKE_BUILD_TYPE


Loading