35 explicit SCHEMA_PARSER(
const BUS_ALIASES& aAliases )
37 for(
const auto& [
name, members] : aAliases )
38 m_aliases.insert_or_assign(
name.Strip( wxString::both ), std::cref( members ) );
41 std::optional<BUS_SCHEMA>
Parse(
const wxString& aText, std::set<wxString>* aAliasesUsed =
nullptr )
43 const bool parsed = expand( aText, {}, {}, m_schema.root, true );
46 *aAliasesUsed = m_schema.aliasesUsed;
51 return std::move( m_schema );
55 bool expandMember(
const wxString& aText,
const wxString& aPrefix,
const std::vector<wxString>& aPath,
56 std::vector<BUS_SCHEMA::NODE>& aMembers )
59 key.Replace(
"\\ ",
" " );
60 key = key.Strip( wxString::both );
61 m_schema.aliasesUsed.insert( key );
62 const auto alias = m_aliases.find( key );
64 if( alias == m_aliases.end() )
66 aMembers.emplace_back();
67 return expand( aText, aPrefix, aPath, aMembers.back(),
false );
70 if( !m_activeAliases.insert( key ).second )
73 for(
const wxString&
text : alias->second.get() )
75 const wxString member =
text.Strip( wxString::both );
82 m_activeAliases.erase( key );
86 bool expand(
const wxString& aText, wxString aPrefix, std::vector<wxString> aPath,
87 BUS_SCHEMA::NODE& aNode,
bool aRoot )
91 std::vector<wxString> members;
95 aNode.
kind = BUS_SCHEMA::NODE::KIND::VECTOR;
101 m_schema.shape = BUS_SCHEMA::SHAPE::VECTOR;
105 for(
const wxString& member : members )
108 addLeaf( member, aPrefix, aPath, aNode.
members.back() );
114 size_t prefixEnd = 0;
118 aNode.
kind = BUS_SCHEMA::NODE::KIND::GROUP;
124 m_schema.shape = BUS_SCHEMA::SHAPE::GROUP;
126 const wxString sourcePrefix =
text.Left( prefixEnd );
127 const auto matches = [&](
size_t offset )
129 return offset < aText.length() && aText[offset] ==
'{'
135 if( !matches( m_schema.prefixEnd ) )
137 m_schema.prefixEnd = aText.find(
'{' );
139 while( m_schema.prefixEnd != wxString::npos && !matches( m_schema.prefixEnd ) )
140 m_schema.prefixEnd = aText.find(
'{', m_schema.prefixEnd + 1 );
142 if( m_schema.prefixEnd == wxString::npos )
146 else if( !prefix.IsEmpty() )
151 if( !prefix.IsEmpty() )
152 aPrefix += prefix +
".";
154 for(
const wxString& member : members )
156 if( !expandMember( member, aPrefix, aPath, aNode.
members ) )
166 wxString local =
text;
167 local.Replace(
"\\ ",
" " );
168 addLeaf( local, aPrefix, aPath, aNode );
172 void addLeaf(
const wxString& aLocal,
const wxString& aPrefix,
const std::vector<wxString>& aPath,
173 BUS_SCHEMA::NODE& aNode )
175 aNode.
leaf = m_schema.leaves.size();
176 m_schema.leaves.push_back(
180 std::map<wxString, std::reference_wrapper<const std::vector<wxString>>> m_aliases;
181 std::set<wxString> m_activeAliases;
189 return SCHEMA_PARSER( aAliases ).Parse( aText );
196 for(
const auto& [
name, members] : aAliases )
198 std::vector<wxString> values;
199 values.reserve( members.size() );
201 for(
const wxString& member : members )
202 values.push_back( member.Strip( wxString::both ) );
204 normalized.insert_or_assign(
name.Strip( wxString::both ), std::move( values ) );
213 for(
const auto& [
text, entry] :
m_cache.Entries() )
215 for(
const wxString&
name : entry->value.aliasesUsed )
218 const auto after = normalized.find(
name );
220 if( ( before ==
m_aliases.end() ) != ( after == normalized.end() )
221 || ( before !=
m_aliases.end() && after != normalized.end() && before->second != after->second ) )
223 dirty.insert(
text );
238 if( cached && !
m_dirty.contains( aText ) )
245 result.tree = std::make_shared<const BUS_SCHEMA::NODE>( std::exchange( schema->root, {} ) );
247 if( cached && cached->
value.schema && *cached->
value.schema == *schema )
250 result.schema = std::make_shared<const BUS_SCHEMA>( std::move( *schema ) );
260 for(
auto it =
m_cache.Entries().begin(); it !=
m_cache.Entries().end(); )
262 const auto current = it++;
264 if( !aLive.contains( current->first ) )
266 m_dirty.erase( current->first );
267 m_cache.Erase( current->first );
272std::shared_ptr<const SCH_CONNECTIVITY::BUS_SCHEMA::NODE>
275 if(
m_dirty.contains( aText ) )
279 return entry ? entry->
value.tree :
nullptr;
286 using KEY = std::pair<std::vector<wxString>, wxString>;
287 std::map<KEY, std::vector<size_t>> candidates;
294 candidates[{ leaf.groupPath, leaf.localName }].push_back(
right );
305 const auto found = candidates.find( { leaf.groupPath, leaf.localName } );
308 if( found != candidates.end() && !found->second.empty() )
310 right = found->second.back();
311 found->second.pop_back();
static bool ParseBusGroup(const wxString &aGroup, wxString *name, std::vector< wxString > *aMemberList, size_t *aPrefixEnd=nullptr)
Parse a bus group label into the name and a list of components.
static bool ParseBusVector(const wxString &aBus, wxString *aName, std::vector< wxString > *aMemberList)
Parse a bus vector (e.g.
CACHE_TABLE< wxString, RESULT >::ENTRY ENTRY
CACHE_TABLE< wxString, RESULT > m_cache
std::set< wxString > m_dirty
void Retain(const std::set< wxString > &aLive)
Erase the entries whose text is not in aLive.
bool SetAliases(const BUS_ALIASES &aAliases)
Replace the alias table.
std::shared_ptr< const BUS_SCHEMA::NODE > FindTree(const wxString &aText) const
Current tree without cache writes.
const ENTRY & Parse(const wxString &aText)
Return the cached entry, and parse again if the entry is missing or dirty.
Value keys and the key session of the schematic connectivity engine.
std::map< wxString, std::vector< wxString > > BUS_ALIASES
Bus alias table, from alias name to member texts.
BUS_ALIGNMENT Align(const BUS_SCHEMA &aLeft, const BUS_SCHEMA &aRight)
Match the leaves of aLeft to the leaves of aRight.
PARSE_RESULT Parse(const std::string &aString, NOTATION aNotation=NOTATION::SI, SIM_VALUE::TYPE aValueType=SIM_VALUE::TYPE_FLOAT)
wxString UnescapeString(const wxString &aSource)
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
Member correspondence between two bus schemas.
wxString text
Container label text.
std::optional< size_t > leaf
Leaf ordinal of a NET node.
std::vector< NODE > members
The parsed form of one bus text.
std::vector< LEAF > leaves
Member nets in declaration order, with nested buses flattened.
@ GROUP
A list such as I2C{SDA SCL}. Members align by name with another group.
static std::optional< BUS_SCHEMA > Parse(const wxString &aText, const BUS_ALIASES &aAliases={})
Parse a vector or group bus text.
wxString result
Test unit parsing edge cases and error handling.