25#include <netlist_lexer.h>
31#include <netlist_reader/netlist_reader.h>
32#include <netlist_reader/kicad_netlist_parser.h>
49 for(
unsigned i = 0; i <
m_netlist->GetCount(); i++ )
57 NETLIST_LEXER( aReader )
69 while( (
token = NextTok() ) != T_EOF )
74 if(
token == T_RIGHT )
89 while( (
token = NextTok() ) != T_EOF )
108 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"Parse: entering components section" ) );
109 while( (
token = NextTok() ) != T_EOF )
111 if(
token == T_RIGHT )
113 else if(
token == T_LEFT )
116 if(
token == T_comp )
123 while( (
token = NextTok() ) != T_EOF )
125 if(
token == T_RIGHT )
127 else if(
token == T_LEFT )
130 if(
token == T_group )
137 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"Parse: entering nets section" ) );
138 while( (
token = NextTok() ) != T_EOF )
140 if(
token == T_RIGHT )
142 else if(
token == T_LEFT )
152 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"Parse: entering libparts section" ) );
153 while( (
token = NextTok() ) != T_EOF )
155 if(
token == T_RIGHT )
157 else if(
token == T_LEFT )
160 if(
token == T_libpart )
192 wxFAIL_MSG( wxString::Format( wxT(
"KICAD_NETLIST_PARSER::Parse(): bad parenthesis "
193 "count (count = %d" ),
212 wxString pin_function;
216 while( (
token = NextTok() ) != T_EOF )
218 if(
token == T_RIGHT )
220 else if(
token == T_LEFT )
226 NeedSYMBOLorNUMBER();
232 NeedSYMBOLorNUMBER();
239 pin_function.Clear();
242 while( (
token = NextTok() ) != T_EOF )
244 if(
token == T_RIGHT )
246 else if(
token == T_LEFT )
252 NeedSYMBOLorNUMBER();
258 NeedSYMBOLorNUMBER();
264 NeedSYMBOLorNUMBER();
270 NeedSYMBOLorNUMBER();
284 if( strtol( code.c_str(),
nullptr, 10 ) >= 1 )
287 name = wxT(
"N-00000") + code;
289 component->AddNet( pin_number,
name, pin_function, pin_type );
325 wxString humanSheetPath;
328 std::vector<KIID> uuids;
329 std::map<wxString, wxString> properties;
330 nlohmann::ordered_map<wxString, wxString> fields;
331 std::unordered_set<wxString> componentClasses;
333 bool duplicatePinsAreJumpers =
false;
334 std::vector<std::set<wxString>> jumperPinGroups;
336 std::vector<COMPONENT::UNIT_INFO> parsedUnits;
339 while( (
token = NextTok() ) != T_RIGHT )
341 if(
token == T_LEFT )
347 NeedSYMBOLorNUMBER();
353 NeedSYMBOLorNUMBER();
359 NeedSYMBOLorNUMBER();
360 footprint = FromUTF8();
366 while( (
token = NextTok() ) != T_RIGHT )
368 if(
token == T_LEFT )
373 NeedSYMBOLorNUMBER();
377 else if(
token == T_part )
379 NeedSYMBOLorNUMBER();
383 else if(
token == T_description )
385 NeedSYMBOLorNUMBER();
390 Expecting(
"part, lib or description" );
393 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"parseComponent: ref='%s' libsource='%s:%s'" ),
402 while( (
token = NextTok() ) != T_RIGHT )
404 if(
token == T_LEFT )
407 if(
token == T_name )
409 NeedSYMBOLorNUMBER();
413 else if(
token == T_value )
415 NeedSYMBOLorNUMBER();
421 Expecting(
"name or value" );
425 if( !propName.IsEmpty() )
426 properties[propName] = std::move( propValue );
431 while( (
token = NextTok() ) != T_RIGHT )
433 if(
token == T_LEFT )
436 if(
token == T_field )
441 while( (
token = NextTok() ) != T_RIGHT )
443 if(
token == T_LEFT )
446 if(
token == T_name )
448 NeedSYMBOLorNUMBER();
452 else if(
token == T_STRING )
458 if( !fieldName.IsEmpty() )
459 fields[fieldName] = std::move( fieldValue );
463 Expecting(
"field" );
469 while( (
token = NextTok() ) != T_EOF )
471 if(
token == T_names )
473 NeedSYMBOLorNUMBER();
478 if(
token == T_tstamps )
480 NeedSYMBOLorNUMBER();
492 while( (
token = NextTok() ) != T_EOF )
494 if(
token == T_RIGHT )
497 uuids.emplace_back(
From_UTF8( CurText() ) );
506 while( (
token = NextTok() ) != T_RIGHT )
508 if(
token == T_LEFT )
511 if(
token == T_unit )
515 while( (
token = NextTok() ) != T_RIGHT )
517 if(
token == T_LEFT )
523 NeedSYMBOLorNUMBER();
529 while( (
token = NextTok() ) != T_RIGHT )
531 if(
token == T_LEFT )
541 if(
token == T_LEFT )
546 NeedSYMBOLorNUMBER();
557 if( !pinNum.IsEmpty() )
558 info.m_pins.emplace_back( pinNum );
573 parsedUnits.push_back(
info );
583 case T_component_classes:
584 while( (
token = NextTok() ) != T_RIGHT )
586 if(
token != T_LEFT )
589 if( (
token = NextTok() ) != T_class )
590 Expecting( T_class );
592 NeedSYMBOLorNUMBER();
593 componentClasses.insert(
From_UTF8( CurText() ) );
599 case T_duplicate_pin_numbers_are_jumpers:
601 NeedSYMBOLorNUMBER();
602 duplicatePinsAreJumpers =
From_UTF8( CurText() ) == wxT(
"1" );
607 case T_jumper_pin_groups:
609 std::set<wxString>* currentGroup =
nullptr;
611 for(
token = NextTok(); currentGroup ||
token != T_RIGHT;
token = NextTok() )
613 if(
token == T_LEFT )
619 currentGroup = &jumperPinGroups.emplace_back();
624 NeedSYMBOLorNUMBER();
625 wxString padName =
From_UTF8( CurText() );
627 wxCHECK2( currentGroup,
continue );
628 currentGroup->insert( padName );
633 currentGroup =
nullptr;
637 Expecting(
"group or pin" );
651 if( !footprint.IsEmpty() && fpid.
Parse( footprint,
true ) >= 0 )
654 error.Printf(
_(
"Invalid footprint ID in\nfile: '%s'\nline: %d\nofff: %d" ),
655 CurSource(), CurLineNumber(), CurOffset() );
668 std::ranges::copy( jumperPinGroups, std::inserter( component->
JumperPadGroups(),
687 std::vector<KIID> members;
690 while( (
token = NextTok() ) != T_EOF )
692 if(
token == T_RIGHT )
694 else if(
token == T_LEFT )
700 NeedSYMBOLorNUMBER();
706 NeedSYMBOLorNUMBER();
712 NeedSYMBOLorNUMBER();
718 while( (
token = NextTok() ) != T_RIGHT )
720 if(
token == T_LEFT )
723 if(
token == T_member )
727 while( (
token = NextTok() ) != T_RIGHT )
729 if(
token == T_LEFT )
732 if(
token == T_uuid )
734 NeedSYMBOLorNUMBER();
744 members.emplace_back( memberUuid );
748 Expecting(
"member" );
762 if( !libId.IsEmpty() && groupLibId.
Parse( libId,
true ) >= 0 )
765 error.Printf(
_(
"Invalid lib_id ID in\nfile: '%s'\nline: %d\nofff: %d" ), CurSource(), CurLineNumber(),
772 std::move( members ) };
801 wxString libPartName;
802 wxArrayString footprintFilters;
803 wxArrayString aliases;
807 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"parseLibPartList: begin libpart" ) );
808 while( (
token = NextTok() ) != T_RIGHT )
810 if(
token == T_LEFT )
816 NeedSYMBOLorNUMBER();
822 NeedSYMBOLorNUMBER();
829 while( (
token = NextTok() ) != T_RIGHT )
831 if(
token == T_LEFT )
840 if(
token == T_RIGHT )
844 Expecting(
"footprint ID" );
846 footprintFilters.Add(
From_UTF8( CurText() ) );
852 while( (
token = NextTok() ) != T_RIGHT )
854 if(
token == T_LEFT )
857 if(
token != T_alias )
858 Expecting( T_alias );
860 NeedSYMBOLorNUMBER();
867 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"parseLibPartList: entering pins for '%s:%s'" ),
868 libName, libPartName );
869 while( (
token = NextTok() ) != T_RIGHT )
871 if(
token == T_LEFT )
878 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"parseLibPartList: pin #%d for '%s:%s'" ),
879 pinCount, libName, libPartName );
883 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"Parsed libpart '%s:%s' pins => pinCount=%d" ),
884 libName, libPartName, pinCount );
895 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"parseLibPartList: assigning pinCount=%d for libpart '%s:%s'" ),
896 pinCount, libName, libPartName );
897 for(
unsigned i = 0; i <
m_netlist->GetCount(); i++ )
899 component =
m_netlist->GetComponent( i );
901 if( component->
IsLibSource( libName, libPartName ) )
905 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"Assign pinCount=%d to component ref='%s' part='%s:%s'" ),
906 pinCount, component->
GetReference(), libName, libPartName );
909 for(
unsigned jj = 0; jj < aliases.GetCount(); jj++ )
911 if( component->
IsLibSource( libName, aliases[jj] ) )
915 wxLogTrace(
"CVPCB_PINCOUNT",
916 wxT(
"Assign pinCount=%d to component ref='%s' via alias='%s:%s'" ),
917 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 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)
The parser for reading the KiCad s-expression netlist format.
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 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...
LINE_READER * m_lineReader
The line reader used to parse the netlist. Not owned.
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.
A logical library item identifier and consists of various portions much like a URI.
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)