diff options
Diffstat (limited to 'pcbnew/pcb_parser.h')
-rw-r--r-- | pcbnew/pcb_parser.h | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/pcbnew/pcb_parser.h b/pcbnew/pcb_parser.h new file mode 100644 index 0000000..cd815ad --- /dev/null +++ b/pcbnew/pcb_parser.h @@ -0,0 +1,327 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 CERN + * Copyright (C) 2012-2016 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file pcb_parser.h + * @brief Pcbnew s-expression file format parser definition. + */ + +#ifndef _PCBNEW_PARSER_H_ +#define _PCBNEW_PARSER_H_ + +#include <pcb_lexer.h> +#include <hashtables.h> +#include <layers_id_colors_and_visibility.h> // LAYER_ID +#include <common.h> // KiROUND +#include <convert_to_biu.h> // IU_PER_MM + + +class BOARD; +class BOARD_ITEM; +class D_PAD; +class DIMENSION; +class DRAWSEGMENT; +class EDA_TEXT; +class EDGE_MODULE; +class TEXTE_MODULE; +class TEXTE_PCB; +class TRACK; +class MODULE; +class PCB_TARGET; +class VIA; +class S3D_MASTER; +class ZONE_CONTAINER; +struct LAYER; + + +/** + * Class PCB_PARSER + * reads a Pcbnew s-expression formatted #LINE_READER object and returns the appropriate + * #BOARD_ITEM object. + */ +class PCB_PARSER : public PCB_LEXER +{ + typedef boost::unordered_map< std::string, LAYER_ID > LAYER_ID_MAP; + typedef boost::unordered_map< std::string, LSET > LSET_MAP; + + BOARD* m_board; + LAYER_ID_MAP m_layerIndices; ///< map layer name to it's index + LSET_MAP m_layerMasks; ///< map layer names to their masks + std::vector<int> m_netCodes; ///< net codes mapping for boards being loaded + bool m_tooRecent; ///< true if version parses as later than supported + int m_requiredVersion; ///< set to the KiCad format version this board requires + + ///> Converts net code using the mapping table if available, + ///> otherwise returns unchanged net code if < 0 or if is is out of range + inline int getNetCode( int aNetCode ) + { + if( ( aNetCode >= 0 ) && ( aNetCode < (int) m_netCodes.size() ) ) + return m_netCodes[aNetCode]; + + return aNetCode; + } + + /** + * function pushValueIntoMap + * Add aValue value in netcode mapping (m_netCodes) at index aIndex + * ensure there is room in m_netCodes for that, and add room if needed. + * @param aIndex = the index ( expected >=0 )of the location to use in m_netCodes + * @param aValue = the netcode value to map + */ + void pushValueIntoMap( int aIndex, int aValue ); + + /** + * Function init + * clears and re-establishes m_layerMap with the default layer names. + * m_layerMap will have some of its entries overwritten whenever a (new) board + * is encountered. + */ + void init(); + + void parseHeader() throw( IO_ERROR, PARSE_ERROR ); + void parseGeneralSection() throw( IO_ERROR, PARSE_ERROR ); + void parsePAGE_INFO() throw( IO_ERROR, PARSE_ERROR ); + void parseTITLE_BLOCK() throw( IO_ERROR, PARSE_ERROR ); + + void parseLayers() throw( IO_ERROR, PARSE_ERROR ); + void parseLayer( LAYER* aLayer ) throw( IO_ERROR, PARSE_ERROR ); + + void parseSetup() throw( IO_ERROR, PARSE_ERROR ); + void parseNETINFO_ITEM() throw( IO_ERROR, PARSE_ERROR ); + void parseNETCLASS() throw( IO_ERROR, PARSE_ERROR ); + + DRAWSEGMENT* parseDRAWSEGMENT() throw( IO_ERROR, PARSE_ERROR ); + TEXTE_PCB* parseTEXTE_PCB() throw( IO_ERROR, PARSE_ERROR ); + DIMENSION* parseDIMENSION() throw( IO_ERROR, PARSE_ERROR ); + + /** + * Function parseMODULE + * @param aInitialComments may be a pointer to a heap allocated initial comment block + * or NULL. If not NULL, then caller has given ownership of a wxArrayString to + * this function and care must be taken to delete it even on exception. + */ + MODULE* parseMODULE( wxArrayString* aInitialComments = 0 ) + throw( IO_ERROR, PARSE_ERROR, FUTURE_FORMAT_ERROR ); + + /** + * Function parseMODULE_unchecked + * Parse a module, but do not replace PARSE_ERROR with FUTURE_FORMAT_ERROR automatically. + */ + MODULE* parseMODULE_unchecked( wxArrayString* aInitialComments = 0 ) + throw( IO_ERROR, PARSE_ERROR ); + TEXTE_MODULE* parseTEXTE_MODULE() throw( IO_ERROR, PARSE_ERROR ); + EDGE_MODULE* parseEDGE_MODULE() throw( IO_ERROR, PARSE_ERROR ); + D_PAD* parseD_PAD( MODULE* aParent = NULL ) throw( IO_ERROR, PARSE_ERROR ); + TRACK* parseTRACK() throw( IO_ERROR, PARSE_ERROR ); + VIA* parseVIA() throw( IO_ERROR, PARSE_ERROR ); + ZONE_CONTAINER* parseZONE_CONTAINER() throw( IO_ERROR, PARSE_ERROR ); + PCB_TARGET* parsePCB_TARGET() throw( IO_ERROR, PARSE_ERROR ); + BOARD* parseBOARD() throw( IO_ERROR, PARSE_ERROR, FUTURE_FORMAT_ERROR ); + + /** + * Function parseBOARD_unchecked + * Parse a module, but do not replace PARSE_ERROR with FUTURE_FORMAT_ERROR automatically. + */ + BOARD* parseBOARD_unchecked() throw( IO_ERROR, PARSE_ERROR ); + + + /** + * Function lookUpLayer + * parses the current token for the layer definition of a #BOARD_ITEM object. + * + * @param aMap is the LAYER_{NUM|MSK}_MAP to use for the lookup. + * + * @throw IO_ERROR if the layer is not valid. + * @throw PARSE_ERROR if the layer syntax is incorrect. + * @return int - The result of the parsed #BOARD_ITEM layer or set designator. + */ + template<class T, class M> + T lookUpLayer( const M& aMap ) throw( PARSE_ERROR, IO_ERROR ); + + /** + * Function parseBoardItemLayer + * parses the layer definition of a #BOARD_ITEM object. + * + * @throw IO_ERROR if the layer is not valid. + * @throw PARSE_ERROR if the layer syntax is incorrect. + * @return The index the parsed #BOARD_ITEM layer. + */ + LAYER_ID parseBoardItemLayer() throw( IO_ERROR, PARSE_ERROR ); + + /** + * Function parseBoardItemLayersAsMask + * parses the layers definition of a #BOARD_ITEM object. + * + * @throw IO_ERROR if any of the layers is not valid. + * @throw PARSE_ERROR if the layers syntax is incorrect. + * @return The mask of layers the parsed #BOARD_ITEM is on. + */ + LSET parseBoardItemLayersAsMask() throw( PARSE_ERROR, IO_ERROR ); + + /** + * Function parseXY + * parses a coordinate pair (xy X Y) in board units (mm). + * + * The parser checks if the previous token was T_LEFT and parses the remainder of + * the token syntax. This is used when parsing a list of coordinate points. This + * way the parser can be used in either case. + * + * @throw PARSE_ERROR if the coordinate pair syntax is incorrect. + * @return A wxPoint object containing the coordinate pair. + */ + wxPoint parseXY() throw( PARSE_ERROR, IO_ERROR ); + + void parseXY( int* aX, int* aY ) throw( PARSE_ERROR, IO_ERROR ); + + /** + * Function parseEDA_TEXT + * parses the common settings for any object derived from #EDA_TEXT. + * + * @throw PARSE_ERROR if the text syntax is not valid. + * @param aText A point to the #EDA_TEXT object to save the parsed settings into. + */ + void parseEDA_TEXT( EDA_TEXT* aText ) throw( PARSE_ERROR, IO_ERROR ); + + S3D_MASTER* parse3DModel() throw( PARSE_ERROR, IO_ERROR ); + + /** + * Function parseDouble + * parses the current token as an ASCII numeric string with possible leading + * whitespace into a double precision floating point number. + * + * @throw IO_ERROR if an error occurs attempting to convert the current token. + * @return The result of the parsed token. + */ + double parseDouble() throw( IO_ERROR ); + + inline double parseDouble( const char* aExpected ) throw( IO_ERROR ) + { + NeedNUMBER( aExpected ); + return parseDouble(); + } + + inline double parseDouble( PCB_KEYS_T::T aToken ) throw( IO_ERROR ) + { + return parseDouble( GetTokenText( aToken ) ); + } + + inline int parseBoardUnits() throw( IO_ERROR ) + { + // There should be no major rounding issues here, since the values in + // the file are in mm and get converted to nano-meters. + // See test program tools/test-nm-biu-to-ascii-mm-round-tripping.cpp + // to confirm or experiment. Use a similar strategy in both places, here + // and in the test program. Make that program with: + // $ make test-nm-biu-to-ascii-mm-round-tripping + return KiROUND( parseDouble() * IU_PER_MM ); + } + + inline int parseBoardUnits( const char* aExpected ) throw( PARSE_ERROR, IO_ERROR ) + { + // Use here KiROUND, not KIROUND (see comments about them) + // when having a function as argument, because it will be called twice + // with KIROUND + return KiROUND( parseDouble( aExpected ) * IU_PER_MM ); + } + + inline int parseBoardUnits( PCB_KEYS_T::T aToken ) throw( PARSE_ERROR, IO_ERROR ) + { + return parseBoardUnits( GetTokenText( aToken ) ); + } + + inline int parseInt() throw( PARSE_ERROR ) + { + return (int)strtol( CurText(), NULL, 10 ); + } + + inline int parseInt( const char* aExpected ) throw( PARSE_ERROR ) + { + NeedNUMBER( aExpected ); + return parseInt(); + } + + inline long parseHex() throw( PARSE_ERROR ) + { + NextTok(); + return strtol( CurText(), NULL, 16 ); + } + + bool parseBool() throw( PARSE_ERROR ); + + /** + * Parse a format version tag like (version 20160417) return the version. + * Expects to start on 'version', and eats the closing paren. + */ + int parseVersion() throw( IO_ERROR, PARSE_ERROR ); + +public: + + PCB_PARSER( LINE_READER* aReader = NULL ) : + PCB_LEXER( aReader ), + m_board( 0 ) + { + init(); + } + + // ~PCB_PARSER() {} + + /** + * Function SetLineReader + * sets @a aLineReader into the parser, and returns the previous one, if any. + * @param aReader is what to read from for tokens, no ownership is received. + * @return LINE_READER* - previous LINE_READER or NULL if none. + */ + LINE_READER* SetLineReader( LINE_READER* aReader ) + { + LINE_READER* ret = PopReader(); + PushReader( aReader ); + return ret; + } + + void SetBoard( BOARD* aBoard ) + { + init(); + m_board = aBoard; + } + + BOARD_ITEM* Parse() throw( IO_ERROR, PARSE_ERROR ); + + /** + * Return whether a version number, if any was parsed, was too recent + */ + bool IsTooRecent() + { + return m_tooRecent; + } + + /** + * Return a string representing the version of kicad required to open this + * file. Not particularly meaningful if IsTooRecent() returns false. + */ + wxString GetRequiredVersion(); + +}; + + +#endif // _PCBNEW_PARSER_H_ |