Add syntax help for bus definitions (and upgrade parser to handle them).

Fixes https://gitlab.com/kicad/code/kicad/issues/4233
This commit is contained in:
Jeff Young 2020-05-10 18:38:44 +01:00
parent cc1ebca242
commit cbe4b79107
9 changed files with 307 additions and 219 deletions

View File

@ -16,7 +16,7 @@ DIALOG_LABEL_EDITOR_BASE::DIALOG_LABEL_EDITOR_BASE( wxWindow* parent, wxWindowID
wxBoxSizer* bMainSizer; wxBoxSizer* bMainSizer;
bMainSizer = new wxBoxSizer( wxVERTICAL ); bMainSizer = new wxBoxSizer( wxVERTICAL );
m_textEntrySizer = new wxFlexGridSizer( 5, 2, 3, 3 ); m_textEntrySizer = new wxFlexGridSizer( 5, 2, 1, 3 );
m_textEntrySizer->AddGrowableCol( 1 ); m_textEntrySizer->AddGrowableCol( 1 );
m_textEntrySizer->AddGrowableRow( 1 ); m_textEntrySizer->AddGrowableRow( 1 );
m_textEntrySizer->SetFlexibleDirection( wxBOTH ); m_textEntrySizer->SetFlexibleDirection( wxBOTH );
@ -27,12 +27,12 @@ DIALOG_LABEL_EDITOR_BASE::DIALOG_LABEL_EDITOR_BASE( wxWindow* parent, wxWindowID
m_labelSingleLine->Wrap( -1 ); m_labelSingleLine->Wrap( -1 );
m_labelSingleLine->SetToolTip( _("Enter the text to be used within the schematic") ); m_labelSingleLine->SetToolTip( _("Enter the text to be used within the schematic") );
m_textEntrySizer->Add( m_labelSingleLine, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 3 ); m_textEntrySizer->Add( m_labelSingleLine, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM, 2 );
m_valueSingleLine = new wxTextCtrl( this, wxID_VALUESINGLE, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER|wxTE_RICH ); m_valueSingleLine = new wxTextCtrl( this, wxID_VALUESINGLE, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER|wxTE_RICH );
m_valueSingleLine->SetMinSize( wxSize( 360,-1 ) ); m_valueSingleLine->SetMinSize( wxSize( 360,-1 ) );
m_textEntrySizer->Add( m_valueSingleLine, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); m_textEntrySizer->Add( m_valueSingleLine, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxBOTTOM, 2 );
m_labelMultiLine = new wxStaticText( this, wxID_ANY, _("Text:"), wxDefaultPosition, wxDefaultSize, 0 ); m_labelMultiLine = new wxStaticText( this, wxID_ANY, _("Text:"), wxDefaultPosition, wxDefaultSize, 0 );
m_labelMultiLine->Wrap( -1 ); m_labelMultiLine->Wrap( -1 );
@ -67,7 +67,7 @@ DIALOG_LABEL_EDITOR_BASE::DIALOG_LABEL_EDITOR_BASE( wxWindow* parent, wxWindowID
m_valueMultiLine->MarkerDefine( wxSTC_MARKNUM_FOLDERTAIL, wxSTC_MARK_EMPTY ); m_valueMultiLine->MarkerDefine( wxSTC_MARKNUM_FOLDERTAIL, wxSTC_MARK_EMPTY );
m_valueMultiLine->SetSelBackground( true, wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) ); m_valueMultiLine->SetSelBackground( true, wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
m_valueMultiLine->SetSelForeground( true, wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHTTEXT ) ); m_valueMultiLine->SetSelForeground( true, wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHTTEXT ) );
m_textEntrySizer->Add( m_valueMultiLine, 1, wxEXPAND|wxRIGHT|wxLEFT, 5 ); m_textEntrySizer->Add( m_valueMultiLine, 1, wxEXPAND|wxBOTTOM, 2 );
m_labelCombo = new wxStaticText( this, wxID_ANY, _("Label:"), wxDefaultPosition, wxDefaultSize, 0 ); m_labelCombo = new wxStaticText( this, wxID_ANY, _("Label:"), wxDefaultPosition, wxDefaultSize, 0 );
m_labelCombo->Wrap( -1 ); m_labelCombo->Wrap( -1 );
@ -76,17 +76,17 @@ DIALOG_LABEL_EDITOR_BASE::DIALOG_LABEL_EDITOR_BASE( wxWindow* parent, wxWindowID
m_valueCombo = new wxComboBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxTE_PROCESS_ENTER ); m_valueCombo = new wxComboBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxTE_PROCESS_ENTER );
m_valueCombo->SetMinSize( wxSize( 360,-1 ) ); m_valueCombo->SetMinSize( wxSize( 360,-1 ) );
m_textEntrySizer->Add( m_valueCombo, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); m_textEntrySizer->Add( m_valueCombo, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 );
m_textSizeLabel = new wxStaticText( this, wxID_ANY, _("Text Size:"), wxDefaultPosition, wxDefaultSize, 0 ); m_textSizeLabel = new wxStaticText( this, wxID_ANY, _("Text Size:"), wxDefaultPosition, wxDefaultSize, 0 );
m_textSizeLabel->Wrap( -1 ); m_textSizeLabel->Wrap( -1 );
m_textEntrySizer->Add( m_textSizeLabel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxRIGHT, 6 ); m_textEntrySizer->Add( m_textSizeLabel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 6 );
wxBoxSizer* bSizeCtrlSizer; wxBoxSizer* bSizeCtrlSizer;
bSizeCtrlSizer = new wxBoxSizer( wxHORIZONTAL ); bSizeCtrlSizer = new wxBoxSizer( wxHORIZONTAL );
m_textSizeCtrl = new wxTextCtrl( this, wxID_SIZE, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_textSizeCtrl = new wxTextCtrl( this, wxID_SIZE, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
bSizeCtrlSizer->Add( m_textSizeCtrl, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxRIGHT|wxLEFT, 6 ); bSizeCtrlSizer->Add( m_textSizeCtrl, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxRIGHT, 6 );
m_textSizeUnits = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, 0 ); m_textSizeUnits = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, 0 );
m_textSizeUnits->Wrap( -1 ); m_textSizeUnits->Wrap( -1 );
@ -96,18 +96,18 @@ DIALOG_LABEL_EDITOR_BASE::DIALOG_LABEL_EDITOR_BASE( wxWindow* parent, wxWindowID
bSizeCtrlSizer->Add( 0, 0, 1, wxEXPAND, 15 ); bSizeCtrlSizer->Add( 0, 0, 1, wxEXPAND, 15 );
m_formattingHelp = new wxHyperlinkCtrl( this, wxID_ANY, _("Syntax help"), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); m_formattingHelp = new wxHyperlinkCtrl( this, wxID_ANY, _("Syntax help"), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
bSizeCtrlSizer->Add( m_formattingHelp, 0, wxBOTTOM|wxRIGHT|wxLEFT, 8 ); bSizeCtrlSizer->Add( m_formattingHelp, 0, wxBOTTOM|wxRIGHT|wxLEFT, 7 );
m_textEntrySizer->Add( bSizeCtrlSizer, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 3 ); m_textEntrySizer->Add( bSizeCtrlSizer, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxBOTTOM, 6 );
m_note1 = new wxStaticText( this, wxID_ANY, _("Note:"), wxDefaultPosition, wxDefaultSize, 0 ); m_note1 = new wxStaticText( this, wxID_ANY, _("Note:"), wxDefaultPosition, wxDefaultSize, 0 );
m_note1->Wrap( -1 ); m_note1->Wrap( -1 );
m_textEntrySizer->Add( m_note1, 0, wxTOP|wxRIGHT, 5 ); m_textEntrySizer->Add( m_note1, 0, wxTOP|wxRIGHT, 2 );
m_note2 = new wxStaticText( this, wxID_ANY, _("The margins around the text are controlled by the text offset ratio\nin Schematic Setup > General > Formatting."), wxDefaultPosition, wxDefaultSize, 0 ); m_note2 = new wxStaticText( this, wxID_ANY, _("The margins around the text are controlled by the text offset ratio\nin Schematic Setup > General > Formatting."), wxDefaultPosition, wxDefaultSize, 0 );
m_note2->Wrap( -1 ); m_note2->Wrap( -1 );
m_textEntrySizer->Add( m_note2, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); m_textEntrySizer->Add( m_note2, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxTOP|wxRIGHT, 2 );
bMainSizer->Add( m_textEntrySizer, 1, wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 12 ); bMainSizer->Add( m_textEntrySizer, 1, wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 12 );

View File

@ -73,10 +73,10 @@
<property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property> <property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
<property name="permission">protected</property> <property name="permission">protected</property>
<property name="rows">5</property> <property name="rows">5</property>
<property name="vgap">3</property> <property name="vgap">1</property>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">
<property name="border">3</property> <property name="border">2</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT</property> <property name="flag">wxALIGN_CENTER_VERTICAL|wxBOTTOM</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxStaticText" expanded="1"> <object class="wxStaticText" expanded="1">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
@ -136,8 +136,8 @@
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">
<property name="border">5</property> <property name="border">2</property>
<property name="flag">wxEXPAND|wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT</property> <property name="flag">wxEXPAND|wxALIGN_CENTER_VERTICAL|wxBOTTOM</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxTextCtrl" expanded="1"> <object class="wxTextCtrl" expanded="1">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
@ -262,8 +262,8 @@
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">
<property name="border">5</property> <property name="border">2</property>
<property name="flag">wxEXPAND|wxRIGHT|wxLEFT</property> <property name="flag">wxEXPAND|wxBOTTOM</property>
<property name="proportion">1</property> <property name="proportion">1</property>
<object class="wxStyledTextCtrl" expanded="1"> <object class="wxStyledTextCtrl" expanded="1">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
@ -390,7 +390,7 @@
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxEXPAND|wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT</property> <property name="flag">wxEXPAND|wxALIGN_CENTER_VERTICAL</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxComboBox" expanded="1"> <object class="wxComboBox" expanded="1">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
@ -456,7 +456,7 @@
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">
<property name="border">6</property> <property name="border">6</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxTOP|wxRIGHT</property> <property name="flag">wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxStaticText" expanded="1"> <object class="wxStaticText" expanded="1">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
@ -516,8 +516,8 @@
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">
<property name="border">3</property> <property name="border">6</property>
<property name="flag">wxEXPAND|wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT</property> <property name="flag">wxEXPAND|wxALIGN_CENTER_VERTICAL|wxBOTTOM</property>
<property name="proportion">1</property> <property name="proportion">1</property>
<object class="wxBoxSizer" expanded="1"> <object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property> <property name="minimum_size"></property>
@ -526,7 +526,7 @@
<property name="permission">none</property> <property name="permission">none</property>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">
<property name="border">6</property> <property name="border">6</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxTOP|wxRIGHT|wxLEFT</property> <property name="flag">wxALIGN_CENTER_VERTICAL|wxTOP|wxRIGHT</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxTextCtrl" expanded="1"> <object class="wxTextCtrl" expanded="1">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
@ -660,7 +660,7 @@
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">
<property name="border">8</property> <property name="border">7</property>
<property name="flag">wxBOTTOM|wxRIGHT|wxLEFT</property> <property name="flag">wxBOTTOM|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxHyperlinkCtrl" expanded="1"> <object class="wxHyperlinkCtrl" expanded="1">
@ -726,7 +726,7 @@
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">
<property name="border">5</property> <property name="border">2</property>
<property name="flag">wxTOP|wxRIGHT</property> <property name="flag">wxTOP|wxRIGHT</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxStaticText" expanded="1"> <object class="wxStaticText" expanded="1">
@ -787,8 +787,8 @@
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">
<property name="border">5</property> <property name="border">2</property>
<property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL</property> <property name="flag">wxEXPAND|wxALIGN_CENTER_VERTICAL|wxTOP|wxRIGHT</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxStaticText" expanded="1"> <object class="wxStaticText" expanded="1">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>

View File

@ -243,39 +243,32 @@ void NETLIST_OBJECT::ConvertBusToNetListItems( NETLIST_OBJECT_LIST& aNetListItem
long member_offset = 0; long member_offset = 0;
auto alias = SCH_SCREEN::GetBusAlias( m_Label ); auto alias = SCH_SCREEN::GetBusAlias( m_Label );
if( alias || conn.IsBusGroupLabel( m_Label ) ) wxString group_name;
bool self_set = false;
std::vector<wxString> bus_contents_vec;
if( alias )
{
for( const wxString& member : alias->Members() )
bus_contents_vec.emplace_back( member );
}
else if( SCH_CONNECTION::ParseBusGroup( m_Label, &group_name, &bus_contents_vec ) )
{ {
wxString group_name;
bool self_set = false;
std::vector<wxString> bus_contents_vec;
if( alias )
{
for( const auto& member : alias->Members() )
bus_contents_vec.emplace_back( member );
}
else
{
wxCHECK_RET( conn.ParseBusGroup( m_Label, &group_name, bus_contents_vec ),
wxString::Format( _( "Failed to parse bus group %s" ), m_Label ) );
}
// For named bus groups, like "USB{DP DM}" // For named bus groups, like "USB{DP DM}"
auto group_prefix = ( group_name != "" ) ? ( group_name + "." ) : ""; wxString group_prefix = ( group_name != "" ) ? ( group_name + "." ) : "";
std::list<wxString> bus_contents( bus_contents_vec.begin(), std::list<wxString> bus_contents( bus_contents_vec.begin(), bus_contents_vec.end() );
bus_contents_vec.end() );
for( const auto& bus_member : bus_contents ) for( const auto& bus_member : bus_contents )
{ {
wxString prefix;
std::vector<wxString> members;
// Nested bus vector inside a bus group // Nested bus vector inside a bus group
if( conn.IsBusVectorLabel( bus_member ) ) if( SCH_CONNECTION::ParseBusVector( bus_member, &prefix, &members ) )
{ {
wxString prefix;
std::vector<wxString> members;
long begin, end; long begin, end;
conn.ParseBusVector( bus_member, &prefix, members );
prefix = group_prefix + prefix; prefix = group_prefix + prefix;
begin = conn.VectorStart(); begin = conn.VectorStart();
end = conn.VectorEnd(); end = conn.VectorEnd();
@ -318,21 +311,15 @@ void NETLIST_OBJECT::ConvertBusToNetListItems( NETLIST_OBJECT_LIST& aNetListItem
} }
} }
} }
else else if( SCH_CONNECTION::ParseBusVector( m_Label, &group_name, &bus_contents_vec ) )
{ {
// Plain bus vector long begin = conn.VectorStart();
wxString prefix; long end = conn.VectorEnd();
std::vector<wxString> members;
long begin, end;
conn.ParseBusVector( m_Label, &prefix, members ); m_Label = bus_contents_vec[0];
begin = conn.VectorStart();
end = conn.VectorEnd();
m_Label = members[0];
m_Member = begin; m_Member = begin;
fillBusVector( aNetListItems, prefix, begin + 1, end, 0 ); fillBusVector( aNetListItems, group_name, begin + 1, end, 0 );
} }
} }

View File

@ -57,10 +57,6 @@
* just USB_DP and USB_DN. * just USB_DP and USB_DN.
* *
*/ */
static std::regex bus_label_re( "^([^[:space:]]+)(\\[[\\d]+\\.+[\\d]+\\])(~?)$" );
static std::regex bus_group_label_re( "^([^[:space:]]+)?\\{((?:[^[:space:]]+(?:\\[[\\d]+\\.+[\\d]+\\])? ?)+)\\}$" );
SCH_CONNECTION::SCH_CONNECTION( SCH_ITEM* aParent, SCH_SHEET_PATH aPath ) : SCH_CONNECTION::SCH_CONNECTION( SCH_ITEM* aParent, SCH_SHEET_PATH aPath ) :
m_sheet( aPath ), m_sheet( aPath ),
@ -113,25 +109,26 @@ bool SCH_CONNECTION::operator!=( const SCH_CONNECTION& aOther ) const
} }
void SCH_CONNECTION::ConfigureFromLabel( wxString aLabel ) void SCH_CONNECTION::ConfigureFromLabel( const wxString& aLabel )
{ {
m_members.clear(); m_members.clear();
m_name = aLabel; m_name = aLabel;
m_local_name = aLabel; m_local_name = aLabel;
wxString prefix;
std::vector<wxString> members;
wxString unescaped = UnescapeString( aLabel ); wxString unescaped = UnescapeString( aLabel );
if( IsBusVectorLabel( unescaped ) ) if( ParseBusVector( unescaped, &prefix, &members ) )
{ {
m_type = CONNECTION_TYPE::BUS; m_type = CONNECTION_TYPE::BUS;
m_vector_prefix = prefix;
std::vector<wxString> members;
ParseBusVector( unescaped, &m_vector_prefix, members );
long i = 0; long i = 0;
for( const auto& vector_member : members ) for( const wxString& vector_member : members )
{ {
auto member = std::make_shared<SCH_CONNECTION>( m_parent, m_sheet ); auto member = std::make_shared<SCH_CONNECTION>( m_parent, m_sheet );
member->m_type = CONNECTION_TYPE::NET; member->m_type = CONNECTION_TYPE::NET;
@ -142,39 +139,34 @@ void SCH_CONNECTION::ConfigureFromLabel( wxString aLabel )
m_members.push_back( member ); m_members.push_back( member );
} }
} }
else if( IsBusGroupLabel( unescaped ) ) else if( ParseBusGroup( unescaped, &prefix, &members ) )
{ {
m_type = CONNECTION_TYPE::BUS_GROUP; m_type = CONNECTION_TYPE::BUS_GROUP;
std::vector<wxString> members; // Named bus groups generate a net prefix, unnamed ones don't
wxString group_name; if( !prefix.IsEmpty() )
prefix += wxT( "." );
if( ParseBusGroup( unescaped, &group_name, members ) ) for( const wxString& group_member : members )
{ {
// Named bus groups generate a net prefix, unnamed ones don't // Handle alias inside bus group member list
wxString prefix = group_name != wxT( "" ) ? ( group_name + wxT( "." ) ) : wxT( "" ); if( auto alias = g_ConnectionGraph->GetBusAlias( group_member ) )
for( const auto& group_member : members )
{ {
// Handle alias inside bus group member list for( const wxString& alias_member : alias->Members() )
if( auto alias = g_ConnectionGraph->GetBusAlias( group_member ) )
{
for( const auto& alias_member : alias->Members() )
{
auto member = std::make_shared< SCH_CONNECTION >( m_parent, m_sheet );
member->SetPrefix( prefix );
member->ConfigureFromLabel( alias_member );
m_members.push_back( member );
}
}
else
{ {
auto member = std::make_shared< SCH_CONNECTION >( m_parent, m_sheet ); auto member = std::make_shared< SCH_CONNECTION >( m_parent, m_sheet );
member->SetPrefix( prefix ); member->SetPrefix( prefix );
member->ConfigureFromLabel( group_member ); member->ConfigureFromLabel( alias_member );
m_members.push_back( member ); m_members.push_back( member );
} }
} }
else
{
auto member = std::make_shared< SCH_CONNECTION >( m_parent, m_sheet );
member->SetPrefix( prefix );
member->ConfigureFromLabel( group_member );
m_members.push_back( member );
}
} }
} }
else else
@ -351,7 +343,7 @@ void SCH_CONNECTION::AppendInfoToMsgPanel( MSG_PANEL_ITEMS& aList ) const
aList.push_back( MSG_PANEL_ITEM( msg, members, RED ) ); aList.push_back( MSG_PANEL_ITEM( msg, members, RED ) );
} }
else if( ParseBusGroup( m_name, &group_name, group_members ) ) else if( ParseBusGroup( m_name, &group_name, &group_members ) )
{ {
for( const auto& group_member : group_members ) for( const auto& group_member : group_members )
{ {
@ -400,7 +392,7 @@ void SCH_CONNECTION::AppendDebugInfoToMsgPanel( MSG_PANEL_ITEMS& aList ) const
bool SCH_CONNECTION::IsBusLabel( const wxString& aLabel ) bool SCH_CONNECTION::IsBusLabel( const wxString& aLabel )
{ {
return IsBusVectorLabel( aLabel ) || IsBusGroupLabel( aLabel ); return ParseBusVector( aLabel, nullptr, nullptr ) || ParseBusGroup( aLabel, nullptr, nullptr );
} }
@ -413,104 +405,128 @@ bool SCH_CONNECTION::MightBeBusLabel( const wxString& aLabel )
} }
bool SCH_CONNECTION::IsBusVectorLabel( const wxString& aLabel ) static bool isSuperSub( wxChar c )
{ {
if( !aLabel.Contains( wxT( "[" ) ) ) return c == '_' || c == '^';
return false; };
try
{
return std::regex_match( std::string( aLabel.mb_str() ), bus_label_re );
}
catch( ... )
{
return false;
}
}
bool SCH_CONNECTION::IsBusGroupLabel( const wxString& aLabel ) bool SCH_CONNECTION::ParseBusVector( const wxString& aBus, wxString* aName,
std::vector<wxString>* aMemberList )
{ {
if( !aLabel.Contains( wxT( "{" ) ) ) auto isDigit = []( wxChar c )
return false; {
static wxString digits( wxT( "0123456789" ) );
return digits.Contains( c );
};
try size_t busLen = aBus.length();
{ size_t i = 0;
return std::regex_match( std::string( aLabel.mb_str() ), bus_group_label_re ); wxString prefix;
} wxString suffix;
catch( ... )
{
return false;
}
}
bool SCH_CONNECTION::ParseBusVector( wxString aBus, wxString* aName,
std::vector<wxString>& aMemberList ) const
{
auto ss_vector = std::string( aBus.mb_str() );
std::smatch matches;
try
{
if( !std::regex_match( ss_vector, matches, bus_label_re ) )
return false;
}
catch( ... )
{
return false;
}
long begin = 0, end = 0;
*aName = wxString( matches[1] );
wxString numberString( matches[2] );
// If we have three match groups, it means there was a tilde at the end of the vector
bool append_tilde = wxString( matches[3] ).IsSameAs( wxT( "~" ) );
// numberString will include the brackets, e.g. [5..0] so skip the first one
size_t i = 1, len = numberString.Len();
wxString tmp; wxString tmp;
long begin = 0;
long end = 0;
int braceNesting = 0;
while( i < len && numberString[i] != '.' ) // Parse prefix
//
for( ; i < busLen; ++i )
{ {
tmp.Append( numberString[i] ); if( aBus[i] == '{' )
i++; {
if( i > 0 && isSuperSub( aBus[i-1] ) )
braceNesting++;
else
return false;
}
else if( aBus[i] == '}' )
{
braceNesting--;
}
if( aBus[i] == ' ' || aBus[i] == ']' )
return false;
if( aBus[i] == '[' )
break;
prefix += aBus[i];
} }
tmp.ToLong( &begin ); // Parse start number
//
i++; // '[' character
while( i < len && numberString[i] == '.' ) for( ; i < busLen; ++i )
i++;
tmp.Empty();
while( i < len && numberString[i] != ']' )
{ {
tmp.Append( numberString[i] ); if( aBus[i] == '.' && i + 1 < busLen && aBus[i+1] == '.' )
i++; {
tmp.ToLong( &begin );
i += 2;
break;
}
if( !isDigit( aBus[i] ) )
return false;
tmp += aBus[i];
} }
tmp.ToLong( &end ); // Parse end number
//
tmp = wxEmptyString;
if( begin < 0 ) for( ; i < busLen; ++i )
begin = 0;
if( end < 0 )
end = 0;
if( begin > end )
std::swap( begin, end );
for( long idx = begin; idx <= end; ++idx )
{ {
wxString str = *aName; if( aBus[i] == ']' )
str << idx; {
tmp.ToLong( &end );
++i;
break;
}
if( append_tilde ) if( !isDigit( aBus[i] ) )
str << '~'; return false;
aMemberList.emplace_back( str ); tmp += aBus[i];
}
// Parse suffix
//
for( ; i < busLen; ++i )
{
if( aBus[i] == '}' )
{
braceNesting--;
suffix += aBus[i];
}
else if( aBus[i] == '~' )
{
suffix += aBus[i];
}
else
{
return false;
}
}
if( braceNesting != 0 )
return false;
if( aName )
*aName = prefix;
if( aMemberList )
{
for( long idx = begin; idx <= end; ++idx )
{
wxString str = prefix;
str << idx;
str << suffix;
aMemberList->emplace_back( str );
}
} }
return true; return true;
@ -518,32 +534,82 @@ bool SCH_CONNECTION::ParseBusVector( wxString aBus, wxString* aName,
bool SCH_CONNECTION::ParseBusGroup( wxString aGroup, wxString* aName, bool SCH_CONNECTION::ParseBusGroup( wxString aGroup, wxString* aName,
std::vector<wxString>& aMemberList ) const std::vector<wxString>* aMemberList )
{ {
auto ss_group = std::string( aGroup.mb_str() ); size_t groupLen = aGroup.length();
std::smatch matches; size_t i = 0;
wxString prefix;
wxString suffix;
wxString tmp;
int braceNesting = 0;
try // Parse prefix
//
for( ; i < groupLen; ++i )
{ {
if( !std::regex_match( ss_group, matches, bus_group_label_re ) ) if( aGroup[i] == '{' )
{ {
return false; if( i > 0 && isSuperSub( aGroup[i-1] ) )
braceNesting++;
else
break;
} }
else if( aGroup[i] == '}' )
{
braceNesting--;
}
if( aGroup[i] == ' ' || aGroup[i] == '[' || aGroup[i] == ']' )
return false;
prefix += aGroup[i];
} }
catch( ... )
{ if( braceNesting != 0 )
return false; return false;
}
*aName = wxString( matches[1] ); if( aName )
*aName = prefix;
wxStringTokenizer tokenizer( wxString( matches[2] ), " " ); // Parse members
while( tokenizer.HasMoreTokens() ) //
i++; // '{' character
for( ; i < groupLen; ++i )
{ {
aMemberList.push_back( tokenizer.GetNextToken() ); if( aGroup[i] == '{' )
{
if( i > 0 && isSuperSub( aGroup[i-1] ) )
braceNesting++;
else
return false;
}
else if( aGroup[i] == '}' )
{
if( braceNesting )
braceNesting--;
else
{
if( aMemberList )
aMemberList->push_back( tmp );
return true;
}
}
if( aGroup[i] == ' ' )
{
if( aMemberList )
aMemberList->push_back( tmp );
tmp.Clear();
continue;
}
tmp += aGroup[i];
} }
return true; return false;
} }

View File

@ -79,7 +79,7 @@ public:
* For CONNECTION_BUS, this will deduce the correct BUS_TYPE and also * For CONNECTION_BUS, this will deduce the correct BUS_TYPE and also
* generate a correct list of members. * generate a correct list of members.
*/ */
void ConfigureFromLabel( wxString aLabel ); void ConfigureFromLabel( const wxString& aLabel );
/** /**
* Clears connectivity information * Clears connectivity information
@ -271,8 +271,8 @@ public:
* @param aMemberList is a list of member strings, e.g. "A7", "A6", and so on * @param aMemberList is a list of member strings, e.g. "A7", "A6", and so on
* @return true if aBus was successfully parsed * @return true if aBus was successfully parsed
*/ */
bool ParseBusVector( wxString aBus, wxString* aName, static bool ParseBusVector( const wxString& aBus, wxString* aName,
std::vector<wxString>& aMemberList ) const; std::vector<wxString>* aMemberList );
/** /**
* Parses a bus group label into the name and a list of components * Parses a bus group label into the name and a list of components
@ -282,8 +282,8 @@ public:
* @param aMemberList is a list of member strings, e.g. "DP", "DM" * @param aMemberList is a list of member strings, e.g. "DP", "DM"
* @return true if aGroup was successfully parsed * @return true if aGroup was successfully parsed
*/ */
bool ParseBusGroup( wxString aGroup, wxString* name, static bool ParseBusGroup( wxString aGroup, wxString* name,
std::vector<wxString>& aMemberList ) const; std::vector<wxString>* aMemberList );
/** /**
* Adds information about the connection object to aList * Adds information about the connection object to aList
@ -312,22 +312,6 @@ public:
*/ */
static bool MightBeBusLabel( const wxString& aLabel ); static bool MightBeBusLabel( const wxString& aLabel );
/**
* Test if \a aLabel has a bus vector notation (simple bus, e.g. A[7..0])
*
* @param aLabel A wxString object containing the label to test.
* @return true if text is a bus notation format otherwise false is returned.
*/
static bool IsBusVectorLabel( const wxString& aLabel );
/**
* Test if \a aLabel has a bus group notation.
*
* @param aLabel A wxString object containing the label to test.
* @return true if text is a bus group notation format
*/
static bool IsBusGroupLabel( const wxString& aLabel );
private: private:
void recacheName(); void recacheName();

View File

@ -2606,7 +2606,7 @@ wxString SCH_EAGLE_PLUGIN::fixSymbolName( const wxString& aName )
wxString SCH_EAGLE_PLUGIN::translateEagleBusName( const wxString& aEagleName ) const wxString SCH_EAGLE_PLUGIN::translateEagleBusName( const wxString& aEagleName ) const
{ {
if( SCH_CONNECTION::IsBusVectorLabel( aEagleName ) ) if( SCH_CONNECTION::ParseBusVector( aEagleName, nullptr, nullptr ) )
return aEagleName; return aEagleName;
wxString ret = "{"; wxString ret = "{";

View File

@ -955,8 +955,8 @@ void SCH_SHEET::GetNetListItem( NETLIST_OBJECT_LIST& aNetListItems, SCH_SHEET_PA
item->m_SheetPathInclude = sheetPath; item->m_SheetPathInclude = sheetPath;
item->m_SheetPath = *aSheetPath; item->m_SheetPath = *aSheetPath;
item->m_Comp = sheetPin; item->m_Comp = sheetPin;
item->m_Link = this; item->m_Link = this;
item->m_Type = NETLIST_ITEM::SHEETLABEL; item->m_Type = NETLIST_ITEM::SHEETLABEL;
item->m_Label = sheetPin->GetText(); item->m_Label = sheetPin->GetText();
item->m_Start = item->m_End = sheetPin->GetPosition(); item->m_Start = item->m_End = sheetPin->GetPosition();
aNetListItems.push_back( item ); aNetListItems.push_back( item );

View File

@ -1243,13 +1243,13 @@ void SCH_TEXT::ShowSyntaxHelp( wxWindow* aParentWindow )
"<table>" "<table>"
" <tr>" " <tr>"
" <th>Markup</th>" " <th>Markup</th>"
" <th>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</th>" " <th></th>"
" <th>Result</th>" " <th>Result</th>"
" </tr>" " </tr>"
" <tr>" " <tr>"
" <td>&nbsp;<br>^{superscript}</td>" " <td>&nbsp;<br>^{superscript}</td>"
" <td></td>" " <td></td>"
" <td>&nbsp;<br><sup>superscript</sup></td>" " <td>&nbsp;<br><sup>superscript</sup>&nbsp;</td>"
" </tr>" " </tr>"
" <tr>" " <tr>"
" <td>&nbsp;<br>Driver Board^{Rev A}</td>" " <td>&nbsp;<br>Driver Board^{Rev A}</td>"
@ -1260,7 +1260,7 @@ void SCH_TEXT::ShowSyntaxHelp( wxWindow* aParentWindow )
" <tr>" " <tr>"
" <td>&nbsp;<br>_{subscript}</td>" " <td>&nbsp;<br>_{subscript}</td>"
" <td></td>" " <td></td>"
" <td>&nbsp;<br><sub>subscript</sub></td>" " <td>&nbsp;<br><sub>subscript</sub>&nbsp;</td>"
" </tr>" " </tr>"
" <tr>" " <tr>"
" <td>&nbsp;<br>D_{0} - D_{15}</td>" " <td>&nbsp;<br>D_{0} - D_{15}</td>"
@ -1294,17 +1294,68 @@ void SCH_TEXT::ShowSyntaxHelp( wxWindow* aParentWindow )
" <tr>" " <tr>"
" <td>&nbsp;<br>${refdes:field}</td>" " <td>&nbsp;<br>${refdes:field}</td>"
" <td></td>" " <td></td>"
" <td>&nbsp;<br><i>field_value</i></td>" " <td>&nbsp;<br><i>field_value</i> of symbol <i>refdes</i></td>"
" </tr>" " </tr>"
" <tr>" " <tr>"
" <td>&nbsp;<br>${R3:VALUE}</td>" " <td>&nbsp;<br>${R3:VALUE}</td>"
" <td></td>" " <td></td>"
" <td>&nbsp;<br>150K</td>" " <td>&nbsp;<br>150K</td>"
" </tr>" " </tr>"
" <tr><td><br></td></tr>"
" <tr><td><br></td></tr>"
" <tr>"
" <th>Bus Definition</th>"
" <th>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</th>"
" <th>Resultant Nets</th>"
" </tr>"
" <tr>"
" <td>&nbsp;<br>prefix[m..n]</td>"
" <td></td>"
" <td>&nbsp;<br>prefixm to prefixn</td>"
" </tr>"
" <tr>"
" <td>&nbsp;<br>D[0..7]</td>"
" <td></td>"
" <td>&nbsp;<br>D0, D1, D2, D3, D4, D5, D6, D7</td>"
" </tr>"
" <tr><td><br></td></tr>"
" <tr>"
" <td>&nbsp;<br>{net1 net2 ...}</td>"
" <td></td>"
" <td>&nbsp;<br>net1, net2, ...</td>"
" </tr>"
" <tr>"
" <td>&nbsp;<br>{SCL SDA}</td>"
" <td></td>"
" <td>&nbsp;<br>SCL, SDA</td>"
" </tr>"
" <tr><td><br></td></tr>"
" <tr>"
" <td>&nbsp;<br>prefix{net1 net2 ...}</td>"
" <td></td>"
" <td>&nbsp;<br>prefix.net1, prefix.net2, ...</td>"
" </tr>"
" <tr>"
" <td>&nbsp;<br>USB1{DP DM}</td>"
" <td></td>"
" <td>&nbsp;<br>USB1.DP, USB1.DM</td>"
" </tr>"
" <tr><td><br></td></tr>"
" <tr>"
" <td>&nbsp;<br>MEM{D_{[1..2]} ~LATCH}</td>"
" <td></td>"
" <td>"
" &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
" &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
" &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
" <u>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</u><br>"
" MEM.D<sub>1</sub>, MEM.D<sub>2</sub>, MEM.LATCH"
" </td>"
" </tr>"
"</table>" ); "</table>" );
HTML_MESSAGE_BOX dlg( aParentWindow, _( "Syntax Help" ) ); HTML_MESSAGE_BOX dlg( aParentWindow, _( "Syntax Help" ) );
dlg.SetDialogSizeInDU( 180, 280 ); dlg.SetDialogSizeInDU( 240, 280 );
dlg.AddHTML_Text( msg ); dlg.AddHTML_Text( msg );
dlg.ShowModal(); dlg.ShowModal();

View File

@ -252,11 +252,11 @@ bool SCH_NETNAME_VALIDATOR::Validate( wxWindow *aParent )
wxString SCH_NETNAME_VALIDATOR::IsValid( const wxString& str ) const wxString SCH_NETNAME_VALIDATOR::IsValid( const wxString& str ) const
{ {
if( SCH_CONNECTION::IsBusGroupLabel( str ) ) if( SCH_CONNECTION::ParseBusGroup( str, nullptr, nullptr ) )
return wxString(); return wxString();
if( ( str.Contains( '[' ) || str.Contains( ']' ) ) && if( ( str.Contains( '[' ) || str.Contains( ']' ) ) &&
!SCH_CONNECTION::IsBusVectorLabel( str ) ) !SCH_CONNECTION::ParseBusVector( str, nullptr, nullptr ) )
return _( "Signal name contains '[' or ']' but is not a valid vector bus name" ); return _( "Signal name contains '[' or ']' but is not a valid vector bus name" );
if( str.Contains( '\r' ) || str.Contains( '\n' ) ) if( str.Contains( '\r' ) || str.Contains( '\n' ) )