KiCad PCB EDA Suite
pcb_parser.h
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2012 CERN
5  * Copyright (C) 2012-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
30 #ifndef _PCBNEW_PARSER_H_
31 #define _PCBNEW_PARSER_H_
32 
33 #include <convert_to_biu.h> // IU_PER_MM
34 #include <hashtables.h>
35 #include <layers_id_colors_and_visibility.h> // PCB_LAYER_ID
36 #include <math/util.h> // KiROUND, Clamp
37 #include <pcb_lexer.h>
38 
39 #include <unordered_map>
40 
41 
42 class ARC;
43 class BOARD;
44 class BOARD_ITEM;
46 class PAD;
48 class DIMENSION_BASE;
49 class PCB_SHAPE;
50 class EDA_TEXT;
51 class FP_SHAPE;
52 class FP_TEXT;
53 class PCB_TEXT;
54 class TRACK;
55 class FOOTPRINT;
56 class PCB_GROUP;
57 class PCB_TARGET;
58 class VIA;
59 class ZONE;
60 class FP_3DMODEL;
61 struct LAYER;
62 
63 
68 class PCB_PARSER : public PCB_LEXER
69 {
70 public:
71  PCB_PARSER( LINE_READER* aReader = NULL ) :
72  PCB_LEXER( aReader ),
73  m_board( nullptr ),
74  m_resetKIIDs( false )
75  {
76  init();
77  }
78 
79  // ~PCB_PARSER() {}
80 
88  {
89  LINE_READER* ret = PopReader();
90  PushReader( aReader );
91  return ret;
92  }
93 
94  void SetBoard( BOARD* aBoard )
95  {
96  init();
97  m_board = aBoard;
98 
99  if( aBoard != nullptr )
100  m_resetKIIDs = true;
101  }
102 
103  BOARD_ITEM* Parse();
104 
111  FOOTPRINT* parseFOOTPRINT( wxArrayString* aInitialComments = 0 );
112 
116  bool IsTooRecent()
117  {
118  return m_tooRecent;
119  }
120 
125  wxString GetRequiredVersion();
126 
127 private:
130  inline int getNetCode( int aNetCode )
131  {
132  if( ( aNetCode >= 0 ) && ( aNetCode < (int) m_netCodes.size() ) )
133  return m_netCodes[aNetCode];
134 
135  return aNetCode;
136  }
137 
146  void pushValueIntoMap( int aIndex, int aValue );
147 
154  void init();
155 
163  void createOldLayerMapping( std::unordered_map< std::string, std::string >& aMap );
164 
169  void skipCurrent();
170 
171  void parseHeader();
172  void parseGeneralSection();
173  void parsePAGE_INFO();
174  void parseTITLE_BLOCK();
175 
176  void parseLayers();
177  void parseLayer( LAYER* aLayer );
178 
179  void parseBoardStackup();
180 
181  void parseSetup();
182  void parseDefaults( BOARD_DESIGN_SETTINGS& aSettings );
183  void parseDefaultTextDims( BOARD_DESIGN_SETTINGS& aSettings, int aLayer );
184  void parseNETINFO_ITEM();
185  void parseNETCLASS();
186 
190 
191  // Parse a footprint, but do not replace PARSE_ERROR with FUTURE_FORMAT_ERROR automatically.
192  FOOTPRINT* parseFOOTPRINT_unchecked( wxArrayString* aInitialComments = 0 );
193 
196  PAD* parsePAD( FOOTPRINT* aParent = NULL );
197 
198  // Parse only the (option ...) inside a pad description
199  bool parsePAD_option( PAD* aPad );
200 
201  ARC* parseARC();
202  TRACK* parseTRACK();
203  VIA* parseVIA();
204  ZONE* parseZONE( BOARD_ITEM_CONTAINER* aParent );
206  BOARD* parseBOARD();
207  void parseGROUP( BOARD_ITEM* aParent );
208 
209  // Parse a board, but do not replace PARSE_ERROR with FUTURE_FORMAT_ERROR automatically.
211 
220  template<class T, class M>
221  T lookUpLayer( const M& aMap );
222 
231 
240 
251  wxPoint parseXY();
252 
253  void parseXY( int* aX, int* aY );
254 
255  std::pair<wxString, wxString> parseProperty();
256 
263  void parseEDA_TEXT( EDA_TEXT* aText );
264 
266 
274  double parseDouble();
275 
276  inline double parseDouble( const char* aExpected )
277  {
278  NeedNUMBER( aExpected );
279  return parseDouble();
280  }
281 
282  inline double parseDouble( PCB_KEYS_T::T aToken )
283  {
284  return parseDouble( GetTokenText( aToken ) );
285  }
286 
287  inline int parseBoardUnits()
288  {
289  // There should be no major rounding issues here, since the values in
290  // the file are in mm and get converted to nano-meters.
291  // See test program tools/test-nm-biu-to-ascii-mm-round-tripping.cpp
292  // to confirm or experiment. Use a similar strategy in both places, here
293  // and in the test program. Make that program with:
294  // $ make test-nm-biu-to-ascii-mm-round-tripping
295  auto retval = parseDouble() * IU_PER_MM;
296 
297  // N.B. we currently represent board units as integers. Any values that are
298  // larger or smaller than those board units represent undefined behavior for
299  // the system. We limit values to the largest that is visible on the screen
300  // This is the diagonal distance of the full screen ~1.5m
301  double int_limit = std::numeric_limits<int>::max() * 0.7071; // 0.7071 = roughly 1/sqrt(2)
302  return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
303  }
304 
305  inline int parseBoardUnits( const char* aExpected )
306  {
307  auto retval = parseDouble( aExpected ) * IU_PER_MM;
308 
309  // N.B. we currently represent board units as integers. Any values that are
310  // larger or smaller than those board units represent undefined behavior for
311  // the system. We limit values to the largest that is visible on the screen
312  double int_limit = std::numeric_limits<int>::max() * 0.7071;
313 
314  // Use here #KiROUND, not EKIROUND (see comments about them) when having a function as
315  // argument, because it will be called twice with #KIROUND.
316  return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
317  }
318 
319  inline int parseBoardUnits( PCB_KEYS_T::T aToken )
320  {
321  return parseBoardUnits( GetTokenText( aToken ) );
322  }
323 
324  inline int parseInt()
325  {
326  return (int)strtol( CurText(), NULL, 10 );
327  }
328 
329  inline int parseInt( const char* aExpected )
330  {
331  NeedNUMBER( aExpected );
332  return parseInt();
333  }
334 
335  inline long parseHex()
336  {
337  NextTok();
338  return strtol( CurText(), NULL, 16 );
339  }
340 
341  bool parseBool();
342 
343  /*
344  * @return if m_resetKIIDs, returns new KIID(), otherwise returns CurStr() as KIID.
345  */
346  KIID CurStrToKIID();
347 
352  void resolveGroups( BOARD_ITEM* aParent );
353 
354  typedef std::unordered_map< std::string, PCB_LAYER_ID > LAYER_ID_MAP;
355  typedef std::unordered_map< std::string, LSET > LSET_MAP;
356  typedef std::unordered_map< wxString, KIID > KIID_MAP;
357 
361  std::set<wxString> m_undefinedLayers;
362  std::vector<int> m_netCodes;
363  bool m_tooRecent;
366 
369 
371 
372  // Group membership info refers to other Uuids in the file.
373  // We don't want to rely on group declarations being last in the file, so
374  // we store info about the group declarations here during parsing and then resolve
375  // them into BOARD_ITEM* after we've parsed the rest of the file.
376  typedef struct
377  {
379  wxString name;
381  std::vector<KIID> memberUuids;
382  } GROUP_INFO;
383 
384  std::vector<GROUP_INFO> m_groupInfos;
385 };
386 
387 
388 #endif // _PCBNEW_PARSER_H_
void parseHeader()
Definition: pcb_parser.cpp:849
Definition: track.h:343
An abstract class from which implementation specific LINE_READERs may be derived to read single lines...
Definition: richio.h:80
KIID CurStrToKIID()
std::unordered_map< wxString, KIID > KIID_MAP
Definition: pcb_parser.h:356
LSET parseBoardItemLayersAsMask()
Parse the layers definition of a BOARD_ITEM object.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:82
TRACK * parseTRACK()
static constexpr double IU_PER_MM
Mock up a conversion function.
VIA * parseVIA()
A set of BOARD_ITEMs (i.e., without duplicates).
Definition: pcb_group.h:50
Read a Pcbnew s-expression formatted LINE_READER object and returns the appropriate BOARD_ITEM object...
Definition: pcb_parser.h:68
std::vector< KIID > memberUuids
Definition: pcb_parser.h:381
void parseBoardStackup()
wxPoint parseXY()
Parse a coordinate pair (xy X Y) in board units (mm).
Definition: pcb_parser.cpp:208
void parseNETINFO_ITEM()
void createOldLayerMapping(std::unordered_map< std::string, std::string > &aMap)
Create a mapping from the (short-lived) bug where layer names were translated.
BOARD * parseBOARD()
Definition: pcb_parser.cpp:517
void parseEDA_TEXT(EDA_TEXT *aText)
Parse the common settings for any object derived from EDA_TEXT.
Definition: pcb_parser.cpp:255
ARC * parseARC()
bool m_tooRecent
true if version parses as later than supported
Definition: pcb_parser.h:363
void parseTITLE_BLOCK()
Definition: pcb_parser.cpp:979
PCB_SHAPE * parsePCB_SHAPE()
int parseBoardUnits(PCB_KEYS_T::T aToken)
Definition: pcb_parser.h:319
int parseBoardUnits()
Definition: pcb_parser.h:287
void parseLayers()
std::unordered_map< std::string, LSET > LSET_MAP
Definition: pcb_parser.h:355
std::unordered_map< std::string, PCB_LAYER_ID > LAYER_ID_MAP
Definition: pcb_parser.h:354
FP_SHAPE * parseFP_SHAPE()
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:119
KIID_MAP m_resetKIIDMap
Definition: pcb_parser.h:368
void parsePAGE_INFO()
Definition: pcb_parser.cpp:923
bool parseBool()
Definition: pcb_parser.cpp:169
void skipCurrent()
Skip the current token level, i.e search for the RIGHT parenthesis which closes the current descripti...
Definition: pcb_parser.cpp:106
Definition: kiid.h:44
bool parsePAD_option(PAD *aPad)
PCB_LAYER_ID
A quick note on layer IDs:
wxString GetRequiredVersion()
Return a string representing the version of KiCad required to open this file.
Definition: pcb_parser.cpp:184
LSET is a set of PCB_LAYER_IDs.
void SetBoard(BOARD *aBoard)
Definition: pcb_parser.h:94
#define NULL
std::pair< wxString, wxString > parseProperty()
Definition: pcb_parser.cpp:240
PCB_TEXT * parsePCB_TEXT()
PCB_PARSER(LINE_READER *aReader=NULL)
Definition: pcb_parser.h:71
PCB_TARGET * parsePCB_TARGET()
PCB_LAYER_ID parseBoardItemLayer()
Parse the layer definition of a BOARD_ITEM object.
FOOTPRINT * parseFOOTPRINT(wxArrayString *aInitialComments=0)
std::vector< GROUP_INFO > m_groupInfos
Definition: pcb_parser.h:384
FP_TEXT * parseFP_TEXT()
PAD * parsePAD(FOOTPRINT *aParent=NULL)
FOOTPRINT * parseFOOTPRINT_unchecked(wxArrayString *aInitialComments=0)
ZONE handles a list of polygons defining a copper zone.
Definition: zone.h:57
BOARD_ITEM * Parse()
Definition: pcb_parser.cpp:473
void parseNETCLASS()
bool m_showLegacyZoneWarning
Definition: pcb_parser.h:370
LINE_READER * SetLineReader(LINE_READER *aReader)
Set aLineReader into the parser, and returns the previous one, if any.
Definition: pcb_parser.h:87
void parseDefaults(BOARD_DESIGN_SETTINGS &aSettings)
int parseInt(const char *aExpected)
Definition: pcb_parser.h:329
void parseGROUP(BOARD_ITEM *aParent)
BOARD * parseBOARD_unchecked()
Definition: pcb_parser.cpp:533
void parseLayer(LAYER *aLayer)
int m_requiredVersion
set to the KiCad format version this board requires
Definition: pcb_parser.h:364
bool IsTooRecent()
Return whether a version number, if any was parsed, was too recent.
Definition: pcb_parser.h:116
void parseDefaultTextDims(BOARD_DESIGN_SETTINGS &aSettings, int aLayer)
Board layer functions and definitions.
Definition: track.h:262
Container to hold information pertinent to a layer of a BOARD.
Definition: board.h:76
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
std::vector< int > m_netCodes
net codes mapping for boards being loaded
Definition: pcb_parser.h:362
int getNetCode(int aNetCode)
< Convert net code using the mapping table if available, otherwise returns unchanged net code if < 0 ...
Definition: pcb_parser.h:130
BOARD * m_board
Definition: pcb_parser.h:358
void parseGeneralSection()
Definition: pcb_parser.cpp:890
void init()
Clear and re-establish m_layerMap with the default layer names.
Definition: pcb_parser.cpp:61
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
void pushValueIntoMap(int aIndex, int aValue)
Add aValue value in netcode mapping (m_netCodes) at aIndex.
Definition: pcb_parser.cpp:127
double parseDouble(PCB_KEYS_T::T aToken)
Definition: pcb_parser.h:282
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
Definition: pcb_parser.cpp:139
const char * GetTokenText(T aTok)
Function GetTokenText is in the DSN namespace and returns the C string representing a SPECCTRA_DB::ke...
Definition: specctra.cpp:69
LAYER_ID_MAP m_layerIndices
map layer name to it's index
Definition: pcb_parser.h:359
Abstract interface for BOARD_ITEMs capable of storing other items inside.
long parseHex()
Definition: pcb_parser.h:335
Definition: pad.h:60
int parseInt()
Definition: pcb_parser.h:324
BOARD_ITEM * parent
Definition: pcb_parser.h:378
DIMENSION_BASE * parseDIMENSION()
Abstract dimension API.
Definition: dimension.h:95
void resolveGroups(BOARD_ITEM *aParent)
Called after parsing a footprint definition or board to build the group membership lists.
Definition: pcb_parser.cpp:756
FP_3DMODEL * parse3DModel()
Definition: pcb_parser.cpp:367
LSET_MAP m_layerMasks
map layer names to their masks
Definition: pcb_parser.h:360
Definition: track.h:83
void parseSetup()
int parseBoardUnits(const char *aExpected)
Definition: pcb_parser.h:305
T lookUpLayer(const M &aMap)
Parse the current token for the layer definition of a BOARD_ITEM object.
std::set< wxString > m_undefinedLayers
set of layers not defined in layers section
Definition: pcb_parser.h:361
bool m_resetKIIDs
reading into an existing board; reset UUIDs
Definition: pcb_parser.h:365
double parseDouble(const char *aExpected)
Definition: pcb_parser.h:276
Container for design settings for a BOARD object.
ZONE * parseZONE(BOARD_ITEM_CONTAINER *aParent)