From b07fa2bfb8ce9ebee3b99f2d1da63dd6163a3a50 Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Sun, 10 Apr 2011 22:36:37 -0500 Subject: [PATCH] more free SWEET software --- new/eeschema_part_sexpr_format_EN.odt | Bin 21944 -> 21994 bytes new/make-dir-lib-source-test-data.sh | 42 +++ new/sch_lpid.cpp | 8 +- new/sch_lpid.h | 2 + new/sch_part.cpp | 121 ++++++-- new/sch_part.h | 141 +++++++-- new/sch_sweet_parser.cpp | 420 +++++++++++++++++++++----- new/sch_sweet_parser.h | 9 +- new/sweet.keywords | 1 + 9 files changed, 632 insertions(+), 112 deletions(-) diff --git a/new/eeschema_part_sexpr_format_EN.odt b/new/eeschema_part_sexpr_format_EN.odt index a503c845b4dd82de30f9b86e744df2b3498f070f..b0c25d85e74d0fac30071a3b333c0f3f54f548e0 100644 GIT binary patch delta 10051 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 Q|MQe0fj}&OR|NEb0Jwb7H2?qr delta 10082 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 diff --git a/new/make-dir-lib-source-test-data.sh b/new/make-dir-lib-source-test-data.sh index 092a95db01..831d012b66 100755 --- a/new/make-dir-lib-source-test-data.sh +++ b/new/make-dir-lib-source-test-data.sh @@ -56,6 +56,28 @@ PIN2=" (padname A24 (font (size 0.9 1.1) italic bold) (visible yes)) )" +PIN3=" + (pin (padname A25))" + +PINS=" + (pin (padname Z12))(pin (padname Y14))(pin (padname Z13))(pin (padname Y15))" + + +PIN_SWAP=" + (pin_swap A23 A24)" + +PIN_RENUM=" + (pin_renum A24 B24)" + +PIN_RENAME=" + (pin_rename #WE LED)" + +PIN_DELETE=" + (pin_del B24)" + +PIN_MERGE="(pin_merge A23 (hide Z12 Y14))(pin_merge A25 (hide Z13 Y15))" + + PROP1=" (property mWatts 12 (effects (at 1 34 270)(font (size .5 1) italic bold)(visible no)) @@ -64,6 +86,10 @@ PROP1=" KEYWORDS=" (keywords varistor batcave einstein)" +ALTERNATES=" + (alternates 7400/7400_b 7400/7400_c)" + + for C in ${CATEGORIES}; do @@ -81,8 +107,16 @@ for C in ${CATEGORIES}; do $TEXT $PIN1 $PIN2 + $PIN3 + $PINS $PROP1 $KEYWORDS + $ALTERNATES + $PIN_SWAP + $PIN_RENUM + $PIN_RENAME + $PIN_DELETE + $PIN_MERGE )" > $BASEDIR/$C/$P.part.$R done # also make the part without a rev: @@ -96,8 +130,16 @@ for C in ${CATEGORIES}; do $TEXT $PIN1 $PIN2 + $PIN3 + $PINS $PROP1 $KEYWORDS + $ALTERNATES + $PIN_SWAP + $PIN_RENUM + $PIN_RENAME + $PIN_DELETE + $PIN_MERGE )" > $BASEDIR/$C/$P.part done done diff --git a/new/sch_lpid.cpp b/new/sch_lpid.cpp index ef24cdb0f8..54c3a621a7 100644 --- a/new/sch_lpid.cpp +++ b/new/sch_lpid.cpp @@ -123,13 +123,19 @@ static int okRevision( const STRING& aField ) //----------------------------------------- -int LPID::Parse( const STRING& aLPID ) +void LPID::clear() { logical.clear(); category.clear(); baseName.clear(); partName.clear(); revision.clear(); +} + + +int LPID::Parse( const STRING& aLPID ) +{ + clear(); const char* rev = EndsWithRev( aLPID ); size_t revNdx; diff --git a/new/sch_lpid.h b/new/sch_lpid.h index c35c5cb3ce..a16dfea64b 100644 --- a/new/sch_lpid.h +++ b/new/sch_lpid.h @@ -30,6 +30,7 @@ namespace SCH { + /** * Class LPID * (aka GUID) is a Logical Part ID and consists of various portions much like a URI. @@ -196,6 +197,7 @@ public: static STRING Format( const STRING& aLogicalLib, const STRING& aPartName, const STRING& aRevision="" ) throw( PARSE_ERROR ); + void clear(); #if defined(DEBUG) static void Test(); diff --git a/new/sch_part.cpp b/new/sch_part.cpp index da66e487e2..9b0fa3e54d 100644 --- a/new/sch_part.cpp +++ b/new/sch_part.cpp @@ -34,7 +34,7 @@ /** * Function formatAt - * returns a formatted "(at X Y [ANGLE])" s-expression + * outputs a formatted "(at X Y [ANGLE])" s-expression */ static void formatAt( OUTPUTFORMATTER* out, const POINT& aPos, ANGLE aAngle, int indent=0 ) throw( IO_ERROR ) @@ -72,6 +72,18 @@ void PART::clear() extends = 0; } + // clear the mandatory fields + for( int ndx = REFERENCE; ndx < END; ++ndx ) + { + delete mandatory[ndx]; + mandatory[ndx] = 0; + } + + // delete properties I own, since their container will not destroy them: + for( PROPERTIES::iterator it = properties.begin(); it != properties.end(); ++it ) + delete *it; + properties.clear(); + // delete graphics I own, since their container will not destroy them: for( GRAPHICS::iterator it = graphics.begin(); it != graphics.end(); ++it ) delete *it; @@ -82,21 +94,13 @@ void PART::clear() delete *it; pins.clear(); - // delete properties I own, since their container will not destroy them: - for( PROPERTIES::iterator it = properties.begin(); it != properties.end(); ++it ) - delete *it; - properties.clear(); + alternates.clear(); keywords.clear(); - contains = 0; + pin_merges.clear(); - // clear the mandatory fields - for( int ndx = REFERENCE; ndx < END; ++ndx ) - { - delete mandatory[ndx]; - mandatory[ndx] = 0; - } + contains = 0; } @@ -141,6 +145,49 @@ PROPERTY* PART::FieldLookup( PROP_ID aPropertyId ) return p; } +PINS::iterator PART::pinFindByPadName( const wxString& aPadName ) +{ + PINS::iterator it; + + for( it = pins.begin(); it != pins.end(); ++it ) + { + if( (*it)->padname.text == aPadName ) + break; + } + + return it; +} + + +PINS::iterator PART::pinFindBySignal( const wxString& aSignal ) +{ + PINS::iterator it; + + for( it = pins.begin(); it != pins.end(); ++it ) + { + if( (*it)->signal.text == aSignal ) + break; + } + + return it; +} + + +bool PART::PinDelete( const wxString& aPadName ) +{ + PINS::iterator it = pinFindByPadName( aPadName ); + if( it != pins.end() ) + { + delete *it; + pins.erase( it ); + return true; + } + + // there is only one reason this can fail: not found: + return false; +} + + PART::~PART() { @@ -185,19 +232,17 @@ void PART::Parse( SWEET_PARSER* aParser , LIB_TABLE* aTable ) throw( IO_ERROR, P } -void PART::PropertyDelete( const wxString& aPropertyName ) throw( IO_ERROR ) +bool PART::PropertyDelete( const wxString& aPropertyName ) { PROPERTIES::iterator it = propertyFind( aPropertyName ); - if( it == properties.end() ) + if( it != properties.end() ) { - wxString msg; - msg.Printf( _( "Unable to find property: %s" ), aPropertyName.GetData() ); - THROW_IO_ERROR( msg ); + delete *it; + properties.erase( it ); + return true; } - delete *it; - properties.erase( it ); - return; + return false; } @@ -258,6 +303,26 @@ void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const (*it)->Format( out, indent+1, ctl ); } + if( alternates.size() ) + { + out->Print( indent+1, "(alternates" ); + for( PART_REFS::const_iterator it = alternates.begin(); it!=alternates.end(); ++it ) + out->Print( 0, " %s", out->Quotes( it->Format() ).c_str() ); + out->Print( 0, ")\n" ); + } + + for( MERGE_SETS::const_iterator mit = pin_merges.begin(); mit != pin_merges.end(); ++mit ) + { + out->Print( indent+1, "(pin_merge %s (hide", out->Quotew( mit->first ).c_str() ); + + const MERGE_SET& mset = *mit->second; + for( MERGE_SET::const_iterator pit = mset.begin(); pit != mset.end(); ++pit ) + { + out->Print( 0, " %s", out->Quotew( *pit ).c_str() ); + } + out->Print( 0, "))\n" ); + } + out->Print( indent, ")\n" ); } @@ -349,18 +414,30 @@ void FONT::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const void PIN::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) { + bool hasSignal = !signal.text.IsEmpty(); + bool hasPadName = !padname.text.IsEmpty(); + out->Print( indent, "(pin %s %s ", ShowType(), ShowShape() ); formatAt( out, pos, angle ); out->Print( 0, "(length %.6g)", InternalToLogical( length ) ); out->Print( 0, "(visible %s)\n", isVisible ? "yes" : "no" ); - signal.Format( out, "signal", indent+1, 0 ); - padname.Format( out, "padname", indent+1, CTL_OMIT_NL ); + if( hasSignal ) + signal.Format( out, "signal", indent+1, hasPadName ? 0 : CTL_OMIT_NL ); + + if( hasPadName ) + padname.Format( out, "padname", indent+1, CTL_OMIT_NL ); + out->Print( 0, ")\n" ); } +PIN::~PIN() +{ +} + + void PINTEXT::Format( OUTPUTFORMATTER* out, const char* aElement, int indent, int ctl ) const throw( IO_ERROR ) { diff --git a/new/sch_part.h b/new/sch_part.h index 093bed71cd..fa489cf57c 100644 --- a/new/sch_part.h +++ b/new/sch_part.h @@ -27,6 +27,10 @@ #define SCH_PART_H_ #include +#include +#include +//#include +#include #define INTERNAL_PER_LOGICAL 10000 ///< no. internal units per logical unit @@ -89,6 +93,13 @@ class PROPERTY; }; +/// a set of pin padnames that are electrically equivalent for a PART. +typedef std::set< wxString > MERGE_SET; + +/// The key is the VISIBLE_PIN from +/// (pin_merge VISIBLE_PIN (hide HIDDEN_PIN1 HIDDEN_PIN2...)) +typedef boost::ptr_map< wxString, MERGE_SET > MERGE_SETS; + class POINT : public wxPoint { @@ -156,11 +167,13 @@ class BASE_GRAPHIC friend class SWEET_PARSER; protected: - PART* owner; + PART* owner; + PART* birthplace; ///< at which PART in inheritance chain was 'this' added public: BASE_GRAPHIC( PART* aOwner ) : - owner( aOwner ) + owner( aOwner ), + birthplace( aOwner ) {} virtual ~BASE_GRAPHIC() {} @@ -342,7 +355,6 @@ class PROPERTY : public BASE_GRAPHIC friend class SWEET_PARSER; protected: - PART* birthplace; ///< at which PART in inheritance chain was this PROPERTY added wxString name; wxString text; TEXT_EFFECTS* effects; @@ -359,7 +371,6 @@ protected: public: PROPERTY( PART* aOwner, const wxChar* aName = wxT( "" ) ) : BASE_GRAPHIC( aOwner ), - birthplace( aOwner ), name( aName ), effects( 0 ) {} @@ -410,7 +421,6 @@ class PIN : public BASE_GRAPHIC public: PIN( PART* aOwner ) : BASE_GRAPHIC( aOwner ), - birthplace( aOwner ), angle( 0 ), connectionType( PR::T_input ), shape( PR::T_line ), @@ -418,6 +428,8 @@ public: isVisible( true ) {} + ~PIN(); + const char* ShowType() const { return SWEET_LEXER::TokenName( PR::T( connectionType ) ); @@ -432,7 +444,6 @@ public: throw( IO_ERROR ); protected: - PART* birthplace; ///< at which PART in inheritance chain was this PIN added POINT pos; ANGLE angle; @@ -448,21 +459,74 @@ protected: int length; ///< length of pin in internal units bool isVisible; ///< pin is visible + wxString pin_merge; ///< padname of (pin_merge ...) that I am a member of, else empty if none }; +/** + * Class PART_REF + * is an LPID with a pointer to the "looked up" PART, which is looked up lazily. + */ +class PART_REF : public LPID +{ +public: + PART_REF() : + LPID(), + part(0) + {} + + /** + * Constructor LPID + * takes aLPID string and parses it. A typical LPID string uses a logical + * library name followed by a part name. + * e.g.: "kicad:passives/R/rev2", or + * e.g.: "mylib:R33" + */ + PART_REF( const STRING& aLPID ) throw( PARSE_ERROR ) : + LPID( aLPID ), + part(0) + { + } + + + /** + * Function Lookup + * returns the PART that this LPID refers to. Never returns NULL, because + * instead an exception would be thrown. + * @throw IO_ERROR if any problem occurs or if the part cannot be found. + */ + PART* Lookup( LIB_TABLE* aLibTable, LIB* aFallBackLib ) throw( IO_ERROR ) + { + if( !part ) + { + part = aLibTable->LookupPart( *this, aFallBackLib ); + } + return part; + } + +protected: + PART* part; ///< The looked-up PART, + ///< no ownership (duh, PARTs are always owned by a LIB) +}; + +typedef std::vector PART_REFS; + + } // namespace SCH //---------------------- +typedef std::set< wxString > KEYWORDS; + namespace SCH { typedef std::vector< BASE_GRAPHIC* > GRAPHICS; -typedef std::vector< PIN* > PINS; typedef std::vector< PROPERTY* > PROPERTIES; -typedef std::set< wxString > KEYWORDS; + +typedef std::vector< PIN* > PINS; + class LPID; class SWEET_PARSER; @@ -533,7 +597,12 @@ public: void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits = 0 ) const throw( IO_ERROR ); - void PropertyDelete( const wxString& aPropertyName ) throw( IO_ERROR ); + /** + * Function PropertyDelete + * deletes the property with aPropertyName if found and returns true, else false + * if not found. + */ + bool PropertyDelete( const wxString& aPropertyName ); /** * Function Field @@ -554,6 +623,31 @@ public: */ PROPERTY* FieldLookup( PROP_ID aPropertyId ); + /** + * Function PinFindByPadName + * finds a PIN based on aPadName or returns NULL if not found. + * @param aPadName is the pin to find + * @return PIN* - the found PIN or NULL if not found. + */ + PIN* PinFindByPadName( const wxString& aPadName ) + { + PINS::iterator it = pinFindByPadName( aPadName ); + return it != pins.end() ? *it : NULL; + } + + PIN* PinFindBySignal( const wxString& aSignal ) + { + PINS::iterator it = pinFindBySignal( aSignal ); + return it != pins.end() ? *it : NULL; + } + + /** + * Function PinDelete + * deletes the pin with aPadName if found and returns true, else false + * if not found. + */ + bool PinDelete( const wxString& aPadName ); + /* void SetValue( const wxString& aValue ) @@ -619,6 +713,15 @@ protected: // not likely to have C++ descendants, but protected none-the-le */ PROPERTIES::iterator propertyFind( const wxString& aPropertyName ); + /** + * Function pinFindByPadName + * searches for a PIN with aPadName and returns a PROPERTIES::iterator which + * is the found item or pins.end() if not found. + */ + PINS::iterator pinFindByPadName( const wxString& aPadName ); + PINS::iterator pinFindBySignal( const wxString& aSignal ); + + POINT anchor; //PART( LIB* aOwner ); @@ -638,18 +741,9 @@ protected: // not likely to have C++ descendants, but protected none-the-le /// actually becomes cached in RAM. STRING body; - // mandatory properties + /// mandatory properties, aka fields. Index into mandatory[] is PROP_ID. PROPERTY* mandatory[END]; -/* - PROPERTY value; - PROPERTY footprint; - PROPERTY model; - PROPERTY datasheet; -*/ - - // separate lists for speed: - /** * Member properties * holds the non-mandatory properties. @@ -669,10 +763,17 @@ protected: // not likely to have C++ descendants, but protected none-the-le PINS pins; /// Alternate body forms. - //ALTERNATES alternates; + PART_REFS alternates; + /// searching aids KEYWORDS keywords; + /** + * A pin_merge set is a set of pins that are all electrically equivalent + * and whose anchor pin is the only one visible. The visible pin is the + * key in the MERGE_SETS boost::ptr_map::map + */ + MERGE_SETS pin_merges; }; } // namespace PART diff --git a/new/sch_sweet_parser.cpp b/new/sch_sweet_parser.cpp index 0b18a8dbea..f0cd6dea63 100644 --- a/new/sch_sweet_parser.cpp +++ b/new/sch_sweet_parser.cpp @@ -27,6 +27,7 @@ #include #include +#include using namespace SCH; using namespace PR; @@ -74,58 +75,6 @@ static inline const int PB( PartBit oneBitOnly ) } -void SWEET_PARSER::parseExtends( PART* me ) -{ - PART* base; - int offset; - - if( contains & PB(extends) ) - Duplicate( T_extends ); - - NeedSYMBOLorNUMBER(); - me->setExtends( new LPID() ); - - offset = me->extends->Parse( CurText() ); - if( offset > -1 ) // -1 is success - THROW_PARSE_ERROR( _("invalid extends LPID"), - CurSource(), - CurLine(), - CurLineNumber(), - CurOffset() + offset ); - - base = libs->LookupPart( *me->extends, me->Owner() ); - - // we could be going in circles here, recursively, or too deep, set limits - // and disallow extending from self (even indirectly) - int extendsDepth = 0; - for( PART* ancestor = base; ancestor && extendsDepthbase ) - { - if( ancestor == me ) - { - THROW_PARSE_ERROR( _("'extends' may not have self as any ancestor"), - CurSource(), - CurLine(), - CurLineNumber(), - CurOffset() ); - } - } - - if( extendsDepth == MAX_INHERITANCE_NESTING ) - { - THROW_PARSE_ERROR( _("max allowed extends depth exceeded"), - CurSource(), - CurLine(), - CurLineNumber(), - CurOffset() ); - } - - me->inherit( *base ); - me->base = base; - contains |= PB(extends); -} - - void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_ERROR ) { T tok; @@ -266,9 +215,7 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E break; case T_property_del: - NeedSYMBOLorNUMBER(); - me->PropertyDelete( FromUTF8() ); - NeedRIGHT(); + parsePropertyDel( me ); break; // reference in a PART is incomplete, it is just the prefix of an @@ -308,6 +255,15 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E prop = me->FieldLookup( PART::MODEL ); goto L_prop; + case T_keywords: + parseKeywords( me ); + break; + + case T_alternates: + // @todo: do we want to inherit alternates? + parseAlternates( me ); + break; + case T_pin: PIN* pin; pin = new PIN( me ); @@ -315,30 +271,29 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E parsePin( pin ); break; - case T_keywords: - parseKeywords( me ); - break; - - - /* - @todo - - case T_alternates: - break; - - // do we want to inherit alternates? - case T_pin_merge: + case T_pin_del: + parsePinDel( me ); break; case T_pin_swap: + parsePinSwap( me ); break; case T_pin_renum: + parsePinRenum( me ); break; case T_pin_rename: + parsePinRename( me ); break; + case T_pin_merge: + parsePinMerge( me ); + break; + + /* + @todo + case T_route_pin_swap: break; */ @@ -361,6 +316,85 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E } +void SWEET_PARSER::parseExtends( PART* me ) +{ + PART* base; + int offset; + + if( contains & PB(extends) ) + Duplicate( T_extends ); + + NeedSYMBOLorNUMBER(); + me->setExtends( new LPID() ); + + offset = me->extends->Parse( CurText() ); + if( offset > -1 ) // -1 is success + THROW_PARSE_ERROR( _("invalid extends LPID"), + CurSource(), + CurLine(), + CurLineNumber(), + CurOffset() + offset ); + + base = libs->LookupPart( *me->extends, me->Owner() ); + + // we could be going in circles here, recursively, or too deep, set limits + // and disallow extending from self (even indirectly) + int extendsDepth = 0; + for( PART* ancestor = base; ancestor && extendsDepthbase ) + { + if( ancestor == me ) + { + THROW_PARSE_ERROR( _("'extends' may not have self as any ancestor"), + CurSource(), + CurLine(), + CurLineNumber(), + CurOffset() ); + } + } + + if( extendsDepth == MAX_INHERITANCE_NESTING ) + { + THROW_PARSE_ERROR( _("max allowed extends depth exceeded"), + CurSource(), + CurLine(), + CurLineNumber(), + CurOffset() ); + } + + me->inherit( *base ); + me->base = base; + contains |= PB(extends); +} + + +void SWEET_PARSER::parseAlternates( PART* me ) +{ + T tok; + PART_REF lpid; + int offset; + + while( ( tok = NextTok() ) != T_RIGHT ) + { + if( !IsSymbol( tok ) && tok != T_NUMBER ) + Expecting( "lpid" ); + + // lpid.clear(); Parse does this + + offset = lpid.Parse( CurText() ); + if( offset > -1 ) + THROW_PARSE_ERROR( _("invalid alternates LPID"), + CurSource(), + CurLine(), + CurLineNumber(), + CurOffset() + offset ); + + // PART_REF assignment should be OK, it contains no ownership + me->alternates.push_back( lpid ); + } +} + + void SWEET_PARSER::parseKeywords( PART* me ) { T tok; @@ -637,6 +671,256 @@ void SWEET_PARSER::parsePin( PIN* me ) } +void SWEET_PARSER::parsePinDel( PART* me ) +{ + wxString padName; + + // we do this somewhat unorthodoxically because we want to avoid doing two lookups, + // which would need to be done to 1) find pin, and 2) delete pin. Only one + // lookup is needed with this scheme. + + NeedSYMBOLorNUMBER(); + padName = FromUTF8(); + + // lookup now while CurOffset() is still meaningful. + PINS::iterator it = me->pinFindByPadName( padName ); + if( it == me->pins.end() ) + { + THROW_PARSE_ERROR( _("undefined pin"), + CurSource(), + CurLine(), + CurLineNumber(), + CurOffset() ); + } + +/* enable in future, but not now while testing + if( (*it)->birthplace == me ) + { + THROW_PARSE_ERROR( _("pin_del allowed for inherited pins only"), + CurSource(), + CurLine(), + CurLineNumber(), + CurOffset() ); + } +*/ + + NeedRIGHT(); + + delete *it; // good thing I'm a friend. + me->pins.erase( it ); +} + + +void SWEET_PARSER::parsePinSwap( PART* me ) +{ + PIN* pin1; + PIN* pin2; + + wxString padName; + + NeedSYMBOLorNUMBER(); + padName = FromUTF8(); + + // lookup now while CurOffset() is still meaningful. + pin1 = me->PinFindByPadName( padName ); + if( !pin1 ) + { + THROW_PARSE_ERROR( _("undefined pin"), + CurSource(), + CurLine(), + CurLineNumber(), + CurOffset() ); + } + + NeedSYMBOLorNUMBER(); + padName = FromUTF8(); + + pin2 = me->PinFindByPadName( padName ); + if( !pin2 ) + { + THROW_PARSE_ERROR( _("undefined pin"), + CurSource(), + CurLine(), + CurLineNumber(), + CurOffset() ); + } + + NeedRIGHT(); + + // swap only the text, but might want to swap entire PIN_TEXTs + pin2->padname.text = pin1->padname.text; + pin1->padname.text = padName; +} + + +void SWEET_PARSER::parsePinRenum( PART* me ) +{ + PIN* pin; + + wxString oldPadName; + wxString newPadName; + + NeedSYMBOLorNUMBER(); + oldPadName = FromUTF8(); + + // lookup now while CurOffset() is still meaningful. + pin = me->PinFindByPadName( oldPadName ); + if( !pin ) + { + THROW_PARSE_ERROR( _("undefined pin"), + CurSource(), + CurLine(), + CurLineNumber(), + CurOffset() ); + } + + NeedSYMBOLorNUMBER(); + newPadName = FromUTF8(); + + NeedRIGHT(); + + // @todo: check for padname legalities + pin->padname.text = newPadName; +} + + +void SWEET_PARSER::parsePinRename( PART* me ) +{ + PIN* pin; + + wxString oldSignal; + wxString newSignal; + + NeedSYMBOLorNUMBER(); + oldSignal = FromUTF8(); + + // lookup now while CurOffset() is still meaningful. + pin = me->PinFindBySignal( oldSignal ); + if( !pin ) + { + THROW_PARSE_ERROR( _("undefined pin"), + CurSource(), + CurLine(), + CurLineNumber(), + CurOffset() ); + } + + NeedSYMBOLorNUMBER(); + newSignal = FromUTF8(); + + NeedRIGHT(); + + pin->signal.text = newSignal; +} + + +void SWEET_PARSER::parsePinMerge( PART* me ) +{ + T tok; + wxString padName; + wxString msg; + + NeedSYMBOLorNUMBER(); + + wxString anchorPadName = FromUTF8(); + + // lookup now while CurOffset() is still good. + PINS::iterator pit = me->pinFindByPadName( anchorPadName ); + if( pit == me->pins.end() ) + { + msg.Printf( _( "undefined pin %s" ), anchorPadName.GetData() ); + THROW_PARSE_ERROR( msg, + CurSource(), + CurLine(), + CurLineNumber(), + CurOffset() ); + } + + if( !(*pit)->pin_merge.IsEmpty() && anchorPadName != (*pit)->pin_merge ) + { + msg.Printf( _( "pin %s already in pin_merge group %s" ), + anchorPadName.GetData(), (*pit)->pin_merge.GetData() ); + + THROW_PARSE_ERROR( msg, + CurSource(), + CurLine(), + CurLineNumber(), + CurOffset() ); + } + + NeedLEFT(); + + tok = NextTok(); + if( tok != T_hide ) + Expecting( T_hide ); + + (*pit)->isVisible = true; + (*pit)->pin_merge = anchorPadName; + + // allocate or find a MERGE_SET; + MERGE_SET& ms = me->pin_merges[anchorPadName]; + + while( ( tok = NextTok() ) != T_RIGHT ) + { + if( !IsSymbol( tok ) && tok != T_NUMBER ) + Expecting( "padname" ); + + padName = FromUTF8(); + + D(printf("padName=%s\n", TO_UTF8( padName ) );) + + // find the PIN and mark it as being in this MERGE_SET or throw + // error if already in another MERGET_SET. + + pit = me->pinFindByPadName( padName ); + if( pit == me->pins.end() ) + { + msg.Printf( _( "undefined pin %s" ), padName.GetData() ); + THROW_PARSE_ERROR( msg, + CurSource(), + CurLine(), + CurLineNumber(), + CurOffset() ); + } + + if( !(*pit)->pin_merge.IsEmpty() && anchorPadName != (*pit)->pin_merge ) + { + msg.Printf( _( "pin %s already in pin_merge group %s" ), + padName.GetData(), (*pit)->pin_merge.GetData() ); + + THROW_PARSE_ERROR( msg, + CurSource(), + CurLine(), + CurLineNumber(), + CurOffset() ); + } + + (*pit)->isVisible = false; + (*pit)->pin_merge = anchorPadName; + + ms.insert( padName ); + } + + NeedRIGHT(); +} + + +void SWEET_PARSER::parsePropertyDel( PART* me ) +{ + NeedSYMBOLorNUMBER(); + + wxString propertyName = FromUTF8(); + + if( !me->PropertyDelete( propertyName ) ) + { + wxString msg; + msg.Printf( _( "Unable to find property: %s" ), propertyName.GetData() ); + THROW_IO_ERROR( msg ); + } + NeedRIGHT(); +} + + void SWEET_PARSER::parseTextEffects( TEXT_EFFECTS* me ) { /* diff --git a/new/sch_sweet_parser.h b/new/sch_sweet_parser.h index 1b8485ca76..7f80c05313 100644 --- a/new/sch_sweet_parser.h +++ b/new/sch_sweet_parser.h @@ -75,14 +75,21 @@ class SWEET_PARSER : public SWEET_LEXER void parseCircle( CIRCLE* me ); void parseArc( ARC* me ); void parseText( GR_TEXT* me ); - void parsePin( PIN* me ); void parseAt( POINT* pos, float* angle ); void parseBool( bool* aBool ); void parseFont( FONT* me ); void parsePinText( PINTEXT* me ); void parseTextEffects( TEXT_EFFECTS* me ); void parseKeywords( PART* me ); + void parseAlternates( PART* me ); + void parsePropertyDel( PART* me ); + void parsePin( PIN* me ); + void parsePinDel( PART* me ); + void parsePinSwap( PART* me ); + void parsePinRenum( PART* me ); + void parsePinRename( PART* me ); + void parsePinMerge( PART* me ); public: diff --git a/new/sweet.keywords b/new/sweet.keywords index d1a98caca5..6d58f73920 100644 --- a/new/sweet.keywords +++ b/new/sweet.keywords @@ -20,6 +20,7 @@ fill filled font footprint +hide input input_low inverted