25#include <fast_float/fast_float.h>
27#include <wx/translation.h>
30#include <pegtl/contrib/parse_tree.hpp>
36#define CALL_INSTANCE( ValueType, Notation, func, ... ) \
39 case SIM_VALUE::TYPE_INT: \
43 func<SIM_VALUE::TYPE_INT, NOTATION::SI>( __VA_ARGS__ ); \
46 case NOTATION::SPICE: \
47 func<SIM_VALUE::TYPE_INT, NOTATION::SPICE>( __VA_ARGS__ ); \
52 case SIM_VALUE::TYPE_FLOAT: \
56 func<SIM_VALUE::TYPE_FLOAT, NOTATION::SI>( __VA_ARGS__ ); \
59 case NOTATION::SPICE: \
60 func<SIM_VALUE::TYPE_FLOAT, NOTATION::SPICE>( __VA_ARGS__ ); \
65 case SIM_VALUE::TYPE_BOOL: \
66 case SIM_VALUE::TYPE_COMPLEX: \
67 case SIM_VALUE::TYPE_STRING: \
68 case SIM_VALUE::TYPE_BOOL_VECTOR: \
69 case SIM_VALUE::TYPE_INT_VECTOR: \
70 case SIM_VALUE::TYPE_FLOAT_VECTOR: \
71 case SIM_VALUE::TYPE_COMPLEX_VECTOR: \
72 wxFAIL_MSG( "Unhandled SIM_VALUE type" ); \
81 template <
typename Rule>
123template <SIM_VALUE::TYPE ValueType, SIM_VALUE_PARSER::NOTATION Notation>
124static inline void doIsValid( tao::pegtl::string_input<>& aIn )
126 tao::pegtl::parse<SIM_VALUE_PARSER::numberGrammar<ValueType, Notation>>( aIn );
133 tao::pegtl::string_input<> in( aString,
"from_content" );
139 catch(
const tao::pegtl::parse_error& )
148template <SIM_VALUE::TYPE ValueType, SIM_VALUE_PARSER::NOTATION Notation>
149static inline std::unique_ptr<tao::pegtl::parse_tree::node>
doParse(
150 tao::pegtl::string_input<>& aIn )
152 return tao::pegtl::parse_tree::parse<SIM_VALUE_PARSER::numberGrammar<ValueType, Notation>,
158template <SIM_VALUE::TYPE ValueType, SIM_VALUE_PARSER::NOTATION Notation>
167 for(
const auto& subnode : aNode.children )
172 aParseResult.
intPart = std::stoll( subnode->string() );
174 aParseResult.
fracPart = std::stoll( subnode->string() );
176 catch(
const std::exception& )
178 aParseResult.
isOk =
false;
184 aParseResult.
exponent = std::stoi( aNode.string() );
194 wxFAIL_MSG(
"Unhandled parse tree node" );
204 tao::pegtl::string_input<> in( aString,
"from_content" );
205 std::unique_ptr<tao::pegtl::parse_tree::node> root;
212 catch( tao::pegtl::parse_error& )
222 for(
const auto& node : root->children )
227 catch(
const std::invalid_argument& e )
229 wxFAIL_MSG( fmt::format(
"Parsing simulator value failed: {:s}", e.what() ) );
242 if( aPrefix.empty() )
247 case 'a':
return -18;
248 case 'f':
return -15;
249 case 'p':
return -12;
265 std::transform( aPrefix.begin(), aPrefix.end(), aPrefix.begin(),
270 else if( aPrefix ==
"p" )
272 else if( aPrefix ==
"n" )
274 else if( aPrefix ==
"u" )
276 else if( aPrefix ==
"m" )
278 else if( aPrefix ==
"" )
280 else if( aPrefix ==
"k" )
282 else if( aPrefix ==
"meg" )
284 else if( aPrefix ==
"g" )
286 else if( aPrefix ==
"t" )
292 wxFAIL_MSG( fmt::format(
"Unknown simulator value suffix: '{:s}'", aPrefix ) );
300 if( aNotation ==
NOTATION::SI && aExponent >= -18 && aExponent <= -15 )
302 aExponentReduction = -18;
305 else if( aExponent >= -15 && aExponent < -12 )
307 aExponentReduction = -15;
310 else if( aExponent >= -12 && aExponent < -9 )
312 aExponentReduction = -12;
315 else if( aExponent >= -9 && aExponent < -6 )
317 aExponentReduction = -9;
320 else if( aExponent >= -6 && aExponent < -3 )
322 aExponentReduction = -6;
325 else if( aExponent >= -3 && aExponent < 0 )
327 aExponentReduction = -3;
330 else if( aExponent >= 0 && aExponent < 3 )
332 aExponentReduction = 0;
335 else if( aExponent >= 3 && aExponent < 6 )
337 aExponentReduction = 3;
340 else if( aExponent >= 6 && aExponent < 9 )
342 aExponentReduction = 6;
345 else if( aExponent >= 9 && aExponent < 12 )
347 aExponentReduction = 9;
350 else if( aExponent >= 12 && aExponent < 15 )
352 aExponentReduction = 12;
355 else if( aNotation ==
NOTATION::SI && aExponent >= 15 && aExponent < 18 )
357 aExponentReduction = 15;
360 else if( aNotation ==
NOTATION::SI && aExponent >= 18 && aExponent <= 21 )
362 aExponentReduction = 18;
366 aExponentReduction = 0;
374 wxString buf( aString );
375 buf.Replace(
',',
'.' );
385 int expReduction = 0;
390 fast_float::from_chars(
394 fast_float::chars_format::skip_white_space | fast_float::chars_format::allow_leading_plus );
408 int expReduction = 0;
412 double reducedValue = aValue / std::pow( 10, expReduction );
414 return fmt::format(
"{:g}{}", reducedValue, prefix );
423 [](
const std::string& aStringVal )
425 for(
char c : aStringVal )
427 if( c !=
'.' && ( c <
'0' || c >
'9' ) )
434 if( plainNumber( aString ) )
452 fast_float::from_chars( parseResult.
significand.data(),
455 fast_float::chars_format::skip_white_space | fast_float::chars_format::allow_leading_plus );
486 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.