/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright The KiCad Developers, see AUTHORS.txt for contributors. * @author Jon Evans * * 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 3 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, see . */ #include #include #include #include #include #include #include using namespace LIBRARY_TABLE_GRAMMAR; struct LIBRARY_TABLE_PARSER_STATE { LIBRARY_TABLE_PARSER_STATE() : target_string( nullptr ), current_row_model( {} ), model( {} ) {} std::string* target_string; LIBRARY_TABLE_ROW_IR current_row_model; LIBRARY_TABLE_IR model; }; template struct LIBRARY_TABLE_PARSER_ACTION : tao::pegtl::nothing { }; template <> struct LIBRARY_TABLE_PARSER_ACTION { static void apply0( LIBRARY_TABLE_PARSER_STATE& s ) { s.model.type = LIBRARY_TABLE_TYPE::SYMBOL; } }; template <> struct LIBRARY_TABLE_PARSER_ACTION { static void apply0( LIBRARY_TABLE_PARSER_STATE& s ) { s.model.type = LIBRARY_TABLE_TYPE::FOOTPRINT; } }; template <> struct LIBRARY_TABLE_PARSER_ACTION { static void apply0( LIBRARY_TABLE_PARSER_STATE& s ) { s.model.type = LIBRARY_TABLE_TYPE::DESIGN_BLOCK; } }; template <> struct LIBRARY_TABLE_PARSER_ACTION { template static void apply( const ActionInput& in, LIBRARY_TABLE_PARSER_STATE& s ) { wxCHECK2( s.target_string, return ); *s.target_string = in.string(); } }; template <> struct LIBRARY_TABLE_PARSER_ACTION { template static void apply( const ActionInput& in, LIBRARY_TABLE_PARSER_STATE& s ) { wxCHECK2( s.target_string, return ); wxCHECK2( in.string().size() >= 2, return ); *s.target_string = in.string().substr( 1, in.string().size() - 2 ); } }; #define DEFINE_STRING_ACTION( Rule, StateVariable ) \ template <> \ struct LIBRARY_TABLE_PARSER_ACTION \ { \ static void apply0( LIBRARY_TABLE_PARSER_STATE& s ) \ { \ s.target_string = &s.StateVariable; \ } \ } \ DEFINE_STRING_ACTION( KEYWORDS::VERSION, model.version ); DEFINE_STRING_ACTION( KEYWORDS::NAME, current_row_model.nickname ); DEFINE_STRING_ACTION( KEYWORDS::TYPE, current_row_model.type ); DEFINE_STRING_ACTION( KEYWORDS::URI, current_row_model.uri ); DEFINE_STRING_ACTION( KEYWORDS::OPTIONS, current_row_model.options ); DEFINE_STRING_ACTION( KEYWORDS::DESCR, current_row_model.description ); // Handle (hidden), (disabled) #define DEFINE_FLAG_ACTION( Rule, StateVariable ) \ template <> \ struct LIBRARY_TABLE_PARSER_ACTION \ { \ static void apply0( LIBRARY_TABLE_PARSER_STATE& s ) \ { \ s.StateVariable = true; \ } \ } \ DEFINE_FLAG_ACTION( HIDDEN_MARKER, current_row_model.hidden ); DEFINE_FLAG_ACTION( DISABLED_MARKER, current_row_model.disabled ); template <> struct LIBRARY_TABLE_PARSER_ACTION { static void apply0( LIBRARY_TABLE_PARSER_STATE& s ) { s.model.rows.emplace_back( s.current_row_model ); s.current_row_model = LIBRARY_TABLE_ROW_IR(); } }; LIBRARY_TABLE_PARSER::LIBRARY_TABLE_PARSER() { } tl::expected LIBRARY_TABLE_PARSER::Parse( const std::filesystem::path& aPath ) { try { file_input in( aPath ); LIBRARY_TABLE_PARSER_STATE state; wxLogTrace( traceLibraries, "LIBRARY_TABLE_PARSER::Parse %s", aPath.string().c_str() ); try { if( !parse( in, state ) ) { wxLogTrace( traceLibraries, "Parsing failed without throwing" ); wxString msg = wxString::Format( _( "An unexpected error occurred while reading library table %s "), aPath.string().c_str() ); return tl::unexpected( LIBRARY_PARSE_ERROR( { .description = msg } ) ); } } catch( const parse_error& e ) { const auto& p = e.positions().front(); std::string msg = fmt::format( "Error at line {}, column {}:\n{}\n{:>{}}\n{}", p.line, p.column, in.line_at( p ), "^", p.column, e.message() ); wxLogTrace( traceLibraries, "%s", msg.c_str() ); return tl::unexpected( LIBRARY_PARSE_ERROR( { .description = wxString::Format( _( "Syntax error at line %zu, column %zu" ), p.line, p.column ), .line = p.line, .column = p.column } ) ); } return state.model; } catch( std::filesystem::filesystem_error& e ) { wxLogTrace( traceLibraries, "LIBRARY_TABLE_PARSER::Parse loading '%s' error: %s", aPath.string(), e.what() ); return tl::unexpected( LIBRARY_PARSE_ERROR( { .description = e.what() } ) ); } } tl::expected LIBRARY_TABLE_PARSER::ParseBuffer( const std::string& aBuffer ) { memory_input in( aBuffer, "" ); LIBRARY_TABLE_PARSER_STATE state; wxLogTrace( traceLibraries, "LIBRARY_TABLE_PARSER::Parse from string buffer" ); try { if( !parse( in, state ) ) { wxLogTrace( traceLibraries, "Parsing failed without throwing" ); return tl::unexpected( LIBRARY_PARSE_ERROR( { .description = _( "An unexpected error occurred while reading library table" ) } ) ); } } catch( const parse_error& e ) { const auto& p = e.positions().front(); std::string msg = fmt::format( "Error at line {}, column {}:\n{}\n{:>{}}\n{}", p.line, p.column, in.line_at( p ), "^", p.column, e.message() ); wxLogTrace( traceLibraries, "%s", msg.c_str() ); return tl::unexpected( LIBRARY_PARSE_ERROR( { .description = wxString::Format( _( "Syntax error at line %zu, column %zu" ), p.line, p.column ), .line = p.line, .column = p.column } ) ); } return state.model; }