KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcb_io_kicad_sexpr_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 The 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, see <https://www.gnu.org/licenses/>.
19 */
20
25
26#ifndef _PCBNEW_PARSER_H_
27#define _PCBNEW_PARSER_H_
28
29#include <eda_units.h>
30#include <core/wx_stl_compat.h>
31#include <line_ending.h>
32#include <hashtables.h>
33#include <lib_id.h>
34#include <layer_ids.h> // PCB_LAYER_ID
35#include <lset.h>
36#include <pcb_lexer.h>
37#include <kiid.h>
38#include <math/box2.h>
39#include <optional>
41#include <drill/drill_span.h>
42#include <string_any_map.h>
43#include <padstack.h>
45
46#include <chrono>
47#include <memory>
48#include <unordered_map>
49#include <utility>
50#include <vector>
51
52
53class PCB_ARC;
54class BOARD;
55class BOARD_ITEM;
56class ZONE_SETTINGS;
59class PAD;
62class PCB_SHAPE;
64class EDA_TEXT;
65class PCB_TEXT;
66class PCB_TEXTBOX;
67class PCB_TRACK;
68class PCB_TABLE;
69class PCB_DRILL_CHART;
70class PCB_DRILL_MAP;
71class PCB_DRILL_CHART;
72class PCB_TABLECELL;
73class FOOTPRINT;
74class PCB_GROUP;
75class PCB_POINT;
76class PCB_TARGET;
77class PCB_GRID_ITEM;
78class PCB_VIA;
79class ZONE;
81class PCB_BARCODE;
82class FP_3DMODEL;
84struct LAYER;
87
88
93class PCB_IO_KICAD_SEXPR_PARSER : public PCB_LEXER
94{
95public:
96
97 typedef std::unordered_map< std::string, PCB_LAYER_ID > LAYER_ID_MAP;
98 typedef std::unordered_map< std::string, LSET > LSET_MAP;
99 typedef std::unordered_map< wxString, KIID > KIID_MAP;
100
102 std::function<bool( wxString, int, wxString, wxString )> aQueryUserCallback,
103 PROGRESS_REPORTER* aProgressReporter = nullptr, unsigned aLineCount = 0,
104 bool aPreserveDestinationStackup = false, bool aAppendToExisting = false ) :
105 PCB_LEXER( aReader ),
106 m_board( aBoard ),
107 m_appendToExisting( aAppendToExisting ),
108 m_preserveDestinationStackup( aPreserveDestinationStackup ),
109 m_progressReporter( aProgressReporter ),
110 m_lastProgressTime( std::chrono::steady_clock::now() ),
111 m_lineCount( aLineCount ),
112 m_queryUserCallback( std::move( aQueryUserCallback ) )
113 {
114 init();
115 }
116
117 // ~PCB_IO_KICAD_SEXPR_PARSER() {}
118
119 BOARD_ITEM* Parse();
120
127 FOOTPRINT* parseFOOTPRINT( wxArrayString* aInitialComments = nullptr );
128
133 {
134 return m_tooRecent;
135 }
136
141 wxString GetRequiredVersion();
142
147 bool IsValidBoardHeader();
148
153 const std::vector<wxString>& GetParseWarnings() const { return m_parseWarnings; }
154
156 void SetLayerMappingHandler( LAYER_MAPPING_HANDLER aHandler ) { m_layerMappingHandler = std::move( aHandler ); }
157
158private:
159
160 // Group membership info refers to other Uuids in the file.
161 // We don't want to rely on group declarations being last in the file, so
162 // we store info about the group declarations here during parsing and then resolve
163 // them into BOARD_ITEM* after we've parsed the rest of the file.
165 {
166 virtual ~GROUP_INFO() = default; // Make polymorphic
167
169 wxString name;
170 bool locked;
173 std::vector<KIID> memberUuids;
174 std::map<wxString, wxString> customProperties;
175 };
176
178 {
180 wxString genType;
182
188 std::vector<std::pair<wxString, std::unique_ptr<BOARD_ITEM>>> templates;
189
190 // The unique_ptr in `templates` makes this struct move-only. std::vector resize
191 // requires a noexcept move-ctor to move (rather than copy, which is deleted), so
192 // declare the move/copy operations explicitly.
193 GENERATOR_INFO() = default;
194 GENERATOR_INFO( GENERATOR_INFO&& ) noexcept = default;
195 GENERATOR_INFO& operator=( GENERATOR_INFO&& ) noexcept = default;
196 GENERATOR_INFO( const GENERATOR_INFO& ) = delete;
197 GENERATOR_INFO& operator=( const GENERATOR_INFO& ) = delete;
198 };
199
203 {
204 BOARD_ITEM* parent = nullptr;
207 std::vector<CONSTRAINT_MEMBER> members;
208 std::optional<double> value;
209 bool driving = true;
210 std::map<wxString, wxString> customProperties;
211 };
212
215 inline int getNetCode( int aNetCode )
216 {
217 if( ( aNetCode >= 0 ) && ( aNetCode < (int) m_netCodes.size() ) )
218 return m_netCodes[aNetCode];
219
220 return aNetCode;
221 }
222
231 void pushValueIntoMap( int aIndex, int aValue );
232
239 void init();
240
241 void checkpoint();
242
250 void createOldLayerMapping( std::unordered_map< std::string, std::string >& aMap );
251
256 void skipCurrent();
257
258 void parseHeader();
259 void parseGeneralSection();
260 void parsePAGE_INFO();
261 void parseTITLE_BLOCK();
262
263 void parseLayers();
264
266 void remapAppendedLayers( const std::vector<LAYER>& aSourceLayers, const LSET& aDestInitialEnabled,
267 int aDestInitialCopperCount );
268 void parseLayer( LAYER* aLayer );
269
270 void parseBoardStackup();
271
272 void parseSetup();
273
275 void parseDefaults( BOARD_DESIGN_SETTINGS& aSettings );
276 void parseDefaultTextDims( BOARD_DESIGN_SETTINGS& aSettings, int aLayer );
277 void parseNETINFO_ITEM();
278 void parseNETCLASS();
280
282
283 void parseTextBoxContent( PCB_TEXTBOX* aTextBox );
284
285 void bakeTextBoxLib( PCB_TEXTBOX* aTextBox );
286
292 void parseLineEnding( LINE_ENDING& aEnding );
293
295 PCB_TEXT* parsePCB_TEXT( BOARD_ITEM* aParent, PCB_TEXT* aBaseText = nullptr );
296 void parsePCB_TEXT_effects( PCB_TEXT* aText, PCB_TEXT* aBaseText = nullptr );
308 bool parseTableBodyToken( PCB_TABLE* aTable, PCB_KEYS_T::T aToken,
309 bool aAllowIdentity );
310 void parseTableBody( PCB_TABLE* aTable, bool aAllowIdentity );
315
316 // Parse a footprint, but do not replace PARSE_ERROR with FUTURE_FORMAT_ERROR automatically.
317 FOOTPRINT* parseFOOTPRINT_unchecked( wxArrayString* aInitialComments = nullptr );
318 void parseFootprintStackup( FOOTPRINT& aFootprint );
319
320 PAD* parsePAD( FOOTPRINT* aParent = nullptr );
321 void parsePAD_primitives( PAD* aPad, PCB_LAYER_ID aLayer );
322 void parsePAD_option( PAD* aPad, PCB_LAYER_ID aLayer );
324 void parsePadstack( PAD* aPad );
325
326 PCB_ARC* parseARC();
329 void parseViastack( PCB_VIA* aVia );
334 BOARD* parseBOARD();
335 void parseGROUP_members( GROUP_INFO& aGroupInfo );
336 void parseGROUP( BOARD_ITEM* aParent );
337 void parseCONSTRAINT( BOARD_ITEM* aParent );
338 void parseGENERATOR( BOARD_ITEM* aParent );
340
341 // Parse a board, but do not replace PARSE_ERROR with FUTURE_FORMAT_ERROR automatically.
343
353 LSET lookUpLayerSet( const LSET_MAP& aMap );
354
363
372
382
394
395 void parseXY( int* aX, int* aY );
396
397 void parseMargins( int& aLeft, int& aTop, int& aRight, int& aBottom );
398
399 void parseZoneDefaults( ZONE_SETTINGS& aZoneSettings );
400
401 void parseZoneLayerProperty( std::map<PCB_LAYER_ID, ZONE_LAYER_PROPERTIES>& aProperties );
402
403 std::pair<wxString, wxString> parseBoardProperty();
404
405 void parseCustomProperty( EDA_ITEM* aItem );
406 void parseCustomProperty( std::map<wxString, wxString>& aProps );
407
408 void parseVariants();
409 void parseFootprintVariant( FOOTPRINT* aFootprint );
410
419
426 void parseEDA_TEXT( EDA_TEXT* aText );
427
435
436 FP_3DMODEL* parse3DModel( bool aFileNameAlreadyParsed = false );
437
445
446 int parseBoardUnits();
447
448 int parseBoardUnits( const char* aExpected, EDA_DATA_TYPE aDataType );
449
450 inline int parseBoardUnits( const PCB_KEYS_T::T aToken, const EDA_DATA_TYPE aDataType = EDA_DATA_TYPE::DISTANCE )
451 {
452 return parseBoardUnits( GetTokenText( aToken ), aDataType );
453 }
454
455 inline int parseInt()
456 {
457 return (int)strtol( CurText(), nullptr, 10 );
458 }
459
460 inline int parseInt( const char* aExpected )
461 {
462 NeedNUMBER( aExpected );
463 return parseInt();
464 }
465
466 inline long parseHex()
467 {
468 NextTok();
469 return strtol( CurText(), nullptr, 16 );
470 }
471
472 bool parseBool();
473
474 std::optional<bool> parseOptBool();
475
486 bool parseMaybeAbsentBool( bool aDefaultValue );
487
488 std::pair<std::optional<bool>, std::optional<bool>> parseFrontBackOptBool( bool aAllowLegacyFormat = false );
489
490 void parseNet( BOARD_CONNECTED_ITEM* aItem );
491
492 /*
493 * @return if m_appendToExisting, returns new KIID(), otherwise returns CurStr() as KIID.
494 */
496
501 void resolveGroups( BOARD_ITEM* aParent );
502 void resolveConstraints( BOARD_ITEM* aParent );
503
505 using TIMEOUT = std::chrono::milliseconds;
506
508 using CLOCK = std::chrono::steady_clock;
509
511 using TIME_PT = std::chrono::time_point<CLOCK>;
512
516 std::set<wxString> m_undefinedLayers;
517 std::vector<int> m_netCodes;
524
527
530
533 unsigned m_lineCount;
534
535 std::vector<GROUP_INFO> m_groupInfos;
536 std::vector<GENERATOR_INFO> m_generatorInfos;
537 std::vector<CONSTRAINT_INFO> m_constraintInfos;
538
539 std::function<bool( wxString aTitle, int aIcon, wxString aMsg, wxString aAction )> m_queryUserCallback;
540
541 std::vector<wxString> m_parseWarnings;
542};
543
544
545#endif // _PCBNEW_PARSER_H_
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
Container for design settings for a BOARD object.
Abstract interface for BOARD_ITEMs capable of storing other items inside.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:409
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:94
Definition kiid.h:46
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
Decorative shape (arrowhead, circle, square) at the start or end of a graphic line,...
Definition line_ending.h:62
An abstract class from which implementation specific LINE_READERs may be derived to read single lines...
Definition richio.h:65
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
Definition pad.h:61
Abstract dimension API.
A drill chart placed on the board, kept in step with the holes.
Turns on drill symbols at the holes, for one layer.
A set of BOARD_ITEMs (i.e., without duplicates).
Definition pcb_group.h:51
void parseCONSTRAINT(BOARD_ITEM *aParent)
wxString m_generatorVersion
Set to the generator version this board requires.
PCB_TABLECELL * parsePCB_TABLECELL(BOARD_ITEM *aParent)
void parseGENERATOR_templates(GENERATOR_INFO &aGenInfo)
std::unordered_map< std::string, PCB_LAYER_ID > LAYER_ID_MAP
std::vector< int > m_netCodes
net codes mapping for boards being loaded
void parseOutlinePoints(SHAPE_LINE_CHAIN &aPoly)
Parses possible outline points and stores them into aPoly.
std::set< wxString > m_undefinedLayers
set of layers not defined in layers section
LAYER_MAPPING_HANDLER m_layerMappingHandler
optional remap of appended layers onto dest
std::vector< CONSTRAINT_INFO > m_constraintInfos
void parseZoneLayerProperty(std::map< PCB_LAYER_ID, ZONE_LAYER_PROPERTIES > &aProperties)
PROGRESS_REPORTER * m_progressReporter
optional; may be nullptr
void parseFootprintStackup(FOOTPRINT &aFootprint)
void createOldLayerMapping(std::unordered_map< std::string, std::string > &aMap)
Create a mapping from the (short-lived) bug where layer names were translated.
bool parseTableBodyToken(PCB_TABLE *aTable, PCB_KEYS_T::T aToken, bool aAllowIdentity)
aAllowIdentity is false inside a drill chart's table_data, where the enclosing form owns uuid,...
void parseZoneDefaults(ZONE_SETTINGS &aZoneSettings)
std::unordered_map< std::string, LSET > LSET_MAP
void parseEDA_TEXT(EDA_TEXT *aText)
Parse the common settings for any object derived from EDA_TEXT.
int parseInt(const char *aExpected)
bool m_tooRecent
true if version parses as later than supported
PCB_LAYER_ID lookUpLayer(const LAYER_ID_MAP &aMap)
Parse the current token for the layer definition of a BOARD_ITEM object.
void remapAppendedLayers(const std::vector< LAYER > &aSourceLayers, const LSET &aDestInitialEnabled, int aDestInitialCopperCount)
Remap the appended layers onto the destination using m_layerMappingHandler, on mismatch.
PCB_REFERENCE_IMAGE * parsePCB_REFERENCE_IMAGE(BOARD_ITEM *aParent)
LAYER_ID_MAP m_layerIndices
map layer name to it's index
const std::vector< wxString > & GetParseWarnings() const
Return any non-fatal parse warnings that occurred during parsing.
void parsePostMachining(PADSTACK::POST_MACHINING_PROPS &aProps)
void parseTableBody(PCB_TABLE *aTable, bool aAllowIdentity)
FP_3DMODEL * parse3DModel(bool aFileNameAlreadyParsed=false)
void parseTextBoxContent(PCB_TEXTBOX *aTextBox)
FOOTPRINT * parseFOOTPRINT(wxArrayString *aInitialComments=nullptr)
void parseLineEnding(LINE_ENDING &aEnding)
Parse a line ending definition from the token stream.
void pushValueIntoMap(int aIndex, int aValue)
Add aValue value in netcode mapping (m_netCodes) at aIndex.
bool m_preserveDestinationStackup
append keeps destination stackup
PCB_DRILL_CHART * parsePCB_DRILL_CHART(BOARD_ITEM *aParent)
std::chrono::steady_clock CLOCK
The type of the time stamps.
void init()
Clear and re-establish m_layerMap with the default layer names.
std::pair< std::optional< bool >, std::optional< bool > > parseFrontBackOptBool(bool aAllowLegacyFormat=false)
void skipCurrent()
Skip the current token level, i.e search for the RIGHT parenthesis which closes the current descripti...
void parseMargins(int &aLeft, int &aTop, int &aRight, int &aBottom)
PCB_LAYER_ID parseBoardItemLayer()
Parse the layer definition of a BOARD_ITEM object.
LSET parseLayersForCuItemWithSoldermask()
Parse the layers definition of a BOARD_ITEM object that has a single copper layer and optional solder...
void parseGENERATOR(BOARD_ITEM *aParent)
std::chrono::milliseconds TIMEOUT
The clock used for the timestamp (guaranteed to be monotonic).
void parsePAD_option(PAD *aPad, PCB_LAYER_ID aLayer)
LSET parseBoardItemLayersAsMask()
Parse the layers definition of a BOARD_ITEM object.
void resolveGroups(BOARD_ITEM *aParent)
Called after parsing a footprint definition or board to build the group membership lists.
void parseDefaultTextDims(BOARD_DESIGN_SETTINGS &aSettings, int aLayer)
std::vector< GROUP_INFO > m_groupInfos
ZONE * parseZONE(BOARD_ITEM_CONTAINER *aParent)
PCB_TABLE * parsePCB_TABLE(BOARD_ITEM *aParent)
std::vector< GENERATOR_INFO > m_generatorInfos
PCB_TEXTBOX * parsePCB_TEXTBOX(BOARD_ITEM *aParent)
std::chrono::time_point< CLOCK > TIME_PT
PCB_TEXT * parsePCB_TEXT(BOARD_ITEM *aParent, PCB_TEXT *aBaseText=nullptr)
unsigned m_lineCount
for progress reporting
VECTOR2I parseXY()
Parse a coordinate pair (xy X Y) in board units (mm).
void parseTEARDROP_PARAMETERS(TEARDROP_PARAMETERS *tdParams)
int m_requiredVersion
set to the KiCad format version this board requires
PAD * parsePAD(FOOTPRINT *aParent=nullptr)
void resolveConstraints(BOARD_ITEM *aParent)
The type of progress bar timeout.
std::function< bool(wxString aTitle, int aIcon, wxString aMsg, wxString aAction)> m_queryUserCallback
void parseNet(BOARD_CONNECTED_ITEM *aItem)
FOOTPRINT * parseFOOTPRINT_unchecked(wxArrayString *aInitialComments=nullptr)
void SetLayerMappingHandler(LAYER_MAPPING_HANDLER aHandler)
Handler to remap an appended board's layers onto the destination board, used on mismatch.
void parseRenderCache(EDA_TEXT *text)
Parse the render cache for any object derived from EDA_TEXT.
PCB_IO_KICAD_SEXPR_PARSER(LINE_READER *aReader, BOARD *aBoard, std::function< bool(wxString, int, wxString, wxString)> aQueryUserCallback, PROGRESS_REPORTER *aProgressReporter=nullptr, unsigned aLineCount=0, bool aPreserveDestinationStackup=false, bool aAppendToExisting=false)
PCB_DRILL_MAP * parsePCB_DRILL_MAP(BOARD_ITEM *aParent)
int parseBoardUnits(const PCB_KEYS_T::T aToken, const EDA_DATA_TYPE aDataType=EDA_DATA_TYPE::DISTANCE)
TIME_PT m_lastProgressTime
for progress reporting
void parseGROUP_members(GROUP_INFO &aGroupInfo)
bool IsTooRecent()
Return whether a version number, if any was parsed, was too recent.
bool IsValidBoardHeader()
Partially parse the input and check if it matches expected header.
void parseFootprintVariant(FOOTPRINT *aFootprint)
std::pair< wxString, wxString > parseBoardProperty()
LSET_MAP m_layerMasks
map layer names to their masks
bool parseMaybeAbsentBool(bool aDefaultValue)
Parses a boolean flag inside a list that existed before boolean normalization.
int parseBoardUnits()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
void bakeTextBoxLib(PCB_TEXTBOX *aTextBox)
Lift disk-parsed values into PCB_TEXTBOX lib storage for new format files.
std::unordered_map< wxString, KIID > KIID_MAP
PCB_DIMENSION_BASE * parseDIMENSION(BOARD_ITEM *aParent)
LSET lookUpLayerSet(const LSET_MAP &aMap)
std::vector< wxString > m_parseWarnings
Non-fatal warnings collected during parsing.
bool m_appendToExisting
reading into an existing board; reset UUIDs
void parsePAD_primitives(PAD *aPad, PCB_LAYER_ID aLayer)
void parsePCB_TEXT_effects(PCB_TEXT *aText, PCB_TEXT *aBaseText=nullptr)
PCB_SHAPE * parsePCB_SHAPE(BOARD_ITEM *aParent)
void parseDefaults(BOARD_DESIGN_SETTINGS &aSettings)
wxString GetRequiredVersion()
Return a string representing the version of KiCad required to open this file.
PCB_BARCODE * parsePCB_BARCODE(BOARD_ITEM *aParent)
A PCB_POINT is a 0-dimensional point that is used to mark a position on a PCB, or more usually a foot...
Definition pcb_point.h:39
Object to handle a bitmap image that can be inserted in a PCB.
A progress reporter interface for use in multi-threaded environments.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
A name/value tuple with unique names and wxAny values.
TEARDROP_PARAMETARS is a helper class to handle parameters needed to build teardrops for a board thes...
ZONE_SETTINGS handles zones parameters.
Handle a list of polygons defining a copper zone.
Definition zone.h:70
Hole classification and drill span, shared by the drill model and the drill writers.
#define LAYER(n, l)
EDA_DATA_TYPE
The type of unit.
Definition eda_units.h:34
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
STL namespace.
PCB_CONSTRAINT_TYPE
The geometric relationship a PCB_CONSTRAINT enforces between its members.
std::function< std::map< wxString, PCB_LAYER_ID >(const std::vector< INPUT_LAYER_DESC > &)> LAYER_MAPPING_HANDLER
Pointer to a function that takes a map of source and KiCad layers and returns a re-mapped version.
Deferred constraint, resolved against the parsed items once the whole file is read,...
GENERATOR_INFO(GENERATOR_INFO &&) noexcept=default
std::vector< std::pair< wxString, std::unique_ptr< BOARD_ITEM > > > templates
Named template items parsed from the generator's (templates …) section.
std::map< wxString, wxString > customProperties
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683