From 5fa0a1a06486f81364525becf2287888a730e64e Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Sat, 17 Sep 2022 08:27:47 +0200 Subject: [PATCH] Sim: Output more descriptive parsing errors --- .../netlist_exporter_spice.cpp | 5 +- eeschema/sim/sim_library_spice.cpp | 7 +- eeschema/sim/sim_model.cpp | 6 +- eeschema/sim/sim_model.h | 1 - eeschema/sim/sim_model_subckt.cpp | 3 +- eeschema/sim/spice_grammar.h | 100 ++++++++++++------ 6 files changed, 80 insertions(+), 42 deletions(-) diff --git a/eeschema/netlist_exporters/netlist_exporter_spice.cpp b/eeschema/netlist_exporters/netlist_exporter_spice.cpp index 607e637875..32278e5fc4 100644 --- a/eeschema/netlist_exporters/netlist_exporter_spice.cpp +++ b/eeschema/netlist_exporters/netlist_exporter_spice.cpp @@ -44,7 +44,7 @@ namespace NETLIST_EXPORTER_SPICE_PARSER { using namespace SPICE_GRAMMAR; - struct textGrammar : spiceSourceGrammar {}; + struct textGrammar : must {}; template struct textSelector : std::false_type {}; template <> struct textSelector : std::true_type {}; @@ -204,7 +204,8 @@ void NETLIST_EXPORTER_SPICE::ReadDirectives( unsigned aNetlistOptions ) try { root = tao::pegtl::parse_tree::parse + NETLIST_EXPORTER_SPICE_PARSER::textSelector, + NETLIST_EXPORTER_SPICE_PARSER::control> ( in ); } catch( const tao::pegtl::parse_error& e ) diff --git a/eeschema/sim/sim_library_spice.cpp b/eeschema/sim/sim_library_spice.cpp index c5248bb634..ffc47cd5f4 100644 --- a/eeschema/sim/sim_library_spice.cpp +++ b/eeschema/sim/sim_library_spice.cpp @@ -35,8 +35,7 @@ namespace SIM_LIBRARY_SPICE_PARSER using namespace SPICE_GRAMMAR; // TODO: unknownLine is already handled in spiceUnit. - struct library : spiceSource {}; - struct libraryGrammar : must {}; + struct libraryGrammar : spiceSourceGrammar {}; template struct librarySelector : std::false_type {}; @@ -57,7 +56,9 @@ void SIM_LIBRARY_SPICE::ReadFile( const wxString& aFilePath ) { tao::pegtl::file_input in( aFilePath.ToStdString() ); auto root = tao::pegtl::parse_tree::parse + SIM_LIBRARY_SPICE_PARSER::librarySelector, + tao::pegtl::nothing, + SIM_LIBRARY_SPICE_PARSER::control> ( in ); SIM_LIBRARY::ReadFile( aFilePath ); diff --git a/eeschema/sim/sim_model.cpp b/eeschema/sim/sim_model.cpp index deea812e71..54081902c6 100644 --- a/eeschema/sim/sim_model.cpp +++ b/eeschema/sim/sim_model.cpp @@ -390,7 +390,8 @@ TYPE SIM_MODEL::ReadTypeFromSpiceCode( const wxString& aSpiceCode ) try { root = tao::pegtl::parse_tree::parse + SIM_MODEL_SPICE_PARSER::spiceUnitSelector, + SIM_MODEL_SPICE_PARSER::control> ( in ); } catch( const tao::pegtl::parse_error& e ) @@ -853,7 +854,8 @@ void SIM_MODEL::ReadSpiceCode( const wxString& aSpiceCode ) try { root = tao::pegtl::parse_tree::parse + SIM_MODEL_SPICE_PARSER::spiceUnitSelector, + SIM_MODEL_SPICE_PARSER::control> ( in ); } catch( tao::pegtl::parse_error& e ) diff --git a/eeschema/sim/sim_model.h b/eeschema/sim/sim_model.h index 740e01880c..0a3b7989c9 100644 --- a/eeschema/sim/sim_model.h +++ b/eeschema/sim/sim_model.h @@ -87,7 +87,6 @@ namespace SIM_MODEL_GRAMMAR opt, sor> {}; - struct fieldParamValuePairs : list {}; struct fieldParamValuePairsGrammar : must, opt, diff --git a/eeschema/sim/sim_model_subckt.cpp b/eeschema/sim/sim_model_subckt.cpp index 13df6dfe52..0e810d20f5 100644 --- a/eeschema/sim/sim_model_subckt.cpp +++ b/eeschema/sim/sim_model_subckt.cpp @@ -81,7 +81,8 @@ void SIM_MODEL_SUBCKT::ReadSpiceCode( const wxString& aSpiceCode ) try { root = tao::pegtl::parse_tree::parse + SIM_MODEL_SUBCKT_SPICE_PARSER::spiceUnitSelector, + SIM_MODEL_SUBCKT_SPICE_PARSER::control> ( in ); } catch( const tao::pegtl::parse_error& e ) diff --git a/eeschema/sim/spice_grammar.h b/eeschema/sim/spice_grammar.h index 8cc7bf9418..56def9935b 100644 --- a/eeschema/sim/spice_grammar.h +++ b/eeschema/sim/spice_grammar.h @@ -88,6 +88,10 @@ namespace SPICE_GRAMMAR struct sep : sor, garbage> {}; + struct modelName : plus, any> {}; + + struct dotModelType : plus {}; + // Ngspice has some heuristic logic to allow + and - in tokens. We replicate that here. struct tokenStart : seq>, opt {}; struct paramValuePairs : list {}; - - struct modelName : plus, any> {}; - - struct dotModelType : plus {}; struct dotModel : seq, - TAO_PEGTL_ISTRING( ".model" ), - sep, - modelName, - sep, - dotModelType, - opt, - opt, - newline> {}; + if_must, + opt, + newline>> {}; struct dotSubcktPinName : seq, - plus, - any>> {}; + plus, any>> {}; struct dotSubcktPinSequence : list {}; struct dotSubcktParams : seq> {}; struct spiceUnit; struct dotSubckt : seq, - TAO_PEGTL_ISTRING( ".subckt" ), - sep, - modelName, - opt, - opt, - opt, - newline, - until> {}; + if_must, + opt, + opt, + newline, + until>> {}; struct modelUnit : sor {}; + // Intentionally no if_must<>. struct dotControl : seq, TAO_PEGTL_ISTRING( ".control" ), until, @@ -159,6 +159,7 @@ namespace SPICE_GRAMMAR struct dotTitleTitle : star, any> {}; + // Intentionally no if_must<>. struct dotTitle : seq, TAO_PEGTL_ISTRING( ".title" ), sep, @@ -169,6 +170,7 @@ namespace SPICE_GRAMMAR struct dotIncludePathWithoutQuotes : star> {}; struct dotIncludePathWithoutApostrophes : star> {}; struct dotIncludePath : star, any> {}; + // Intentionally no if_must<>. struct dotInclude : seq, TAO_PEGTL_ISTRING( ".include" ), sep, @@ -183,6 +185,13 @@ namespace SPICE_GRAMMAR newline> {}; + // Intentionally no if_must<>. + struct dotLine : seq, + one<'.'>, + until> {}; + + + // Intentionally no if_must<>. struct kLine : seq, one<'K'>, until, @@ -192,12 +201,8 @@ namespace SPICE_GRAMMAR until, until> {}; - - struct dotLine : seq, - one<'.'>, - until> {}; - - struct unknownLine : seq, any>, until> {}; + struct unknownLine : seq, any>, + until> {}; struct spiceUnit : sor {}; - struct spiceSourceGrammar : must {}; + struct spiceSourceNothrow : star> {}; + struct spiceSourceGrammar : spiceSource {}; + + + template inline constexpr const char* errorMessage = nullptr; + template <> inline constexpr auto errorMessage = + "expected newline not followed by a line continuation"; + template <> inline constexpr auto errorMessage = + "expected token separator (typ. one or more whitespace, parenthesis, '=', ',', line continuation)"; + template <> inline constexpr auto errorMessage> = ""; + template <> inline constexpr auto errorMessage = "expected model name"; + template <> inline constexpr auto errorMessage = "expected model type"; + template <> inline constexpr auto errorMessage> = ""; + template <> inline constexpr auto errorMessage> = ""; + template <> inline constexpr auto errorMessage> = ""; + template <> inline constexpr auto errorMessage> = + "expected a (possibly empty) sequence of Spice lines followed by an .ends line"; + + // We create a custom PEGTL control to modify the parser error messages. + struct error + { + template static constexpr bool raise_on_failure = false; + template static constexpr auto message = errorMessage; + }; + + template using control = must_if::control; } #endif // SPICE_GRAMMAR_H