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( wxT( "KICAD_NETLIST_PARSER::Parse(): bad parenthesis "
171  "count (count = %d" ),
172  plevel ) );
173  }
174 }
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 289 of file kicad_netlist_reader.cpp.

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

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

178 {
179  /* Parses a section like
180  * (net (code 20) (name /PC-A0)
181  * (node (ref "BUS1") (pin "62)")
182  * (node (ref "U3") ("pin 3") (pin_function "clock"))
183  * (node (ref "U9") (pin "M6") (pin_function "reset")))
184  */
185 
186  COMPONENT* component = NULL;
187  wxString code;
188  wxString name;
189  wxString reference;
190  wxString pin_number;
191  wxString pin_function;
192  wxString pin_type;
193 
194  // The token net was read, so the next data is (code <number>)
195  while( (token = NextTok() ) != T_EOF )
196  {
197  if( token == T_RIGHT )
198  break;
199  else if( token == T_LEFT )
200  token = NextTok();
201 
202  switch( token )
203  {
204  case T_code:
205  NeedSYMBOLorNUMBER();
206  code = FROM_UTF8( CurText() );
207  NeedRIGHT();
208  break;
209 
210  case T_name:
211  NeedSYMBOLorNUMBER();
212  name = FROM_UTF8( CurText() );
213  NeedRIGHT();
214  break;
215 
216  case T_node:
217  // By default: no pin function or type.
218  pin_function.Clear();
219  pin_type.Clear();
220 
221  while( (token = NextTok() ) != T_EOF )
222  {
223  if( token == T_RIGHT )
224  break;
225  else if( token == T_LEFT )
226  token = NextTok();
227 
228  switch( token )
229  {
230  case T_ref:
231  NeedSYMBOLorNUMBER();
232  reference = FROM_UTF8( CurText() );
233  NeedRIGHT();
234  break;
235 
236  case T_pin:
237  NeedSYMBOLorNUMBER();
238  pin_number = FROM_UTF8( CurText() );
239  NeedRIGHT();
240  break;
241 
242  case T_pinfunction:
243  NeedSYMBOLorNUMBER();
244  pin_function = FROM_UTF8( CurText() );
245  NeedRIGHT();
246  break;
247 
248  case T_pintype:
249  NeedSYMBOLorNUMBER();
250  pin_type = FROM_UTF8( CurText() );
251  NeedRIGHT();
252  break;
253 
254  default:
255  skipCurrent();
256  break;
257  }
258  }
259 
260  if( strtol( code.c_str(), NULL, 10 ) >= 1 )
261  {
262  if( name.IsEmpty() ) // Give a dummy net name like N-000009
263  name = wxT("N-00000") + code;
264 
265  component = m_netlist->GetComponentByReference( reference );
266 
267  // Cannot happen if the netlist is valid.
268  if( component == NULL )
269  {
270  wxString msg;
271  msg.Printf( _( "Cannot find component with ref '%s' in netlist." ),
272  reference );
275  }
276 
277  component->AddNet( pin_number, name, pin_function, pin_type );
278  }
279  break;
280 
281  default:
282  skipCurrent();
283  break;
284  }
285  }
286 }
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: