KiCad PCB EDA Suite
KICAD_NETLIST_PARSER Class Reference

KICAD_NETLIST_PARSER is 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 ()
 Function skipCurrent Skip the current token level, i.e search for the RIGHT parenthesis which closes the current description. More...
 
void parseComponent ()
 Function 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 ()
 Function parseNet Parses a section like (net (code 20) (name /PC-A0) (node (ref BUS1) (pin 62)) (node (ref U3) (pin 3)) (node (ref U9) (pin M6))) More...
 
void parseLibPartList ()
 Function parseLibPartList reads 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

KICAD_NETLIST_PARSER is the parser for reading the KiCad s-expression netlist format.

Definition at line 293 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 55 of file kicad_netlist_reader.cpp.

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

372  {
373  return NETLIST_LEXER::TokenName( aTok );
374  }

◆ Parse()

void KICAD_NETLIST_PARSER::Parse ( )

Function Parse parse the full netlist.

Definition at line 84 of file kicad_netlist_reader.cpp.

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

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

◆ parseComponent()

void KICAD_NETLIST_PARSER::parseComponent ( )
private

Function 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))

Definition at line 281 of file kicad_netlist_reader.cpp.

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

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

Referenced by Parse().

◆ parseLibPartList()

void KICAD_NETLIST_PARSER::parseLibPartList ( )
private

Function parseLibPartList reads 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 module info

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

Definition at line 440 of file kicad_netlist_reader.cpp.

441 {
442  /* Parses a section like
443  * (libpart (lib device) (part C)
444  * (aliases
445  * (alias Cxx)
446  * (alias Cyy))
447  * (description "Condensateur non polarise")
448  * (footprints
449  * (fp SM*)
450  * (fp C?)
451  * (fp C1-1))
452  * (fields
453  * (field (name Reference) C)
454  * (field (name Value) C))
455  * (pins
456  * (pin (num 1) (name ~) (type passive))
457  * (pin (num 2) (name ~) (type passive))))
458  *
459  * Currently footprints section/fp are read and data stored
460  * other fields (unused) are skipped
461  */
462  COMPONENT* component = NULL;
463  wxString libName;
464  wxString libPartName;
465  wxArrayString footprintFilters;
466  wxArrayString aliases;
467  int pinCount = 0;
468 
469  // The last token read was libpart, so read the next token
470  while( (token = NextTok()) != T_RIGHT )
471  {
472  if( token == T_LEFT )
473  token = NextTok();
474 
475  switch( token )
476  {
477  case T_lib:
478  NeedSYMBOLorNUMBER();
479  libName = FROM_UTF8( CurText() );
480  NeedRIGHT();
481  break;
482 
483  case T_part:
484  NeedSYMBOLorNUMBER();
485  libPartName = FROM_UTF8( CurText() );
486  NeedRIGHT();
487  break;
488 
489  case T_footprints:
490  // Read all fp elements (footprint filter item)
491  while( (token = NextTok()) != T_RIGHT )
492  {
493  if( token == T_LEFT )
494  token = NextTok();
495 
496  if( token != T_fp )
497  Expecting( T_fp );
498 
499  NeedSYMBOLorNUMBER();
500  footprintFilters.Add( FROM_UTF8( CurText() ) );
501  NeedRIGHT();
502  }
503  break;
504 
505  case T_aliases:
506  while( (token = NextTok()) != T_RIGHT )
507  {
508  if( token == T_LEFT )
509  token = NextTok();
510 
511  if( token != T_alias )
512  Expecting( T_alias );
513 
514  NeedSYMBOLorNUMBER();
515  aliases.Add( FROM_UTF8( CurText() ) );
516  NeedRIGHT();
517  }
518  break;
519 
520  case T_pins:
521  while( (token = NextTok()) != T_RIGHT )
522  {
523  if( token == T_LEFT )
524  token = NextTok();
525 
526  if( token != T_pin )
527  Expecting( T_pin );
528 
529  pinCount++;
530 
531  skipCurrent();
532  }
533  break;
534 
535  default:
536  // Skip not used data (i.e all other tokens)
537  skipCurrent();
538  break;
539  }
540  }
541 
542  // Find all of the components that reference this component library part definition.
543  for( unsigned i = 0; i < m_netlist->GetCount(); i++ )
544  {
545  component = m_netlist->GetComponent( i );
546 
547  if( component->IsLibSource( libName, libPartName ) )
548  {
549  component->SetFootprintFilters( footprintFilters );
550  component->SetPinCount( pinCount );
551  }
552 
553  for( unsigned jj = 0; jj < aliases.GetCount(); jj++ )
554  {
555  if( component->IsLibSource( libName, aliases[jj] ) )
556  {
557  component->SetFootprintFilters( footprintFilters );
558  component->SetPinCount( pinCount );
559  }
560  }
561 
562  }
563 }
bool IsLibSource(const wxString &aLibrary, const wxString &aName) const
Definition: pcb_netlist.h:177
static wxString FROM_UTF8(const char *cstring)
function FROM_UTF8 converts a UTF8 encoded C string to a wxString for all wxWidgets build modes.
Definition: macros.h:109
NETLIST * m_netlist
The netlist to parse into. Not owned.
void skipCurrent()
Function skipCurrent Skip the current token level, i.e search for the RIGHT parenthesis which closes ...
unsigned GetCount() const
Function GetCount.
Definition: pcb_netlist.h:224
#define NULL
void SetPinCount(int aPinCount)
Definition: pcb_netlist.h:167
COMPONENT is used to store components and all of their related information found in a netlist.
Definition: pcb_netlist.h:80
COMPONENT * GetComponent(unsigned aIndex)
Function GetComponent returns the COMPONENT at aIndex.
Definition: pcb_netlist.h:233
void SetFootprintFilters(const wxArrayString &aFilters)
Definition: pcb_netlist.h:164

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

Referenced by Parse().

◆ parseNet()

void KICAD_NETLIST_PARSER::parseNet ( )
private

Function parseNet Parses a section like (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  int nodecount = 0;
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 
215  if( name.IsEmpty() ) // Give a dummy net name like N-000109
216  name = wxT("N-00000") + code;
217 
218  break;
219 
220  case T_node:
221  pin_function.Clear(); // By default: no pin function.
222 
223  while( (token = NextTok()) != T_EOF )
224  {
225  if( token == T_RIGHT )
226  break;
227  else if( token == T_LEFT )
228  token = NextTok();
229 
230  switch( token )
231  {
232  case T_ref:
233  NeedSYMBOLorNUMBER();
234  reference = FROM_UTF8( CurText() );
235  NeedRIGHT();
236  break;
237 
238  case T_pin:
239  NeedSYMBOLorNUMBER();
240  pin_number = FROM_UTF8( CurText() );
241  NeedRIGHT();
242  break;
243 
244  case T_pinfunction:
245  NeedSYMBOLorNUMBER();
246  pin_function = FROM_UTF8( CurText() );
247  NeedRIGHT();
248  break;
249 
250  default:
251  skipCurrent();
252  break;
253  }
254  }
255 
256 
257  component = m_netlist->GetComponentByReference( reference );
258 
259  // Cannot happen if the netlist is valid.
260  if( component == NULL )
261  {
262  wxString msg;
263  msg.Printf( _( "Cannot find component with reference designator \"%s\" in netlist." ),
264  reference );
267  }
268 
269  component->AddNet( pin_number, name, pin_function );
270  nodecount++;
271  break;
272 
273  default:
274  skipCurrent();
275  break;
276  }
277  }
278 }
char * Line() const
Function Line returns a pointer to the last line that was read in.
Definition: richio.h:140
static wxString FROM_UTF8(const char *cstring)
function FROM_UTF8 converts a UTF8 encoded C string to a wxString for all wxWidgets build modes.
Definition: macros.h:109
virtual const wxString & GetSource() const
Function GetSource returns the name of the source of the lines in an abstract sense.
Definition: richio.h:131
NETLIST * m_netlist
The netlist to parse into. Not owned.
void skipCurrent()
Function skipCurrent Skip the current token level, i.e search for the RIGHT parenthesis which closes ...
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:171
#define NULL
LINE_READER * m_lineReader
The line reader used to parse the netlist. Not owned.
virtual unsigned LineNumber() const
Function Line Number returns the line number of the last line read from this LINE_READER.
Definition: richio.h:160
COMPONENT is used to store components and all of their related information found in a netlist.
Definition: pcb_netlist.h:80
unsigned Length() const
Function Length returns the number of bytes in the last line read from this LINE_READER.
Definition: richio.h:169
const char * name
Definition: DXF_plotter.cpp:59
#define _(s)
Definition: 3d_actions.cpp:33
COMPONENT * GetComponentByReference(const wxString &aReference)
Function GetComponentByReference returns a COMPONENT by aReference.
void AddNet(const wxString &aPinName, const wxString &aNetName, const wxString &aPinFunction)
Definition: pcb_netlist.h:128

References _, COMPONENT::AddNet(), FROM_UTF8(), NETLIST::GetComponentByReference(), LINE_READER::GetSource(), LINE_READER::Length(), LINE_READER::Line(), LINE_READER::LineNumber(), m_lineReader, m_netlist, name, NULL, 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 362 of file netlist_reader.h.

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

References m_netlist.

◆ skipCurrent()

void KICAD_NETLIST_PARSER::skipCurrent ( )
private

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

Definition at line 64 of file kicad_netlist_reader.cpp.

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

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 297 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 298 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: