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:
parent
cc1ebca242
commit
cbe4b79107
|
@ -16,7 +16,7 @@ DIALOG_LABEL_EDITOR_BASE::DIALOG_LABEL_EDITOR_BASE( wxWindow* parent, wxWindowID
|
|||
wxBoxSizer* bMainSizer;
|
||||
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->AddGrowableRow( 1 );
|
||||
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->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->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->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->SetSelBackground( true, wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
|
||||
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->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->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->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;
|
||||
bSizeCtrlSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
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->Wrap( -1 );
|
||||
|
@ -96,18 +96,18 @@ DIALOG_LABEL_EDITOR_BASE::DIALOG_LABEL_EDITOR_BASE( wxWindow* parent, wxWindowID
|
|||
bSizeCtrlSizer->Add( 0, 0, 1, wxEXPAND, 15 );
|
||||
|
||||
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->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->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 );
|
||||
|
|
|
@ -73,10 +73,10 @@
|
|||
<property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="rows">5</property>
|
||||
<property name="vgap">3</property>
|
||||
<property name="vgap">1</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">3</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT</property>
|
||||
<property name="border">2</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxBOTTOM</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticText" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
|
@ -136,8 +136,8 @@
|
|||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND|wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT</property>
|
||||
<property name="border">2</property>
|
||||
<property name="flag">wxEXPAND|wxALIGN_CENTER_VERTICAL|wxBOTTOM</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxTextCtrl" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
|
@ -262,8 +262,8 @@
|
|||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND|wxRIGHT|wxLEFT</property>
|
||||
<property name="border">2</property>
|
||||
<property name="flag">wxEXPAND|wxBOTTOM</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxStyledTextCtrl" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
|
@ -390,7 +390,7 @@
|
|||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<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>
|
||||
<object class="wxComboBox" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
|
@ -456,7 +456,7 @@
|
|||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<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>
|
||||
<object class="wxStaticText" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
|
@ -516,8 +516,8 @@
|
|||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">3</property>
|
||||
<property name="flag">wxEXPAND|wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT</property>
|
||||
<property name="border">6</property>
|
||||
<property name="flag">wxEXPAND|wxALIGN_CENTER_VERTICAL|wxBOTTOM</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
|
@ -526,7 +526,7 @@
|
|||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<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>
|
||||
<object class="wxTextCtrl" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
|
@ -660,7 +660,7 @@
|
|||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">8</property>
|
||||
<property name="border">7</property>
|
||||
<property name="flag">wxBOTTOM|wxRIGHT|wxLEFT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxHyperlinkCtrl" expanded="1">
|
||||
|
@ -726,7 +726,7 @@
|
|||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="border">2</property>
|
||||
<property name="flag">wxTOP|wxRIGHT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticText" expanded="1">
|
||||
|
@ -787,8 +787,8 @@
|
|||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL</property>
|
||||
<property name="border">2</property>
|
||||
<property name="flag">wxEXPAND|wxALIGN_CENTER_VERTICAL|wxTOP|wxRIGHT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticText" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
|
|
|
@ -243,39 +243,32 @@ void NETLIST_OBJECT::ConvertBusToNetListItems( NETLIST_OBJECT_LIST& aNetListItem
|
|||
long member_offset = 0;
|
||||
|
||||
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}"
|
||||
auto group_prefix = ( group_name != "" ) ? ( group_name + "." ) : "";
|
||||
wxString group_prefix = ( group_name != "" ) ? ( group_name + "." ) : "";
|
||||
|
||||
std::list<wxString> bus_contents( bus_contents_vec.begin(),
|
||||
bus_contents_vec.end() );
|
||||
std::list<wxString> bus_contents( bus_contents_vec.begin(), bus_contents_vec.end() );
|
||||
|
||||
for( const auto& bus_member : bus_contents )
|
||||
{
|
||||
wxString prefix;
|
||||
std::vector<wxString> members;
|
||||
|
||||
// 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;
|
||||
|
||||
conn.ParseBusVector( bus_member, &prefix, members );
|
||||
prefix = group_prefix + prefix;
|
||||
begin = conn.VectorStart();
|
||||
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
|
||||
wxString prefix;
|
||||
std::vector<wxString> members;
|
||||
long begin, end;
|
||||
long begin = conn.VectorStart();
|
||||
long end = conn.VectorEnd();
|
||||
|
||||
conn.ParseBusVector( m_Label, &prefix, members );
|
||||
begin = conn.VectorStart();
|
||||
end = conn.VectorEnd();
|
||||
|
||||
m_Label = members[0];
|
||||
m_Label = bus_contents_vec[0];
|
||||
m_Member = begin;
|
||||
|
||||
fillBusVector( aNetListItems, prefix, begin + 1, end, 0 );
|
||||
fillBusVector( aNetListItems, group_name, begin + 1, end, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -57,10 +57,6 @@
|
|||
* 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 ) :
|
||||
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_name = aLabel;
|
||||
m_local_name = aLabel;
|
||||
|
||||
wxString prefix;
|
||||
std::vector<wxString> members;
|
||||
|
||||
wxString unescaped = UnescapeString( aLabel );
|
||||
|
||||
if( IsBusVectorLabel( unescaped ) )
|
||||
if( ParseBusVector( unescaped, &prefix, &members ) )
|
||||
{
|
||||
m_type = CONNECTION_TYPE::BUS;
|
||||
m_vector_prefix = prefix;
|
||||
|
||||
std::vector<wxString> members;
|
||||
|
||||
ParseBusVector( unescaped, &m_vector_prefix, members );
|
||||
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 );
|
||||
member->m_type = CONNECTION_TYPE::NET;
|
||||
|
@ -142,39 +139,34 @@ void SCH_CONNECTION::ConfigureFromLabel( wxString aLabel )
|
|||
m_members.push_back( member );
|
||||
}
|
||||
}
|
||||
else if( IsBusGroupLabel( unescaped ) )
|
||||
else if( ParseBusGroup( unescaped, &prefix, &members ) )
|
||||
{
|
||||
m_type = CONNECTION_TYPE::BUS_GROUP;
|
||||
|
||||
std::vector<wxString> members;
|
||||
wxString group_name;
|
||||
// Named bus groups generate a net prefix, unnamed ones don't
|
||||
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
|
||||
wxString prefix = group_name != wxT( "" ) ? ( group_name + wxT( "." ) ) : wxT( "" );
|
||||
|
||||
for( const auto& group_member : members )
|
||||
// Handle alias inside bus group member list
|
||||
if( auto alias = g_ConnectionGraph->GetBusAlias( group_member ) )
|
||||
{
|
||||
// Handle alias inside bus group member list
|
||||
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
|
||||
for( const wxString& alias_member : alias->Members() )
|
||||
{
|
||||
auto member = std::make_shared< SCH_CONNECTION >( m_parent, m_sheet );
|
||||
member->SetPrefix( prefix );
|
||||
member->ConfigureFromLabel( group_member );
|
||||
member->ConfigureFromLabel( alias_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
|
||||
|
@ -351,7 +343,7 @@ void SCH_CONNECTION::AppendInfoToMsgPanel( MSG_PANEL_ITEMS& aList ) const
|
|||
|
||||
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 )
|
||||
{
|
||||
|
@ -400,7 +392,7 @@ void SCH_CONNECTION::AppendDebugInfoToMsgPanel( MSG_PANEL_ITEMS& aList ) const
|
|||
|
||||
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 false;
|
||||
|
||||
try
|
||||
{
|
||||
return std::regex_match( std::string( aLabel.mb_str() ), bus_label_re );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return c == '_' || c == '^';
|
||||
};
|
||||
|
||||
|
||||
bool SCH_CONNECTION::IsBusGroupLabel( const wxString& aLabel )
|
||||
bool SCH_CONNECTION::ParseBusVector( const wxString& aBus, wxString* aName,
|
||||
std::vector<wxString>* aMemberList )
|
||||
{
|
||||
if( !aLabel.Contains( wxT( "{" ) ) )
|
||||
return false;
|
||||
auto isDigit = []( wxChar c )
|
||||
{
|
||||
static wxString digits( wxT( "0123456789" ) );
|
||||
return digits.Contains( c );
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
return std::regex_match( std::string( aLabel.mb_str() ), bus_group_label_re );
|
||||
}
|
||||
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();
|
||||
size_t busLen = aBus.length();
|
||||
size_t i = 0;
|
||||
wxString prefix;
|
||||
wxString suffix;
|
||||
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] );
|
||||
i++;
|
||||
if( aBus[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] == '.' )
|
||||
i++;
|
||||
|
||||
tmp.Empty();
|
||||
|
||||
while( i < len && numberString[i] != ']' )
|
||||
for( ; i < busLen; ++i )
|
||||
{
|
||||
tmp.Append( numberString[i] );
|
||||
i++;
|
||||
if( aBus[i] == '.' && i + 1 < busLen && aBus[i+1] == '.' )
|
||||
{
|
||||
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 )
|
||||
begin = 0;
|
||||
|
||||
if( end < 0 )
|
||||
end = 0;
|
||||
|
||||
if( begin > end )
|
||||
std::swap( begin, end );
|
||||
|
||||
for( long idx = begin; idx <= end; ++idx )
|
||||
for( ; i < busLen; ++i )
|
||||
{
|
||||
wxString str = *aName;
|
||||
str << idx;
|
||||
if( aBus[i] == ']' )
|
||||
{
|
||||
tmp.ToLong( &end );
|
||||
++i;
|
||||
break;
|
||||
}
|
||||
|
||||
if( append_tilde )
|
||||
str << '~';
|
||||
if( !isDigit( aBus[i] ) )
|
||||
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;
|
||||
|
@ -518,32 +534,82 @@ bool SCH_CONNECTION::ParseBusVector( wxString aBus, 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() );
|
||||
std::smatch matches;
|
||||
size_t groupLen = aGroup.length();
|
||||
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;
|
||||
}
|
||||
|
||||
*aName = wxString( matches[1] );
|
||||
if( aName )
|
||||
*aName = prefix;
|
||||
|
||||
wxStringTokenizer tokenizer( wxString( matches[2] ), " " );
|
||||
while( tokenizer.HasMoreTokens() )
|
||||
// Parse members
|
||||
//
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ public:
|
|||
* For CONNECTION_BUS, this will deduce the correct BUS_TYPE and also
|
||||
* generate a correct list of members.
|
||||
*/
|
||||
void ConfigureFromLabel( wxString aLabel );
|
||||
void ConfigureFromLabel( const wxString& aLabel );
|
||||
|
||||
/**
|
||||
* Clears connectivity information
|
||||
|
@ -271,8 +271,8 @@ public:
|
|||
* @param aMemberList is a list of member strings, e.g. "A7", "A6", and so on
|
||||
* @return true if aBus was successfully parsed
|
||||
*/
|
||||
bool ParseBusVector( wxString aBus, wxString* aName,
|
||||
std::vector<wxString>& aMemberList ) const;
|
||||
static bool ParseBusVector( const wxString& aBus, wxString* aName,
|
||||
std::vector<wxString>* aMemberList );
|
||||
|
||||
/**
|
||||
* 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"
|
||||
* @return true if aGroup was successfully parsed
|
||||
*/
|
||||
bool ParseBusGroup( wxString aGroup, wxString* name,
|
||||
std::vector<wxString>& aMemberList ) const;
|
||||
static bool ParseBusGroup( wxString aGroup, wxString* name,
|
||||
std::vector<wxString>* aMemberList );
|
||||
|
||||
/**
|
||||
* Adds information about the connection object to aList
|
||||
|
@ -312,22 +312,6 @@ public:
|
|||
*/
|
||||
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:
|
||||
void recacheName();
|
||||
|
||||
|
|
|
@ -2606,7 +2606,7 @@ wxString SCH_EAGLE_PLUGIN::fixSymbolName( const wxString& aName )
|
|||
|
||||
wxString SCH_EAGLE_PLUGIN::translateEagleBusName( const wxString& aEagleName ) const
|
||||
{
|
||||
if( SCH_CONNECTION::IsBusVectorLabel( aEagleName ) )
|
||||
if( SCH_CONNECTION::ParseBusVector( aEagleName, nullptr, nullptr ) )
|
||||
return aEagleName;
|
||||
|
||||
wxString ret = "{";
|
||||
|
|
|
@ -955,8 +955,8 @@ void SCH_SHEET::GetNetListItem( NETLIST_OBJECT_LIST& aNetListItems, SCH_SHEET_PA
|
|||
item->m_SheetPathInclude = sheetPath;
|
||||
item->m_SheetPath = *aSheetPath;
|
||||
item->m_Comp = sheetPin;
|
||||
item->m_Link = this;
|
||||
item->m_Type = NETLIST_ITEM::SHEETLABEL;
|
||||
item->m_Link = this;
|
||||
item->m_Type = NETLIST_ITEM::SHEETLABEL;
|
||||
item->m_Label = sheetPin->GetText();
|
||||
item->m_Start = item->m_End = sheetPin->GetPosition();
|
||||
aNetListItems.push_back( item );
|
||||
|
|
|
@ -1243,13 +1243,13 @@ void SCH_TEXT::ShowSyntaxHelp( wxWindow* aParentWindow )
|
|||
"<table>"
|
||||
" <tr>"
|
||||
" <th>Markup</th>"
|
||||
" <th> </th>"
|
||||
" <th></th>"
|
||||
" <th>Result</th>"
|
||||
" </tr>"
|
||||
" <tr>"
|
||||
" <td> <br>^{superscript}</td>"
|
||||
" <td></td>"
|
||||
" <td> <br><sup>superscript</sup></td>"
|
||||
" <td> <br><sup>superscript</sup> </td>"
|
||||
" </tr>"
|
||||
" <tr>"
|
||||
" <td> <br>Driver Board^{Rev A}</td>"
|
||||
|
@ -1260,7 +1260,7 @@ void SCH_TEXT::ShowSyntaxHelp( wxWindow* aParentWindow )
|
|||
" <tr>"
|
||||
" <td> <br>_{subscript}</td>"
|
||||
" <td></td>"
|
||||
" <td> <br><sub>subscript</sub></td>"
|
||||
" <td> <br><sub>subscript</sub> </td>"
|
||||
" </tr>"
|
||||
" <tr>"
|
||||
" <td> <br>D_{0} - D_{15}</td>"
|
||||
|
@ -1294,17 +1294,68 @@ void SCH_TEXT::ShowSyntaxHelp( wxWindow* aParentWindow )
|
|||
" <tr>"
|
||||
" <td> <br>${refdes:field}</td>"
|
||||
" <td></td>"
|
||||
" <td> <br><i>field_value</i></td>"
|
||||
" <td> <br><i>field_value</i> of symbol <i>refdes</i></td>"
|
||||
" </tr>"
|
||||
" <tr>"
|
||||
" <td> <br>${R3:VALUE}</td>"
|
||||
" <td></td>"
|
||||
" <td> <br>150K</td>"
|
||||
" </tr>"
|
||||
" <tr><td><br></td></tr>"
|
||||
" <tr><td><br></td></tr>"
|
||||
" <tr>"
|
||||
" <th>Bus Definition</th>"
|
||||
" <th> </th>"
|
||||
" <th>Resultant Nets</th>"
|
||||
" </tr>"
|
||||
" <tr>"
|
||||
" <td> <br>prefix[m..n]</td>"
|
||||
" <td></td>"
|
||||
" <td> <br>prefixm to prefixn</td>"
|
||||
" </tr>"
|
||||
" <tr>"
|
||||
" <td> <br>D[0..7]</td>"
|
||||
" <td></td>"
|
||||
" <td> <br>D0, D1, D2, D3, D4, D5, D6, D7</td>"
|
||||
" </tr>"
|
||||
" <tr><td><br></td></tr>"
|
||||
" <tr>"
|
||||
" <td> <br>{net1 net2 ...}</td>"
|
||||
" <td></td>"
|
||||
" <td> <br>net1, net2, ...</td>"
|
||||
" </tr>"
|
||||
" <tr>"
|
||||
" <td> <br>{SCL SDA}</td>"
|
||||
" <td></td>"
|
||||
" <td> <br>SCL, SDA</td>"
|
||||
" </tr>"
|
||||
" <tr><td><br></td></tr>"
|
||||
" <tr>"
|
||||
" <td> <br>prefix{net1 net2 ...}</td>"
|
||||
" <td></td>"
|
||||
" <td> <br>prefix.net1, prefix.net2, ...</td>"
|
||||
" </tr>"
|
||||
" <tr>"
|
||||
" <td> <br>USB1{DP DM}</td>"
|
||||
" <td></td>"
|
||||
" <td> <br>USB1.DP, USB1.DM</td>"
|
||||
" </tr>"
|
||||
" <tr><td><br></td></tr>"
|
||||
" <tr>"
|
||||
" <td> <br>MEM{D_{[1..2]} ~LATCH}</td>"
|
||||
" <td></td>"
|
||||
" <td>"
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" <u> </u><br>"
|
||||
" MEM.D<sub>1</sub>, MEM.D<sub>2</sub>, MEM.LATCH"
|
||||
" </td>"
|
||||
" </tr>"
|
||||
"</table>" );
|
||||
|
||||
HTML_MESSAGE_BOX dlg( aParentWindow, _( "Syntax Help" ) );
|
||||
dlg.SetDialogSizeInDU( 180, 280 );
|
||||
dlg.SetDialogSizeInDU( 240, 280 );
|
||||
|
||||
dlg.AddHTML_Text( msg );
|
||||
dlg.ShowModal();
|
||||
|
|
|
@ -252,11 +252,11 @@ bool SCH_NETNAME_VALIDATOR::Validate( wxWindow *aParent )
|
|||
|
||||
wxString SCH_NETNAME_VALIDATOR::IsValid( const wxString& str ) const
|
||||
{
|
||||
if( SCH_CONNECTION::IsBusGroupLabel( str ) )
|
||||
if( SCH_CONNECTION::ParseBusGroup( str, nullptr, nullptr ) )
|
||||
return wxString();
|
||||
|
||||
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" );
|
||||
|
||||
if( str.Contains( '\r' ) || str.Contains( '\n' ) )
|
||||
|
|
Loading…
Reference in New Issue