21#include <netlist_lexer.h>
45 for(
unsigned i = 0; i <
m_netlist->GetCount(); i++ )
53 NETLIST_LEXER( aReader )
65 while( (
token = NextTok() ) != T_EOF )
70 if(
token == T_RIGHT )
85 while( (
token = NextTok() ) != T_EOF )
104 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"Parse: entering components section" ) );
105 while( (
token = NextTok() ) != T_EOF )
107 if(
token == T_RIGHT )
109 else if(
token == T_LEFT )
112 if(
token == T_comp )
119 while( (
token = NextTok() ) != T_EOF )
121 if(
token == T_RIGHT )
123 else if(
token == T_LEFT )
126 if(
token == T_group )
133 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"Parse: entering nets section" ) );
134 while( (
token = NextTok() ) != T_EOF )
136 if(
token == T_RIGHT )
138 else if(
token == T_LEFT )
148 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"Parse: entering libparts section" ) );
149 while( (
token = NextTok() ) != T_EOF )
151 if(
token == T_RIGHT )
153 else if(
token == T_LEFT )
156 if(
token == T_libpart )
188 wxFAIL_MSG( wxString::Format( wxT(
"KICAD_NETLIST_PARSER::Parse(): bad parenthesis "
189 "count (count = %d" ),
208 wxString pin_function;
212 while( (
token = NextTok() ) != T_EOF )
214 if(
token == T_RIGHT )
216 else if(
token == T_LEFT )
222 NeedSYMBOLorNUMBER();
228 NeedSYMBOLorNUMBER();
235 pin_function.Clear();
238 while( (
token = NextTok() ) != T_EOF )
240 if(
token == T_RIGHT )
242 else if(
token == T_LEFT )
248 NeedSYMBOLorNUMBER();
254 NeedSYMBOLorNUMBER();
260 NeedSYMBOLorNUMBER();
266 NeedSYMBOLorNUMBER();
280 if( strtol( code.c_str(),
nullptr, 10 ) >= 1 )
283 name = wxT(
"N-00000") + code;
285 component->AddNet( pin_number,
name, pin_function, pin_type );
321 wxString humanSheetPath;
324 std::vector<KIID> uuids;
325 std::map<wxString, wxString> properties;
326 nlohmann::ordered_map<wxString, wxString> fields;
327 std::unordered_set<wxString> componentClasses;
329 bool duplicatePinsAreJumpers =
false;
330 std::vector<std::set<wxString>> jumperPinGroups;
332 std::vector<COMPONENT::UNIT_INFO> parsedUnits;
335 while( (
token = NextTok() ) != T_RIGHT )
337 if(
token == T_LEFT )
343 NeedSYMBOLorNUMBER();
349 NeedSYMBOLorNUMBER();
355 NeedSYMBOLorNUMBER();
356 footprint = FromUTF8();
362 while( (
token = NextTok() ) != T_RIGHT )
364 if(
token == T_LEFT )
369 NeedSYMBOLorNUMBER();
373 else if(
token == T_part )
375 NeedSYMBOLorNUMBER();
379 else if(
token == T_description )
381 NeedSYMBOLorNUMBER();
386 Expecting(
"part, lib or description" );
389 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"parseComponent: ref='%s' libsource='%s:%s'" ),
398 while( (
token = NextTok() ) != T_RIGHT )
400 if(
token == T_LEFT )
403 if(
token == T_name )
405 NeedSYMBOLorNUMBER();
409 else if(
token == T_value )
411 NeedSYMBOLorNUMBER();
417 Expecting(
"name or value" );
421 if( !propName.IsEmpty() )
422 properties[propName] = std::move( propValue );
427 while( (
token = NextTok() ) != T_RIGHT )
429 if(
token == T_LEFT )
432 if(
token == T_field )
437 while( (
token = NextTok() ) != T_RIGHT )
439 if(
token == T_LEFT )
442 if(
token == T_name )
444 NeedSYMBOLorNUMBER();
448 else if(
token == T_STRING )
454 if( !fieldName.IsEmpty() )
455 fields[fieldName] = std::move( fieldValue );
459 Expecting(
"field" );
465 while( (
token = NextTok() ) != T_EOF )
467 if(
token == T_names )
469 NeedSYMBOLorNUMBER();
474 if(
token == T_tstamps )
476 NeedSYMBOLorNUMBER();
488 while( (
token = NextTok() ) != T_EOF )
490 if(
token == T_RIGHT )
493 uuids.emplace_back(
From_UTF8( CurText() ) );
502 while( (
token = NextTok() ) != T_RIGHT )
504 if(
token == T_LEFT )
507 if(
token == T_unit )
511 while( (
token = NextTok() ) != T_RIGHT )
513 if(
token == T_LEFT )
519 NeedSYMBOLorNUMBER();
525 while( (
token = NextTok() ) != T_RIGHT )
527 if(
token == T_LEFT )
537 if(
token == T_LEFT )
542 NeedSYMBOLorNUMBER();
553 if( !pinNum.IsEmpty() )
554 info.m_pins.emplace_back( pinNum );
569 parsedUnits.push_back(
info );
579 case T_component_classes:
580 while( (
token = NextTok() ) != T_RIGHT )
582 if(
token != T_LEFT )
585 if( (
token = NextTok() ) != T_class )
586 Expecting( T_class );
588 NeedSYMBOLorNUMBER();
589 componentClasses.insert(
From_UTF8( CurText() ) );
595 case T_duplicate_pin_numbers_are_jumpers:
597 NeedSYMBOLorNUMBER();
598 duplicatePinsAreJumpers =
From_UTF8( CurText() ) == wxT(
"1" );
603 case T_jumper_pin_groups:
605 std::set<wxString>* currentGroup =
nullptr;
607 for(
token = NextTok(); currentGroup ||
token != T_RIGHT;
token = NextTok() )
609 if(
token == T_LEFT )
615 currentGroup = &jumperPinGroups.emplace_back();
620 NeedSYMBOLorNUMBER();
621 wxString padName =
From_UTF8( CurText() );
623 wxCHECK2( currentGroup,
continue );
624 currentGroup->insert( padName );
629 currentGroup =
nullptr;
633 Expecting(
"group or pin" );
647 if( !footprint.IsEmpty() && fpid.
Parse( footprint,
true ) >= 0 )
649 THROW_IO_ERRORF(
_(
"Invalid footprint ID in\nfile: '%s'\nline: %d\noffset: %d" ),
650 CurSource(), CurLineNumber(), CurOffset() );
661 std::ranges::copy( jumperPinGroups, std::inserter( component->
JumperPadGroups(),
680 std::vector<KIID> members;
683 while( (
token = NextTok() ) != T_EOF )
685 if(
token == T_RIGHT )
687 else if(
token == T_LEFT )
693 NeedSYMBOLorNUMBER();
699 NeedSYMBOLorNUMBER();
705 NeedSYMBOLorNUMBER();
711 while( (
token = NextTok() ) != T_RIGHT )
713 if(
token == T_LEFT )
716 if(
token == T_member )
720 while( (
token = NextTok() ) != T_RIGHT )
722 if(
token == T_LEFT )
725 if(
token == T_uuid )
727 NeedSYMBOLorNUMBER();
737 members.emplace_back( memberUuid );
741 Expecting(
"member" );
755 if( !libId.IsEmpty() && groupLibId.
Parse( libId,
true ) >= 0 )
757 THROW_IO_ERRORF(
_(
"Invalid lib_id ID in\nfile: '%s'\nline: %d\noffset: %d" ),
758 CurSource(), CurLineNumber(), CurOffset() );
762 std::move( members ) };
791 wxString libPartName;
792 wxArrayString footprintFilters;
793 wxArrayString aliases;
797 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"parseLibPartList: begin libpart" ) );
798 while( (
token = NextTok() ) != T_RIGHT )
800 if(
token == T_LEFT )
806 NeedSYMBOLorNUMBER();
812 NeedSYMBOLorNUMBER();
819 while( (
token = NextTok() ) != T_RIGHT )
821 if(
token == T_LEFT )
830 if(
token == T_RIGHT )
834 Expecting(
"footprint ID" );
836 footprintFilters.Add(
From_UTF8( CurText() ) );
842 while( (
token = NextTok() ) != T_RIGHT )
844 if(
token == T_LEFT )
847 if(
token != T_alias )
848 Expecting( T_alias );
850 NeedSYMBOLorNUMBER();
857 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"parseLibPartList: entering pins for '%s:%s'" ),
858 libName, libPartName );
859 while( (
token = NextTok() ) != T_RIGHT )
861 if(
token == T_LEFT )
868 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"parseLibPartList: pin #%d for '%s:%s'" ),
869 pinCount, libName, libPartName );
873 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"Parsed libpart '%s:%s' pins => pinCount=%d" ),
874 libName, libPartName, pinCount );
885 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"parseLibPartList: assigning pinCount=%d for libpart '%s:%s'" ),
886 pinCount, libName, libPartName );
887 for(
unsigned i = 0; i <
m_netlist->GetCount(); i++ )
889 component =
m_netlist->GetComponent( i );
891 if( component->
IsLibSource( libName, libPartName ) )
895 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"Assign pinCount=%d to component ref='%s' part='%s:%s'" ),
896 pinCount, component->
GetReference(), libName, libPartName );
899 for(
unsigned jj = 0; jj < aliases.GetCount(); jj++ )
901 if( component->
IsLibSource( libName, aliases[jj] ) )
905 wxLogTrace(
"CVPCB_PINCOUNT",
906 wxT(
"Assign pinCount=%d to component ref='%s' via alias='%s:%s'" ),
907 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_ERRORF(msg,...)
static bool IsNumber(char x)
wxString From_UTF8(const char *cstring)