27#include <netlist_lexer.h>
50 for(
unsigned i = 0; i <
m_netlist->GetCount(); i++ )
58 NETLIST_LEXER( aReader )
60 m_lineReader = aReader;
70 while( (
token = NextTok() ) != T_EOF )
75 if(
token == T_RIGHT )
90 while( (
token = NextTok() ) != T_EOF )
109 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"Parse: entering components section" ) );
111 while( (
token = NextTok() ) != T_EOF )
113 if(
token == T_RIGHT )
115 else if(
token == T_LEFT )
118 if(
token == T_comp )
125 while( (
token = NextTok() ) != T_EOF )
127 if(
token == T_RIGHT )
129 else if(
token == T_LEFT )
132 if(
token == T_group )
139 while( (
token = NextTok() ) != T_EOF )
141 if(
token == T_RIGHT )
143 else if(
token == T_LEFT )
146 if(
token == T_variant )
153 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"Parse: entering nets section" ) );
155 while( (
token = NextTok() ) != T_EOF )
157 if(
token == T_RIGHT )
159 else if(
token == T_LEFT )
169 while( (
token = NextTok() ) != T_EOF )
171 if(
token == T_RIGHT )
173 else if(
token == T_LEFT )
176 if(
token == T_net_chain )
183 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"Parse: entering libparts section" ) );
185 while( (
token = NextTok() ) != T_EOF )
187 if(
token == T_RIGHT )
189 else if(
token == T_LEFT )
192 if(
token == T_libpart )
224 wxFAIL_MSG( wxString::Format( wxT(
"KICAD_NETLIST_PARSER::Parse(): bad parenthesis "
225 "count (count = %d" ),
244 wxString pin_function;
248 while( (
token = NextTok() ) != T_EOF )
250 if(
token == T_RIGHT )
252 else if(
token == T_LEFT )
258 NeedSYMBOLorNUMBER();
264 NeedSYMBOLorNUMBER();
271 pin_function.Clear();
274 while( (
token = NextTok() ) != T_EOF )
276 if(
token == T_RIGHT )
278 else if(
token == T_LEFT )
284 NeedSYMBOLorNUMBER();
290 NeedSYMBOLorNUMBER();
296 NeedSYMBOLorNUMBER();
302 NeedSYMBOLorNUMBER();
316 if( strtol( code.c_str(),
nullptr, 10 ) >= 1 )
319 name = wxT(
"N-00000") + code;
321 component->AddNet( pin_number,
name, pin_function, pin_type );
357 wxString humanSheetPath;
360 std::vector<KIID> uuids;
361 std::map<wxString, wxString> properties;
362 nlohmann::ordered_map<wxString, wxString> fields;
363 std::unordered_set<wxString> componentClasses;
365 bool duplicatePinsAreJumpers =
false;
366 std::vector<std::set<wxString>> jumperPinGroups;
368 std::vector<COMPONENT::UNIT_INFO> parsedUnits;
369 std::vector<COMPONENT_VARIANT> parsedVariants;
372 while( (
token = NextTok() ) != T_RIGHT )
374 if(
token == T_LEFT )
380 NeedSYMBOLorNUMBER();
386 NeedSYMBOLorNUMBER();
392 NeedSYMBOLorNUMBER();
393 footprint = FromUTF8();
399 while( (
token = NextTok() ) != T_RIGHT )
401 if(
token == T_LEFT )
406 NeedSYMBOLorNUMBER();
410 else if(
token == T_part )
412 NeedSYMBOLorNUMBER();
416 else if(
token == T_description )
418 NeedSYMBOLorNUMBER();
423 Expecting(
"part, lib or description" );
426 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"parseComponent: ref='%s' libsource='%s:%s'" ),
435 while( (
token = NextTok() ) != T_RIGHT )
437 if(
token == T_LEFT )
440 if(
token == T_name )
442 NeedSYMBOLorNUMBER();
446 else if(
token == T_value )
448 NeedSYMBOLorNUMBER();
454 Expecting(
"name or value" );
458 if( !propName.IsEmpty() )
459 properties[propName] = std::move( propValue );
464 while( (
token = NextTok() ) != T_RIGHT )
466 if(
token == T_LEFT )
469 if(
token == T_field )
474 while( (
token = NextTok() ) != T_RIGHT )
476 if(
token == T_LEFT )
479 if(
token == T_name )
481 NeedSYMBOLorNUMBER();
485 else if(
token == T_STRING )
491 if( !fieldName.IsEmpty() )
492 fields[fieldName] = std::move( fieldValue );
496 Expecting(
"field" );
502 while( (
token = NextTok() ) != T_EOF )
504 if(
token == T_names )
506 NeedSYMBOLorNUMBER();
511 if(
token == T_tstamps )
513 NeedSYMBOLorNUMBER();
525 while( (
token = NextTok() ) != T_EOF )
527 if(
token == T_RIGHT )
530 uuids.emplace_back(
From_UTF8( CurText() ) );
539 while( (
token = NextTok() ) != T_RIGHT )
541 if(
token == T_LEFT )
544 if(
token == T_unit )
546 COMPONENT::UNIT_INFO
info;
548 while( (
token = NextTok() ) != T_RIGHT )
550 if(
token == T_LEFT )
556 NeedSYMBOLorNUMBER();
562 while( (
token = NextTok() ) != T_RIGHT )
564 if(
token == T_LEFT )
574 if(
token == T_LEFT )
579 NeedSYMBOLorNUMBER();
590 if( !pinNum.IsEmpty() )
591 info.m_pins.emplace_back( pinNum );
606 parsedUnits.push_back(
info );
617 case T_component_classes:
618 while( (
token = NextTok() ) != T_RIGHT )
620 if(
token != T_LEFT )
623 if( (
token = NextTok() ) != T_class )
624 Expecting( T_class );
626 NeedSYMBOLorNUMBER();
627 componentClasses.insert(
From_UTF8( CurText() ) );
633 case T_duplicate_pin_numbers_are_jumpers:
635 NeedSYMBOLorNUMBER();
636 duplicatePinsAreJumpers =
From_UTF8( CurText() ) == wxT(
"1" );
641 case T_jumper_pin_groups:
643 std::set<wxString>* currentGroup =
nullptr;
645 for(
token = NextTok(); currentGroup ||
token != T_RIGHT;
token = NextTok() )
647 if(
token == T_LEFT )
653 currentGroup = &jumperPinGroups.emplace_back();
658 NeedSYMBOLorNUMBER();
659 wxString padName =
From_UTF8( CurText() );
661 wxCHECK2( currentGroup,
continue );
662 currentGroup->insert( padName );
667 currentGroup =
nullptr;
671 Expecting(
"group or pin" );
680 while( (
token = NextTok() ) != T_RIGHT )
682 if(
token == T_LEFT )
685 if(
token != T_variant )
691 COMPONENT_VARIANT variant;
695 if(
token == T_LEFT )
701 NeedSYMBOLorNUMBER();
710 bool hasValue =
false;
712 while( (
token = NextTok() ) != T_RIGHT )
714 if(
token == T_LEFT )
717 if(
token == T_name )
719 NeedSYMBOLorNUMBER();
723 else if(
token == T_value )
725 NeedSYMBOLorNUMBER();
732 Expecting(
"name or value" );
736 if( propName.IsEmpty() )
739 bool propBool =
true;
743 wxString normalized = propValue;
744 normalized.MakeLower();
746 if( normalized == wxT(
"0" ) || normalized == wxT(
"false" ) )
748 else if( normalized == wxT(
"1" ) || normalized == wxT(
"true" ) )
751 propBool = !propValue.IsEmpty();
754 if( propName.CmpNoCase( wxT(
"dnp" ) ) == 0 )
756 variant.
m_dnp = propBool;
759 else if( propName.CmpNoCase( wxT(
"exclude_from_bom" ) ) == 0 )
764 else if( propName.CmpNoCase( wxT(
"exclude_from_sim" ) ) == 0 )
769 else if( propName.CmpNoCase( wxT(
"exclude_from_pos_files" ) ) == 0 )
779 while( (
token = NextTok() ) != T_RIGHT )
781 if(
token == T_LEFT )
784 if(
token == T_field )
789 while( (
token = NextTok() ) != T_RIGHT )
791 if(
token == T_LEFT )
794 if(
token == T_name )
796 NeedSYMBOLorNUMBER();
800 else if(
token == T_value )
802 NeedSYMBOLorNUMBER();
806 else if(
token == T_STRING )
812 if( !fieldName.IsEmpty() )
813 variant.
m_fields[fieldName] = std::move( fieldValue );
817 Expecting(
"field" );
828 if( !variant.
m_name.IsEmpty() )
829 parsedVariants.push_back( std::move( variant ) );
842 if( !footprint.IsEmpty() && fpid.
Parse( footprint,
true ) >= 0 )
845 error.Printf(
_(
"Invalid footprint ID in\nfile: '%s'\nline: %d\noffset: %d" ),
846 CurSource(), CurLineNumber(), CurOffset() );
859 std::ranges::copy( jumperPinGroups, std::inserter( component->
JumperPadGroups(),
863 for(
const COMPONENT_VARIANT& variant : parsedVariants )
882 std::vector<KIID> members;
885 while( (
token = NextTok() ) != T_EOF )
887 if(
token == T_RIGHT )
889 else if(
token == T_LEFT )
895 NeedSYMBOLorNUMBER();
901 NeedSYMBOLorNUMBER();
907 NeedSYMBOLorNUMBER();
913 while( (
token = NextTok() ) != T_RIGHT )
915 if(
token == T_LEFT )
918 if(
token == T_member )
922 while( (
token = NextTok() ) != T_RIGHT )
924 if(
token == T_LEFT )
927 if(
token == T_uuid )
929 NeedSYMBOLorNUMBER();
939 members.emplace_back( memberUuid );
943 Expecting(
"member" );
957 if( !libId.IsEmpty() && groupLibId.
Parse( libId,
true ) >= 0 )
960 error.Printf(
_(
"Invalid lib_id ID in\nfile: '%s'\nline: %d\noffset: %d" ), CurSource(), CurLineNumber(),
966 NETLIST_GROUP*
group =
new NETLIST_GROUP{ std::move(
name ), std::move( uuid ), std::move( groupLibId ),
967 std::move( members ) };
978 wxString description;
982 if(
token == T_LEFT )
988 NeedSYMBOLorNUMBER();
994 NeedSYMBOLorNUMBER();
1005 if( !
name.IsEmpty() )
1014 wxString chainClass;
1016 std::vector<wxString> members;
1017 std::vector<std::pair<wxString, wxString>> terminals;
1019 while( (
token = NextTok() ) != T_EOF )
1021 if(
token == T_RIGHT )
1023 else if(
token == T_LEFT )
1029 NeedSYMBOLorNUMBER();
1035 NeedSYMBOLorNUMBER();
1040 case T_net_chain_class:
1041 NeedSYMBOLorNUMBER();
1047 NeedSYMBOLorNUMBER();
1053 while( (
token = NextTok() ) != T_RIGHT )
1055 if(
token == T_LEFT )
1058 if(
token == T_member )
1060 while( (
token = NextTok() ) != T_RIGHT )
1062 if(
token == T_LEFT )
1065 if(
token == T_net )
1067 NeedSYMBOLorNUMBER();
1068 members.emplace_back(
From_UTF8( CurText() ) );
1080 case T_terminal_pins:
1081 while( (
token = NextTok() ) != T_RIGHT )
1083 if(
token == T_LEFT )
1086 if(
token == T_terminal_pin )
1091 while( (
token = NextTok() ) != T_RIGHT )
1093 if(
token == T_LEFT )
1096 if(
token == T_ref )
1098 NeedSYMBOLorNUMBER();
1102 else if(
token == T_pin )
1104 NeedSYMBOLorNUMBER();
1112 if( !ref.IsEmpty() && !
pin.IsEmpty() )
1113 terminals.emplace_back( ref,
pin );
1126 for(
const wxString& netName : members )
1129 for(
const auto& term : terminals )
1130 m_netlist->AddSignalTerminalPin(
name, term.first, term.second );
1132 if( !netClass.IsEmpty() )
1135 if( !colorStr.IsEmpty() )
1138 if( !chainClass.IsEmpty() )
1167 wxString libPartName;
1168 wxArrayString footprintFilters;
1169 wxArrayString aliases;
1173 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"parseLibPartList: begin libpart" ) );
1174 while( (
token = NextTok() ) != T_RIGHT )
1176 if(
token == T_LEFT )
1182 NeedSYMBOLorNUMBER();
1188 NeedSYMBOLorNUMBER();
1195 while( (
token = NextTok() ) != T_RIGHT )
1197 if(
token == T_LEFT )
1206 if(
token == T_RIGHT )
1210 Expecting(
"footprint ID" );
1212 footprintFilters.Add(
From_UTF8( CurText() ) );
1218 while( (
token = NextTok() ) != T_RIGHT )
1220 if(
token == T_LEFT )
1223 if(
token != T_alias )
1224 Expecting( T_alias );
1226 NeedSYMBOLorNUMBER();
1233 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"parseLibPartList: entering pins for '%s:%s'" ),
1234 libName, libPartName );
1235 while( (
token = NextTok() ) != T_RIGHT )
1237 if(
token == T_LEFT )
1240 if(
token != T_pin )
1244 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"parseLibPartList: pin #%d for '%s:%s'" ),
1245 pinCount, libName, libPartName );
1249 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"Parsed libpart '%s:%s' pins => pinCount=%d" ),
1250 libName, libPartName, pinCount );
1261 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"parseLibPartList: assigning pinCount=%d for libpart '%s:%s'" ),
1262 pinCount, libName, libPartName );
1263 for(
unsigned i = 0; i <
m_netlist->GetCount(); i++ )
1265 component =
m_netlist->GetComponent( i );
1267 if( component->
IsLibSource( libName, libPartName ) )
1271 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"Assign pinCount=%d to component ref='%s' part='%s:%s'" ),
1272 pinCount, component->
GetReference(), libName, libPartName );
1275 for(
unsigned jj = 0; jj < aliases.GetCount(); jj++ )
1277 if( component->
IsLibSource( libName, aliases[jj] ) )
1281 wxLogTrace(
"CVPCB_PINCOUNT",
1282 wxT(
"Assign pinCount=%d to component ref='%s' via alias='%s:%s'" ),
1283 pinCount, component->
GetReference(), libName, aliases[jj] );
Store all of the related component information found in a netlist.
void SetLibrary(const wxString &aLibrary)
const wxString & GetReference() const
void AddVariant(const COMPONENT_VARIANT &aVariant)
void SetProperties(std::map< wxString, wxString > aProps)
void SetPinCount(int aPinCount)
void SetUnitInfo(const std::vector< UNIT_INFO > &aUnits)
bool IsLibSource(const wxString &aLibrary, const wxString &aName) const
void SetFootprintFilters(const wxArrayString &aFilters)
void SetFields(nlohmann::ordered_map< wxString, wxString > aFields)
void SetHumanReadablePath(const wxString &aPath)
void SetDuplicatePadNumbersAreJumpers(bool aEnabled)
void SetComponentClassNames(const std::unordered_set< wxString > &aClassNames)
std::vector< std::set< wxString > > & JumperPadGroups()
void SetName(const wxString &aName)
KICAD_NETLIST_PARSER(LINE_READER *aReader, NETLIST *aNetlist)
void parseComponent()
Parse a component description: (comp (ref P1) (value DB25FEMELLE) (footprint DB25FC) (libsource (lib ...
void Parse()
Function Parse parse the full netlist.
void parseVariant()
Parse a variant section (variant (name "VariantName") (description "Description"))
void parseNet()
Parse a net section (net (code 20) (name /PC-A0) (node (ref BUS1) (pin 62)) (node (ref U3) (pin 3)) (...
void parseLibPartList()
Read the section "libparts" in the netlist: (libparts (libpart (lib device) (part C) (description "Co...
void parseGroup()
Parse a group section (group (name "GroupName") (member (uuid "..."))))
void skipCurrent()
Skip the current token level, i.e search for the RIGHT parenthesis which closes the current descripti...
NETLIST * m_netlist
The netlist to parse into. Not owned.
virtual void LoadNetlist() override
Load the contents of the netlist file into aNetlist.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
An abstract class from which implementation specific LINE_READERs may be derived to read single lines...
CMP_READER * m_footprintReader
The reader used to load the footprint links. If NULL, footprint links are not read.
LINE_READER * m_lineReader
The line reader of the netlist.
NETLIST * m_netlist
The net list to read the file(s) into.
Store information read from a netlist along with the flags used to update the NETLIST in the BOARD.
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
static bool IsNumber(char x)
wxString From_UTF8(const char *cstring)
bool m_excludedFromPosFiles
bool m_hasExcludedFromBOM
bool m_hasExcludedFromSim
bool m_hasExcludedFromPosFiles
nlohmann::ordered_map< wxString, wxString > m_fields