summaryrefslogtreecommitdiff
path: root/new/sch_sweet_parser.cpp
diff options
context:
space:
mode:
authorsaurabhb172020-02-26 16:14:17 +0530
committerGitHub2020-02-26 16:14:17 +0530
commit003d02608917e7a69d1a98438837e94ccf68352a (patch)
tree1392c90227aeea231c1d86371131e04c40382918 /new/sch_sweet_parser.cpp
parent886d9cb772e81d2e5262284bc3082664f084337f (diff)
parente255d0622297488c1c52755be670733418c994cf (diff)
downloadKiCad-eSim-003d02608917e7a69d1a98438837e94ccf68352a.tar.gz
KiCad-eSim-003d02608917e7a69d1a98438837e94ccf68352a.tar.bz2
KiCad-eSim-003d02608917e7a69d1a98438837e94ccf68352a.zip
Merge pull request #3 from saurabhb17/master
secondary files
Diffstat (limited to 'new/sch_sweet_parser.cpp')
-rw-r--r--new/sch_sweet_parser.cpp1561
1 files changed, 1561 insertions, 0 deletions
diff --git a/new/sch_sweet_parser.cpp b/new/sch_sweet_parser.cpp
new file mode 100644
index 0000000..f0be7bd
--- /dev/null
+++ b/new/sch_sweet_parser.cpp
@@ -0,0 +1,1561 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2011 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
+ * Copyright (C) 2010 KiCad Developers, see change_log.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
+ */
+
+#include <sch_sweet_parser.h>
+#include <sch_part.h>
+#include <sch_lib_table.h>
+#include <sch_lpid.h>
+
+#include <macros.h>
+
+using namespace SCH;
+using namespace PR;
+
+
+#define MAX_INHERITANCE_NESTING 6 ///< max depth of inheritance, no problem going larger
+
+
+static inline int internal( const STRING& aCoord )
+{
+ return LogicalToInternal( strtod( aCoord.c_str(), NULL ) );
+}
+
+static inline int fromWidth( const STRING& aWidth )
+{
+ return WidthToInternal( strtod( aWidth.c_str(), NULL ) );
+}
+
+static inline int fromFontz( const STRING& aFontSize )
+{
+ return FontzToInternal( strtod( aFontSize.c_str(), NULL ) );
+}
+
+
+/**
+ * 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 "extends" keyword, inheriting from another PART
+ value,
+ anchor,
+ reference,
+ footprint,
+ datasheet,
+ model,
+ keywords,
+};
+
+
+/// Function PB
+/// is a PartBit shifter for PART::contains field.
+static inline const int PB( PartBit oneBitOnly )
+{
+ return ( 1 << oneBitOnly );
+}
+
+
+void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_ERROR )
+{
+ T tok;
+
+ libs = aTable;
+
+ // empty everything out, could be re-parsing this object and it may not be empty.
+ me->clear();
+
+#if 0
+ // Be flexible regarding the starting point of the stream.
+ // Caller may not have read the first two tokens out of the
+ // stream: T_LEFT and T_part, so ignore them if seen here.
+ // The 1st two tokens T_LEFT and T_part are then optional in the grammar.
+ if( ( tok = NextTok() ) == T_LEFT )
+ {
+ if( ( tok = NextTok() ) != T_part )
+ Expecting( T_part );
+ }
+
+#else
+ // "( part" are not optional
+ NeedLEFT();
+
+ if( ( tok = NextTok() ) != T_part )
+ Expecting( T_part );
+#endif
+
+ NeedSYMBOLorNUMBER(); // toss NAME_HINT
+ tok = NextTok();
+
+ // extends must be _first_ thing, if it is present at all, after NAME_HINT
+ if( tok == T_extends )
+ {
+ parseExtends( me );
+ tok = NextTok();
+ }
+
+ for( ; tok!=T_RIGHT; tok = NextTok() )
+ {
+ if( tok == T_LEFT )
+ {
+ PROPERTY* prop;
+
+ tok = NextTok();
+
+ // because exceptions are thrown, any 'new' allocation has to be stored
+ // somewhere other than on the stack, ASAP.
+
+ switch( tok )
+ {
+ default:
+ // describe what we expect at this level
+ Expecting(
+ "anchor|value|footprint|model|keywords|alternates\n"
+ "|property\n"
+ " |property_del\n"
+ "|pin\n"
+ " |pin_merge|pin_swap|pin_renum|pin_rename|route_pin_swap\n"
+ "|polyline|line|rectangle|circle|arc|bezier|text"
+ );
+ break;
+
+ case T_anchor:
+ if( contains & PB(anchor) )
+ Duplicate( tok );
+ NeedNUMBER( "anchor x" );
+ me->anchor.x = internal( CurText() );
+ NeedNUMBER( "anchor y" );
+ me->anchor.y = internal( CurText() );
+ contains |= PB(anchor);
+ break;
+
+ case T_line:
+ case T_polyline:
+ POLY_LINE* pl;
+ pl = new POLY_LINE( me );
+ me->graphics.push_back( pl );
+ parsePolyLine( pl );
+ break;
+
+ case T_rectangle:
+ RECTANGLE* rect;
+ rect = new RECTANGLE( me );
+ me->graphics.push_back( rect );
+ parseRectangle( rect );
+ break;
+
+ case T_circle:
+ CIRCLE* circ;
+ circ = new CIRCLE( me );
+ me->graphics.push_back( circ );
+ parseCircle( circ );
+ break;
+
+ case T_arc:
+ ARC* arc;
+ arc = new ARC( me );
+ me->graphics.push_back( arc );
+ parseArc( arc );
+ break;
+
+ case T_bezier:
+ BEZIER* bezier;
+ bezier = new BEZIER( me );
+ me->graphics.push_back( bezier );
+ parseBezier( bezier );
+ break;
+
+ case T_text:
+ GR_TEXT* text;
+ text = new GR_TEXT( me );
+ me->graphics.push_back( text );
+ parseText( text );
+ break;
+
+ case T_property:
+ prop = new PROPERTY( me );
+ // @todo check for uniqueness
+ me->properties.push_back( prop );
+ NeedSYMBOLorNUMBER();
+ prop->name = FromUTF8();
+
+ L_prop:
+ NeedSYMBOLorNUMBER();
+ prop->text = FromUTF8();
+ tok = NextTok();
+ if( tok == T_LEFT )
+ {
+ tok = NextTok();
+ if( tok != T_effects )
+ Expecting( T_effects );
+ parseTextEffects( prop->EffectsLookup() );
+ NeedRIGHT();
+ }
+ else if( tok != T_RIGHT )
+ Expecting( ") | effects" );
+ break;
+
+ case T_property_del:
+ parsePropertyDel( me );
+ break;
+
+ // reference in a PART is incomplete, it is just the prefix of an
+ // unannotated reference. Only components have full reference designators.
+ case T_reference:
+ if( contains & PB(reference) )
+ Duplicate( tok );
+ contains |= PB(reference);
+ prop = me->FieldLookup( PART::REFERENCE );
+ goto L_prop;
+
+ case T_value:
+ if( contains & PB(value) )
+ Duplicate( tok );
+ contains |= PB(value);
+ prop = me->FieldLookup( PART::VALUE );
+ goto L_prop;
+
+ case T_footprint:
+ if( contains & PB(footprint) )
+ Duplicate( tok );
+ contains |= PB(footprint);
+ prop = me->FieldLookup( PART::FOOTPRINT );
+ goto L_prop;
+
+ case T_datasheet:
+ if( contains & PB(datasheet) )
+ Duplicate( tok );
+ contains |= PB(datasheet);
+ prop = me->FieldLookup( PART::DATASHEET );
+ goto L_prop;
+
+ case T_model:
+ if( contains & PB(model) )
+ Duplicate( tok );
+ contains |= PB(model);
+ 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:
+ // @todo PADNAMEs must be unique
+ PIN* pin;
+ pin = new PIN( me );
+ me->pins.push_back( pin );
+ parsePin( pin );
+ break;
+
+ 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;
+ */
+ }
+ }
+
+ else
+ {
+ switch( tok )
+ {
+ default:
+ Unexpected( tok );
+ }
+ }
+ }
+
+ contains |= PB(parsed);
+
+ me->contains |= contains;
+}
+
+
+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( const PART* ancestor = base; ancestor && extendsDepth<MAX_INHERITANCE_NESTING;
+ ++extendsDepth, ancestor = ancestor->base )
+ {
+ 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;
+
+ while( ( tok = NextTok() ) != T_RIGHT )
+ {
+ if( !IsSymbol( tok ) && tok!=T_NUMBER )
+ Expecting( "symbol|number" );
+
+ // just insert them, duplicates are silently removed and tossed.
+ me->keywords.insert( FromUTF8() );
+ }
+}
+
+
+void SWEET_PARSER::parseFont( FONT* me )
+{
+ /*
+ # The FONT value needs to be defined. Currently, EESchema does not support
+ # different fonts. In the future this feature may be implemented and at
+ # that time FONT will have to be defined. Initially, only the font size and
+ # style are required. Italic and bold styles are optional. The font size
+ # height and width are in units yet to be determined.
+ (font [FONT] (size HEIGHT WIDTH) [italic] [bold])
+ */
+
+ // handle the [FONT] 'position dependently', i.e. first
+ T tok = NextTok();
+ bool sawBold = false;
+ bool sawItalic = false;
+ bool sawSize = false;
+
+ if( IsSymbol( tok ) )
+ {
+ me->name = FromUTF8();
+ tok = NextTok();
+ }
+
+ for( ; tok != T_RIGHT; tok = NextTok() )
+ {
+ if( tok == T_LEFT )
+ {
+ tok = NextTok();
+
+ switch( tok )
+ {
+ case T_size:
+ if( sawSize )
+ Duplicate( T_size );
+ sawSize = true;
+
+ NeedNUMBER( "size height" );
+ me->size.height = fromFontz( CurText() );
+
+ NeedNUMBER( "size width" );
+ me->size.width = fromFontz( CurText() );
+ NeedRIGHT();
+ break;
+
+ default:
+ Expecting( "size" );
+ }
+ }
+ else
+ {
+ switch( tok )
+ {
+ case T_bold:
+ if( sawBold )
+ Duplicate( T_bold );
+ sawBold = true;
+ me->bold = true;
+ break;
+
+ case T_italic:
+ if( sawItalic )
+ Duplicate( T_italic );
+ sawItalic = true;
+ me->italic = true;
+ break;
+
+ default:
+ Unexpected( "bold|italic" );
+ }
+ }
+ }
+}
+
+
+void SWEET_PARSER::parseBool( bool* aBool )
+{
+ T tok = NeedSYMBOL();
+
+ switch( tok )
+ {
+ case T_yes:
+ case T_no:
+ *aBool = (tok == T_yes);
+ break;
+ default:
+ Expecting( "yes|no" );
+ }
+}
+
+
+void SWEET_PARSER::parseStroke( STROKE* me )
+{
+ /*
+ (stroke [WIDTH] [(style [(dashed...)]...)])
+
+ future place holder for arrow heads, dashed lines, all line glamour
+ */
+
+ NeedNUMBER( "stroke" );
+ *me = fromWidth( CurText() );
+ NeedRIGHT();
+}
+
+
+void SWEET_PARSER::parsePinText( PINTEXT* me )
+{
+ /* either:
+ (signal SIGNAL (font [FONT] (size HEIGHT WIDTH) [italic] [bold])(visible YES))
+ or
+ (pad PADNAME (font [FONT] (size HEIGHT WIDTH) [italic] [bold])(visible YES))
+ */
+ T tok;
+ bool sawFont = false;
+ bool sawVis = false;
+
+ // pad or signal text
+ NeedSYMBOLorNUMBER();
+ me->text = FromUTF8();
+
+ while( ( tok = NextTok() ) != T_RIGHT )
+ {
+ if( tok == T_LEFT )
+ {
+ tok = NextTok();
+
+ switch( tok )
+ {
+ case T_font:
+ if( sawFont )
+ Duplicate( tok );
+ sawFont = true;
+ parseFont( &me->font );
+ break;
+
+ case T_visible:
+ if( sawVis )
+ Duplicate( tok );
+ sawVis = true;
+ parseBool( &me->isVisible );
+ NeedRIGHT();
+ break;
+
+ default:
+ Expecting( "font" );
+ }
+ }
+
+ else
+ {
+ switch( tok )
+ {
+ default:
+ Expecting( T_LEFT );
+ }
+ }
+ }
+}
+
+
+void SWEET_PARSER::parsePin( PIN* me )
+{
+ /*
+ (pin TYPE SHAPE
+ (at X Y [ANGLE])
+ (length LENGTH)
+ (signal NAME (font [FONT] (size HEIGHT WIDTH) [italic] [bold])(visible YES))
+ (pad NUMBER (font [FONT] (size HEIGHT WIDTH) [italic] [bold] (visible YES))
+ (visible YES)
+ )
+ */
+
+ T tok;
+ bool sawShape = false;
+ bool sawType = false;
+ bool sawAt = false;
+ bool sawLen = false;
+ bool sawSignal = false;
+ bool sawPad = false;
+ bool sawVis = false;
+
+ while( ( tok = NextTok() ) != T_RIGHT )
+ {
+ if( tok == T_LEFT )
+ {
+ tok = NextTok();
+
+ switch( tok )
+ {
+ case T_at:
+ if( sawAt )
+ Duplicate( tok );
+ sawAt = true;
+ parseAt( &me->pos, &me->angle );
+ break;
+
+ case T_length:
+ if( sawLen )
+ Duplicate( tok );
+ sawLen = true;
+ NeedNUMBER( "length" );
+ me->length = internal( CurText() );
+ NeedRIGHT();
+ break;
+
+ case T_signal:
+ if( sawSignal )
+ Duplicate( tok );
+ sawSignal = true;
+ parsePinText( &me->signal );
+ break;
+
+ case T_pad:
+ if( sawPad )
+ Duplicate( tok );
+ sawPad = true;
+ parsePinText( &me->pad );
+ break;
+
+ case T_visible:
+ if( sawVis )
+ Duplicate( tok );
+ sawVis = true;
+ parseBool( &me->isVisible );
+ NeedRIGHT();
+ break;
+
+ default:
+ Unexpected( tok );
+ }
+ }
+
+ else // not wrapped in parentheses
+ {
+ switch( tok )
+ {
+ case T_in:
+ case T_out:
+ case T_inout:
+ case T_tristate:
+ case T_passive:
+ case T_unspecified:
+ case T_power_in:
+ case T_power_out:
+ case T_open_collector:
+ case T_open_emitter:
+ case T_unconnected:
+ if( sawType )
+ Duplicate( tok );
+ sawType = true;
+ me->connectionType = tok;
+ break;
+
+ case T_none:
+ case T_line:
+ case T_inverted:
+ case T_clock:
+ case T_inverted_clk:
+ case T_input_low:
+ case T_clock_low:
+ case T_falling_edge:
+ case T_non_logic:
+ if( sawShape )
+ Duplicate( tok );
+ sawShape = true;
+ me->shape = tok;
+ break;
+
+ default:
+ Unexpected( tok );
+ }
+ }
+ }
+}
+
+
+void SWEET_PARSER::parsePinDel( PART* me )
+{
+ wxString pad;
+
+ // 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();
+ pad = FromUTF8();
+
+ // lookup now while CurOffset() is still meaningful.
+ PINS::iterator it = me->pinFindByPad( pad );
+ 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 pad;
+
+ NeedSYMBOLorNUMBER();
+ pad = FromUTF8();
+
+ // lookup now while CurOffset() is still meaningful.
+ pin1 = me->PinFindByPad( pad );
+ if( !pin1 )
+ {
+ THROW_PARSE_ERROR( _("undefined pin"),
+ CurSource(),
+ CurLine(),
+ CurLineNumber(),
+ CurOffset() );
+ }
+
+ NeedSYMBOLorNUMBER();
+ pad = FromUTF8();
+
+ pin2 = me->PinFindByPad( pad );
+ 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->pad.text = pin1->pad.text;
+ pin1->pad.text = pad;
+}
+
+
+void SWEET_PARSER::parsePinRenum( PART* me )
+{
+ PIN* pin;
+
+ wxString oldPad;
+ wxString newPad;
+
+ NeedSYMBOLorNUMBER();
+ oldPad = FromUTF8();
+
+ // lookup now while CurOffset() is still meaningful.
+ pin = me->PinFindByPad( oldPad );
+ if( !pin )
+ {
+ THROW_PARSE_ERROR( _("undefined pin"),
+ CurSource(),
+ CurLine(),
+ CurLineNumber(),
+ CurOffset() );
+ }
+
+ NeedSYMBOLorNUMBER();
+ newPad = FromUTF8();
+
+ NeedRIGHT();
+
+ // @todo: check for pad legalities
+ pin->pad.text = newPad;
+}
+
+
+void SWEET_PARSER::parsePinRename( PART* me )
+{
+ PIN* pin;
+
+ wxString pad;
+ wxString newSignal;
+
+ NeedSYMBOLorNUMBER();
+ pad = FromUTF8();
+
+ // lookup now while CurOffset() is still meaningful.
+ pin = me->PinFindByPad( pad );
+ 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 pad;
+ wxString signal;
+ wxString msg;
+
+ NeedSYMBOLorNUMBER();
+
+ wxString anchorPad = FromUTF8();
+
+ // lookup now while CurOffset() is still good.
+ PINS::iterator pit = me->pinFindByPad( anchorPad );
+ if( pit == me->pins.end() )
+ {
+ msg.Printf( _( "undefined pin %s" ), anchorPad.GetData() );
+ THROW_PARSE_ERROR( msg,
+ CurSource(),
+ CurLine(),
+ CurLineNumber(),
+ CurOffset() );
+ }
+
+ if( !(*pit)->pin_merge.IsEmpty() && anchorPad != (*pit)->pin_merge )
+ {
+ msg.Printf( _( "pin %s already in pin_merge group %s" ),
+ anchorPad.GetData(), (*pit)->pin_merge.GetData() );
+
+ THROW_PARSE_ERROR( msg,
+ CurSource(),
+ CurLine(),
+ CurLineNumber(),
+ CurOffset() );
+ }
+
+ (*pit)->isVisible = true;
+ (*pit)->pin_merge = anchorPad;
+
+ // allocate or find a MERGE_SET;
+ MERGE_SET& ms = me->pin_merges[anchorPad];
+
+ while( ( tok = NextTok() ) != T_RIGHT )
+ {
+ if( tok == T_LEFT )
+ {
+ tok = NextTok();
+
+ switch( tok )
+ {
+ case T_signals:
+ {
+ PINS sigPins; // no ownership
+
+ while( ( tok = NextTok() ) != T_RIGHT )
+ {
+ if( !IsSymbol( tok ) && tok != T_NUMBER )
+ Expecting( "signal" );
+
+ signal = FromUTF8();
+
+ sigPins.clear();
+
+ me->PinsFindBySignal( &sigPins, signal );
+
+ if( !sigPins.size() )
+ {
+ msg.Printf( _( "no pins with signal %s" ), signal.GetData() );
+ THROW_PARSE_ERROR( msg,
+ CurSource(),
+ CurLine(),
+ CurLineNumber(),
+ CurOffset() );
+ }
+
+ for( pit = sigPins.begin(); pit != sigPins.end(); ++pit )
+ {
+ if( !(*pit)->pin_merge.IsEmpty() && anchorPad != (*pit)->pin_merge )
+ {
+ msg.Printf( _( "signal pin %s already in pin_merge group %s" ),
+ pad.GetData(), (*pit)->pin_merge.GetData() );
+
+ THROW_PARSE_ERROR( msg,
+ CurSource(),
+ CurLine(),
+ CurLineNumber(),
+ CurOffset() );
+ }
+
+ (*pit)->isVisible = true;
+ (*pit)->pin_merge = anchorPad;
+ ms.insert( pad );
+ }
+ }
+ }
+ break;
+
+ case T_pads:
+ while( ( tok = NextTok() ) != T_RIGHT )
+ {
+ if( !IsSymbol( tok ) && tok != T_NUMBER )
+ Expecting( "pad" );
+
+ pad = FromUTF8();
+
+ D(printf("pad=%s\n", TO_UTF8( pad ) );)
+
+ // find the PIN and mark it as being in this MERGE_SET or throw
+ // error if already in another MERGET_SET.
+
+ pit = me->pinFindByPad( pad );
+ if( pit == me->pins.end() )
+ {
+ msg.Printf( _( "undefined pin %s" ), pad.GetData() );
+ THROW_PARSE_ERROR( msg,
+ CurSource(),
+ CurLine(),
+ CurLineNumber(),
+ CurOffset() );
+ }
+
+ if( !(*pit)->pin_merge.IsEmpty() /* && anchorPad != (*pit)->pin_merge */ )
+ {
+ msg.Printf( _( "pin %s already in pin_merge group %s" ),
+ pad.GetData(), (*pit)->pin_merge.GetData() );
+
+ THROW_PARSE_ERROR( msg,
+ CurSource(),
+ CurLine(),
+ CurLineNumber(),
+ CurOffset() );
+ }
+
+ (*pit)->isVisible = false;
+ (*pit)->pin_merge = anchorPad;
+
+ ms.insert( pad );
+ }
+ break;
+
+ default:
+ Expecting( "pads|signals" );
+ break;
+ }
+ }
+ else
+ {
+ Expecting( T_LEFT );
+ }
+ }
+}
+
+
+void SWEET_PARSER::parsePropertyDel( PART* me )
+{
+ NeedSYMBOLorNUMBER();
+
+ wxString propertyName = FromUTF8();
+
+ if( !me->PropDelete( propertyName ) )
+ {
+ wxString msg;
+ msg.Printf( _( "Unable to find property: %s" ), propertyName.GetData() );
+ THROW_IO_ERROR( msg );
+ }
+ NeedRIGHT();
+}
+
+
+void SWEET_PARSER::parseTextEffects( TEXT_EFFECTS* me )
+{
+ /*
+ (effects [PROPERTY]
+
+ # Position requires X and Y coordinates. Position coordinates can be
+ # non-intergr. Angle is in degrees and defaults to 0 if not defined.
+ (at X Y [ANGLE])
+
+ # The FONT value needs to be defined. Currently, EESchema does not support
+ # different fonts. In the future this feature may be implemented and at
+ # that time FONT will have to be defined. Initially, only the font size and
+ # style are required. Italic and bold styles are optional. The font size
+ # height and width are in units yet to be determined.
+ (font [FONT] (size HEIGHT WIDTH) [italic] [bold])
+
+ # Valid visibility values are yes and no.
+ (visible YES)
+ )
+ */
+
+ bool sawFont = false;
+ bool sawAt = false;
+ bool sawVis = false;
+
+ T tok = NextTok();
+
+ if( IsSymbol( tok ) )
+ {
+ me->propName = FromUTF8();
+ tok = NextTok();
+ }
+
+ for( ; tok != T_RIGHT; tok = NextTok() )
+ {
+ if( tok != T_LEFT )
+ Expecting( T_LEFT );
+
+ tok = NextTok();
+
+ switch( tok )
+ {
+ case T_at:
+ if( sawAt )
+ Duplicate( tok );
+ sawAt = true;
+ parseAt( &me->pos, &me->angle );
+ break;
+
+ case T_font:
+ if( sawFont )
+ Duplicate( tok );
+ sawFont = true;
+ parseFont( &me->font );
+ break;
+
+ case T_visible:
+ if( sawVis )
+ Duplicate( sawVis );
+ sawVis = true;
+ parseBool( &me->isVisible );
+ NeedRIGHT();
+ break;
+
+ default:
+ Expecting( "at|font|visible" );
+ }
+ }
+}
+
+
+void SWEET_PARSER::parsePolyLine( POLY_LINE* me )
+{
+ /*
+ (polyline|line
+ (pts (xy X Y) (xy X Y) (xy X Y) (xy X Y) (xy X Y))
+
+ # Line widths are in percent of a pin delta
+ [(stroke [WIDTH] [(style [(dashed...)]...)])]
+
+
+ # Valid fill types are none, filled, and transparent.
+ (fill FILL_TYPE)
+ )
+ */
+
+ T tok;
+ int count = 0;
+ bool sawStroke = false;
+ bool sawFill = false;
+
+ while( ( tok = NextTok() ) != T_RIGHT )
+ {
+ if( tok != T_LEFT )
+ Expecting( T_LEFT );
+
+ tok = NextTok();
+
+ switch( tok )
+ {
+ case T_stroke:
+ if( sawStroke )
+ Duplicate( tok );
+ sawStroke = true;
+ parseStroke( &me->stroke );
+ break;
+
+ case T_pts:
+ if( count )
+ Duplicate( tok );
+ for( ; ( tok = NextTok() ) != T_RIGHT; ++count )
+ {
+ if( tok != T_LEFT )
+ Expecting( T_LEFT );
+
+ tok = NeedSYMBOL();
+ if( tok != T_xy )
+ Expecting( T_xy );
+
+ me->pts.push_back( POINT() );
+
+ NeedNUMBER( "x" );
+ me->pts.back().x = internal( CurText() );
+
+ NeedNUMBER( "y" );
+ me->pts.back().y = internal( CurText() );
+
+ NeedRIGHT();
+ }
+ if( count < 2 )
+ Expecting( ">= 2 pts" );
+ break;
+
+ case T_fill:
+ if( sawFill )
+ Duplicate( tok );
+ tok = NeedSYMBOL();
+ switch( tok )
+ {
+ case T_none:
+ case T_filled:
+ case T_transparent:
+ me->fillType = tok;
+ break;
+ default:
+ Expecting( "none|filled|transparent" );
+ }
+ NeedRIGHT();
+ sawFill = true;
+ break;
+
+ default:
+ Expecting( "pts|stroke|fill" );
+ }
+ }
+}
+
+
+void SWEET_PARSER::parseBezier( BEZIER* me )
+{
+ parsePolyLine( me );
+}
+
+
+void SWEET_PARSER::parseRectangle( RECTANGLE* me )
+{
+ /*
+ (rectangle (start X Y) (end X Y) (stroke WIDTH) (fill FILL_TYPE))
+ */
+
+ T tok;
+ bool sawStart = false;
+ bool sawEnd = false;
+ bool sawStroke = false;
+ bool sawFill = false;
+
+ while( ( tok = NextTok() ) != T_RIGHT )
+ {
+ if( tok != T_LEFT )
+ Expecting( T_LEFT );
+
+ tok = NextTok();
+
+ switch( tok )
+ {
+ case T_stroke:
+ if( sawStroke )
+ Duplicate( tok );
+ sawStroke = true;
+ parseStroke( &me->stroke );
+ break;
+
+ case T_fill:
+ if( sawFill )
+ Duplicate( tok );
+ sawFill = true;
+ tok = NeedSYMBOL();
+ switch( tok )
+ {
+ case T_none:
+ case T_filled:
+ case T_transparent:
+ me->fillType = tok;
+ break;
+ default:
+ Expecting( "none|filled|transparent" );
+ }
+ NeedRIGHT();
+ break;
+
+ case T_start:
+ if( sawStart )
+ Duplicate( tok );
+ sawStart = true;
+ NeedNUMBER( "x" );
+ me->start.x = internal( CurText() );
+ NeedNUMBER( "y" );
+ me->start.y = internal( CurText() );
+ NeedRIGHT();
+ break;
+
+ case T_end:
+ if( sawEnd )
+ Duplicate( tok );
+ sawEnd = true;
+ NeedNUMBER( "x" );
+ me->end.x = internal( CurText() );
+ NeedNUMBER( "y" );
+ me->end.y = internal( CurText() );
+ NeedRIGHT();
+ break;
+
+ default:
+ Expecting( "start|end|stroke|fill" );
+ }
+ }
+}
+
+
+void SWEET_PARSER::parseCircle( CIRCLE* me )
+{
+ /*
+ (circle (center X Y)
+ # Radius length is in units if defined or mils.
+ (radius LENGTH)
+ (stroke WIDTH)
+ (fill FILL_TYPE)
+ )
+ */
+
+ T tok;
+ bool sawCenter = false;
+ bool sawRadius = false;
+ bool sawStroke = false;
+ bool sawFill = false;
+
+ while( ( tok = NextTok() ) != T_RIGHT )
+ {
+ if( tok != T_LEFT )
+ Expecting( T_LEFT );
+
+ tok = NextTok();
+
+ switch( tok )
+ {
+ case T_stroke:
+ if( sawStroke )
+ Duplicate( tok );
+ sawStroke = true;
+ parseStroke( &me->stroke );
+ break;
+
+ case T_fill:
+ if( sawFill )
+ Duplicate( tok );
+ sawFill = true;
+ tok = NeedSYMBOL();
+ switch( tok )
+ {
+ case T_none:
+ case T_filled:
+ case T_transparent:
+ me->fillType = tok;
+ break;
+ default:
+ Expecting( "none|filled|transparent" );
+ }
+ NeedRIGHT();
+ break;
+
+ case T_center:
+ if( sawCenter )
+ Duplicate( tok );
+ sawCenter = true;
+ NeedNUMBER( "center x" );
+ me->center.x = internal( CurText() );
+ NeedNUMBER( "center y" );
+ me->center.y = internal( CurText() );
+ NeedRIGHT();
+ break;
+
+ case T_radius:
+ if( sawRadius )
+ Duplicate( tok );
+ sawRadius = true;
+ NeedNUMBER( "radius" );
+ me->radius = internal( CurText() );
+ NeedRIGHT();
+ break;
+
+ default:
+ Expecting( "center|radius|stroke|fill" );
+ }
+ }
+}
+
+
+void SWEET_PARSER::parseArc( ARC* me )
+{
+ /*
+ (arc (pos X Y) (radius RADIUS) (start X Y) (end X Y)
+ (stroke WIDTH)
+ (fill FILL_TYPE)
+ )
+ */
+
+ T tok;
+ bool sawPos = false;
+ bool sawStart = false;
+ bool sawEnd = false;
+ bool sawRadius = false;
+ bool sawStroke = false;
+ bool sawFill = false;
+
+ while( ( tok = NextTok() ) != T_RIGHT )
+ {
+ if( tok != T_LEFT )
+ Expecting( T_LEFT );
+
+ tok = NextTok();
+
+ switch( tok )
+ {
+ case T_stroke:
+ if( sawStroke )
+ Duplicate( tok );
+ sawStroke = true;
+ parseStroke( &me->stroke );
+ break;
+
+ case T_fill:
+ if( sawFill )
+ Duplicate( tok );
+ sawFill = true;
+ tok = NeedSYMBOL();
+ switch( tok )
+ {
+ case T_none:
+ case T_filled:
+ case T_transparent:
+ me->fillType = tok;
+ break;
+ default:
+ Expecting( "none|filled|transparent" );
+ }
+ NeedRIGHT();
+ break;
+
+ case T_pos:
+ if( sawPos )
+ Duplicate( tok );
+ sawPos = true;
+ NeedNUMBER( "pos x" );
+ me->pos.x = internal( CurText() );
+ NeedNUMBER( "pos y" );
+ me->pos.y = internal( CurText() );
+ NeedRIGHT();
+ break;
+
+ case T_radius:
+ if( sawRadius )
+ Duplicate( tok );
+ sawRadius = true;
+ NeedNUMBER( "radius" );
+ me->radius = internal( CurText() );
+ NeedRIGHT();
+ break;
+
+ case T_start:
+ if( sawStart )
+ Duplicate( tok );
+ sawStart = true;
+ NeedNUMBER( "start x" );
+ me->start.x = internal( CurText() );
+ NeedNUMBER( "start y" );
+ me->start.y = internal( CurText() );
+ NeedRIGHT();
+ break;
+
+ case T_end:
+ if( sawEnd )
+ Duplicate( tok );
+ sawEnd = true;
+ NeedNUMBER( "end x" );
+ me->end.x = internal( CurText() );
+ NeedNUMBER( "end y" );
+ me->end.y = internal( CurText() );
+ NeedRIGHT();
+ break;
+
+ default:
+ Expecting( "center|radius|stroke|fill" );
+ }
+ }
+}
+
+
+void SWEET_PARSER::parseAt( POINT* pos, float* angle )
+{
+ T tok;
+
+ NeedNUMBER( "at x" );
+ pos->x = internal( CurText() );
+
+ NeedNUMBER( "at y" );
+ pos->y = internal( CurText() );
+
+ tok = NextTok();
+ if( angle && tok == T_NUMBER )
+ {
+ *angle = strtod( CurText(), NULL );
+ tok = NextTok();
+ }
+ if( tok != T_RIGHT )
+ Expecting( T_RIGHT );
+}
+
+
+void SWEET_PARSER::parseText( GR_TEXT* me )
+{
+ /*
+ (text "This is the text that gets drawn."
+ (at X Y [ANGLE])
+
+ # Valid horizontal justification values are center, right, and left. Valid
+ # vertical justification values are center, top, bottom.
+ (justify HORIZONTAL_JUSTIFY VERTICAL_JUSTIFY)
+ (font [FONT] (size HEIGHT WIDTH) [italic] [bold])
+ (visible YES)
+ (fill FILL_TYPE)
+ )
+ */
+
+ T tok;
+ bool sawAt = false;
+ bool sawFill = false;
+ bool sawFont = false;
+ bool sawVis = false;
+ bool sawJust = false;
+ bool sawText = false;
+
+ while( ( tok = NextTok() ) != T_RIGHT )
+ {
+ if( tok == T_LEFT )
+ {
+ tok = NextTok();
+
+ switch( tok )
+ {
+ case T_at:
+ if( sawAt )
+ Duplicate( tok );
+ parseAt( &me->pos, &me->angle );
+ sawAt = true;
+ break;
+
+ case T_fill:
+ if( sawFill )
+ Duplicate( tok );
+ tok = NeedSYMBOL();
+ switch( tok )
+ {
+ case T_none:
+ case T_filled:
+ case T_transparent:
+ me->fillType = tok;
+ break;
+ default:
+ Expecting( "none|filled|transparent" );
+ }
+ NeedRIGHT();
+ sawFill = true;
+ break;
+
+ case T_justify:
+ if( sawJust )
+ Duplicate( tok );
+ tok = NeedSYMBOL();
+ switch( tok )
+ {
+ case T_center:
+ case T_right:
+ case T_left:
+ me->hjustify = tok;
+ break;
+ default:
+ Expecting( "center|right|left" );
+ }
+
+ tok = NeedSYMBOL();
+ switch( tok )
+ {
+ case T_center:
+ case T_top:
+ case T_bottom:
+ me->vjustify = tok;
+ break;
+ default:
+ Expecting( "center|top|bottom" );
+ }
+ NeedRIGHT();
+ sawJust = true;
+ break;
+
+ case T_visible:
+ if( sawVis )
+ Duplicate( tok );
+ parseBool( &me->isVisible );
+ NeedRIGHT();
+ sawVis = true;
+ break;
+
+ case T_font:
+ if( sawFont )
+ Duplicate( tok );
+ sawFont = true;
+ parseFont( &me->font );
+ break;
+
+ default:
+ Expecting( "at|justify|font|visible|fill" );
+ }
+ }
+ else
+ {
+ if( !IsSymbol( tok ) && tok != T_NUMBER )
+ Expecting( T_STRING );
+
+ if( sawText )
+ Duplicate( tok );
+ sawText = true;
+
+ me->text = wxString::FromUTF8( CurText() );
+ }
+ }
+}
+