Constructed and organized all the /new infrastructure to get a Sweet string being passed

to PART::Parse() from test program.  Ready now to complete the PART parsing.
This commit is contained in:
Dick Hollenbeck 2010-12-29 19:47:14 -06:00
parent 3caca699cc
commit 70b17eed1d
12 changed files with 248 additions and 147 deletions

View File

@ -5,9 +5,6 @@ eeschema/cmp_library_lexer.h
eeschema/cmp_library_keywords.*
eeschema/template_fieldnames_keywords.*
eeschema/template_fieldnames_lexer.h
new/html
new/sch_lib_table_keywords.cpp
new/sch_lib_table_lexer.h
pcbnew/dialogs/dialog_freeroute_exchange_help_html.h
Makefile
CMakeFiles
@ -20,3 +17,8 @@ install_manifest.txt
Documentation/doxygen
*.cmake
*.bak
new/html
new/sch_lib_table_keywords.cpp
new/sch_lib_table_lexer.h
new/sweet_keywords.cpp
new/sweet_lexer.h

View File

@ -86,6 +86,8 @@ add_executable( test_sch_lib_table
sch_lib.cpp
sch_lpid.cpp
sch_dir_lib_source.cpp
sch_part.cpp
sweet_keywords.cpp
${PROJECT_SOURCE_DIR}/common/richio.cpp
${PROJECT_SOURCE_DIR}/common/dsnlexer.cpp
)
@ -98,3 +100,10 @@ make_lexer(
${CMAKE_CURRENT_SOURCE_DIR}/sch_lib_table_keywords.cpp
ELT_T
)
make_lexer(
${CMAKE_CURRENT_SOURCE_DIR}/sweet.keywords
${CMAKE_CURRENT_SOURCE_DIR}/sweet_lexer.h
${CMAKE_CURRENT_SOURCE_DIR}/sweet_keywords.cpp
PART_T
)

View File

@ -157,7 +157,7 @@ static inline bool isDigit( char c )
* segment, i.e. the string segment of interest is [start,tail)
* @param separator is the separating byte, expected: '.' or '/', depending on context.
*/
static const char* endsWithRev( const char* start, const char* tail, char separator )
static const char* endsWithRev( const char* start, const char* tail, char separator = '/' )
{
bool sawDigit = false;
@ -181,7 +181,7 @@ static const char* endsWithRev( const char* start, const char* tail, char separa
return 0;
}
static inline const char* endsWithRev( const STRING& aPartName, char separator )
static inline const char* endsWithRev( const STRING& aPartName, char separator = '/' )
{
return endsWithRev( aPartName.c_str(), aPartName.c_str()+aPartName.size(), separator );
}
@ -194,8 +194,8 @@ bool BY_REV::operator() ( const STRING& s1, const STRING& s2 ) const
{
// avoid instantiating new STRINGs, and thank goodness that c_str() is const.
const char* rev1 = endsWithRev( s1, '/' );
const char* rev2 = endsWithRev( s2, '/' );
const char* rev1 = endsWithRev( s1 );
const char* rev2 = endsWithRev( s2 );
int rootLen1 = rev1 ? rev1 - s1.c_str() : s1.size();
int rootLen2 = rev2 ? rev2 - s2.c_str() : s2.size();
@ -290,7 +290,7 @@ STRING DIR_LIB_SOURCE::makeFileName( const STRING& aPartName )
STRING fileName = sourceURI + "/";
const char* rev = endsWithRev( aPartName, '/' );
const char* rev = endsWithRev( aPartName );
if( rev )
{
@ -406,7 +406,7 @@ void DIR_LIB_SOURCE::GetCategoricalPartNames( STRINGS* aResults, const STRING& a
while( it != limit )
{
const char* rev = endsWithRev( *it, '/' );
const char* rev = endsWithRev( *it );
// all cached partnames have a rev string in useVersioning mode
assert( rev );
@ -434,7 +434,13 @@ void DIR_LIB_SOURCE::ReadPart( STRING* aResult, const STRING& aPartName, const S
throw( IO_ERROR )
{
STRING partName = aPartName; // appended with aRev too if not empty
const char* rev = endsWithRev( partName, '/' );
const char* rev = endsWithRev( partName );
if( !useVersioning && (aRev.size() || rev) )
{
STRING msg = "this type 'dir' LIB_SOURCE not using 'useVersioning' option, cannot ask for a revision";
throw IO_ERROR( msg );
}
if( aRev.size() )
{
@ -443,7 +449,7 @@ void DIR_LIB_SOURCE::ReadPart( STRING* aResult, const STRING& aPartName, const S
partName += "/" + aRev;
rev = endsWithRev( partName, '/' );
rev = endsWithRev( partName );
}
// partName is the exact part name we need here, or if rev is NULL,
@ -474,7 +480,8 @@ void DIR_LIB_SOURCE::ReadPart( STRING* aResult, const STRING& aPartName, const S
// some unrelated name that is larger.
if( it == partnames.end() || it->compare( 0, search.size(), search ) != 0 )
{
partName += " rev not found.";
partName.insert( partName.begin(), '\'' );
partName += "' is not present without a revision.";
throw IO_ERROR( partName );
}
@ -651,7 +658,7 @@ void DIR_LIB_SOURCE::Test( int argc, char** argv )
catch( IO_ERROR ioe )
{
printf( "exception: %s\n", (const char*) wxConvertWX2MB( ioe.errorText ) );
printf( "exception: %s\n", (const char*) ioe.errorText.ToUTF8() ) );
}
}

View File

@ -22,9 +22,14 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <memory> // std::auto_ptr
#include <wx/string.h>
#include <sch_lib.h>
#include <sch_lpid.h>
#include <sch_part.h>
#include <sweet_lexer.h>
#include <sch_lib_table.h>
using namespace SCH;
@ -44,9 +49,40 @@ LIB::~LIB()
}
PART* LIB::LookupPart( const LPID& aLPID ) throw( IO_ERROR )
PART* LIB::LookupPart( const LPID& aLPID, LIB_TABLE* aLibTable ) throw( IO_ERROR )
{
return 0;
PART* part;
// If part not already cached
if( 1 /* @todo test cache */ )
{
// load it.
part = new PART( this, aLPID.GetPartName(), aLPID.GetRevision() );
std::auto_ptr<PART> wrapped( part );
source->ReadPart( &part->body, aLPID.GetPartName(), aLPID.GetRevision() );
#if defined(DEBUG)
const STRING& body = part->body;
printf( "body: %s", body.c_str() );
if( !body.size() || body[body.size()-1] != '\n' )
printf( "\n" );
#endif
SWEET_LEXER sw( part->body, wxString::FromUTF8("body") /* @todo have ReadPart give better source */ );
part->Parse( &sw, aLibTable );
// stuff the part into this LIBs cache:
// @todo
wrapped.release();
}
return part;
}

View File

@ -33,7 +33,7 @@ namespace SCH {
class LPID;
class PART;
class LIB_TABLE;
/**
* Class LIB_SOURCE
@ -69,7 +69,7 @@ protected: ///< derived classes must implement
* Function ReadPart
* fetches @a aPartName's s-expression into @a aResult after clear()ing aResult.
*/
virtual void ReadPart( STRING* aResult, const STRING& aPartName, const STRING& aRev = "" )
virtual void ReadPart( STR_UTF* aResult, const STRING& aPartName, const STRING& aRev = "" )
throw( IO_ERROR ) = 0;
/**
@ -80,7 +80,7 @@ protected: ///< derived classes must implement
* does not have a version string, then the most recent version is fetched.
* @param aResults receives the s-expressions
*/
virtual void ReadParts( STRINGS* aResults, const STRINGS& aPartNames )
virtual void ReadParts( STR_UTFS* aResults, const STRINGS& aPartNames )
throw( IO_ERROR ) = 0;
/**
@ -239,12 +239,15 @@ public:
* @param aLPID is the part to lookup. The logicalLibName can be empty in it
* since yes, we know which LIB is in play.
*
* @param aLibTable is the LIB_TABLE view that is in effect for inheritance,
* and comes from the big containing SCHEMATIC object.
*
* @return PART* - The desired PART and will never be NULL. No ownership is
* given to caller. PARTs always reside in the cache that is a LIB.
*
* @throw IO_ERROR if the part cannot be found or loaded.
*/
PART* LookupPart( const LPID& aLPID )
PART* LookupPart( const LPID& aLPID, LIB_TABLE* aLibTable )
throw( IO_ERROR );
/**
@ -315,13 +318,13 @@ public:
protected:
STRING fetch; // scratch, used to fetch things, grows to worst case size.
STRINGS vfetch; // scratch, used to fetch things.
STR_UTF fetch; // scratch, used to fetch things, grows to worst case size.
STR_UTFS vfetch; // scratch, used to fetch things.
STRING name;
LIB_SOURCE* source;
LIB_SINK* sink;
STRING libraryURI;
// STRING libraryURI;
STRINGS categories;

View File

@ -187,53 +187,46 @@ STRINGS LIB_TABLE::GetLogicalLibs()
}
PART* LIB_TABLE::LookupPart( const LPID& aLogicalPartID, LIB* aLocalLib )
PART* LIB_TABLE::LookupPart( const LPID& aLPID, LIB* aLocalLib )
throw( IO_ERROR )
{
LIB* lib = lookupLib( aLogicalPartID, aLocalLib );
LIB* lib = lookupLib( aLPID, aLocalLib );
return lib->LookupPart( aLogicalPartID );
return lib->LookupPart( aLPID, this );
}
LIB* LIB_TABLE::lookupLib( const LPID& aLogicalPartID, LIB* aLocalLib )
LIB* LIB_TABLE::lookupLib( const LPID& aLPID, LIB* aFallBackLib )
throw( IO_ERROR )
{
if( aLocalLib )
if( aLPID.GetLogicalLib().size() )
{
return aLocalLib;
}
else
{
const STRING& logName = aLogicalPartID.GetLogicalLib();
if( logName.size() )
ROW* row = FindRow( aLPID.GetLogicalLib() );
if( !row )
{
ROW* row = FindRow( logName );
if( !row )
{
STRING msg = "Unable to find logical lib ";
msg += logName;
throw IO_ERROR( msg );
}
if( !row->lib )
{
loadLib( row );
}
assert( row->lib ); // loadLib() throws if cannot load
return row->lib;
}
else
{
STRING msg = "No logicalLibName in LPID and no localLib";
STRING msg = "lib table contains no logical lib '";
msg += aLPID.GetLogicalLib();
msg += '\'';
throw IO_ERROR( msg );
}
if( !row->lib )
{
loadLib( row );
}
assert( row->lib ); // fix loadLib() to throw if cannot load
return row->lib;
}
// return NULL; never get here
if( aFallBackLib )
{
return aFallBackLib;
}
STRING msg = "lookupLib() requires logicalLibName or a fallback lib";
throw IO_ERROR( msg );
}
@ -262,6 +255,7 @@ void LIB_TABLE::loadLib( ROW* aRow ) throw( IO_ERROR )
aRow->lib = new LIB( aRow->GetLogicalName(), source.release(), NULL );
}
/*
else if( !libType.compare( "schematic" ) )
{
// @todo code and load SCHEMATIC_LIB_SOURCE
@ -276,6 +270,14 @@ void LIB_TABLE::loadLib( ROW* aRow ) throw( IO_ERROR )
{
// @todo code and load HTTP_LIB_SOURCE
}
*/
else
{
STRING msg = "cannot load unknown libType: '";
msg += libType;
msg += '\'';
throw IO_ERROR( msg );
}
}
@ -334,7 +336,7 @@ bool LIB_TABLE::InsertRow( std::auto_ptr<ROW>& aRow, bool doReplace )
}
#if 0 && defined(DEBUG)
#if 1 && defined(DEBUG)
// build this with a Debug CMAKE_BUILD_TYPE
@ -346,7 +348,7 @@ void LIB_TABLE::Test()
SCH_LIB_TABLE_LEXER slr(
"(lib_table \n"
" (lib (logical www) (type http) (full_uri http://kicad.org/libs) (options \" \"))\n"
" (lib (logical meparts) (type dir) (full_uri /tmp/eeschema-lib) (options \" \"))\n"
" (lib (logical meparts) (type dir) (full_uri /tmp/eeschema-lib) (options useVersioning))\n"
" (lib (logical old-project) (type schematic)(full_uri /tmp/old-schematic.sch) (options \" \"))\n"
,
@ -368,9 +370,9 @@ void LIB_TABLE::Test()
printf( "std::exception\n" );
}
catch( IO_ERROR ioe )
catch( IO_ERROR& ioe )
{
printf( "exception: %s\n", (const char*) wxConvertWX2MB( ioe.errorText ) );
printf( "exception: %s\n", (const char*) ioe.errorText.ToUTF8() );
}
STRING_FORMATTER sf;
@ -401,6 +403,18 @@ void LIB_TABLE::Test()
{
printf( "logicalName: %s\n", it->c_str() );
}
try
{
// find a part
LPID lpid( "meparts:tigers/ears/rev10" );
LookupPart( lpid );
}
catch( IO_ERROR& ioe )
{
printf( "exception: %s\n", (const char*) ioe.errorText.ToUTF8() );
}
}

View File

@ -350,14 +350,12 @@ private:
* finds or loads a LIB based on @a aLogicalPartID or @a aFallBackLib.
* If the LIB is already loaded then it is returned as is, else it is loaded.
*
* @param aLogicalPartID may hold the logicalLibName. If
* logicalLibName is empty, then @a aLocalLib should not be NULL.
* @param aLogicalPartID holds the partName and may also hold the logicalLibName. If
* logicalLibName is empty, then @a aFallBackLib should not be NULL.
*
* @param aLocalLib is used if not NULL, and should be supplied especiallly if
* aLogicalPartID has an empty logicalLibName. This is for the case when
* a partName must come from the same LIB as the referring content.
* For example, a PART extends another PART in the same LIB and the extends
* LPID has no logical lib name.
* @param aFallBackLib is used only if aLogicalPartID has an empty logicalLibName.
* This is for the case when an LPID has no logicalLibName because the LPID is using
* a partName from the same LIB as was the referring content.
*
* @return LIB* - this will never be NULL, and no ownership is transfered because
* all LIBs live in the LIB_TABLEs. You only get to point to them in some LIB_TABLE.
@ -365,7 +363,7 @@ private:
*
* @throw IO_ERROR if any problem occurs or if the LIB cannot be found or cannot be loaded.
*/
LIB* lookupLib( const LPID& aLogicalPartID, LIB* aLocalLib = NULL ) throw( IO_ERROR );
LIB* lookupLib( const LPID& aLogicalPartID, LIB* aFallBackLib = NULL ) throw( IO_ERROR );
/**
* Function loadLib

View File

@ -114,6 +114,7 @@ int LPID::Parse( const STRING& aLPID )
logical.clear();
category.clear();
baseName.clear();
partName.clear();
revision.clear();
const char* rev = EndsWithRev( aLPID );
@ -193,12 +194,6 @@ LPID::LPID( const STRING& aLPID ) throw( PARSE_ERROR )
}
const STRING& LPID::GetLogicalLib() const
{
return logical;
}
int LPID::SetLogicalLib( const STRING& aLogical )
{
int offset = okLogical( aLogical );
@ -210,63 +205,49 @@ int LPID::SetLogicalLib( const STRING& aLogical )
}
const STRING& LPID::GetCategory() const
{
return category;
}
int LPID::SetCategory( const STRING& aCategory )
{
int offset = okCategory( aCategory );
if( offset == -1 )
{
category = aCategory;
// set the partName too
if( category.size() )
{
partName = category;
partName += '/';
partName += baseName;
}
else
partName = baseName;
}
return offset;
}
const STRING& LPID::GetBaseName() const
{
return baseName;
}
int LPID::SetBaseName( const STRING& aBaseName )
{
int offset = okBase( aBaseName );
if( offset == -1 )
{
baseName = aBaseName;
// set the partName too
if( category.size() )
{
partName = category;
partName += '/';
partName += baseName;
}
else
partName = baseName;
}
return offset;
}
STRING LPID::GetPartName() const
{
STRING ret;
// return [category/]baseName
if( category.size() )
{
ret += category;
ret += '/';
}
ret += baseName;
return ret;
}
const STRING& LPID::GetRevision() const
{
return revision;
}
int LPID::SetRevision( const STRING& aRevision )
{
int offset = okRevision( aRevision );
@ -306,7 +287,7 @@ STRING LPID::Format() const
}
#if 1 && defined(DEBUG)
#if 0 && defined(DEBUG)
// build this with Debug CMAKE_BUILD_TYPE

View File

@ -84,7 +84,10 @@ public:
* for this portion since it comes from the library table and is considered
* read only here.
*/
const STRING& GetLogicalLib() const;
const STRING& GetLogicalLib() const
{
return logical;
}
/**
* Function SetCategory
@ -100,7 +103,10 @@ public:
* returns the category of this part id, "passives" in the example at the
* top of the class description.
*/
const STRING& GetCategory() const;
const STRING& GetCategory() const
{
return category;
}
/**
* Function SetCategory
@ -116,7 +122,10 @@ public:
* Function GetBaseName
* returns the part name without the category.
*/
const STRING& GetBaseName() const;
const STRING& GetBaseName() const
{
return baseName;
}
/**
* Function SetBaseName
@ -131,20 +140,19 @@ public:
* Function GetPartName
* returns the part name, i.e. category/baseName without revision.
*/
STRING GetPartName() const;
/**
* Function SetBaseName
* overrides the part name portion of the LPID to @a aPartName
not really needed, partname is an agreggate anyway, just parse a new one.
void SetPartName( const STRING& aPartName );
*/
const STRING& GetPartName() const
{
return partName;
}
/**
* Function GetRevision
* returns the revision portion of the LPID.
*/
const STRING& GetRevision() const;
const STRING& GetRevision() const
{
return revision;
}
/**
* Function SetRevision
@ -171,6 +179,7 @@ protected:
STRING category; ///< or empty
STRING baseName; ///< without category
STRING revision; ///< "revN[N..]" or empty
STRING partName; ///< cannot be set directory, set via SetBaseName() & SetCategory()
};
} // namespace SCH

View File

@ -22,12 +22,18 @@
*/
#include "sch_part.h"
#include <sch_part.h>
#include <sweet_lexer.h>
#include <wx/wx.h> // _()
using namespace SCH;
void PART::Parse( LIB* aLexer ) throw( PARSE_ERROR )
void PART::Parse( SWEET_LEXER* aLexer, LIB_TABLE* aTable ) throw( PARSE_ERROR )
{
// Wayne's world, if he still wants it.
}

View File

@ -27,9 +27,31 @@
#include <sch_lib.h>
class SWEET_LEXER;
namespace SCH {
/**
* Enum PartBit
* is a set of bit positions that can be used to create flag bits within
* PART::contains to indicate what state the PART is in and what it contains, i.e.
* whether the PART has been parsed, and what the PART contains, categorically.
*/
enum PartBit
{
PARSED, ///< have parsed this part already, otherwise 'body' text must be parsed
EXTENDS, ///< saw and "extends" keyword, inheriting from another PART
};
/// Function PB
/// is a PartBit shifter for PART::contains field.
static inline const int PB( PartBit oneBitOnly )
{
return ( 1 << oneBitOnly );
}
/**
* Class PART
* will have to be unified with what Wayne is doing. I want a separate copy
@ -47,19 +69,23 @@ class PART
/// be done by PARTS_LIST, a class derived from LIB.
friend class LIB;
/// a private constructor, only a LIB can instantiate a PART.
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.
bool parsed; ///< true if the body as been parsed already.
LIB* owner; ///< which LIB am I a part of (pun if you want)
int contains; ///< has bits from Enum PartParts
STRING extends; ///< LPID of base part
STRING name; ///< example "passives/R", immutable.
STRING partName; ///< example "passives/R", immutable.
STRING revision; // @todo need a single search key, this won't do.
/// s-expression text for the part, initially empty, and read in as this part
/// actually becomes cached in RAM.
@ -81,7 +107,6 @@ protected: // not likely to have C++ descendants, but protected none-the-le
// lots of other stuff, like the mandatory properties.
public:
/**
@ -91,7 +116,6 @@ public:
*/
void Inherit( const PART& aBasePart );
/**
* Function Owner
* returns the LIB* owner of this part.
@ -100,12 +124,23 @@ public:
/**
* Function Parse
* translates the \a body string into a binary form that is represented
* translates a Sweet string into a binary form that is represented
* by the normal fields of this class. Parse is expected to call Inherit()
* if this part extends any other.
*
* @param aLexer is an instance of SWEET_LEXER, rewound at the first line.
*
* @param aLibTable is the LIB_TABLE view that is in effect for inheritance,
* and comes from the big containing SCHEMATIC object.
*/
void Parse( LIB* aLexer ) throw( PARSE_ERROR );
void Parse( SWEET_LEXER* aLexer, LIB_TABLE* aTable ) throw( PARSE_ERROR );
/*
void SetBody( const STR_UTF& aSExpression )
{
body = aSExpression;
}
*/
};
} // namespace PART

View File

@ -13,14 +13,19 @@
/**
* Type STRING
* holds a sequence of 8 bit bytes that represent a sequence
* of variable multi-byte international characters, with unspecified encoding.
* holds a sequence of 8 bit bytes that represent a sequence of variable
* length multi-byte international characters, with unspecified encoding.
*/
typedef std::string STRING;
/**
* Type STRINGS
* is an "array like" list of STRINGs
*/
typedef std::deque<STRING> STRINGS;
/**
* Type STRING_UTF8
* Type STR_UTF
* holds a UTF8 encoded sequence of 8 bit bytes that represent a sequence
* of variable multi-byte international characters. UTF8 is the chosen encoding
* for all Kicad data files so that they can be transported from one nation to another
@ -29,19 +34,15 @@ typedef std::string STRING;
* Filenames may be encoded on disk using an encoding chosen by the host operating
* system. Nonetheless, Kicad data file _content_ is always UTF8 encoded, regardless
* of host operating system.
* STRING_UTF is UTF8 encoded, by definition.
* STR_UTF is UTF8 encoded, by definition.
*/
typedef STRING STRING_UTF8;
typedef STRING STR_UTF;
/**
* Type STRINGS_UTF8
* is an "array like" list of STRING_UTF8s
* Type STR_UTFS
* is an "array like" list of STR_UTFs
*/
typedef std::deque<STRING> STRINGS_UTF8;
typedef std::deque<STRING> STRINGS;
typedef std::deque<STRING> STR_UTFS;
/** @} string_types */