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 )
168 aParseResult.
intPart = std::stol( subnode->string() );
170 aParseResult.
fracPart = std::stol( subnode->string() );
175 aParseResult.
exponent = std::stoi( aNode.string() );
185 wxFAIL_MSG(
"Unhandled parse tree node" );
195 tao::pegtl::string_input<> in( aString,
"from_content" );
196 std::unique_ptr<tao::pegtl::parse_tree::node> root;
203 catch( tao::pegtl::parse_error& )
213 for(
const auto& node : root->children )
218 catch(
const std::invalid_argument& e )
220 wxFAIL_MSG( fmt::format(
"Parsing simulator value failed: {:s}", e.what() ) );
233 if( aPrefix.empty() )
238 case 'a':
return -18;
239 case 'f':
return -15;
240 case 'p':
return -12;
255 case NOTATION::SPICE:
256 std::transform( aPrefix.begin(), aPrefix.end(), aPrefix.begin(),
261 else if( aPrefix ==
"p" )
263 else if( aPrefix ==
"n" )
265 else if( aPrefix ==
"u" )
267 else if( aPrefix ==
"m" )
269 else if( aPrefix ==
"" )
271 else if( aPrefix ==
"k" )
273 else if( aPrefix ==
"meg" )
275 else if( aPrefix ==
"g" )
277 else if( aPrefix ==
"t" )
283 wxFAIL_MSG( fmt::format(
"Unknown simulator value suffix: '{:s}'", aPrefix ) );
291 if( aNotation == NOTATION::SI && aExponent >= -18 && aExponent <= -15 )
293 aExponentReduction = -18;
296 else if( aExponent >= -15 && aExponent < -12 )
298 aExponentReduction = -15;
301 else if( aExponent >= -12 && aExponent < -9 )
303 aExponentReduction = -12;
306 else if( aExponent >= -9 && aExponent < -6 )
308 aExponentReduction = -9;
311 else if( aExponent >= -6 && aExponent < -3 )
313 aExponentReduction = -6;
316 else if( aExponent >= -3 && aExponent < 0 )
318 aExponentReduction = -3;
321 else if( aExponent >= 0 && aExponent < 3 )
323 aExponentReduction = 0;
326 else if( aExponent >= 3 && aExponent < 6 )
328 aExponentReduction = 3;
331 else if( aExponent >= 6 && aExponent < 9 )
333 aExponentReduction = 6;
334 return ( aNotation == NOTATION::SI ) ?
"M" :
"Meg";
336 else if( aExponent >= 9 && aExponent < 12 )
338 aExponentReduction = 9;
341 else if( aExponent >= 12 && aExponent < 15 )
343 aExponentReduction = 12;
346 else if( aNotation == NOTATION::SI && aExponent >= 15 && aExponent < 18 )
348 aExponentReduction = 15;
351 else if( aNotation == NOTATION::SI && aExponent >= 18 && aExponent <= 21 )
353 aExponentReduction = 18;
357 aExponentReduction = 0;
365 wxString buf( aString );
366 buf.Replace(
',',
'.' );
379 int expReduction = 0;
384 return fmt::format(
"{:g}{}",
388 catch(
const std::invalid_argument& )
401 int expReduction = 0;
405 double reducedValue = aValue / std::pow( 10, expReduction );
407 return fmt::format(
"{:g}{}", reducedValue, prefix );
426 catch(
const std::invalid_argument& )
458 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