CADSTAR Parts: Add parsing of hierarchy tree

This commit is contained in:
Roberto Fernandez Bautista 2023-03-12 16:12:03 +01:00
parent b70fe88145
commit 59d88e1871
4 changed files with 124 additions and 7 deletions

View File

@ -68,6 +68,12 @@ struct spaced_ch : seq<star<WHITESPACE>, one<CHAR_TO_FIND...>>{};
*/
struct QUOTED_STRING : seq<one<'"'>, STRING_EXCLUDING<one<'"'>>, one<'"'>> {};
/**
* String inside single quotation marks
*/
struct SINGLE_QUOTED_STRING : seq<one<'\''>, STRING_EXCLUDING<one<'\''>>, one<'\''>> {};
/**
* String inside brackets with preceding spaces
*/
@ -104,6 +110,33 @@ struct FORMAT : seq
{};
// Newer Parts files have possibility of specifying a tree-like structure to show hierarchy
//
// Example:
//+N0 'root' &
//'part1' 'part2'
//+N1 N0 'subnode1' 'part3' 'part4'
struct HIERARCHY_NODE_INDEX : plus<digit>{};
struct HIERARCHY_CURRENT_NODE : seq<one<'N'>, HIERARCHY_NODE_INDEX>{};
struct HIERARCHY_PARENT_NODE : seq<one<'N'>, HIERARCHY_NODE_INDEX>{}; // Different action
struct HIERARCHY_NODE_NAME : SINGLE_QUOTED_STRING {};
struct HIERARCHY_PART_NAME : SINGLE_QUOTED_STRING {};
struct HIERARCHY_NODE_ENTRY :
seq
<
bol,
one<'+'>,
HIERARCHY_CURRENT_NODE, // N1
plus<WHITESPACE_OR_CONTINUATION>,
opt<HIERARCHY_PARENT_NODE>, // N0
star<WHITESPACE_OR_CONTINUATION>,
HIERARCHY_NODE_NAME, // 'subnode1'
star<WHITESPACE_OR_CONTINUATION>,
plus<HIERARCHY_PART_NAME, star<WHITESPACE_OR_CONTINUATION>>, // 'part1' 'part2'
opt<eol>
>
{};
// **************
// * PART ENTRY *
// **************
@ -542,8 +575,9 @@ struct PART_ENTRY :
* Grammar for CADSTAR Parts Library file format (*.lib)
*/
struct GRAMMAR :
must<seq<
must<
opt<FORMAT>,
star<star<EMPTY_LINE>, HIERARCHY_NODE_ENTRY>,
plus
<
sor
@ -555,8 +589,8 @@ struct GRAMMAR :
>,
opt<TAO_PEGTL_ISTRING( ".END"), opt<eol>>,
star<EMPTY_LINE>,
must<eolf>
>>
tao::pegtl::eof // just putting "eof" results in ambiguous symbol
>
{};

View File

@ -32,6 +32,7 @@ struct CADSTAR_SWAP_GROUP;
struct CADSTAR_ATTRIBUTE_VALUE;
struct CADSTAR_PART_SYMBOL_ENTRY;
struct CADSTAR_PART_PIN;
struct CADSTAR_PART_NODE;
/**
* CADSTAR Parts Library (*.lib) model - a data structure describing the contents of the
@ -39,8 +40,9 @@ struct CADSTAR_PART_PIN;
*/
struct CADSTAR_PARTS_LIB_MODEL
{
std::optional<long> m_FormatNumber;
std::vector<CADSTAR_PART_ENTRY> m_PartEntries;
std::optional<long> m_FormatNumber;
std::map<long, CADSTAR_PART_NODE> m_HierarchyNodes;
std::vector<CADSTAR_PART_ENTRY> m_PartEntries;
};
@ -230,4 +232,12 @@ struct CADSTAR_SWAP_GROUP
std::vector<std::vector<long>> m_Gates;
};
struct CADSTAR_PART_NODE
{
std::optional<long> m_ParentNodeIdx;
std::string m_Name;
std::vector<std::string> m_PartNames; ///< Part names belonging to this hierarchy
};
#endif //CADSTAR_PARTS_LIB_MODEL_H

View File

@ -39,6 +39,8 @@ struct CADSTAR_LIB_PARSER_STATE
std::string m_CurrentAttrName;
std::string m_CurrentSignalName;
long m_CurrentLong = 0;
CADSTAR_PART_NODE m_CurrentNode;
long m_CurrentNodeIdx = 0;
std::vector<long> m_CurrentPinEquivalenceGroup;
std::set<std::string> m_CurrentElementsParsed;
bool m_ReadOnly = false;
@ -89,6 +91,7 @@ DEFINE_CONTENT_TO_NUMBER_ACTION( PINNUM, m_CurrentLong );
DEFINE_CONTENT_TO_NUMBER_ACTION( MAX_PIN_COUNT, m_CurrentPart.m_MaxPinCount );
DEFINE_CONTENT_TO_NUMBER_ACTION( PIN_IDENTIFIER, m_CurrentPin.m_Identifier );
DEFINE_CONTENT_TO_NUMBER_ACTION( PIN_LOADING, m_CurrentPin.m_Loading );
DEFINE_CONTENT_TO_NUMBER_ACTION( HIERARCHY_NODE_INDEX, m_CurrentLong );
// unfortunately the one below needs to be defined separately
@ -176,6 +179,69 @@ struct CADSTAR_LIB_PARSER_ACTION<STR_SEGMENT_EXCLUDING<EXCLUSION_RULES...>>
}
};
//
// HIERARCHY actions
//
template <>
struct CADSTAR_LIB_PARSER_ACTION<HIERARCHY_NODE_ENTRY>
{
static void apply0( CADSTAR_LIB_PARSER_STATE& s )
{
assert( s.m_CurrentString == "" && s.m_CurrentAttrName == "" );
s.m_ParsedModel.m_HierarchyNodes.insert(
{ s.m_CurrentNodeIdx, std::move( s.m_CurrentNode ) } );
s.m_CurrentNode = CADSTAR_PART_NODE();
}
};
template <>
struct CADSTAR_LIB_PARSER_ACTION<HIERARCHY_CURRENT_NODE>
{
static void apply0( CADSTAR_LIB_PARSER_STATE& s )
{
assert( s.m_CurrentString == "" && s.m_CurrentAttrName == "" );
s.m_CurrentNodeIdx = s.m_CurrentLong;
}
};
template <>
struct CADSTAR_LIB_PARSER_ACTION<HIERARCHY_PARENT_NODE>
{
static void apply0( CADSTAR_LIB_PARSER_STATE& s )
{
assert( s.m_CurrentString == "" && s.m_CurrentAttrName == "" );
s.m_CurrentNode.m_ParentNodeIdx = s.m_CurrentLong;
}
};
template <>
struct CADSTAR_LIB_PARSER_ACTION<HIERARCHY_NODE_NAME>
{
static void apply0( CADSTAR_LIB_PARSER_STATE& s )
{
assert( s.m_CurrentAttrName == "" );
s.m_CurrentNode.m_Name = std::move( s.m_CurrentString );
s.m_CurrentString = "";
}
};
template <>
struct CADSTAR_LIB_PARSER_ACTION<HIERARCHY_PART_NAME>
{
static void apply0( CADSTAR_LIB_PARSER_STATE& s )
{
assert( s.m_CurrentAttrName == "" );
s.m_CurrentNode.m_PartNames.push_back( std::move( s.m_CurrentString ) );
s.m_CurrentString = "";
}
};
// PART_ENTRY action
// We just push the part to the vector of parts in our state
template <>

View File

@ -193,9 +193,14 @@ BOOST_AUTO_TEST_CASE( ReadContent )
"# Format 32\r\n"
"\r\n"
"\r\n"
" \r\n"
"\r\n"
"+N0 'root' &\r\n"
"'part1' &\r\n"
"'part2'\r\n"
"+N1 N0 'subnode1' &\r\n"
"'part3' &\r\n"
"'part4'\r\n"
"\r\n"
" \r\n"
"\r\n"
".<Part name> (<Part number>):<Part version>;<Description>\r\n"
"<PCB Component Refname> (<PCB Alternate Refname>)\r\n"
@ -242,6 +247,8 @@ BOOST_AUTO_TEST_CASE( ReadContent )
std::optional<std::string> nullOptString;
BOOST_CHECK_EQUAL( result.m_FormatNumber, 32 );
BOOST_REQUIRE_EQUAL( result.m_HierarchyNodes.size(), 2 ); // root and subnode
BOOST_REQUIRE_EQUAL( result.m_PartEntries.size(), 1 );
BOOST_CHECK_EQUAL( result.m_PartEntries[0].m_Name, "<Part name>" );