Sim: Output more descriptive parsing errors

This commit is contained in:
Mikolaj Wielgus 2022-09-17 08:27:47 +02:00
parent 5f85c3b8b9
commit 5fa0a1a064
6 changed files with 80 additions and 42 deletions

View File

@ -44,7 +44,7 @@ namespace NETLIST_EXPORTER_SPICE_PARSER
{
using namespace SPICE_GRAMMAR;
struct textGrammar : spiceSourceGrammar {};
struct textGrammar : must<spiceSourceNothrow> {};
template <typename Rule> struct textSelector : std::false_type {};
template <> struct textSelector<modelUnit> : 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::textGrammar,
NETLIST_EXPORTER_SPICE_PARSER::textSelector>
NETLIST_EXPORTER_SPICE_PARSER::textSelector,
NETLIST_EXPORTER_SPICE_PARSER::control>
( in );
}
catch( const tao::pegtl::parse_error& e )

View File

@ -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<library> {};
struct libraryGrammar : spiceSourceGrammar {};
template <typename Rule> 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::libraryGrammar,
SIM_LIBRARY_SPICE_PARSER::librarySelector>
SIM_LIBRARY_SPICE_PARSER::librarySelector,
tao::pegtl::nothing,
SIM_LIBRARY_SPICE_PARSER::control>
( in );
SIM_LIBRARY::ReadFile( aFilePath );

View File

@ -390,7 +390,8 @@ TYPE SIM_MODEL::ReadTypeFromSpiceCode( const wxString& aSpiceCode )
try
{
root = tao::pegtl::parse_tree::parse<SIM_MODEL_SPICE_PARSER::spiceUnitGrammar,
SIM_MODEL_SPICE_PARSER::spiceUnitSelector>
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::spiceUnitGrammar,
SIM_MODEL_SPICE_PARSER::spiceUnitSelector>
SIM_MODEL_SPICE_PARSER::spiceUnitSelector,
SIM_MODEL_SPICE_PARSER::control>
( in );
}
catch( tao::pegtl::parse_error& e )

View File

@ -87,7 +87,6 @@ namespace SIM_MODEL_GRAMMAR
opt<sep>,
sor<quotedString,
unquotedString>> {};
struct fieldParamValuePairs : list<fieldParamValuePair, sep> {};
struct fieldParamValuePairsGrammar : must<opt<sep>,
opt<fieldParamValuePairs>,

View File

@ -81,7 +81,8 @@ void SIM_MODEL_SUBCKT::ReadSpiceCode( const wxString& aSpiceCode )
try
{
root = tao::pegtl::parse_tree::parse<SIM_MODEL_SUBCKT_SPICE_PARSER::spiceUnitGrammar,
SIM_MODEL_SUBCKT_SPICE_PARSER::spiceUnitSelector>
SIM_MODEL_SUBCKT_SPICE_PARSER::spiceUnitSelector,
SIM_MODEL_SUBCKT_SPICE_PARSER::control>
( in );
}
catch( const tao::pegtl::parse_error& e )

View File

@ -88,6 +88,10 @@ namespace SPICE_GRAMMAR
struct sep : sor<plus<continuation>,
garbage> {};
struct modelName : plus<not_at<garbage>, any> {};
struct dotModelType : plus<alpha> {};
// Ngspice has some heuristic logic to allow + and - in tokens. We replicate that here.
struct tokenStart : seq<opt<one<'+', '-'>>,
opt<seq<star<sor<tao::pegtl::digit,
@ -108,12 +112,8 @@ namespace SPICE_GRAMMAR
sep,
paramValue> {};
struct paramValuePairs : list<paramValuePair, sep> {};
struct modelName : plus<not_at<garbage>, any> {};
struct dotModelType : plus<alpha> {};
struct dotModel : seq<opt<sep>,
TAO_PEGTL_ISTRING( ".model" ),
if_must<TAO_PEGTL_ISTRING( ".model" ),
sep,
modelName,
sep,
@ -121,12 +121,11 @@ namespace SPICE_GRAMMAR
opt<sep,
paramValuePairs>,
opt<sep>,
newline> {};
newline>> {};
struct dotSubcktPinName : seq<not_at<TAO_PEGTL_ISTRING( "params:" )>,
plus<not_at<space>,
any>> {};
plus<not_at<space>, any>> {};
struct dotSubcktPinSequence : list<dotSubcktPinName, sep> {};
struct dotSubcktParams : seq<TAO_PEGTL_ISTRING( "params:" ),
sep,
@ -135,7 +134,7 @@ namespace SPICE_GRAMMAR
until<newline>> {};
struct spiceUnit;
struct dotSubckt : seq<opt<sep>,
TAO_PEGTL_ISTRING( ".subckt" ),
if_must<TAO_PEGTL_ISTRING( ".subckt" ),
sep,
modelName,
opt<sep,
@ -145,13 +144,14 @@ namespace SPICE_GRAMMAR
opt<sep>,
newline,
until<dotSubcktEnd,
spiceUnit>> {};
spiceUnit>>> {};
struct modelUnit : sor<dotModel,
dotSubckt> {};
// Intentionally no if_must<>.
struct dotControl : seq<opt<sep>,
TAO_PEGTL_ISTRING( ".control" ),
until<TAO_PEGTL_ISTRING( ".endc" )>,
@ -159,6 +159,7 @@ namespace SPICE_GRAMMAR
struct dotTitleTitle : star<not_at<newline>, any> {};
// Intentionally no if_must<>.
struct dotTitle : seq<opt<sep>,
TAO_PEGTL_ISTRING( ".title" ),
sep,
@ -169,6 +170,7 @@ namespace SPICE_GRAMMAR
struct dotIncludePathWithoutQuotes : star<not_one<'"'>> {};
struct dotIncludePathWithoutApostrophes : star<not_one<'\''>> {};
struct dotIncludePath : star<not_at<newline>, any> {};
// Intentionally no if_must<>.
struct dotInclude : seq<opt<sep>,
TAO_PEGTL_ISTRING( ".include" ),
sep,
@ -183,6 +185,13 @@ namespace SPICE_GRAMMAR
newline> {};
// Intentionally no if_must<>.
struct dotLine : seq<opt<sep>,
one<'.'>,
until<newline>> {};
// Intentionally no if_must<>.
struct kLine : seq<opt<sep>,
one<'K'>,
until<sep>,
@ -192,13 +201,9 @@ namespace SPICE_GRAMMAR
until<sep>,
until<newline>> {};
struct dotLine : seq<opt<sep>,
one<'.'>,
struct unknownLine : seq<plus<not_at<newline>, any>,
until<newline>> {};
struct unknownLine : seq<plus<not_at<newline>, any>, until<newline>> {};
struct spiceUnit : sor<modelUnit,
dotControl,
@ -212,7 +217,36 @@ namespace SPICE_GRAMMAR
struct spiceSource : star<spiceUnit> {};
struct spiceSourceGrammar : must<spiceSource> {};
struct spiceSourceNothrow : star<try_catch<spiceUnit>> {};
struct spiceSourceGrammar : spiceSource {};
template <typename> inline constexpr const char* errorMessage = nullptr;
template <> inline constexpr auto errorMessage<newline> =
"expected newline not followed by a line continuation";
template <> inline constexpr auto errorMessage<sep> =
"expected token separator (typ. one or more whitespace, parenthesis, '=', ',', line continuation)";
template <> inline constexpr auto errorMessage<opt<sep>> = "";
template <> inline constexpr auto errorMessage<modelName> = "expected model name";
template <> inline constexpr auto errorMessage<dotModelType> = "expected model type";
template <> inline constexpr auto errorMessage<opt<sep,
paramValuePairs>> = "";
template <> inline constexpr auto errorMessage<opt<sep,
dotSubcktPinSequence>> = "";
template <> inline constexpr auto errorMessage<opt<sep,
dotSubcktParams>> = "";
template <> inline constexpr auto errorMessage<until<dotSubcktEnd,
spiceUnit>> =
"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 <typename Rule> static constexpr bool raise_on_failure = false;
template <typename Rule> static constexpr auto message = errorMessage<Rule>;
};
template <typename Rule> using control = must_if<error>::control<Rule>;
}
#endif // SPICE_GRAMMAR_H