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 SetLineReader (LINE_READER *aLineReader)
 
void SetNetlist (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 278 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 54 of file kicad_netlist_reader.cpp.

54  :
55  NETLIST_LEXER( aReader )
56 {
57  m_lineReader = aReader;
58  m_netlist = aNetlist;
59  token = T_NONE;
60 }
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 294 of file netlist_reader.h.

295  {
296  return NETLIST_LEXER::TokenName( aTok );
297  }

◆ Parse()

void KICAD_NETLIST_PARSER::Parse ( )

Function Parse parse the full netlist.

Definition at line 83 of file kicad_netlist_reader.cpp.

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

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

◆ 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;
309  KIID_PATH path;
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 }
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
void SetLibrary(const wxString &aLibrary)
Definition: pcb_netlist.h:120
NETLIST * m_netlist
The netlist to parse into. Not owned.
void skipCurrent()
Skip the current token level, i.e search for the RIGHT parenthesis which closes the current descripti...
void SetProperties(std::map< wxString, wxString > &aProps)
Definition: pcb_netlist.h:126
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
void AddComponent(COMPONENT *aComponent)
Add aComponent to the NETLIST.
#define _(s)
Store all of the related footprint information found in a netlist.
Definition: pcb_netlist.h:84
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition: lib_id.cpp:49
const char * name
Definition: DXF_plotter.cpp:56
void SetName(const wxString &aName)
Definition: pcb_netlist.h:117
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

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 }
bool IsLibSource(const wxString &aLibrary, const wxString &aName) const
Definition: pcb_netlist.h:155
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
NETLIST * m_netlist
The netlist to parse into. Not owned.
void skipCurrent()
Skip the current token level, i.e search for the RIGHT parenthesis which closes the current descripti...
unsigned GetCount() const
Definition: pcb_netlist.h:228
void SetPinCount(int aPinCount)
Definition: pcb_netlist.h:145
Store all of the related footprint information found in a netlist.
Definition: pcb_netlist.h:84
COMPONENT * GetComponent(unsigned aIndex)
Return the COMPONENT at aIndex.
Definition: pcb_netlist.h:236
void SetFootprintFilters(const wxArrayString &aFilters)
Definition: pcb_netlist.h:142

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 }
char * Line() const
Return a pointer to the last line that was read in.
Definition: richio.h:117
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
virtual const wxString & GetSource() const
Returns the name of the source of the lines in an abstract sense.
Definition: richio.h:109
NETLIST * m_netlist
The netlist to parse into. Not owned.
void skipCurrent()
Skip the current token level, i.e search for the RIGHT parenthesis which closes the current descripti...
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
LINE_READER * m_lineReader
The line reader used to parse the netlist. Not owned.
virtual unsigned LineNumber() const
Return the line number of the last line read from this LINE_READER.
Definition: richio.h:135
#define _(s)
Store all of the related footprint information found in a netlist.
Definition: pcb_netlist.h:84
unsigned Length() const
Return the number of bytes in the last line read from this LINE_READER.
Definition: richio.h:143
const char * name
Definition: DXF_plotter.cpp:56
void AddNet(const wxString &aPinName, const wxString &aNetName, const wxString &aPinFunction, const wxString &aPinType)
Definition: pcb_netlist.h:103
COMPONENT * GetComponentByReference(const wxString &aReference)
Return a COMPONENT by aReference.

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().

◆ SetLineReader()

void KICAD_NETLIST_PARSER::SetLineReader ( LINE_READER aLineReader)

◆ SetNetlist()

void KICAD_NETLIST_PARSER::SetNetlist ( NETLIST aNetlist)
inline

Definition at line 285 of file netlist_reader.h.

285 { m_netlist = aNetlist; }
NETLIST * m_netlist
The netlist to parse into. Not owned.

References m_netlist.

◆ 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 63 of file kicad_netlist_reader.cpp.

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

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 353 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 354 of file netlist_reader.h.

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

◆ token

NL_T::T KICAD_NETLIST_PARSER::token
private

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