diff --git a/new/eeschema_part_sexpr_format_EN.odt b/new/eeschema_part_sexpr_format_EN.odt index a503c845b4..b0c25d85e7 100644 Binary files a/new/eeschema_part_sexpr_format_EN.odt and b/new/eeschema_part_sexpr_format_EN.odt differ 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