20#include <fast_float/fast_float.h>
30#include <fmt/format.h>
40#include <unordered_map>
45#define M_PI 3.14159265358979323846
50 using VALUE = std::variant<double, std::string>;
66 strncpy(token.
text, str.c_str(),
sizeof(token.
text) - 1);
67 token.
text[
sizeof(token.
text) - 1] =
'\0';
82 return std::string(token.
text);
97 if( std::holds_alternative<double>( aVal ) )
98 return MakeValue( std::get<double>( aVal ) );
100 const auto& str = std::get<std::string>( aVal );
105 auto result = fast_float::from_chars( str.data(), str.data() + str.size(), value );
107 if(
result.ec != std::errc() ||
result.ptr != str.data() + str.size() )
108 throw std::invalid_argument(
"Invalid number format" );
121 if( std::holds_alternative<std::string>( aVal ) )
122 return std::get<std::string>( aVal );
124 const auto num = std::get<double>( aVal );
127 constexpr double tolerance = 1e-10;
128 double rounded = std::round( num );
132 return fmt::format(
"{:.0f}", rounded );
134 return fmt::format(
"{}", num );
150 if( std::holds_alternative<double>( aVal ) )
151 return std::get<double>( aVal ) != 0.0;
153 return !std::get<std::string>( aVal ).empty();
168 const auto leftVal = leftNum.GetValue();
169 const auto rightVal = rightNum.GetValue();
180 if( rightVal == 0.0 )
184 if( rightVal == 0.0 )
223 BIN_OP_DATA( std::unique_ptr<NODE> aLeft,
char aOperation, std::unique_ptr<NODE> aRight ) :
236 FUNC_DATA( std::string aName, std::vector<std::unique_ptr<NODE>> aArguments ) :
242 std::vector<std::unique_ptr<NODE>>
args;
249 std::variant<std::string, double, BIN_OP_DATA, FUNC_DATA>
data;
254 auto node = std::make_unique<NODE>();
256 node->data = std::move( aText );
260 static std::unique_ptr<NODE>
CreateCalc( std::unique_ptr<NODE> aExpr )
262 auto node = std::make_unique<NODE>();
264 node->data =
BIN_OP_DATA( std::move( aExpr ),
'=',
nullptr );
268 static std::unique_ptr<NODE>
CreateVar( std::string aName )
270 auto node = std::make_unique<NODE>();
272 node->data = std::move( aName );
278 auto node = std::make_unique<NODE>();
286 auto node = std::make_unique<NODE>();
288 node->data = std::move( aValue );
292 static std::unique_ptr<NODE>
CreateBinOp( std::unique_ptr<NODE> aLeft,
char aOp, std::unique_ptr<NODE> aRight )
294 auto node = std::make_unique<NODE>();
296 node->data =
BIN_OP_DATA( std::move( aLeft ), aOp, std::move( aRight ) );
300 static std::unique_ptr<NODE>
CreateFunction( std::string aName, std::vector<std::unique_ptr<NODE>> aArgs )
302 auto node = std::make_unique<NODE>();
304 node->data =
FUNC_DATA( std::move( aName ), std::move( aArgs ) );
313 node->
data = std::move( aText );
319 auto node =
new NODE();
321 node->data =
BIN_OP_DATA( std::unique_ptr<NODE>( aExpr ),
'=',
nullptr );
329 node->
data = std::move( aName );
345 node->
data = std::move( aValue );
353 node->
data =
BIN_OP_DATA( std::unique_ptr<NODE>( aLeft ), aOp, std::unique_ptr<NODE>( aRight ) );
361 node->
data =
FUNC_DATA( std::move( aName ), std::move( *aArgs ) );
367 template<
typename Visitor>
370 return std::forward<Visitor>( aVisitor )( *this );
379 nodes.emplace_back( std::move( aNode ) );
384 nodes.emplace_back( std::unique_ptr<NODE>( aNode ) );
391 const std::vector<std::unique_ptr<NODE>>&
GetNodes()
const {
return nodes; }
396 std::vector<std::unique_ptr<NODE>>
nodes;
430 using VAR_CALLBACK = std::function<RESULT<VALUE>(
const std::string& aVariableName)>;
449 mutable std::random_device
m_rd;
static std::tuple< std::string, std::vector< std::string >, bool > ProcessWithDetails(const DOC &aDoc, VAR_CALLBACK aCallback)
Process document with detailed error reporting.
EVAL_VISITOR::VAR_CALLBACK VAR_CALLBACK
static std::pair< std::string, bool > Process(const DOC &aDoc, VAR_CALLBACK aVariableCallback)
Process document using callback for variable resolution.
const std::vector< std::unique_ptr< NODE > > & GetNodes() const
void AddNodeRaw(NODE *aNode)
std::string GetErrorSummary() const
void AddNode(std::unique_ptr< NODE > aNode)
std::vector< std::unique_ptr< NODE > > nodes
const std::vector< std::string > & GetErrors() const
std::function< RESULT< VALUE >(const std::string &aVariableName)> VAR_CALLBACK
EVAL_VISITOR(VAR_CALLBACK aVariableCallback, ERROR_COLLECTOR &aErrorCollector)
Construct evaluator with variable callback function.
RESULT< VALUE > evaluateFunction(const FUNC_DATA &aFunc) const
VAR_CALLBACK m_variableCallback
RESULT< VALUE > operator()(const NODE &aNode) const
ERROR_COLLECTOR & m_errors
static std::unique_ptr< NODE > CreateFunction(std::string aName, std::vector< std::unique_ptr< NODE > > aArgs)
static NODE * CreateFunctionRaw(std::string aName, std::vector< std::unique_ptr< NODE > > *aArgs)
static std::unique_ptr< NODE > CreateNumber(double aValue)
static std::unique_ptr< NODE > CreateString(std::string aValue)
static std::unique_ptr< NODE > CreateBinOp(std::unique_ptr< NODE > aLeft, char aOp, std::unique_ptr< NODE > aRight)
static std::unique_ptr< NODE > CreateVar(std::string aName)
static NODE * CreateStringRaw(std::string aValue)
static std::unique_ptr< NODE > CreateCalc(std::unique_ptr< NODE > aExpr)
static NODE * CreateCalcRaw(NODE *aExpr)
std::variant< std::string, double, BIN_OP_DATA, FUNC_DATA > data
static NODE * CreateNumberRaw(double aValue)
RESULT< VALUE > Accept(Visitor &&aVisitor) const
static std::unique_ptr< NODE > CreateText(std::string aText)
static NODE * CreateVarRaw(std::string aName)
static NODE * CreateTextRaw(std::string aText)
static NODE * CreateBinOpRaw(NODE *aLeft, char aOp, NODE *aRight)
PARSE_CONTEXT(const PARSE_CONTEXT &)=delete
PARSE_CONTEXT & operator=(const PARSE_CONTEXT &)=delete
PARSE_CONTEXT(PARSE_CONTEXT &&)=delete
PARSE_CONTEXT(ERROR_COLLECTOR &aErrorCollector)
PARSE_CONTEXT & operator=(PARSE_CONTEXT &&)=delete
static bool IsTruthy(const VALUE &aVal)
static VALUE ConcatStrings(const VALUE &aLeft, const VALUE &aRight)
static RESULT< double > ToDouble(const VALUE &aVal)
static char ToChar(const VALUE &aVal)
static RESULT< VALUE > ArithmeticOp(const VALUE &aLeft, const VALUE &aRight, char aOp)
static std::string ToString(const VALUE &aVal)
TOKEN_TYPE MakeNumberToken(double val)
thread_local ERROR_COLLECTOR * g_errorCollector
RESULT< T > MakeError(std::string aMsg)
std::variant< double, std::string > VALUE
TOKEN_TYPE MakeStringToken(const std::string &str)
std::string GetTokenString(const TOKEN_TYPE &token)
double GetTokenDouble(const TOKEN_TYPE &token)
RESULT< T > MakeValue(T aVal)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
std::unique_ptr< NODE > right
BIN_OP_DATA(std::unique_ptr< NODE > aLeft, char aOperation, std::unique_ptr< NODE > aRight)
std::unique_ptr< NODE > left
FUNC_DATA(std::string aName, std::vector< std::unique_ptr< NODE > > aArguments)
std::vector< std::unique_ptr< NODE > > args
wxString result
Test unit parsing edge cases and error handling.