26#include <wx/translation.h>
29#include <pegtl/contrib/parse_tree.hpp>
34#define CALL_INSTANCE( ValueType, Notation, func, ... ) \
37 case SIM_VALUE::TYPE_INT: \
41 func<SIM_VALUE::TYPE_INT, NOTATION::SI>( __VA_ARGS__ ); \
44 case NOTATION::SPICE: \
45 func<SIM_VALUE::TYPE_INT, NOTATION::SPICE>( __VA_ARGS__ ); \
50 case SIM_VALUE::TYPE_FLOAT: \
54 func<SIM_VALUE::TYPE_FLOAT, NOTATION::SI>( __VA_ARGS__ ); \
57 case NOTATION::SPICE: \
58 func<SIM_VALUE::TYPE_FLOAT, NOTATION::SPICE>( __VA_ARGS__ ); \
63 case SIM_VALUE::TYPE_BOOL: \
64 case SIM_VALUE::TYPE_COMPLEX: \
65 case SIM_VALUE::TYPE_STRING: \
66 case SIM_VALUE::TYPE_BOOL_VECTOR: \
67 case SIM_VALUE::TYPE_INT_VECTOR: \
68 case SIM_VALUE::TYPE_FLOAT_VECTOR: \
69 case SIM_VALUE::TYPE_COMPLEX_VECTOR: \
70 wxFAIL_MSG( "Unhandled SIM_VALUE type" ); \
79 template <
typename Rule>
117 NOTATION aNotation = NOTATION::SI );
121template <SIM_VALUE::TYPE ValueType, SIM_VALUE_PARSER::NOTATION Notation>
122static inline void doIsValid( tao::pegtl::string_input<>& aIn )
124 tao::pegtl::parse<SIM_VALUE_PARSER::numberGrammar<ValueType, Notation>>( aIn );
131 tao::pegtl::string_input<> in( aString,
"from_content" );
137 catch(
const tao::pegtl::parse_error& )
146template <SIM_VALUE::TYPE ValueType, SIM_VALUE_PARSER::NOTATION Notation>
147static inline std::unique_ptr<tao::pegtl::parse_tree::node>
doParse(
148 tao::pegtl::string_input<>& aIn )
150 return tao::pegtl::parse_tree::parse<SIM_VALUE_PARSER::numberGrammar<ValueType, Notation>,
156template <SIM_VALUE::TYPE ValueType, SIM_VALUE_PARSER::NOTATION Notation>
165 for(
const auto& subnode : aNode.children )
170 aParseResult.
intPart = std::stoll( subnode->string() );
172 aParseResult.
fracPart = std::stoll( subnode->string() );
174 catch(
const std::exception& )
176 aParseResult.
isOk =
false;
182 aParseResult.
exponent = std::stoi( aNode.string() );
192 wxFAIL_MSG(
"Unhandled parse tree node" );
202 tao::pegtl::string_input<> in( aString,
"from_content" );
203 std::unique_ptr<tao::pegtl::parse_tree::node> root;
210 catch( tao::pegtl::parse_error& )
220 for(
const auto& node : root->children )
225 catch(
const std::invalid_argument& e )
227 wxFAIL_MSG( fmt::format(
"Parsing simulator value failed: {:s}", e.what() ) );
240 if( aPrefix.empty() )
245 case 'a':
return -18;
246 case 'f':
return -15;
247 case 'p':
return -12;
262 case NOTATION::SPICE:
263 std::transform( aPrefix.begin(), aPrefix.end(), aPrefix.begin(),
268 else if( aPrefix ==
"p" )
270 else if( aPrefix ==
"n" )
272 else if( aPrefix ==
"u" )
274 else if( aPrefix ==
"m" )
276 else if( aPrefix ==
"" )
278 else if( aPrefix ==
"k" )
280 else if( aPrefix ==
"meg" )
282 else if( aPrefix ==
"g" )
284 else if( aPrefix ==
"t" )
290 wxFAIL_MSG( fmt::format(
"Unknown simulator value suffix: '{:s}'", aPrefix ) );
298 if( aNotation == NOTATION::SI && aExponent >= -18 && aExponent <= -15 )
300 aExponentReduction = -18;
303 else if( aExponent >= -15 && aExponent < -12 )
305 aExponentReduction = -15;
308 else if( aExponent >= -12 && aExponent < -9 )
310 aExponentReduction = -12;
313 else if( aExponent >= -9 && aExponent < -6 )
315 aExponentReduction = -9;
318 else if( aExponent >= -6 && aExponent < -3 )
320 aExponentReduction = -6;
323 else if( aExponent >= -3 && aExponent < 0 )
325 aExponentReduction = -3;
328 else if( aExponent >= 0 && aExponent < 3 )
330 aExponentReduction = 0;
333 else if( aExponent >= 3 && aExponent < 6 )
335 aExponentReduction = 3;
338 else if( aExponent >= 6 && aExponent < 9 )
340 aExponentReduction = 6;
341 return ( aNotation == NOTATION::SI ) ?
"M" :
"Meg";
343 else if( aExponent >= 9 && aExponent < 12 )
345 aExponentReduction = 9;
348 else if( aExponent >= 12 && aExponent < 15 )
350 aExponentReduction = 12;
353 else if( aNotation == NOTATION::SI && aExponent >= 15 && aExponent < 18 )
355 aExponentReduction = 15;
358 else if( aNotation == NOTATION::SI && aExponent >= 18 && aExponent <= 21 )
360 aExponentReduction = 18;
364 aExponentReduction = 0;
372 wxString buf( aString );
373 buf.Replace(
',',
'.' );
386 int expReduction = 0;
391 return fmt::format(
"{:g}{}",
395 catch(
const std::invalid_argument& )
408 int expReduction = 0;
412 double reducedValue = aValue / std::pow( 10, expReduction );
414 return fmt::format(
"{:g}{}", reducedValue, prefix );
433 catch(
const std::invalid_argument& )
465 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)
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