KiCad PCB EDA Suite
KICAD_NETLIST_PARSER Class Reference

The parser for reading the KiCad s-expression netlist format. More...

#include <netlist_reader.h>

Inheritance diagram for KICAD_NETLIST_PARSER:

Public Member Functions

 KICAD_NETLIST_PARSER (LINE_READER *aReader, NETLIST *aNetlist)
 
void Parse ()
 Function Parse parse the full netlist. More...
 
const char * getTokenName (NL_T::T aTok)
 

Private Member Functions

void skipCurrent ()
 Skip the current token level, i.e search for the RIGHT parenthesis which closes the current description. More...
 
void parseComponent ()
 Parse a component description: (comp (ref P1) (value DB25FEMELLE) (footprint DB25FC) (libsource (lib conn) (part DB25)) (property (name PINCOUNT) (value 25)) (sheetpath (names /) (tstamps /)) (tstamp 3256759C)) More...
 
void parseNet ()
 Parse a net section (net (code 20) (name /PC-A0) (node (ref BUS1) (pin 62)) (node (ref U3) (pin 3)) (node (ref U9) (pin M6))) More...
 
void parseLibPartList ()
 Read the section "libparts" in the netlist: (libparts (libpart (lib device) (part C) (description "Condensateur non polarise") (footprints (fp SM*) (fp C?) (fp C1-1)) (fields (field (name Reference) C) (field (name Value) C)) (pins (pin (num 1) (name ~) (type passive)) (pin (num 2) (name ~) (type passive)))) More...
 

Private Attributes

NL_T::T token
 
LINE_READERm_lineReader
 The line reader used to parse the netlist. Not owned. More...
 
NETLISTm_netlist
 The netlist to parse into. Not owned. More...
 

Detailed Description

The parser for reading the KiCad s-expression netlist format.

Definition at line 269 of file netlist_reader.h.

Constructor & Destructor Documentation

◆ KICAD_NETLIST_PARSER()

KICAD_NETLIST_PARSER::KICAD_NETLIST_PARSER ( LINE_READER aReader,
NETLIST aNetlist 
)

Definition at line 53 of file kicad_netlist_reader.cpp.

53 :
54 NETLIST_LEXER( aReader )
55{
56 m_lineReader = aReader;
57 m_netlist = aNetlist;
58 token = T_NONE;
59}
NETLIST * m_netlist
The netlist to parse into. Not owned.
LINE_READER * m_lineReader
The line reader used to parse the netlist. Not owned.

References m_lineReader, m_netlist, and token.

Member Function Documentation

◆ getTokenName()

const char * KICAD_NETLIST_PARSER::getTokenName ( NL_T::T  aTok)
inline

Definition at line 281 of file netlist_reader.h.

282 {
283 return NETLIST_LEXER::TokenName( aTok );
284 }

◆ Parse()

void KICAD_NETLIST_PARSER::Parse ( )

Function Parse parse the full netlist.

Definition at line 82 of file kicad_netlist_reader.cpp.

83{
84 int plevel = 0; // the count of ')' to read at end of file after parsing all sections
85
86 while( ( token = NextTok() ) != T_EOF )
87 {
88 if( token == T_LEFT )
89 token = NextTok();
90
91 switch( token )
92 {
93 case T_export: // The netlist starts here.
94 // nothing to do here, just increment the count of ')' to read at end of file
95 plevel++;
96 break;
97
98 case T_version: // The netlist starts here.
99 // version id not yet used: read it but does not use it
100 NextTok();
101 NeedRIGHT();
102 break;
103
104 case T_components: // The section comp starts here.
105 while( ( token = NextTok() ) != T_EOF )
106 {
107 if( token == T_RIGHT )
108 break;
109 else if( token == T_LEFT )
110 token = NextTok();
111
112 if( token == T_comp ) // A component section found. Read it
114 }
115
116 break;
117
118 case T_nets: // The section nets starts here.
119 while( ( token = NextTok() ) != T_EOF )
120 {
121 if( token == T_RIGHT )
122 break;
123 else if( token == T_LEFT )
124 token = NextTok();
125
126 if( token == T_net ) // A net section if found. Read it
127 parseNet();
128 }
129
130 break;
131
132 case T_libparts: // The section libparts starts here.
133 while( ( token = NextTok() ) != T_EOF )
134 {
135 if( token == T_RIGHT )
136 break;
137 else if( token == T_LEFT )
138 token = NextTok();
139
140 if( token == T_libpart ) // A libpart section if found. Read it
142 }
143
144 break;
145
146 case T_libraries: // The section libraries starts here.
147 // List of libraries in use.
148 // Not used here, just skip it
149 skipCurrent();
150 break;
151
152 case T_design: // The section design starts here.
153 // Not used (mainly they are comments), just skip it
154 skipCurrent();
155 break;
156
157 case T_RIGHT: // The closing parenthesis of the file.
158 plevel--;
159 break;
160
161 default:
162 skipCurrent();
163 break;
164 }
165 }
166
167 if( plevel != 0 )
168 {
169 wxFAIL_MSG( wxString::Format( wxT( "KICAD_NETLIST_PARSER::Parse(): bad parenthesis "
170 "count (count = %d" ),
171 plevel ) );
172 }
173}
void parseComponent()
Parse a component description: (comp (ref P1) (value DB25FEMELLE) (footprint DB25FC) (libsource (lib ...
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 skipCurrent()
Skip the current token level, i.e search for the RIGHT parenthesis which closes the current descripti...
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200

References Format(), parseComponent(), parseLibPartList(), parseNet(), skipCurrent(), and token.

Referenced by KICAD_NETLIST_READER::LoadNetlist().

◆ parseComponent()

void KICAD_NETLIST_PARSER::parseComponent ( )
private

Parse a component description: (comp (ref P1) (value DB25FEMELLE) (footprint DB25FC) (libsource (lib conn) (part DB25)) (property (name PINCOUNT) (value 25)) (sheetpath (names /) (tstamps /)) (tstamp 3256759C))

Definition at line 288 of file kicad_netlist_reader.cpp.

289{
290 /* Parses a section like
291 * (comp (ref P1)
292 * (value DB25FEMALE)
293 * (footprint DB25FC)
294 * (libsource (lib conn) (part DB25))
295 * (property (name PINCOUNT) (value 25))
296 * (sheetpath (names /) (tstamps /))
297 * (tstamp 68183921-93a5-49ac-91b0-49d05a0e1647))
298 *
299 * other fields (unused) are skipped
300 * A component need a reference, value, footprint name and a full time stamp
301 * The full time stamp is the sheetpath time stamp + the component time stamp
302 */
303 LIB_ID fpid;
304 wxString footprint;
305 wxString ref;
306 wxString value;
307 wxString library;
308 wxString name;
310
311 std::vector<KIID> uuids;
312 std::map<wxString, wxString> properties;
313
314 // The token comp was read, so the next data is (ref P1)
315 while( (token = NextTok() ) != T_RIGHT )
316 {
317 if( token == T_LEFT )
318 token = NextTok();
319
320 switch( token )
321 {
322 case T_ref:
323 NeedSYMBOLorNUMBER();
324 ref = FROM_UTF8( CurText() );
325 NeedRIGHT();
326 break;
327
328 case T_value:
329 NeedSYMBOLorNUMBER();
330 value = FROM_UTF8( CurText() );
331 NeedRIGHT();
332 break;
333
334 case T_footprint:
335 NeedSYMBOLorNUMBER();
336 footprint = FromUTF8();
337 NeedRIGHT();
338 break;
339
340 case T_libsource:
341 // Read libsource
342 while( ( token = NextTok() ) != T_RIGHT )
343 {
344 if( token == T_LEFT )
345 token = NextTok();
346
347 if( token == T_lib )
348 {
349 NeedSYMBOLorNUMBER();
350 library = FROM_UTF8( CurText() );
351 NeedRIGHT();
352 }
353 else if( token == T_part )
354 {
355 NeedSYMBOLorNUMBER();
356 name = FROM_UTF8( CurText() );
357 NeedRIGHT();
358 }
359 else if( token == T_description )
360 {
361 NeedSYMBOLorNUMBER();
362 NeedRIGHT();
363 }
364 else
365 {
366 Expecting( "part, lib or description" );
367 }
368 }
369 break;
370
371 case T_property:
372 {
373 wxString propName;
374 wxString propValue;
375
376 while( (token = NextTok() ) != T_RIGHT )
377 {
378 if( token == T_LEFT )
379 token = NextTok();
380
381 if( token == T_name )
382 {
383 NeedSYMBOLorNUMBER();
384 propName = FROM_UTF8( CurText() );
385 NeedRIGHT();
386 }
387 else if( token == T_value )
388 {
389 NeedSYMBOLorNUMBER();
390 propValue = FROM_UTF8( CurText() );
391 NeedRIGHT();
392 }
393 else
394 {
395 Expecting( "name or value" );
396 }
397 }
398
399 if( !propName.IsEmpty() )
400 properties[ propName ] = propValue;
401 }
402 break;
403
404 case T_sheetpath:
405 while( ( token = NextTok() ) != T_EOF )
406 {
407 if( token == T_tstamps )
408 break;
409 }
410
411 NeedSYMBOLorNUMBER();
412 path = KIID_PATH( FROM_UTF8( CurText() ) );
413 NeedRIGHT();
414 NeedRIGHT();
415 break;
416
417 case T_tstamps:
418 while( ( token = NextTok() ) != T_EOF )
419 {
420 if( token == T_RIGHT )
421 break;
422
423 uuids.emplace_back( FROM_UTF8( CurText() ) );
424 }
425
426 break;
427
428 default:
429 // Skip not used data (i.e all other tokens)
430 skipCurrent();
431 break;
432 }
433 }
434
435 if( !footprint.IsEmpty() && fpid.Parse( footprint, true ) >= 0 )
436 {
437 wxString error;
438 error.Printf( _( "Invalid footprint ID in\nfile: '%s'\nline: %d\noffset: %d" ),
439 CurSource(), CurLineNumber(), CurOffset() );
440
441 THROW_IO_ERROR( error );
442 }
443
444 COMPONENT* component = new COMPONENT( fpid, ref, value, path, uuids );
445 component->SetName( name );
446 component->SetLibrary( library );
447 component->SetProperties( properties );
448 m_netlist->AddComponent( component );
449}
const char * name
Definition: DXF_plotter.cpp:56
Store all of the related footprint information found in a netlist.
Definition: pcb_netlist.h:85
void SetLibrary(const wxString &aLibrary)
Definition: pcb_netlist.h:122
void SetProperties(std::map< wxString, wxString > &aProps)
Definition: pcb_netlist.h:131
void SetName(const wxString &aName)
Definition: pcb_netlist.h:119
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition: lib_id.cpp:50
void AddComponent(COMPONENT *aComponent)
Add aComponent to the NETLIST.
#define _(s)
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
static wxString FROM_UTF8(const char *cstring)
Convert a UTF8 encoded C string to a wxString for all wxWidgets build modes.
Definition: macros.h:110

References _, NETLIST::AddComponent(), COMPONENT, FROM_UTF8(), library, m_netlist, name, LIB_ID::Parse(), path, COMPONENT::SetLibrary(), COMPONENT::SetName(), COMPONENT::SetProperties(), skipCurrent(), THROW_IO_ERROR, and token.

Referenced by Parse().

◆ parseLibPartList()

void KICAD_NETLIST_PARSER::parseLibPartList ( )
private

Read the section "libparts" in the netlist: (libparts (libpart (lib device) (part C) (description "Condensateur non polarise") (footprints (fp SM*) (fp C?) (fp C1-1)) (fields (field (name Reference) C) (field (name Value) C)) (pins (pin (num 1) (name ~) (type passive)) (pin (num 2) (name ~) (type passive))))

And add the strings giving the footprint filter (subsection footprints) of the corresponding footprint info

This section is used by CvPcb, and is not useful in Pcbnew, therefore it it not always read

Definition at line 452 of file kicad_netlist_reader.cpp.

453{
454 /* Parses a section like
455 * (libpart (lib device) (part C)
456 * (aliases
457 * (alias Cxx)
458 * (alias Cyy))
459 * (description "Condensateur non polarise")
460 * (footprints
461 * (fp SM*)
462 * (fp C?)
463 * (fp C1-1))
464 * (fields
465 * (field (name Reference) C)
466 * (field (name Value) C))
467 * (pins
468 * (pin (num 1) (name ~) (type passive))
469 * (pin (num 2) (name ~) (type passive))))
470 *
471 * Currently footprints section/fp are read and data stored
472 * other fields (unused) are skipped
473 */
474 COMPONENT* component = NULL;
475 wxString libName;
476 wxString libPartName;
477 wxArrayString footprintFilters;
478 wxArrayString aliases;
479 int pinCount = 0;
480
481 // The last token read was libpart, so read the next token
482 while( (token = NextTok() ) != T_RIGHT )
483 {
484 if( token == T_LEFT )
485 token = NextTok();
486
487 switch( token )
488 {
489 case T_lib:
490 NeedSYMBOLorNUMBER();
491 libName = FROM_UTF8( CurText() );
492 NeedRIGHT();
493 break;
494
495 case T_part:
496 NeedSYMBOLorNUMBER();
497 libPartName = FROM_UTF8( CurText() );
498 NeedRIGHT();
499 break;
500
501 case T_footprints:
502 // Read all fp elements (footprint filter item)
503 while( (token = NextTok() ) != T_RIGHT )
504 {
505 if( token == T_LEFT )
506 token = NextTok();
507
508 if( token != T_fp )
509 Expecting( T_fp );
510
511 NeedSYMBOLorNUMBER();
512 footprintFilters.Add( FROM_UTF8( CurText() ) );
513 NeedRIGHT();
514 }
515 break;
516
517 case T_aliases:
518 while( (token = NextTok() ) != T_RIGHT )
519 {
520 if( token == T_LEFT )
521 token = NextTok();
522
523 if( token != T_alias )
524 Expecting( T_alias );
525
526 NeedSYMBOLorNUMBER();
527 aliases.Add( FROM_UTF8( CurText() ) );
528 NeedRIGHT();
529 }
530 break;
531
532 case T_pins:
533 while( (token = NextTok() ) != T_RIGHT )
534 {
535 if( token == T_LEFT )
536 token = NextTok();
537
538 if( token != T_pin )
539 Expecting( T_pin );
540
541 pinCount++;
542
543 skipCurrent();
544 }
545 break;
546
547 default:
548 // Skip not used data (i.e all other tokens)
549 skipCurrent();
550 break;
551 }
552 }
553
554 // Find all of the components that reference this component library part definition.
555 for( unsigned i = 0; i < m_netlist->GetCount(); i++ )
556 {
557 component = m_netlist->GetComponent( i );
558
559 if( component->IsLibSource( libName, libPartName ) )
560 {
561 component->SetFootprintFilters( footprintFilters );
562 component->SetPinCount( pinCount );
563 }
564
565 for( unsigned jj = 0; jj < aliases.GetCount(); jj++ )
566 {
567 if( component->IsLibSource( libName, aliases[jj] ) )
568 {
569 component->SetFootprintFilters( footprintFilters );
570 component->SetPinCount( pinCount );
571 }
572 }
573
574 }
575}
void SetPinCount(int aPinCount)
Definition: pcb_netlist.h:150
bool IsLibSource(const wxString &aLibrary, const wxString &aName) const
Definition: pcb_netlist.h:160
void SetFootprintFilters(const wxArrayString &aFilters)
Definition: pcb_netlist.h:147
unsigned GetCount() const
Definition: pcb_netlist.h:234
COMPONENT * GetComponent(unsigned aIndex)
Return the COMPONENT at aIndex.
Definition: pcb_netlist.h:242

References FROM_UTF8(), NETLIST::GetComponent(), NETLIST::GetCount(), COMPONENT::IsLibSource(), m_netlist, COMPONENT::SetFootprintFilters(), COMPONENT::SetPinCount(), skipCurrent(), and token.

Referenced by Parse().

◆ parseNet()

void KICAD_NETLIST_PARSER::parseNet ( )
private

Parse a net section (net (code 20) (name /PC-A0) (node (ref BUS1) (pin 62)) (node (ref U3) (pin 3)) (node (ref U9) (pin M6)))

and set the corresponding pads netnames

Definition at line 176 of file kicad_netlist_reader.cpp.

177{
178 /* Parses a section like
179 * (net (code 20) (name /PC-A0)
180 * (node (ref "BUS1") (pin "62)")
181 * (node (ref "U3") ("pin 3") (pin_function "clock"))
182 * (node (ref "U9") (pin "M6") (pin_function "reset")))
183 */
184
185 COMPONENT* component = NULL;
186 wxString code;
187 wxString name;
188 wxString reference;
189 wxString pin_number;
190 wxString pin_function;
191 wxString pin_type;
192
193 // The token net was read, so the next data is (code <number>)
194 while( (token = NextTok() ) != T_EOF )
195 {
196 if( token == T_RIGHT )
197 break;
198 else if( token == T_LEFT )
199 token = NextTok();
200
201 switch( token )
202 {
203 case T_code:
204 NeedSYMBOLorNUMBER();
205 code = FROM_UTF8( CurText() );
206 NeedRIGHT();
207 break;
208
209 case T_name:
210 NeedSYMBOLorNUMBER();
211 name = FROM_UTF8( CurText() );
212 NeedRIGHT();
213 break;
214
215 case T_node:
216 // By default: no pin function or type.
217 pin_function.Clear();
218 pin_type.Clear();
219
220 while( (token = NextTok() ) != T_EOF )
221 {
222 if( token == T_RIGHT )
223 break;
224 else if( token == T_LEFT )
225 token = NextTok();
226
227 switch( token )
228 {
229 case T_ref:
230 NeedSYMBOLorNUMBER();
231 reference = FROM_UTF8( CurText() );
232 NeedRIGHT();
233 break;
234
235 case T_pin:
236 NeedSYMBOLorNUMBER();
237 pin_number = FROM_UTF8( CurText() );
238 NeedRIGHT();
239 break;
240
241 case T_pinfunction:
242 NeedSYMBOLorNUMBER();
243 pin_function = FROM_UTF8( CurText() );
244 NeedRIGHT();
245 break;
246
247 case T_pintype:
248 NeedSYMBOLorNUMBER();
249 pin_type = FROM_UTF8( CurText() );
250 NeedRIGHT();
251 break;
252
253 default:
254 skipCurrent();
255 break;
256 }
257 }
258
259 if( strtol( code.c_str(), NULL, 10 ) >= 1 )
260 {
261 if( name.IsEmpty() ) // Give a dummy net name like N-000009
262 name = wxT("N-00000") + code;
263
264 component = m_netlist->GetComponentByReference( reference );
265
266 // Cannot happen if the netlist is valid.
267 if( component == NULL )
268 {
269 wxString msg;
270 msg.Printf( _( "Cannot find component with ref '%s' in netlist." ),
271 reference );
274 }
275
276 component->AddNet( pin_number, name, pin_function, pin_type );
277 }
278 break;
279
280 default:
281 skipCurrent();
282 break;
283 }
284 }
285}
void AddNet(const wxString &aPinName, const wxString &aNetName, const wxString &aPinFunction, const wxString &aPinType)
Definition: pcb_netlist.h:103
virtual const wxString & GetSource() const
Returns the name of the source of the lines in an abstract sense.
Definition: richio.h:109
virtual unsigned LineNumber() const
Return the line number of the last line read from this LINE_READER.
Definition: richio.h:135
unsigned Length() const
Return the number of bytes in the last line read from this LINE_READER.
Definition: richio.h:143
char * Line() const
Return a pointer to the last line that was read in.
Definition: richio.h:117
COMPONENT * GetComponentByReference(const wxString &aReference)
Return a COMPONENT by aReference.
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164

References _, COMPONENT::AddNet(), FROM_UTF8(), NETLIST::GetComponentByReference(), LINE_READER::GetSource(), LINE_READER::Length(), LINE_READER::Line(), LINE_READER::LineNumber(), m_lineReader, m_netlist, name, skipCurrent(), THROW_PARSE_ERROR, and token.

Referenced by Parse().

◆ skipCurrent()

void KICAD_NETLIST_PARSER::skipCurrent ( )
private

Skip the current token level, i.e search for the RIGHT parenthesis which closes the current description.

Definition at line 62 of file kicad_netlist_reader.cpp.

63{
64 int curr_level = 0;
65
66 while( ( token = NextTok() ) != T_EOF )
67 {
68 if( token == T_LEFT )
69 curr_level--;
70
71 if( token == T_RIGHT )
72 {
73 curr_level++;
74
75 if( curr_level > 0 )
76 return;
77 }
78 }
79}

References token.

Referenced by Parse(), parseComponent(), parseLibPartList(), and parseNet().

Member Data Documentation

◆ m_lineReader

LINE_READER* KICAD_NETLIST_PARSER::m_lineReader
private

The line reader used to parse the netlist. Not owned.

Definition at line 340 of file netlist_reader.h.

Referenced by KICAD_NETLIST_PARSER(), and parseNet().

◆ m_netlist

NETLIST* KICAD_NETLIST_PARSER::m_netlist
private

The netlist to parse into. Not owned.

Definition at line 341 of file netlist_reader.h.

Referenced by KICAD_NETLIST_PARSER(), parseComponent(), parseLibPartList(), and parseNet().

◆ token

NL_T::T KICAD_NETLIST_PARSER::token
private

The documentation for this class was generated from the following files: