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.