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)