KiCad PCB EDA Suite
Loading...
Searching...
No Matches
library_table_parser.cpp
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 The KiCad Developers, see AUTHORS.txt for contributors.
5 * @author Jon Evans <[email protected]>
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * 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
21#include <fmt/format.h>
22#include <pegtl/contrib/parse_tree.hpp>
23#include <wx/log.h>
24
27#include <trace_helpers.h>
28#include <boost/locale/boundary/types.hpp>
29
30
31using namespace LIBRARY_TABLE_GRAMMAR;
32
33
46
47
48template <typename Rule>
49struct LIBRARY_TABLE_PARSER_ACTION : tao::pegtl::nothing<Rule>
50{
51};
52
53
54template <>
56{
61};
62
63
64template <>
66{
71};
72
73
74template <>
75struct LIBRARY_TABLE_PARSER_ACTION<KEYWORDS::DESIGN_BLOCK_LIB_TABLE>
76{
81};
82
83template <>
85{
86 template <typename ActionInput>
87 static void apply( const ActionInput& in, LIBRARY_TABLE_PARSER_STATE& s )
88 {
89 wxCHECK2( s.target_string, return );
90 *s.target_string = in.string();
91 }
92};
93
94
95template <>
97{
98 template <typename ActionInput>
99 static void apply( const ActionInput& in, LIBRARY_TABLE_PARSER_STATE& s )
100 {
101 wxCHECK2( s.target_string, return );
102 wxCHECK2( in.string().size() >= 2, return );
103 std::string inner = in.string().substr( 1, in.string().size() - 2 );
104 std::string unescaped;
105 unescaped.reserve( inner.size() );
106
107 for( size_t ii = 0; ii < inner.size(); ++ii )
108 {
109 if( inner[ii] != '\\' || ii + 1 == inner.size() )
110 {
111 unescaped += inner[ii];
112 }
113 else
114 {
115 switch( inner[++ii] )
116 {
117 case 'n': unescaped += '\n'; break;
118 case 'r': unescaped += '\r'; break;
119 case '\\': unescaped += '\\'; break;
120 case '"': unescaped += '"'; break;
121 default: unescaped += '\\'; unescaped += inner[ii]; break;
122 }
123 }
124 }
125
126 *s.target_string = std::move( unescaped );
127 }
128};
129
130
131#define DEFINE_STRING_ACTION( Rule, StateVariable ) \
132template <> \
133struct LIBRARY_TABLE_PARSER_ACTION<Rule> \
134{ \
135 static void apply0( LIBRARY_TABLE_PARSER_STATE& s ) \
136 { \
137 s.target_string = &s.StateVariable; \
138 } \
139} \
140
142DEFINE_STRING_ACTION( KEYWORDS::NAME, current_row_model.nickname );
143DEFINE_STRING_ACTION( KEYWORDS::TYPE, current_row_model.type );
144DEFINE_STRING_ACTION( KEYWORDS::URI, current_row_model.uri );
145DEFINE_STRING_ACTION( KEYWORDS::OPTIONS, current_row_model.options );
146DEFINE_STRING_ACTION( KEYWORDS::DESCR, current_row_model.description );
147
148// Handle (hidden), (disabled)
149#define DEFINE_FLAG_ACTION( Rule, StateVariable ) \
150template <> \
151struct LIBRARY_TABLE_PARSER_ACTION<Rule> \
152{ \
153 static void apply0( LIBRARY_TABLE_PARSER_STATE& s ) \
154 { \
155 s.StateVariable = true; \
156 } \
157} \
158
159DEFINE_FLAG_ACTION( HIDDEN_MARKER, current_row_model.hidden );
160DEFINE_FLAG_ACTION( DISABLED_MARKER, current_row_model.disabled );
161
162
163template <>
165{
167 {
168 s.model.rows.emplace_back( s.current_row_model );
170 }
171};
172
173
177
178
179tl::expected<LIBRARY_TABLE_IR, LIBRARY_PARSE_ERROR> LIBRARY_TABLE_PARSER::Parse(
180 const std::filesystem::path& aPath )
181{
182 try
183 {
184 file_input in( aPath );
185
187 wxLogTrace( traceLibraries, "LIBRARY_TABLE_PARSER::Parse %s", aPath.string().c_str() );
188
189 try
190 {
191 if( !parse<LIB_TABLE_FILE, LIBRARY_TABLE_PARSER_ACTION>( in, state ) )
192 {
193 wxLogTrace( traceLibraries, "Parsing failed without throwing" );
194 wxString msg = wxString::Format( _( "An unexpected error occurred while reading library table %s "),
195 aPath.string().c_str() );
196 return tl::unexpected( LIBRARY_PARSE_ERROR( { .description = msg } ) );
197 }
198 }
199 catch( const parse_error& e )
200 {
201 const auto& p = e.positions().front();
202 std::string msg = fmt::format( "Error at line {}, column {}:\n{}\n{:>{}}\n{}",
203 p.line, p.column, in.line_at( p ), "^", p.column,
204 e.message() );
205
206 wxLogTrace( traceLibraries, "%s", msg.c_str() );
207
208 return tl::unexpected( LIBRARY_PARSE_ERROR( {
209 .description = wxString::Format( _( "Syntax error at line %zu, column %zu" ),
210 p.line, p.column ),
211 .line = p.line,
212 .column = p.column
213 } ) );
214 }
215
216 return state.model;
217 }
218 catch( std::filesystem::filesystem_error& e )
219 {
220 wxLogTrace( traceLibraries, "LIBRARY_TABLE_PARSER::Parse loading '%s' error: %s", aPath.string(), e.what() );
221
222 return tl::unexpected( LIBRARY_PARSE_ERROR( {
223 .description = e.what()
224 } ) );
225 }
226}
227
228
229tl::expected<LIBRARY_TABLE_IR, LIBRARY_PARSE_ERROR> LIBRARY_TABLE_PARSER::ParseBuffer( const std::string& aBuffer )
230{
231 memory_input in( aBuffer, "" );
233 wxLogTrace( traceLibraries, "LIBRARY_TABLE_PARSER::Parse from string buffer" );
234
235 try
236 {
237 if( !parse<LIB_TABLE_FILE, LIBRARY_TABLE_PARSER_ACTION>( in, state ) )
238 {
239 wxLogTrace( traceLibraries, "Parsing failed without throwing" );
240
241 return tl::unexpected( LIBRARY_PARSE_ERROR( {
242 .description = _( "An unexpected error occurred while reading library table" )
243 } ) );
244 }
245 }
246 catch( const parse_error& e )
247 {
248 const auto& p = e.positions().front();
249 std::string msg = fmt::format( "Error at line {}, column {}:\n{}\n{:>{}}\n{}",
250 p.line, p.column, in.line_at( p ), "^", p.column,
251 e.message() );
252
253 wxLogTrace( traceLibraries, "%s", msg.c_str() );
254
255 return tl::unexpected( LIBRARY_PARSE_ERROR( {
256 .description = wxString::Format( _( "Syntax error at line %zu, column %zu" ),
257 p.line, p.column ),
258 .line = p.line,
259 .column = p.column
260 } ) );
261 }
262
263 return state.model;
264}
tl::expected< LIBRARY_TABLE_IR, LIBRARY_PARSE_ERROR > ParseBuffer(const std::string &aBuffer)
tl::expected< LIBRARY_TABLE_IR, LIBRARY_PARSE_ERROR > Parse(const std::filesystem::path &aPath)
#define _(s)
const wxChar *const traceLibraries
Flag to enable library table and library manager tracing.
#define DEFINE_FLAG_ACTION(Rule, StateVariable)
#define DEFINE_STRING_ACTION(Rule, StateVariable)
The intermediate representation that a library table is parsed into.
std::vector< LIBRARY_TABLE_ROW_IR > rows
LIBRARY_TABLE_TYPE type
static void apply0(LIBRARY_TABLE_PARSER_STATE &s)
static void apply0(LIBRARY_TABLE_PARSER_STATE &s)
static void apply0(LIBRARY_TABLE_PARSER_STATE &s)
static void apply(const ActionInput &in, LIBRARY_TABLE_PARSER_STATE &s)
static void apply(const ActionInput &in, LIBRARY_TABLE_PARSER_STATE &s)
LIBRARY_TABLE_ROW_IR current_row_model
KIBIS_MODEL * model
wxLogTrace helper definitions.