more free software, sweet parser nearing completion

This commit is contained in:
Dick Hollenbeck 2011-03-27 01:07:25 -05:00
parent 137d132985
commit 5b0e60e663
7 changed files with 456 additions and 105 deletions

View File

@ -8,17 +8,58 @@ PARTS="eyes ears feet"
REVS="rev1 rev5 rev10"
LINE="(line (pts (xy 12 13)(xy 12 20))(line_width 1.5))"
RECT="(rectangle (start 4 5)(end 6 8)(line_width 2.3)(fill transparent))"
CIRCLE="(circle (center 1 0)(radius 5)(line_width 2.1)(fill none))"
ARC="(arc (pos 22 33)(radius 12)(start 2 4)(end 13 33)(line_width 2.3)(fill filled))"
BEZIER="(bezier (fill none)(line_width 2.0)(pts (xy 0 1)(xy 2 4)))"
TEXT="(text \"This is some text\" (at 23 23 90.0)(justify left bottom)(visible yes)(fill filled))"
PIN="(pin input line (at 7 8 90.0)(length 2)(visible YES))"
# add to pin
# (name NAME (font [FONT] (size HEIGHT WIDTH) [ITALIC] [BOLD])(visible YES))
# (number NUMBER (font [FONT] (size HEIGHT WIDTH) [ITALIC] [BOLD] (visible YES))
REFERENCE="
(reference U
(effects (at 12 13 180)(font (size .7 1))(visible yes))
)"
LINE="
(line
(pts (xy 12 13)(xy 12 20))(line_width 1.5)
)"
RECT="
(rectangle
(start 4 5)(end 6 8)(line_width 2.3)(fill transparent)
)"
CIRCLE="
(circle
(center 1 0)(radius 5)(line_width 2.1)(fill none)
)"
ARC="
(arc
(pos 22 33)(radius 12)(start 2 4)(end 13 33)(line_width 2.3)(fill filled)
)"
BEZIER="
(bezier
(fill none)(line_width 2.0)(pts (xy 0 1)(xy 2 4))
)"
TEXT="
(text \"This is some text\" (at 23 23 90.0)(justify left bottom)(visible yes)(fill filled)
(font arial (size .8 1.2))
)"
PIN1="
(pin output line (at 7 8 90)(length 2)(visible yes)
(signal #WE (font (size 0.9 1.1) bold)(visible yes))
(padname A23 (font (size 0.9 1.1) italic bold) (visible yes))
)"
PIN2="
(pin input line (at 8 8)(length 2)(visible yes)
(signal #WAIT (font (size 0.9 1.1) bold)(visible yes))
(padname A24 (font (size 0.9 1.1) italic bold) (visible yes))
)"
PROP1="
(property mWatts 12
(effects (at 1 34 270)(font (size .5 1) italic bold)(visible no))
)"
for C in ${CATEGORIES}; do
@ -28,24 +69,30 @@ for C in ${CATEGORIES}; do
for P in ${PARTS}; do
for R in ${REVS}; do
echo "(part $C/$P (value 22)(footprint SM0805)(model Airplane)
$REFERENCE
$LINE
$RECT
$CIRCLE
$ARC
$BEZIER
$TEXT
$PIN
$PIN1
$PIN2
$PROP1
)" > $BASEDIR/$C/$P.part.$R
done
# also make the part without a rev:
echo "(part $C/$P (value 22)(footprint SM0805)(model Airplane)
$REFERENCE
$LINE
$RECT
$CIRCLE
$ARC
$BEZIER
$TEXT
$PIN
$PIN1
$PIN2
$PROP1
)" > $BASEDIR/$C/$P.part
done
done

View File

@ -38,7 +38,12 @@ PART::PART( LIB* aOwner, const STRING& aPartNameAndRev ) :
contains( 0 ),
partNameAndRev( aPartNameAndRev ),
extends( 0 ),
base( 0 )
base( 0 ),
reference( this, wxT( "reference " ) ),
value( this, wxT( "value" ) ),
footprint( this, wxT( "footprint" ) ),
model( this, wxT( "model" ) ),
datasheet( this, wxT( "datasheet" ) )
{
// Our goal is to have class LIB only instantiate what is needed, so print here
// what it is doing. It is the only class where PART can be instantiated.
@ -64,7 +69,11 @@ void PART::clear()
delete *it;
pins.clear();
// @todo delete all properties
// delete non-mandatory properties I own, since their container will not destroy them:
for( PROPERTIES::iterator it = properties.begin(); it != properties.end(); ++it )
delete *it;
properties.clear();
}

View File

@ -41,6 +41,7 @@ namespace SCH {
class PART;
class SWEET_PARSER;
class PROPERTY;
};
@ -57,10 +58,12 @@ public:
{}
};
typedef float ANGLE;
namespace SCH {
class GR_FONT
class FONT
{
friend class PART;
friend class SWEET_PARSER;
@ -72,13 +75,32 @@ protected:
bool bold;
public:
GR_FONT() :
FONT() :
italic( false ),
bold( false )
{}
};
class BASE_GRAPHIC
struct TEXT_EFFECTS
{
POINT pos;
ANGLE angle;
FONT font;
bool isVisible;
PROPERTY* property; ///< only used from a COMPONENT, specifies PROPERTY in PART
wxString propName; ///< only used from a COMPONENT, specifies PROPERTY in PART
TEXT_EFFECTS() :
angle( 0 ),
isVisible( false ),
property( 0 )
{}
};
class BASE_GRAPHIC
{
friend class PART;
friend class SWEET_PARSER;
@ -186,13 +208,15 @@ class GR_TEXT : public BASE_GRAPHIC
protected:
POINT pos;
float angle;
ANGLE angle;
int fillType; ///< T_none, T_filled, or T_transparent
int hjustify; ///< T_center, T_right, or T_left
int vjustify; ///< T_center, T_top, or T_bottom
bool isVisible;
wxString text;
// FONT font;
FONT font;
public:
GR_TEXT( PART* aOwner ) :
@ -206,36 +230,71 @@ public:
};
class PIN : public BASE_GRAPHIC
class PROPERTY : public BASE_GRAPHIC
{
friend class PART;
friend class SWEET_PARSER;
protected:
POINT pos;
float angle;
int connectionType; ///< T_input, T_output, T_bidirectional, T_tristate, T_passive, T_unspecified,
///< T_power_in, T_power_out, T_open_collector, T_open_emitter, or T_unconnected.
int shape; ///< T_none, T_line, T_inverted, T_clock, T_inverted_clk, T_input_low, T_clock_low,
///< T_falling_edge, T_non_logic.
int length; ///< length of pin in internal units
wxString name;
wxString number;
bool nameIsVisible; ///< name is visible
bool numIsVisible; ///< number is visible
bool isVisible; ///< pin is visible
PART* birthplace; ///< at which PART in inheritance chain was this PROPERTY added
wxString name;
wxString text;
TEXT_EFFECTS effects;
public:
PROPERTY( PART* aOwner, const wxChar* aName = wxT( "" ) ) :
BASE_GRAPHIC( aOwner ),
birthplace( aOwner ),
name( aName )
{}
};
struct PINTEXT
{
wxString text;
FONT font;
bool isVisible;
PINTEXT() :
isVisible( true )
{}
};
class PIN : public BASE_GRAPHIC
{
friend class PART;
friend class SWEET_PARSER;
public:
PIN( PART* aOwner ) :
BASE_GRAPHIC( aOwner ),
birthplace( aOwner ),
angle( 0 ),
connectionType( PR::T_input ),
shape( PR::T_line ),
length( 0 ),
nameIsVisible( true ),
numIsVisible( true ),
isVisible( true )
{}
protected:
PART* birthplace; ///< at which PART in inheritance chain was this PIN added
POINT pos;
ANGLE angle;
PINTEXT padname;
PINTEXT signal;
int connectionType; ///< T_input, T_output, T_bidirectional, T_tristate, T_passive, T_unspecified,
///< T_power_in, T_power_out, T_open_collector, T_open_emitter, or T_unconnected.
int shape; ///< T_none, T_line, T_inverted, T_clock, T_inverted_clk, T_input_low, T_clock_low,
///< T_falling_edge, T_non_logic.
int length; ///< length of pin in internal units
bool isVisible; ///< pin is visible
};
@ -249,6 +308,7 @@ namespace SCH {
typedef std::vector< BASE_GRAPHIC* > GRAPHICS;
typedef std::vector< PIN* > PINS;
typedef std::vector< PROPERTY* > PROPERTIES;
class LPID;
class SWEET_PARSER;
@ -306,12 +366,20 @@ protected: // not likely to have C++ descendants, but protected none-the-le
/// actually becomes cached in RAM.
STRING body;
// bool cachedRevisions; ///< allows lazy loading of revision of this same part name
// mandatory properties
PROPERTY reference; ///< prefix only, only components have full references
PROPERTY value;
PROPERTY footprint;
PROPERTY model;
PROPERTY datasheet;
// 3 separate lists for speed:
// separate lists for speed:
/// A property list.
//PROPERTIES properties;
/**
* Member properties
* holds the non-mandatory properties.
*/
PROPERTIES properties;
/**
* Member graphics
@ -325,14 +393,9 @@ protected: // not likely to have C++ descendants, but protected none-the-le
*/
PINS pins;
/// Alternate body forms.
//ALTERNATES alternates;
// mandatory properties
wxString value;
wxString footprint;
wxString model;
wxString keywords;
@ -361,6 +424,7 @@ public:
*/
void Parse( SWEET_PARSER* aParser, LIB_TABLE* aLibTable ) throw( IO_ERROR, PARSE_ERROR );
/*
void SetValue( const wxString& aValue )
{
value = aValue;
@ -387,6 +451,7 @@ public:
{
return model;
}
*/
/*
void SetBody( const STR_UTF& aSExpression )

View File

@ -250,14 +250,44 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E
parseText( text );
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);
NeedSYMBOLorNUMBER();
me->reference.text = FromUTF8();
tok = NextTok();
if( tok == T_LEFT )
{
tok = NextTok();
if( tok != T_effects )
Expecting( T_effects );
parseTextEffects( &me->reference.effects );
NeedRIGHT();
}
else if( tok != T_RIGHT )
Expecting( ") | effects" );
break;
case T_value:
if( contains & PB(VALUE) )
Duplicate( tok );
contains |= PB(VALUE);
NeedSYMBOLorNUMBER();
me->SetValue( FROM_UTF8( CurText() ) );
// @todo handle optional (effects..) here
NeedRIGHT();
me->value.text = FromUTF8();
tok = NextTok();
if( tok == T_LEFT )
{
tok = NextTok();
if( tok != T_effects )
Expecting( T_effects );
parseTextEffects( &me->value.effects );
NeedRIGHT();
}
else if( tok != T_RIGHT )
Expecting( ") | effects" );
break;
case T_footprint:
@ -265,9 +295,37 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E
Duplicate( tok );
contains |= PB(FOOTPRINT);
NeedSYMBOLorNUMBER();
me->SetFootprint( FROM_UTF8( CurText() ) );
// @todo handle optional (effects..) here
NeedRIGHT();
me->footprint.text = FromUTF8();
tok = NextTok();
if( tok == T_LEFT )
{
tok = NextTok();
if( tok != T_effects )
Expecting( T_effects );
parseTextEffects( &me->footprint.effects );
NeedRIGHT();
}
else if( tok != T_RIGHT )
Expecting( ") | effects" );
break;
case T_datasheet:
if( contains & PB(MODEL) )
Duplicate( tok );
contains |= PB(MODEL);
NeedSYMBOLorNUMBER();
me->datasheet.text = FromUTF8();
tok = NextTok();
if( tok == T_LEFT )
{
tok = NextTok();
if( tok != T_effects )
Expecting( T_effects );
parseTextEffects( &me->datasheet.effects );
NeedRIGHT();
}
else if( tok != T_RIGHT )
Expecting( ") | effects" );
break;
case T_model:
@ -275,9 +333,40 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E
Duplicate( tok );
contains |= PB(MODEL);
NeedSYMBOLorNUMBER();
me->SetModel( FROM_UTF8( CurText() ) );
// @todo handle optional (effects..) here
NeedRIGHT();
me->model.text = FromUTF8();
tok = NextTok();
if( tok == T_LEFT )
{
tok = NextTok();
if( tok != T_effects )
Expecting( T_effects );
parseTextEffects( &me->model.effects );
NeedRIGHT();
}
else if( tok != T_RIGHT )
Expecting( ") | effects" );
break;
case T_property:
PROPERTY* property;
property = new PROPERTY( me );
// @todo check for uniqueness
me->properties.push_back( property );
NeedSYMBOLorNUMBER();
property->name = FromUTF8();
NeedSYMBOLorNUMBER();
property->text = FromUTF8();
tok = NextTok();
if( tok == T_LEFT )
{
tok = NextTok();
if( tok != T_effects )
Expecting( T_effects );
parseTextEffects( &property->effects );
NeedRIGHT();
}
else if( tok != T_RIGHT )
Expecting( ") | effects" );
break;
case T_pin:
@ -287,16 +376,15 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E
parsePin( pin );
break;
/*
/*
@todo
case T_keywords:
break;
case T_alternates:
break;
case T_property:
break;
case T_property_del:
break;
@ -315,15 +403,7 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E
case T_route_pin_swap:
break;
*/
// Not sure about reference in a PART, comes in at COMPONENT object.
// It is maybe just a hint here or a prefix.
case T_reference:
if( contains & PB(REFERENCE) )
Duplicate( tok );
contains |= PB(REFERENCE);
break;
*/
}
}
@ -333,7 +413,7 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E
}
void SWEET_PARSER::parseFont( GR_FONT* me )
void SWEET_PARSER::parseFont( FONT* me )
{
/*
# The FONT value needs to be defined. Currently, EESchema does not support
@ -344,9 +424,7 @@ void SWEET_PARSER::parseFont( GR_FONT* me )
(font [FONT] (size HEIGHT WIDTH) [italic] [bold])
*/
// handle the [FONT] position dependently, i.e. first
// handle the [FONT] 'position dependently', i.e. first
T tok = NextTok();
bool sawBold = false;
bool sawItalic = false;
@ -363,40 +441,47 @@ void SWEET_PARSER::parseFont( GR_FONT* me )
if( tok == T_LEFT )
{
tok = NextTok();
if( tok != T_size )
Expecting( T_size );
if( sawSize )
Duplicate( T_size );
sawSize = true;
switch( tok )
{
case T_size:
if( sawSize )
Duplicate( T_size );
sawSize = true;
NeedNUMBER( "size height" );
me->size.SetHeight( internal( CurText() ) );
NeedNUMBER( "size height" );
me->size.SetHeight( internal( CurText() ) );
NeedNUMBER( "size width" );
me->size.SetWidth( internal( CurText() ) );
NeedRIGHT();
NeedNUMBER( "size width" );
me->size.SetWidth( internal( CurText() ) );
NeedRIGHT();
break;
default:
Expecting( "size" );
}
}
else
{
if( tok == T_bold )
switch( tok )
{
case T_bold:
if( sawBold )
Duplicate( T_bold );
sawBold = true;
me->bold = true;
}
else if( tok == T_italic )
{
break;
case T_italic:
if( sawItalic )
Duplicate( T_italic );
sawItalic = true;
me->italic = true;
break;
default:
Unexpected( "bold|italic" );
}
else
Unexpected( tok );
}
tok = NextTok();
@ -420,26 +505,81 @@ void SWEET_PARSER::parseBool( bool* aBool )
}
void SWEET_PARSER::parsePinText( PINTEXT* me )
{
/* either:
(signal SIGNAL (font [FONT] (size HEIGHT WIDTH) [italic] [bold])(visible YES))
or
(padname PADNAME (font [FONT] (size HEIGHT WIDTH) [italic] [bold])(visible YES))
*/
T tok;
bool sawFont = false;
bool sawVis = false;
// padname 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)
(name NAME (font [FONT] (size HEIGHT WIDTH) [italic] [bold])(visible YES))
(number NUMBER (font [FONT] (size HEIGHT WIDTH) [italic] [bold] (visible YES))
(signal NAME (font [FONT] (size HEIGHT WIDTH) [italic] [bold])(visible YES))
(padname 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 sawName = false;
bool sawNum = false;
bool sawVis = false;
bool sawShape = false;
bool sawType = false;
bool sawAt = false;
bool sawLen = false;
bool sawSignal = false;
bool sawPadName = false;
bool sawVis = false;
while( ( tok = NextTok() ) != T_RIGHT )
{
@ -465,11 +605,19 @@ void SWEET_PARSER::parsePin( PIN* me )
NeedRIGHT();
break;
/* @todo and associated fonts
case T_name:
case T_number:
case T_signal:
if( sawSignal )
Duplicate( tok );
sawSignal = true;
parsePinText( &me->signal );
break;
case T_padname:
if( sawPadName )
Duplicate( tok );
sawPadName = true;
parsePinText( &me->padname );
break;
*/
case T_visible:
if( sawVis )
@ -528,6 +676,79 @@ void SWEET_PARSER::parsePin( PIN* me )
}
void SWEET_PARSER::parseTextEffects( TEXT_EFFECTS* me )
{
/*
(effects [PROPERTY]
# Position requires an 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();
}
while( tok != T_RIGHT )
{
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" );
}
tok = NextTok();
}
}
void SWEET_PARSER::parsePolyLine( POLY_LINE* me )
{
/*
@ -1000,8 +1221,10 @@ void SWEET_PARSER::parseText( GR_TEXT* me )
break;
case T_font:
// @todo
if( sawFont )
Duplicate( tok );
sawFont = true;
parseFont( &me->font );
break;
default:

View File

@ -44,7 +44,11 @@ class ARC;
class BEZIER;
class GR_TEXT;
class PIN;
class GR_FONT;
class FONT;
class PROPERTY;
struct PINTEXT;
struct TEXT_EFFECTS;
/**
@ -73,7 +77,10 @@ class SWEET_PARSER : public SWEET_LEXER
void parsePin( PIN* me );
void parseAt( POINT* pos, float* angle );
void parseBool( bool* aBool );
void parseFont( GR_FONT* me );
void parseFont( FONT* me );
void parsePinText( PINTEXT* me );
void parseTextEffects( TEXT_EFFECTS* me );
public:

View File

@ -32,14 +32,13 @@ length
line
line_width
model
name
no
non_logic
none
number
open_collector
open_emitter
output
padname
part
passive
pin
@ -61,6 +60,7 @@ reference
right
route_alt_swap
route_pin_swap
signal
size
start
start_angle