23#include <netlist_lexer.h>
46 for(
unsigned i = 0; i <
m_netlist->GetCount(); i++ )
54 NETLIST_LEXER( aReader )
56 m_lineReader = aReader;
66 while( (
token = NextTok() ) != T_EOF )
71 if(
token == T_RIGHT )
86 while( (
token = NextTok() ) != T_EOF )
105 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"Parse: entering components section" ) );
107 while( (
token = NextTok() ) != T_EOF )
109 if(
token == T_RIGHT )
111 else if(
token == T_LEFT )
114 if(
token == T_comp )
121 while( (
token = NextTok() ) != T_EOF )
123 if(
token == T_RIGHT )
125 else if(
token == T_LEFT )
128 if(
token == T_group )
135 while( (
token = NextTok() ) != T_EOF )
137 if(
token == T_RIGHT )
139 else if(
token == T_LEFT )
142 if(
token == T_variant )
149 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"Parse: entering nets section" ) );
151 while( (
token = NextTok() ) != T_EOF )
153 if(
token == T_RIGHT )
155 else if(
token == T_LEFT )
165 while( (
token = NextTok() ) != T_EOF )
167 if(
token == T_RIGHT )
169 else if(
token == T_LEFT )
172 if(
token == T_net_chain )
179 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"Parse: entering libparts section" ) );
181 while( (
token = NextTok() ) != T_EOF )
183 if(
token == T_RIGHT )
185 else if(
token == T_LEFT )
188 if(
token == T_libpart )
220 wxFAIL_MSG( wxString::Format( wxT(
"KICAD_NETLIST_PARSER::Parse(): bad parenthesis "
221 "count (count = %d" ),
240 wxString pin_function;
244 while( (
token = NextTok() ) != T_EOF )
246 if(
token == T_RIGHT )
248 else if(
token == T_LEFT )
254 NeedSYMBOLorNUMBER();
260 NeedSYMBOLorNUMBER();
267 pin_function.Clear();
270 while( (
token = NextTok() ) != T_EOF )
272 if(
token == T_RIGHT )
274 else if(
token == T_LEFT )
280 NeedSYMBOLorNUMBER();
286 NeedSYMBOLorNUMBER();
292 NeedSYMBOLorNUMBER();
298 NeedSYMBOLorNUMBER();
312 if( strtol( code.c_str(),
nullptr, 10 ) >= 1 )
315 name = wxT(
"N-00000") + code;
317 component->AddNet( pin_number,
name, pin_function, pin_type );
353 wxString humanSheetPath;
356 std::vector<KIID> uuids;
357 std::map<wxString, wxString> properties;
358 nlohmann::ordered_map<wxString, wxString> fields;
359 std::unordered_set<wxString> componentClasses;
361 bool duplicatePinsAreJumpers =
false;
362 JUMPER_GROUP_SET jumperPinGroups;
364 std::vector<COMPONENT::UNIT_INFO> parsedUnits;
365 std::vector<COMPONENT_VARIANT> parsedVariants;
368 while( (
token = NextTok() ) != T_RIGHT )
370 if(
token == T_LEFT )
376 NeedSYMBOLorNUMBER();
382 NeedSYMBOLorNUMBER();
388 NeedSYMBOLorNUMBER();
389 footprint = FromUTF8();
395 while( (
token = NextTok() ) != T_RIGHT )
397 if(
token == T_LEFT )
402 NeedSYMBOLorNUMBER();
406 else if(
token == T_part )
408 NeedSYMBOLorNUMBER();
412 else if(
token == T_description )
414 NeedSYMBOLorNUMBER();
419 Expecting(
"part, lib or description" );
422 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"parseComponent: ref='%s' libsource='%s:%s'" ),
431 while( (
token = NextTok() ) != T_RIGHT )
433 if(
token == T_LEFT )
436 if(
token == T_name )
438 NeedSYMBOLorNUMBER();
442 else if(
token == T_value )
444 NeedSYMBOLorNUMBER();
450 Expecting(
"name or value" );
454 if( !propName.IsEmpty() )
455 properties[propName] = std::move( propValue );
460 while( (
token = NextTok() ) != T_RIGHT )
462 if(
token == T_LEFT )
465 if(
token == T_field )
470 while( (
token = NextTok() ) != T_RIGHT )
472 if(
token == T_LEFT )
475 if(
token == T_name )
477 NeedSYMBOLorNUMBER();
481 else if(
token == T_STRING )
487 if( !fieldName.IsEmpty() )
488 fields[fieldName] = std::move( fieldValue );
492 Expecting(
"field" );
498 while( (
token = NextTok() ) != T_EOF )
500 if(
token == T_names )
502 NeedSYMBOLorNUMBER();
507 if(
token == T_tstamps )
509 NeedSYMBOLorNUMBER();
521 while( (
token = NextTok() ) != T_EOF )
523 if(
token == T_RIGHT )
526 uuids.emplace_back(
From_UTF8( CurText() ) );
535 while( (
token = NextTok() ) != T_RIGHT )
537 if(
token == T_LEFT )
540 if(
token == T_unit )
542 COMPONENT::UNIT_INFO
info;
544 while( (
token = NextTok() ) != T_RIGHT )
546 if(
token == T_LEFT )
552 NeedSYMBOLorNUMBER();
558 while( (
token = NextTok() ) != T_RIGHT )
560 if(
token == T_LEFT )
570 if(
token == T_LEFT )
575 NeedSYMBOLorNUMBER();
586 if( !pinNum.IsEmpty() )
587 info.m_pins.emplace_back( pinNum );
602 parsedUnits.push_back(
info );
613 case T_component_classes:
614 while( (
token = NextTok() ) != T_RIGHT )
616 if(
token != T_LEFT )
619 if( (
token = NextTok() ) != T_class )
620 Expecting( T_class );
622 NeedSYMBOLorNUMBER();
623 componentClasses.insert(
From_UTF8( CurText() ) );
629 case T_duplicate_pin_numbers_are_jumpers:
631 NeedSYMBOLorNUMBER();
632 duplicatePinsAreJumpers =
From_UTF8( CurText() ) == wxT(
"1" );
637 case T_jumper_pin_groups:
639 std::set<wxString> currentNames;
640 bool inGroup =
false;
642 for(
token = NextTok(); inGroup ||
token != T_RIGHT;
token = NextTok() )
644 if(
token == T_LEFT )
655 NeedSYMBOLorNUMBER();
656 wxString padName =
From_UTF8( CurText() );
658 wxCHECK2( inGroup,
continue );
659 currentNames.insert( padName );
665 jumperPinGroups.
Add( std::move( *
group ) );
667 currentNames.clear();
672 Expecting(
"group or pin" );
681 while( (
token = NextTok() ) != T_RIGHT )
683 if(
token == T_LEFT )
686 if(
token != T_variant )
692 COMPONENT_VARIANT variant;
696 if(
token == T_LEFT )
702 NeedSYMBOLorNUMBER();
711 bool hasValue =
false;
713 while( (
token = NextTok() ) != T_RIGHT )
715 if(
token == T_LEFT )
718 if(
token == T_name )
720 NeedSYMBOLorNUMBER();
724 else if(
token == T_value )
726 NeedSYMBOLorNUMBER();
733 Expecting(
"name or value" );
737 if( propName.IsEmpty() )
740 bool propBool =
true;
752 propBool = !propValue.IsEmpty();
755 if( propName.CmpNoCase( wxT(
"dnp" ) ) == 0 )
757 variant.
m_dnp = propBool;
760 else if( propName.CmpNoCase( wxT(
"exclude_from_bom" ) ) == 0 )
765 else if( propName.CmpNoCase( wxT(
"exclude_from_sim" ) ) == 0 )
770 else if( propName.CmpNoCase( wxT(
"exclude_from_pos_files" ) ) == 0 )
780 while( (
token = NextTok() ) != T_RIGHT )
782 if(
token == T_LEFT )
785 if(
token == T_field )
790 while( (
token = NextTok() ) != T_RIGHT )
792 if(
token == T_LEFT )
795 if(
token == T_name )
797 NeedSYMBOLorNUMBER();
801 else if(
token == T_value )
803 NeedSYMBOLorNUMBER();
807 else if(
token == T_STRING )
813 if( !fieldName.IsEmpty() )
814 variant.
m_fields[fieldName] = std::move( fieldValue );
818 Expecting(
"field" );
829 if( !variant.
m_name.IsEmpty() )
830 parsedVariants.push_back( std::move( variant ) );
843 if( !footprint.IsEmpty() && fpid.
Parse( footprint,
true ) >= 0 )
845 THROW_IO_ERRORF(
_(
"Invalid footprint ID in\nfile: '%s'\nline: %d\noffset: %d" ),
846 CurSource(), CurLineNumber(), CurOffset() );
860 for(
const COMPONENT_VARIANT& variant : parsedVariants )
882 std::vector<KIID_PATH> members;
885 while( (
token = NextTok() ) != T_EOF )
887 if(
token == T_RIGHT )
889 else if(
token == T_LEFT )
895 NeedSYMBOLorNUMBER();
902 NeedSYMBOLorNUMBER();
903 wxString uuidStr =
From_UTF8( CurText() );
907 if( uuidStr.StartsWith( wxT(
"/" ) ) )
917 NeedSYMBOLorNUMBER();
923 while( (
token = NextTok() ) != T_RIGHT )
925 if(
token == T_LEFT )
928 if(
token == T_member )
932 while( (
token = NextTok() ) != T_RIGHT )
934 if(
token == T_LEFT )
937 if(
token == T_uuid )
939 NeedSYMBOLorNUMBER();
949 members.emplace_back( memberUuid );
953 Expecting(
"member" );
967 if( !libId.IsEmpty() && groupLibId.
Parse( libId,
true ) >= 0 )
969 THROW_IO_ERRORF(
_(
"Invalid lib_id ID in\nfile: '%s'\nline: %d\noffset: %d" ),
970 CurSource(), CurLineNumber(), CurOffset() );
973 NETLIST_GROUP*
group =
new NETLIST_GROUP{ std::move(
name ), std::move( uuid ), std::move( groupLibId ),
974 std::move( members ) };
985 wxString description;
989 if(
token == T_LEFT )
995 NeedSYMBOLorNUMBER();
1001 NeedSYMBOLorNUMBER();
1012 if( !
name.IsEmpty() )
1021 wxString chainClass;
1023 std::vector<wxString> members;
1024 std::vector<std::pair<wxString, wxString>> terminals;
1026 while( (
token = NextTok() ) != T_EOF )
1028 if(
token == T_RIGHT )
1030 else if(
token == T_LEFT )
1036 NeedSYMBOLorNUMBER();
1042 NeedSYMBOLorNUMBER();
1047 case T_net_chain_class:
1048 NeedSYMBOLorNUMBER();
1054 NeedSYMBOLorNUMBER();
1060 while( (
token = NextTok() ) != T_RIGHT )
1062 if(
token == T_LEFT )
1065 if(
token == T_member )
1067 while( (
token = NextTok() ) != T_RIGHT )
1069 if(
token == T_LEFT )
1072 if(
token == T_net )
1074 NeedSYMBOLorNUMBER();
1075 members.emplace_back(
From_UTF8( CurText() ) );
1087 case T_terminal_pins:
1088 while( (
token = NextTok() ) != T_RIGHT )
1090 if(
token == T_LEFT )
1093 if(
token == T_terminal_pin )
1098 while( (
token = NextTok() ) != T_RIGHT )
1100 if(
token == T_LEFT )
1103 if(
token == T_ref )
1105 NeedSYMBOLorNUMBER();
1109 else if(
token == T_pin )
1111 NeedSYMBOLorNUMBER();
1119 if( !ref.IsEmpty() && !
pin.IsEmpty() )
1120 terminals.emplace_back( ref,
pin );
1133 for(
const wxString& netName : members )
1136 for(
const auto& term : terminals )
1137 m_netlist->AddSignalTerminalPin(
name, term.first, term.second );
1139 if( !netClass.IsEmpty() )
1142 if( !colorStr.IsEmpty() )
1145 if( !chainClass.IsEmpty() )
1174 wxString libPartName;
1175 wxArrayString footprintFilters;
1176 wxArrayString aliases;
1180 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"parseLibPartList: begin libpart" ) );
1181 while( (
token = NextTok() ) != T_RIGHT )
1183 if(
token == T_LEFT )
1189 NeedSYMBOLorNUMBER();
1195 NeedSYMBOLorNUMBER();
1202 while( (
token = NextTok() ) != T_RIGHT )
1204 if(
token == T_LEFT )
1213 if(
token == T_RIGHT )
1217 Expecting(
"footprint ID" );
1219 footprintFilters.Add(
From_UTF8( CurText() ) );
1225 while( (
token = NextTok() ) != T_RIGHT )
1227 if(
token == T_LEFT )
1230 if(
token != T_alias )
1231 Expecting( T_alias );
1233 NeedSYMBOLorNUMBER();
1240 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"parseLibPartList: entering pins for '%s:%s'" ),
1241 libName, libPartName );
1242 while( (
token = NextTok() ) != T_RIGHT )
1244 if(
token == T_LEFT )
1247 if(
token != T_pin )
1251 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"parseLibPartList: pin #%d for '%s:%s'" ),
1252 pinCount, libName, libPartName );
1256 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"Parsed libpart '%s:%s' pins => pinCount=%d" ),
1257 libName, libPartName, pinCount );
1268 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"parseLibPartList: assigning pinCount=%d for libpart '%s:%s'" ),
1269 pinCount, libName, libPartName );
1270 for(
unsigned i = 0; i <
m_netlist->GetCount(); i++ )
1272 component =
m_netlist->GetComponent( i );
1274 if( component->
IsLibSource( libName, libPartName ) )
1278 wxLogTrace(
"CVPCB_PINCOUNT", wxT(
"Assign pinCount=%d to component ref='%s' part='%s:%s'" ),
1279 pinCount, component->
GetReference(), libName, libPartName );
1282 for(
unsigned jj = 0; jj < aliases.GetCount(); jj++ )
1284 if( component->
IsLibSource( libName, aliases[jj] ) )
1288 wxLogTrace(
"CVPCB_PINCOUNT",
1289 wxT(
"Assign pinCount=%d to component ref='%s' via alias='%s:%s'" ),
1290 pinCount, component->
GetReference(), libName, aliases[jj] );
static std::optional< VECTOR2D > normalized(const VECTOR2D &aVec)
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)
JUMPER_GROUP_SET & JumperPadGroups()
void SetComponentClassNames(const std::unordered_set< wxString > &aClassNames)
void SetName(const wxString &aName)
void Add(JUMPER_GROUP aGroup)
Add a JUMPER_GROUP to the set.
static std::optional< JUMPER_GROUP > Make(std::set< wxString > aNames)
Factory method to create a JUMPER_GROUP from a set of names.
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.
static KIID FromName(const std::string &aName)
Return a KIID derived from a name, the same name always gives the same KIID.
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 wxString From_UTF8(const char *cstring)
Convert a UTF8 encoded C string to a wxString for all wxWidgets build modes.
_OUT_STRING AsString(const std::string &aString)
static bool IsNumber(char x)
bool m_excludedFromPosFiles
bool m_hasExcludedFromBOM
bool m_hasExcludedFromSim
bool m_hasExcludedFromPosFiles
nlohmann::ordered_map< wxString, wxString > m_fields