21#include <fast_float/fast_float.h>
23#include <wx/translation.h>
26#include <pegtl/contrib/parse_tree.hpp>
32#define CALL_INSTANCE( ValueType, Notation, func, ... ) \
35 case SIM_VALUE::TYPE_INT: \
39 func<SIM_VALUE::TYPE_INT, NOTATION::SI>( __VA_ARGS__ ); \
42 case NOTATION::SPICE: \
43 func<SIM_VALUE::TYPE_INT, NOTATION::SPICE>( __VA_ARGS__ ); \
48 case SIM_VALUE::TYPE_FLOAT: \
52 func<SIM_VALUE::TYPE_FLOAT, NOTATION::SI>( __VA_ARGS__ ); \
55 case NOTATION::SPICE: \
56 func<SIM_VALUE::TYPE_FLOAT, NOTATION::SPICE>( __VA_ARGS__ ); \
61 case SIM_VALUE::TYPE_BOOL: \
62 case SIM_VALUE::TYPE_COMPLEX: \
63 case SIM_VALUE::TYPE_STRING: \
64 case SIM_VALUE::TYPE_BOOL_VECTOR: \
65 case SIM_VALUE::TYPE_INT_VECTOR: \
66 case SIM_VALUE::TYPE_FLOAT_VECTOR: \
67 case SIM_VALUE::TYPE_COMPLEX_VECTOR: \
68 wxFAIL_MSG( "Unhandled SIM_VALUE type" ); \
77 template <
typename Rule>
119template <SIM_VALUE::TYPE ValueType, SIM_VALUE_PARSER::NOTATION Notation>
120static inline void doIsValid( tao::pegtl::string_input<>& aIn )
122 tao::pegtl::parse<SIM_VALUE_PARSER::numberGrammar<ValueType, Notation>>( aIn );
129 tao::pegtl::string_input<> in( aString,
"from_content" );
135 catch(
const tao::pegtl::parse_error& )
144template <SIM_VALUE::TYPE ValueType, SIM_VALUE_PARSER::NOTATION Notation>
145static inline std::unique_ptr<tao::pegtl::parse_tree::node>
doParse(
146 tao::pegtl::string_input<>& aIn )
148 return tao::pegtl::parse_tree::parse<SIM_VALUE_PARSER::numberGrammar<ValueType, Notation>,
154template <SIM_VALUE::TYPE ValueType, SIM_VALUE_PARSER::NOTATION Notation>
163 for(
const auto& subnode : aNode.children )
168 aParseResult.
intPart = std::stoll( subnode->string() );
170 aParseResult.
fracPart = std::stoll( subnode->string() );
172 catch(
const std::exception& )
174 aParseResult.
isOk =
false;
180 aParseResult.
exponent = std::stoi( aNode.string() );
190 wxFAIL_MSG(
"Unhandled parse tree node" );
200 tao::pegtl::string_input<> in( aString,
"from_content" );
201 std::unique_ptr<tao::pegtl::parse_tree::node> root;
208 catch( tao::pegtl::parse_error& )
218 for(
const auto& node : root->children )
223 catch(
const std::invalid_argument& e )
225 wxFAIL_MSG( fmt::format(
"Parsing simulator value failed: {:s}", e.what() ) );
238 if( aPrefix.empty() )
243 case 'a':
return -18;
244 case 'f':
return -15;
245 case 'p':
return -12;
261 std::transform( aPrefix.begin(), aPrefix.end(), aPrefix.begin(),
266 else if( aPrefix ==
"p" )
268 else if( aPrefix ==
"n" )
270 else if( aPrefix ==
"u" )
272 else if( aPrefix ==
"m" )
274 else if( aPrefix ==
"" )
276 else if( aPrefix ==
"k" )
278 else if( aPrefix ==
"meg" )
280 else if( aPrefix ==
"g" )
282 else if( aPrefix ==
"t" )
288 wxFAIL_MSG( fmt::format(
"Unknown simulator value suffix: '{:s}'", aPrefix ) );
296 if( aNotation ==
NOTATION::SI && aExponent >= -18 && aExponent <= -15 )
298 aExponentReduction = -18;
301 else if( aExponent >= -15 && aExponent < -12 )
303 aExponentReduction = -15;
306 else if( aExponent >= -12 && aExponent < -9 )
308 aExponentReduction = -12;
311 else if( aExponent >= -9 && aExponent < -6 )
313 aExponentReduction = -9;
316 else if( aExponent >= -6 && aExponent < -3 )
318 aExponentReduction = -6;
321 else if( aExponent >= -3 && aExponent < 0 )
323 aExponentReduction = -3;
326 else if( aExponent >= 0 && aExponent < 3 )
328 aExponentReduction = 0;
331 else if( aExponent >= 3 && aExponent < 6 )
333 aExponentReduction = 3;
336 else if( aExponent >= 6 && aExponent < 9 )
338 aExponentReduction = 6;
341 else if( aExponent >= 9 && aExponent < 12 )
343 aExponentReduction = 9;
346 else if( aExponent >= 12 && aExponent < 15 )
348 aExponentReduction = 12;
351 else if( aNotation ==
NOTATION::SI && aExponent >= 15 && aExponent < 18 )
353 aExponentReduction = 15;
356 else if( aNotation ==
NOTATION::SI && aExponent >= 18 && aExponent <= 21 )
358 aExponentReduction = 18;
362 aExponentReduction = 0;
370 wxString buf( aString );
371 buf.Replace(
',',
'.' );
381 int expReduction = 0;
386 fast_float::from_chars(
390 fast_float::chars_format::skip_white_space | fast_float::chars_format::allow_leading_plus );
404 int expReduction = 0;
408 double reducedValue = aValue / std::pow( 10, expReduction );
410 return fmt::format(
"{:g}{}", reducedValue, prefix );
419 [](
const std::string& aStringVal )
421 for(
char c : aStringVal )
423 if( c !=
'.' && ( c <
'0' || c >
'9' ) )
430 if( plainNumber( aString ) )
448 fast_float::from_chars( parseResult.
significand.data(),
451 fast_float::chars_format::skip_white_space | fast_float::chars_format::allow_leading_plus );
482 return std::abs( aLH -
ToDouble( aRH ) ) <= std::numeric_limits<double>::epsilon();
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
static std::string Normalize(double aValue)
static bool Equal(double aLH, const std::string &aRH)
static std::string ConvertNotation(const std::string &aString, NOTATION aFromNotation, NOTATION aToNotation)
static double ToDouble(const std::string &aString, double aDefault=NAN)
static int ToInt(const std::string &aString, int aDefault=-1)
static std::string ToSpice(const std::string &aString)
SIM_VALUE_GRAMMAR::NOTATION NOTATION
bool IsValid(const std::string &aString, SIM_VALUE::TYPE aValueType=SIM_VALUE::TYPE_FLOAT, NOTATION aNotation=NOTATION::SI)
PARSE_RESULT Parse(const std::string &aString, NOTATION aNotation=NOTATION::SI, SIM_VALUE::TYPE aValueType=SIM_VALUE::TYPE_FLOAT)
int UnitPrefixToExponent(std::string aPrefix, NOTATION aNotation=NOTATION::SI)
std::string ExponentToUnitPrefix(double aExponent, int &aExponentReduction, NOTATION aNotation=NOTATION::SI)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
static void handleNodeForParse(tao::pegtl::parse_tree::node &aNode, SIM_VALUE_PARSER::PARSE_RESULT &aParseResult)
static std::unique_ptr< tao::pegtl::parse_tree::node > doParse(tao::pegtl::string_input<> &aIn)
#define CALL_INSTANCE(ValueType, Notation, func,...)
static void doIsValid(tao::pegtl::string_input<> &aIn)
std::optional< int64_t > fracPart
std::optional< int > unitPrefixExponent
std::optional< int > exponent
std::optional< int64_t > intPart
wxString result
Test unit parsing edge cases and error handling.