Sim: Output more descriptive parsing errors
This commit is contained in:
parent
5f85c3b8b9
commit
5fa0a1a064
|
@ -44,7 +44,7 @@ namespace NETLIST_EXPORTER_SPICE_PARSER
|
||||||
{
|
{
|
||||||
using namespace SPICE_GRAMMAR;
|
using namespace SPICE_GRAMMAR;
|
||||||
|
|
||||||
struct textGrammar : spiceSourceGrammar {};
|
struct textGrammar : must<spiceSourceNothrow> {};
|
||||||
|
|
||||||
template <typename Rule> struct textSelector : std::false_type {};
|
template <typename Rule> struct textSelector : std::false_type {};
|
||||||
template <> struct textSelector<modelUnit> : std::true_type {};
|
template <> struct textSelector<modelUnit> : std::true_type {};
|
||||||
|
@ -204,7 +204,8 @@ void NETLIST_EXPORTER_SPICE::ReadDirectives( unsigned aNetlistOptions )
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
root = tao::pegtl::parse_tree::parse<NETLIST_EXPORTER_SPICE_PARSER::textGrammar,
|
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 );
|
( in );
|
||||||
}
|
}
|
||||||
catch( const tao::pegtl::parse_error& e )
|
catch( const tao::pegtl::parse_error& e )
|
||||||
|
|
|
@ -35,8 +35,7 @@ namespace SIM_LIBRARY_SPICE_PARSER
|
||||||
using namespace SPICE_GRAMMAR;
|
using namespace SPICE_GRAMMAR;
|
||||||
|
|
||||||
// TODO: unknownLine is already handled in spiceUnit.
|
// TODO: unknownLine is already handled in spiceUnit.
|
||||||
struct library : spiceSource {};
|
struct libraryGrammar : spiceSourceGrammar {};
|
||||||
struct libraryGrammar : must<library> {};
|
|
||||||
|
|
||||||
|
|
||||||
template <typename Rule> struct librarySelector : std::false_type {};
|
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() );
|
tao::pegtl::file_input in( aFilePath.ToStdString() );
|
||||||
auto root = tao::pegtl::parse_tree::parse<SIM_LIBRARY_SPICE_PARSER::libraryGrammar,
|
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 );
|
( in );
|
||||||
|
|
||||||
SIM_LIBRARY::ReadFile( aFilePath );
|
SIM_LIBRARY::ReadFile( aFilePath );
|
||||||
|
|
|
@ -390,7 +390,8 @@ TYPE SIM_MODEL::ReadTypeFromSpiceCode( const wxString& aSpiceCode )
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
root = tao::pegtl::parse_tree::parse<SIM_MODEL_SPICE_PARSER::spiceUnitGrammar,
|
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 );
|
( in );
|
||||||
}
|
}
|
||||||
catch( const tao::pegtl::parse_error& e )
|
catch( const tao::pegtl::parse_error& e )
|
||||||
|
@ -853,7 +854,8 @@ void SIM_MODEL::ReadSpiceCode( const wxString& aSpiceCode )
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
root = tao::pegtl::parse_tree::parse<SIM_MODEL_SPICE_PARSER::spiceUnitGrammar,
|
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 );
|
( in );
|
||||||
}
|
}
|
||||||
catch( tao::pegtl::parse_error& e )
|
catch( tao::pegtl::parse_error& e )
|
||||||
|
|
|
@ -87,7 +87,6 @@ namespace SIM_MODEL_GRAMMAR
|
||||||
opt<sep>,
|
opt<sep>,
|
||||||
sor<quotedString,
|
sor<quotedString,
|
||||||
unquotedString>> {};
|
unquotedString>> {};
|
||||||
|
|
||||||
struct fieldParamValuePairs : list<fieldParamValuePair, sep> {};
|
struct fieldParamValuePairs : list<fieldParamValuePair, sep> {};
|
||||||
struct fieldParamValuePairsGrammar : must<opt<sep>,
|
struct fieldParamValuePairsGrammar : must<opt<sep>,
|
||||||
opt<fieldParamValuePairs>,
|
opt<fieldParamValuePairs>,
|
||||||
|
|
|
@ -81,7 +81,8 @@ void SIM_MODEL_SUBCKT::ReadSpiceCode( const wxString& aSpiceCode )
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
root = tao::pegtl::parse_tree::parse<SIM_MODEL_SUBCKT_SPICE_PARSER::spiceUnitGrammar,
|
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 );
|
( in );
|
||||||
}
|
}
|
||||||
catch( const tao::pegtl::parse_error& e )
|
catch( const tao::pegtl::parse_error& e )
|
||||||
|
|
|
@ -88,6 +88,10 @@ namespace SPICE_GRAMMAR
|
||||||
struct sep : sor<plus<continuation>,
|
struct sep : sor<plus<continuation>,
|
||||||
garbage> {};
|
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.
|
// Ngspice has some heuristic logic to allow + and - in tokens. We replicate that here.
|
||||||
struct tokenStart : seq<opt<one<'+', '-'>>,
|
struct tokenStart : seq<opt<one<'+', '-'>>,
|
||||||
opt<seq<star<sor<tao::pegtl::digit,
|
opt<seq<star<sor<tao::pegtl::digit,
|
||||||
|
@ -108,12 +112,8 @@ namespace SPICE_GRAMMAR
|
||||||
sep,
|
sep,
|
||||||
paramValue> {};
|
paramValue> {};
|
||||||
struct paramValuePairs : list<paramValuePair, sep> {};
|
struct paramValuePairs : list<paramValuePair, sep> {};
|
||||||
|
|
||||||
struct modelName : plus<not_at<garbage>, any> {};
|
|
||||||
|
|
||||||
struct dotModelType : plus<alpha> {};
|
|
||||||
struct dotModel : seq<opt<sep>,
|
struct dotModel : seq<opt<sep>,
|
||||||
TAO_PEGTL_ISTRING( ".model" ),
|
if_must<TAO_PEGTL_ISTRING( ".model" ),
|
||||||
sep,
|
sep,
|
||||||
modelName,
|
modelName,
|
||||||
sep,
|
sep,
|
||||||
|
@ -121,12 +121,11 @@ namespace SPICE_GRAMMAR
|
||||||
opt<sep,
|
opt<sep,
|
||||||
paramValuePairs>,
|
paramValuePairs>,
|
||||||
opt<sep>,
|
opt<sep>,
|
||||||
newline> {};
|
newline>> {};
|
||||||
|
|
||||||
|
|
||||||
struct dotSubcktPinName : seq<not_at<TAO_PEGTL_ISTRING( "params:" )>,
|
struct dotSubcktPinName : seq<not_at<TAO_PEGTL_ISTRING( "params:" )>,
|
||||||
plus<not_at<space>,
|
plus<not_at<space>, any>> {};
|
||||||
any>> {};
|
|
||||||
struct dotSubcktPinSequence : list<dotSubcktPinName, sep> {};
|
struct dotSubcktPinSequence : list<dotSubcktPinName, sep> {};
|
||||||
struct dotSubcktParams : seq<TAO_PEGTL_ISTRING( "params:" ),
|
struct dotSubcktParams : seq<TAO_PEGTL_ISTRING( "params:" ),
|
||||||
sep,
|
sep,
|
||||||
|
@ -135,7 +134,7 @@ namespace SPICE_GRAMMAR
|
||||||
until<newline>> {};
|
until<newline>> {};
|
||||||
struct spiceUnit;
|
struct spiceUnit;
|
||||||
struct dotSubckt : seq<opt<sep>,
|
struct dotSubckt : seq<opt<sep>,
|
||||||
TAO_PEGTL_ISTRING( ".subckt" ),
|
if_must<TAO_PEGTL_ISTRING( ".subckt" ),
|
||||||
sep,
|
sep,
|
||||||
modelName,
|
modelName,
|
||||||
opt<sep,
|
opt<sep,
|
||||||
|
@ -145,13 +144,14 @@ namespace SPICE_GRAMMAR
|
||||||
opt<sep>,
|
opt<sep>,
|
||||||
newline,
|
newline,
|
||||||
until<dotSubcktEnd,
|
until<dotSubcktEnd,
|
||||||
spiceUnit>> {};
|
spiceUnit>>> {};
|
||||||
|
|
||||||
|
|
||||||
struct modelUnit : sor<dotModel,
|
struct modelUnit : sor<dotModel,
|
||||||
dotSubckt> {};
|
dotSubckt> {};
|
||||||
|
|
||||||
|
|
||||||
|
// Intentionally no if_must<>.
|
||||||
struct dotControl : seq<opt<sep>,
|
struct dotControl : seq<opt<sep>,
|
||||||
TAO_PEGTL_ISTRING( ".control" ),
|
TAO_PEGTL_ISTRING( ".control" ),
|
||||||
until<TAO_PEGTL_ISTRING( ".endc" )>,
|
until<TAO_PEGTL_ISTRING( ".endc" )>,
|
||||||
|
@ -159,6 +159,7 @@ namespace SPICE_GRAMMAR
|
||||||
|
|
||||||
|
|
||||||
struct dotTitleTitle : star<not_at<newline>, any> {};
|
struct dotTitleTitle : star<not_at<newline>, any> {};
|
||||||
|
// Intentionally no if_must<>.
|
||||||
struct dotTitle : seq<opt<sep>,
|
struct dotTitle : seq<opt<sep>,
|
||||||
TAO_PEGTL_ISTRING( ".title" ),
|
TAO_PEGTL_ISTRING( ".title" ),
|
||||||
sep,
|
sep,
|
||||||
|
@ -169,6 +170,7 @@ namespace SPICE_GRAMMAR
|
||||||
struct dotIncludePathWithoutQuotes : star<not_one<'"'>> {};
|
struct dotIncludePathWithoutQuotes : star<not_one<'"'>> {};
|
||||||
struct dotIncludePathWithoutApostrophes : star<not_one<'\''>> {};
|
struct dotIncludePathWithoutApostrophes : star<not_one<'\''>> {};
|
||||||
struct dotIncludePath : star<not_at<newline>, any> {};
|
struct dotIncludePath : star<not_at<newline>, any> {};
|
||||||
|
// Intentionally no if_must<>.
|
||||||
struct dotInclude : seq<opt<sep>,
|
struct dotInclude : seq<opt<sep>,
|
||||||
TAO_PEGTL_ISTRING( ".include" ),
|
TAO_PEGTL_ISTRING( ".include" ),
|
||||||
sep,
|
sep,
|
||||||
|
@ -183,6 +185,13 @@ namespace SPICE_GRAMMAR
|
||||||
newline> {};
|
newline> {};
|
||||||
|
|
||||||
|
|
||||||
|
// Intentionally no if_must<>.
|
||||||
|
struct dotLine : seq<opt<sep>,
|
||||||
|
one<'.'>,
|
||||||
|
until<newline>> {};
|
||||||
|
|
||||||
|
|
||||||
|
// Intentionally no if_must<>.
|
||||||
struct kLine : seq<opt<sep>,
|
struct kLine : seq<opt<sep>,
|
||||||
one<'K'>,
|
one<'K'>,
|
||||||
until<sep>,
|
until<sep>,
|
||||||
|
@ -192,13 +201,9 @@ namespace SPICE_GRAMMAR
|
||||||
until<sep>,
|
until<sep>,
|
||||||
until<newline>> {};
|
until<newline>> {};
|
||||||
|
|
||||||
|
struct unknownLine : seq<plus<not_at<newline>, any>,
|
||||||
struct dotLine : seq<opt<sep>,
|
|
||||||
one<'.'>,
|
|
||||||
until<newline>> {};
|
until<newline>> {};
|
||||||
|
|
||||||
struct unknownLine : seq<plus<not_at<newline>, any>, until<newline>> {};
|
|
||||||
|
|
||||||
|
|
||||||
struct spiceUnit : sor<modelUnit,
|
struct spiceUnit : sor<modelUnit,
|
||||||
dotControl,
|
dotControl,
|
||||||
|
@ -212,7 +217,36 @@ namespace SPICE_GRAMMAR
|
||||||
|
|
||||||
|
|
||||||
struct spiceSource : star<spiceUnit> {};
|
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
|
#endif // SPICE_GRAMMAR_H
|
||||||
|
|
Loading…
Reference in New Issue