Skip to content
Snippets Groups Projects
Commit 927ee3db authored by Vincent Templier's avatar Vincent Templier
Browse files
parents fb95bb1c 896e0f00
No related branches found
No related tags found
No related merge requests found
Showing
with 4663 additions and 8 deletions
...@@ -11,4 +11,7 @@ __pycache__ ...@@ -11,4 +11,7 @@ __pycache__
*.pyc *.pyc
# Mermaid # Mermaid
*.mmd *.mmd
\ No newline at end of file
# Doxygen
xml*/
\ No newline at end of file
#ifndef _AIDGE_CONDITIONAL_DATA_H_
#define _AIDGE_CONDITIONAL_DATA_H_
#include <vector>
#include <string>
#include <stdexcept> //error
#include <memory>
#include <map>
namespace Aidge{
// struct ConditionalTokenTypes2 {
// enum class logicalOperators {
// AND = 1,
// OR,
// NOT
// };
// enum class logicalComparators {
// EQ,
// NEQ
// };
// enum class value {
// KEY,
// INTEGER,
// FLOAT,
// STRING,
// NODE,
// LAMBDA,
// };
// enum class tag {
// ARGSEP,
// LPAREN,
// RPAREN,
// STOP
// };
// const std::map<logicalComparators, int> precLogicalOperators{
// {logicalOperators::NOT,3},
// {logicalOperators::AND,2},
// {logicalOperators::OR,1}
// };
// };
/////////////////////////
// the data type in AST Intepretation
////////////////////////
class BaseConditionalValue {
public:
virtual ~BaseConditionalValue() {}
};
template <typename T>
class ConditionalValue : public BaseConditionalValue {
public:
ConditionalValue(const T& data) : value(data) {}
T value;
};
struct ConditionalData {
/**
* @brief generic type to propagete all the different values in the AST interpretation
*/
//void* value;
std::unique_ptr<BaseConditionalValue> value;
const std::type_info* type;
/////////////////////////////////
//
////////////////////////////////
/**
* @brief set a value
*/
template <typename T>
void setValue(const T& newValue) {
//make sure that the old value is free
deleteValue();
value = std::make_unique<ConditionalValue<T>>(newValue);
type = &typeid(T);
}
/**
* @brief get the actual value
* @details recaste the value to the templaited type and checks that the conversion type is compatible with type
* @tparam the type of the return value
* @return the value
*/
template <typename T>
T getValue() const {
if (type && *type == typeid(T)) {
//const Value<T>* typedValue = dynamic_cast<const Value<T>*>(static_cast<const BaseValue*>(value));
const ConditionalValue<T>* typedValue = dynamic_cast<const ConditionalValue<T>*>(value.get());
if (typedValue) {
return typedValue->value;
}
}
throw std::runtime_error(std::string("DATA ERROR ") + type->name() + " != " + typeid(T).name());
}
///////////////////////////////////
//
///////////////////////////////////
std::string getType() const {
return type ? type->name() : "nullptr";
}
template <typename T>
bool isTypeEqualTo() const {
return (type && *type == typeid(T));
}
void deleteValue() {
if (type) {
value.reset();
type = nullptr;
}
}
~ConditionalData() { // TODO best can we have a liste of type supported ?
deleteValue();
}
};
}
#endif //_AIDGE_CONDITIONAL_DATA_H_
\ No newline at end of file
#ifndef _AIDGE_CONDITIONAL_INTERPRETER_H_
#define _AIDGE_CONDITIONAL_INTERPRETER_H_
#include "nodeTester/ConditionalParser.hpp"
#include "nodeTester/ConditionalData.hpp"
#include <memory> // for shared_ptr
#include <unordered_map>
#include <functional>
#include "graph/Node.hpp"
#include <sstream>
namespace Aidge{
//////////////////////////////
//
/////////////////////////////
/**
* @brief class used to register any lambda function without context,
* it encapsulates the source lambda in a lambda which takes as argument ConditionalData* which are any type.
* @see ConditionalData
*/
class ConditionalRegisterFunction {
//////////////////////////
//Safe recaste
//////////////////////////
/**
* @brief recaste the ConditionalData* to the argument type of the lambda
* @tparam T type of the lambda argument
* @see ConditionalData
*/
template <typename T>
T safeCastInput(ConditionalData* data) {
//cnvertion and type cheking
if (data->isTypeEqualTo<T>()){
return data->getValue<T>();
}else{
throw std::invalid_argument( "incompatible input type " + data->getType() +" "+ typeid(T).name() );
}
}
/**
* @brief recaste the output of the lambda to a ConditionalData*
* @tparam T type of the lambda return
* @see ConditionalData
*/
template <typename T>
ConditionalData* safeCastOutput(T data) {
ConditionalData* out = new ConditionalData;
out->setValue<T>(data);
return out;
}
//////////////////////
// get all the type of the function
//////////////////////
/**
* @brief Retrieves information about a function's return type and argument types.
* @tparam T The function type.
*/
template <typename T>
struct function_traits;
/**
* @brief Specialization of function_traits for function pointers.
* @tparam R The return type of the function.
* @tparam Args The argument types of the function.
*/
template <typename R, typename... Args>
struct function_traits<R (*)(Args...)> {
using return_type = R;
static constexpr std::size_t arity = sizeof...(Args);
template <std::size_t N>
struct argument {
static_assert(N < arity, "Index out of range.");
using type = typename std::tuple_element<N, std::tuple<Args...>>::type;
};
};
/**
* @brief Specialization of function_traits for std::function types.
* @tparam R The return type of the function.
* @tparam Args The argument types of the function.
*/
template <typename R, typename... Args>
struct function_traits<std::function<R(Args...)>> {
using return_type = R;
static constexpr std::size_t arity = sizeof...(Args);
template <std::size_t N>
struct argument {
static_assert(N < arity, "Index out of range.");
using type = typename std::tuple_element<N, std::tuple<Args...>>::type;
};
};
/////////////////////
//change the function to ConditionalData*(std::vector<ConditionalData*>)
/////////////////////
/**
* @brief Converts a function to a ConditionalData*(std::vector<ConditionalData*>).
* @tparam F The type of the function to convert.
* @tparam ParamsIdx The indices of the function parameters.
* @param f The function to convert.
* @return The pointer to the converted function.
*/
template <class F, std::size_t... ParamsIdx>
auto funcPointer(F f, std::index_sequence<ParamsIdx...>) {
//wrapp the lambda in a new one that as ConditionalData as inputs and output
return [this,f](std::vector<ConditionalData*> &args) {
if (args.size() != sizeof...(ParamsIdx)){
std::ostringstream errorMessage;
errorMessage << "bad Number of argument: get " << args.size() << " need " << sizeof...(ParamsIdx) << "\n";
throw std::runtime_error(errorMessage.str());
}
//assert(args.size() == sizeof...(ParamsIdx));//the size of the vector valide
using FuncTraits = function_traits<decltype(f)>;
using outType = typename FuncTraits::return_type;
outType result = f(safeCastInput<typename FuncTraits::template argument<ParamsIdx>::type>(args[ParamsIdx])...);
//typename
return safeCastOutput<outType>(result);
};
}
/**
* @brief Converts a function pointer to a ConditionalData*(std::vector<ConditionalData*>).
* @tparam R The return type of the function.
* @tparam Params The parameter types of the function.
* @param f The function pointer to convert.
* @return The pointer to the converted function.
*/
template <class R,class... Params>
auto funcPointer(R (*f)(Params...)) {
return funcPointer(f, std::index_sequence_for<Params...>{});
}
/**
* @brief Converts a std::function to a ConditionalData*(std::vector<ConditionalData*>).
* @tparam R The return type of the function.
* @tparam Params The parameter types of the function.
* @param f The function pointer to convert.
* @return The pointer to the converted function.
*/
template <class R,class... Params>
auto funcPointer(std::function<R(Params...)> f) {
return funcPointer(f, std::index_sequence_for<Params...>{});
}
///////////////////
// interface
///////////////////
public:
/**
* @brief Default constructor
*/
ConditionalRegisterFunction(){}
/**
* @brief Inserts a function into the map with the provided key.
* @tparam T The function type.
* @param key The key to associate with the function.
* @param f The function to insert.
*/
template <class T>
void insert(const std::string key,T f){
mWlambda.insert({ key, funcPointer(f)});
}
/**
* @brief Runs the function associated with the given key, using the provided vector of input data.
* @param key The key of the function to run.
* @param datas The vector of input data.
* @return A pointer to the output ConditionalData object.
*/
ConditionalData* run(const std::string key,std::vector<ConditionalData*> & datas);
private:
/// @brief map of name and the converted function.
std::map<const std::string, std::function<ConditionalData*(std::vector<ConditionalData*> &)>> mWlambda;
};
///////////////////
//AST tree node
// ////////////////
/**
* @brief this class interprets AST to generate a test on a graph node. For each AST node,
* it generates an interpretation and registers lambda functions that can be used in the test expression.
* there are two lambda control mechanisms:
* - A cpp mechanism which allows any lambda to be inserted into the constructor that use templaite
* - A user mechanism limited to lambda bool(NodePtr)
* @see ConditionalParser use to get the AST
*/
class ConditionalInterpreter
{
private:
/**
* @brief the AST generate by the Parser
* @see ConditionalParser
*/
std::shared_ptr<Aidge::AstConditionalNode> mTree;
/**
* @brief the registery for the lambda fuction
* @see ConditionalRegisterFunction
*/
ConditionalRegisterFunction mLambdaRegiter;
public:
/**
* @brief Constructor
* @param ConditionalExpressions The expression of the test to be performed on the nodes
*/
ConditionalInterpreter(const std::string ConditionalExpressions);
/**
* @brief Test a node depending of the ConditionalExpressions
* @details the AST is visit using \ref visit() whith the $ init whit the nodeOp
* @return bool the match node has the initialized expresion
* @see visit() This function uses the visit() function to perform the evaluation.
*/
bool test( const NodePtr nodeOp);
/**
* @brief Interface for inserting custom lambda bool(NodePtr) functions in AST interpretation,
* it will be available in the ConditionalExpressions expretion as : key($)
* @param key The key that will be used to call the function in the expression
* @param f The pointer to function
*/
void insertLambda(const std::string key,std::function<bool(Aidge::NodePtr)> f);
/////
private:
/**
* @brief Recursive AST traversal function, using the for interpreting AST nodes function,
* using \ref ASTnodeInterpreterF fuctions
* @param NodeOp The node currently being tested
* @param nodes The AST given by the parsing process
*/
std::vector<ConditionalData*> visit(const ASTNodeCh& nodes, const NodePtr NodeOp );
/**
* @defgroup ASTnodeInterpreterF Functions for interpreting AST nodes
* @brief For each node type in the AST, function defines the processing to be performed
* they return a std::vector<ConditionalData*> which corresponds to the value(s) obtained
*/
/**
* @ingroup ASTnodeInterpreterF
* @brief Function that does something.
*/
std::vector<ConditionalData*> fLambda(const std::shared_ptr<AstConditionalNode>& node,std::vector<ConditionalData*> datas);
/**
* @ingroup ASTnodeInterpreterF
* @brief Converted the lexeme to a int and to ConditionalData*
*/
std::vector<ConditionalData*> fStrToInteger(const std::shared_ptr<AstConditionalNode>& node);
/**
* @ingroup ASTnodeInterpreterF
* @brief Converted the lexeme to a float and to ConditionalData*
*/
std::vector<ConditionalData*> fStrToFloat(const std::shared_ptr<AstConditionalNode>& node);
/**
* @ingroup ASTnodeInterpreterF
* @brief Converted the lexeme to a str and to ConditionalData*
*/
std::vector<ConditionalData*> fStrToStr(const std::shared_ptr<AstConditionalNode>& node);
/**
* @ingroup ASTnodeInterpreterF
* @brief makes the == operation between two previously converted ConditionalData*
*/
std::vector<ConditionalData*> fEq(std::vector<ConditionalData*> datas);
/**
* @ingroup ASTnodeInterpreterF
* @brief makes the != operation between two previously converted ConditionalData*
*/
std::vector<ConditionalData*> fNeq(std::vector<ConditionalData*> datas);
/**
* @ingroup ASTnodeInterpreterF
* @brief makes the && operation between two previously converted ConditionalData* in bool
*/
std::vector<ConditionalData*> fAnd(std::vector<ConditionalData*> datas);
/**
* @ingroup ASTnodeInterpreterF
* @brief makes the || operation between two previously converted ConditionalData* in bool
*/
std::vector<ConditionalData*> fOr(std::vector<ConditionalData*> datas);
/**
* @ingroup ASTnodeInterpreterF
* @brief makes the ! operation
*/
std::vector<ConditionalData*> fNot(std::vector<ConditionalData*> datas);
};
}
#endif //_AIDGE_CONDITIONAL_INTERPRETER_H_
/**
* @file
* @brief
* @version file 1.0.0
* @author vl241552
* @copyright
* Copyright (c) 2023 CEA, LIST, Embedded Artificial Intelligence Laboratory. All
* rights reserved.
*/
#ifndef _AIDGE_CONDITIONAL_LEXER_H_
#define _AIDGE_CONDITIONAL_LEXER_H_
#include <string>
#include <regex>
#include <memory> // for shared_ptr
#include <stdexcept> //error
#include <sstream>
namespace Aidge{
/**
* @brief enum for all types of token use in the parsing
* 7-5 type
* 4-0 id
*/
enum class ConditionalTokenTypes
{
NOT = (1 << 4)+3, /**< ! */
AND = (1 << 4)+2, /**< && */
OR = (1 << 4)+1, /**< || */
EQ = (1 << 5)+1, /**< == */
NEQ = (1 << 5)+2, /**< != */
KEY = (1 << 6) +1 , /**< [A-Za-z][A-Za-z0-9_]* */
INTEGER = (1 << 6) +2 , /**< [0-9]+ */
FLOAT = (1 << 6) +3 , /**< [0-9]+\.[0-9]* */
STRING = (1 << 6) +4 , /**< \'.*\' */
BOOL = (1 << 6) +5 , /**< true|false */
NODE = (1 << 6) +6 , /**< \$ */
LAMBDA = (1 << 6) +7 , /**< [A-Za-z][A-Za-z0-9_]*\( */
ARGSEP = (1<<7) +1, /**< , */
LPAREN = (1<<7) +2, /**< \( */
RPAREN = (1<<7) +3, /**< \) */
STOP = 0,
};
/**
* @brief token holder
*/
class ConditionalToken
{
public:
/**
* @brief Token container
* @param type one of the token type
* @param lexeme String representing aditional information of the token
*/
ConditionalToken(const ConditionalTokenTypes type , const std::string lexeme );
/**
* @brief get the lexeme
* @return std::string
*/
const std::string getLexeme(void);
/**
* @brief get the token type
*
* @return ConditionalTokenTypes
*/
const ConditionalTokenTypes getType(void);
/**
* @brief copy the token
* @return deep copy of the token
*/
std::shared_ptr<Aidge::ConditionalToken> copy();
std::ostringstream rep(void);
private:
/**
* @brief additional information of the token
*/
const std::string mLexeme;
/**
* @brief type of the token
* @see ConditionalTokenTypes
*/
const ConditionalTokenTypes mType;
};
class ConditionalLexer
{
public:
ConditionalLexer( const std::string ConditionalExpressions );
/**
* @brief Get the next token on the ConditionalExpressions
* @return ConditionalToken
*/
std::shared_ptr<ConditionalToken> getNextToken(void);
/**
* @brief Restart at the start of the ConditionalExpressions
*
*/
void rstPosition(void);
/**
* @brief Test if the string is completely read
* @return bool
*/
bool isEnd(void);
/**
* @brief Get the representation of the class
* @return string
*/
const std::string rep(){
return mConditionalExpressions;
}
private:
/**
* @brief Constructs an error message to display the character not understood by the lexer
* @return error mesage
*/
std::runtime_error badTokenError(const std::string& currentChars,std::size_t position);
/**
* @brief The expression of the test to be performed on the nodes
*/
const std::string mConditionalExpressions;
/**
* @brief The lexer's current position in mConditionalExpressions
*/
std::size_t mPosition;
};
/////////////////////////////////////
}
#endif //_AIDGE_CONDITIONAL_LEXER_H_
\ No newline at end of file
#ifndef _AIDGE_CONDITIONAL_PARSER_H_
#define _AIDGE_CONDITIONAL_PARSER_H_
#include "nodeTester/ConditionalLexer.hpp"
#include <memory> // for shared_ptr
namespace Aidge{
const std::map<ConditionalTokenTypes, std::size_t> ConditionalPrec{
{ConditionalTokenTypes::AND,2},
{ConditionalTokenTypes::OR,1}
};
class AstConditionalNode; // Forward declaration
using ASTNodeCh = std::vector<std::shared_ptr<AstConditionalNode>>;
/**
* @brief this class is the node of an AST tree, this
*/
class AstConditionalNode: public std::enable_shared_from_this<AstConditionalNode>
{
public:
AstConditionalNode(std::shared_ptr<ConditionalToken> token,ASTNodeCh child ={});
/**
* @brief get the lexeme of the token
* @return the lexeme value
*/
std::string getValue() const;
/**
* @brief get the type of the token
* @return the type
*/
ConditionalTokenTypes getType() const;
/**
* @brief get the child of the node
* @return child
*/
const ASTNodeCh& getChilds() const ;
/**
* @brief test if the node is a leaf in the tree
* @return true if a leaf
*/
bool isLeaf() const ;
/**
* @brief get the number of child
* @return the number of child
*/
std::size_t nbChild() const;
private:
/**
* @brief the token of the node
*/
const std::shared_ptr<ConditionalToken> mToken;
/**
* @brief list of child
*/
const ASTNodeCh mChild;
};
/**
* @brief this class uses the lexer to create an AST according to a set of gramer rules
*/
class ConditionalParser{
public:
/**
* @brief AST graph creation function
* @param ConditionalExpressions String representing the logical fuction to be performed
*/
ConditionalParser(const std::string ConditionalExpressions);
/**
* @brief AST graph creation function
* @return The AST tree
*/
std::shared_ptr<AstConditionalNode> parse(void);
private:
/**
* @brief restart at the start of the ConditionalExpressions for LEXER and restart mCurrentToken
*/
void rstParser(void);
//////////////////
/**
* @defgroup ParsingFunctions Function for creating AST
* @brief Functions for recursive construction of the AST representing grammar rules
*/
/**
* @ingroup ParsingFunctions
* @brief Token reading and verification function
*
*/
void ackToken(ConditionalTokenTypes tokenType);
/**
* @ingroup ParsingFunctions
* @brief Function of grammar rules for values : (KEY|INTEGER|FOAT|STRING|LAMBDA lambda)
* @return AST node
*/
std::shared_ptr<AstConditionalNode> constructAstVal(void);
/**
* @ingroup ParsingFunctions
* @brief Function of grammar rules for comparison : val (EQ|NEQ) val | LPAREN expr RPAREN
* @return AST node
*/
std::shared_ptr<AstConditionalNode> constructAstCmpr(void);
/**
* @ingroup ParsingFunctions
* @brief Function of grammar rules for arguments of a lambda : LAMBDA val (ARGSEP val)* RPAREN
* @return AST node
*/
std::shared_ptr<AstConditionalNode> constructAstLambda(void);
/**
* @ingroup ParsingFunctions
* @brief Function of grammar rules for a expresion : cmpr ((AND | OR) cmpr)*
* @return AST node
*/
std::shared_ptr<AstConditionalNode> constructAstExpr(std::size_t precLimit = 0);
/**
* @brief The actual token in the parce
*/
std::shared_ptr<ConditionalToken> mCurrentToken;
/**
* @brief The lexem use
*/
ConditionalLexer mLexer;
};
}
#endif //_AIDGE_CONDITIONAL_PARSER_H_
#ifndef _AIDGE_AST_NODE_H_
#define _AIDGE_AST_NODE_H_
#include <string>
#include <type_traits>
#include <vector>
#include <memory>
#include "utilsParsing/ParsingToken.hpp"
namespace Aidge{
template <typename EnumType>
class AstNode: public std::enable_shared_from_this<AstNode>
{
static_assert(std::is_enum<EnumType>::value, "AstNode EnumType must be an enum type");
public:
AstNode(std::shared_ptr<ParsingToken<EnumType>> token,std::vector<std::shared_ptr<AstNode>> child ={}):mToken(token),mChild(child){}
/**
* @brief get the type of the token
* @return the type
*/
EnumType getType() const{
return mToken->getType();
}
/**
* @brief get the lexeme of the token
* @return the lexeme
*/
std::string getValue() const{
return mToken->getLexeme();
}
/**
* @brief get the child of the node
* @return child
*/
const std::vector<std::shared_ptr<AstNode>>& getChilds() const {
return mChild;
}
/**
* @brief test if the node is a leaf in the tree
* @return true if a leaf
*/
bool isLeaf() const {
return mChild.size() == 0;
}
/**
* @brief get the number of child
* @return the number of child
*/
std::size_t nbChild() const{
return mChild.size();
}
private:
/**
* @brief the token of the node
*/
const std::shared_ptr<ParsingToken<EnumType>> mToken;
/**
* @brief list of child
*/
const std::vector<std::shared_ptr<AstNode>> mChild;
};
}
#endif //_AIDGE_AST_NODE_H_
#ifndef _AIDGE_PARSING_TOKEN_H_
#define _AIDGE_PARSING_TOKEN_H_
#include <string>
#include <type_traits>
namespace Aidge{
template <typename EnumType>
class ParsingToken: public std::enable_shared_from_this<ParsingToken>
{
static_assert(std::is_enum<EnumType>::value, "ParsingToken EnumType must be an enum type");
public:
/**
* @brief Token container
* @param type one of the token type
* @param lexeme String representing aditional information of the token
*/
ParsingToken(const EnumType type , const std::string lexeme )mLexeme(lexeme),mType(type){}
/**
* @brief get the lexeme
* @return std::string
*/
const std::string getLexeme(void){
return mLexeme;
}
/**
* @brief get the token type
*
* @return ParsingToken
*/
const EnumType getType(void){
return mType;
}
/**
* @brief copy the token
* @return deep copy of the token
*/
std::shared_ptr<Aidge::ParsingToken> copy();
//TODO
std::ostringstream rep(void){
std::ostringstream out;
out << " Token (" << mLexeme <<")" << "\n";
return out;
}
private:
/**
* @brief additional information of the token
*/
const std::string mLexeme;
/**
* @brief type of the token
* @see ConditionalTokenTypes
*/
const EnumType mType;
};
}
#endif //_AIDGE_PARSING_TOKEN_H_
\ No newline at end of file
#include "nodeTester/ConditionalInterpreter.hpp"
using namespace Aidge;
///////////////////////////////
//ConditionalRegisterFunction
///////////////////////////////
ConditionalData* ConditionalRegisterFunction::run(const std::string key,std::vector<ConditionalData*> & datas){
auto lambdaIt = mWlambda.find(key);
if (lambdaIt != mWlambda.end()) {
return lambdaIt->second(datas);
}else {
throw std::runtime_error("can not run Lambda due to invalid key: " + key);
}
}
//////////////////////
//ConditionalInterpreter
///////////////////////
ConditionalInterpreter::ConditionalInterpreter(const std::string ConditionalExpressions)
:mLambdaRegiter()
{
ConditionalParser conditionalParser = ConditionalParser(ConditionalExpressions);
mTree = conditionalParser.parse();
///lambda by default
mLambdaRegiter.insert("getType",+[](NodePtr NodeOp){return NodeOp->type();});
}
bool ConditionalInterpreter::test( const NodePtr nodeOp)
{
try{
std::vector<ConditionalData*> r = visit({mTree},nodeOp);
if (r.size() != 1){
throw std::runtime_error("Multy output interpretation output");
}else{
if (!r[0]->isTypeEqualTo<bool>()){
throw std::runtime_error("TEST OUT MUST BE A BOOL ");
}else{
return r[0]->getValue<bool>();
}
}
}catch(const std::exception& e){
std::ostringstream errorMessage;
errorMessage << "Error in test " << "\n\t" << e.what() << "\n";
throw std::runtime_error(errorMessage.str());
}
}
void ConditionalInterpreter::insertLambda(const std::string key,std::function<bool(Aidge::NodePtr)> f){
mLambdaRegiter.insert<std::function<bool(Aidge::NodePtr)> >(key, f);
}
/////
std::vector<ConditionalData*> ConditionalInterpreter::visit(const ASTNodeCh& nodes, const NodePtr nodeOp ){
std::vector<ConditionalData*> dataVector;
for ( std::shared_ptr<AstConditionalNode> node : nodes) {
try{
switch (node->getType()){
///////////////////////////////////
//OPERATOR
///////////////////////////////////
case ConditionalTokenTypes::NOT:
{
std::vector<ConditionalData*> tmp = fNot(visit(node->getChilds(),nodeOp));
dataVector.insert(dataVector.end(), tmp.begin(), tmp.end());
}
break;
case ConditionalTokenTypes::AND:
{
std::vector<ConditionalData*> tmp = fAnd(visit(node->getChilds(),nodeOp));
dataVector.insert(dataVector.end(), tmp.begin(), tmp.end());
}
break;
case ConditionalTokenTypes::OR:
{
std::vector<ConditionalData*> tmp = fOr(visit(node->getChilds(),nodeOp));
dataVector.insert(dataVector.end(), tmp.begin(), tmp.end());
}
break;
case ConditionalTokenTypes::EQ:
{
std::vector<ConditionalData*> tmp = fEq(visit(node->getChilds(),nodeOp));
dataVector.insert(dataVector.end(), tmp.begin(), tmp.end());
}
break;
case ConditionalTokenTypes::NEQ:
{
std::vector<ConditionalData*> tmp = fNeq(visit(node->getChilds(),nodeOp));
dataVector.insert(dataVector.end(), tmp.begin(), tmp.end());
}
break;
///////////////////////////////////
//VALUE
///////////////////////////////////
case ConditionalTokenTypes::KEY:
break;
case ConditionalTokenTypes::INTEGER:
{
std::vector<ConditionalData*> tmp = fStrToInteger(node);
dataVector.insert(dataVector.end(), tmp.begin(), tmp.end());
}
break;
case ConditionalTokenTypes::FLOAT:
{
std::vector<ConditionalData*> tmp = fStrToFloat(node);
dataVector.insert(dataVector.end(), tmp.begin(), tmp.end());
}
break;
case ConditionalTokenTypes::STRING:
{
std::vector<ConditionalData*> tmp = fStrToStr(node);
dataVector.insert(dataVector.end(), tmp.begin(), tmp.end());
}
break;
case ConditionalTokenTypes::NODE: //TODO
{
ConditionalData* data = new ConditionalData;
data->setValue<NodePtr>(nodeOp);
std::vector<ConditionalData*> tmp = {data};
dataVector.insert(dataVector.end(), tmp.begin(), tmp.end());
}
break;
case ConditionalTokenTypes::LAMBDA:
{
std::vector<ConditionalData*> tmp = fLambda(node,visit(node->getChilds(),nodeOp));
dataVector.insert(dataVector.end(), tmp.begin(), tmp.end());
}
break;
case ConditionalTokenTypes::BOOL: //TODO
{
ConditionalData* data = new ConditionalData;
if(node->getValue() == "true"){
data->setValue<bool>(true);
}else{
data->setValue<bool>(false);
}
std::vector<ConditionalData*> tmp = {data};
dataVector.insert(dataVector.end(), tmp.begin(), tmp.end());
}
break;
case ConditionalTokenTypes::ARGSEP:
case ConditionalTokenTypes::LPAREN:
case ConditionalTokenTypes::RPAREN:
case ConditionalTokenTypes::STOP:
default:
throw std::runtime_error("NODE TYPE NOT SUPORTED IN ConditionalInterpreter");
}
}catch(const std::exception& e){
std::ostringstream errorMessage;
errorMessage << "Error in visiting AST for node"<< nodeOp->name() << "\n\t" << e.what() << "\n";
throw std::runtime_error(errorMessage.str());
}
}
return dataVector;
}
//////////////////////
//value convertor
/////////////////////
std::vector<ConditionalData*> ConditionalInterpreter::fStrToInteger(const std::shared_ptr<AstConditionalNode>& node)
{
std::vector<ConditionalData*> dataVector;
ConditionalData* data = new ConditionalData;
data->setValue<int>(std::stoi(node->getValue()));
dataVector.push_back(data);
return dataVector;
}
std::vector<ConditionalData*> ConditionalInterpreter::fStrToFloat(const std::shared_ptr<AstConditionalNode>& node)
{
std::vector<ConditionalData*> dataVector;
ConditionalData* data = new ConditionalData;
data->setValue<float>(std::stof(node->getValue()));
dataVector.push_back(data);
return dataVector;
}
std::vector<ConditionalData*> ConditionalInterpreter::fStrToStr(const std::shared_ptr<AstConditionalNode>& node)
{
std::vector<ConditionalData*> dataVector;
ConditionalData* data = new ConditionalData;
data->setValue<std::string>(node->getValue());
dataVector.push_back(data);
return dataVector;
}
std::vector<ConditionalData*> ConditionalInterpreter::fLambda(const std::shared_ptr<AstConditionalNode>& node,std::vector<ConditionalData*> datas)
{
//if the lambda have input
std::vector<ConditionalData*> dataVector;
ConditionalData* data;
try {
data = mLambdaRegiter.run(node->getValue(),datas);
} catch (const std::exception& e) {
std::ostringstream errorMessage;
errorMessage << "Error in conditional interpretation when run the "<< node->getValue() <<" Lambda\n\t" << e.what() << "\n";
throw std::runtime_error(errorMessage.str());
}
dataVector.push_back(data);
datas.clear();
return dataVector;
}
std::vector<ConditionalData*> ConditionalInterpreter::fEq(std::vector<ConditionalData*> datas)
{
if (datas.size() != 2){
throw std::runtime_error("EQ need 2 arg and get :" + datas.size());
}
auto a = datas[0];
auto b = datas[1];
if (a->getType() != b->getType()){
throw std::runtime_error("EQ Unsuported between type :" + a->getType() +" "+ b->getType());
}
std::vector<ConditionalData*> dataVector;
ConditionalData* data = new ConditionalData;
if (a->isTypeEqualTo<int>()) {
data->setValue<bool>( a->getValue<int>() == b->getValue<int>());
}else if (a->isTypeEqualTo<float>()){
data->setValue<bool>( a->getValue<float>() == b->getValue<float>());
}else if (a->isTypeEqualTo<std::string>()){
data->setValue<bool>( a->getValue<std::string>() == b->getValue<std::string>());
}else if (a->isTypeEqualTo<bool>()){
data->setValue<bool>( a->getValue<bool>() == b->getValue<bool>());
}else{
throw std::runtime_error("EQ Unknown type encountered :" + a->getType() );
}
dataVector.push_back(data);
datas.clear();
return dataVector;
}
std::vector<ConditionalData*> ConditionalInterpreter::fNeq(std::vector<ConditionalData*> datas)
{
if (datas.size() != 2){
throw std::runtime_error("NEQ need 2 arg and get :" + datas.size());
}
auto a = datas[0];
auto b = datas[1];
if (a->getType() != b->getType()){
throw std::runtime_error("NEQ Unsuported between type :" + a->getType() +" "+ b->getType());
}
std::vector<ConditionalData*> dataVector;
ConditionalData* data = new ConditionalData;
if (a->isTypeEqualTo<int>()) {
data->setValue<bool>( a->getValue<int>() != b->getValue<int>());
}else if (a->isTypeEqualTo<float>()){
data->setValue<bool>( a->getValue<float>() != b->getValue<float>());
}else if (a->isTypeEqualTo<std::string>()){
data->setValue<bool>( a->getValue<std::string>() != b->getValue<std::string>());
}else
{
throw std::runtime_error("NEQ Unknown type encountered :" + a->getType() );
}
dataVector.push_back(data);
datas.clear();
return dataVector;
}
std::vector<ConditionalData*> ConditionalInterpreter::fAnd(std::vector<ConditionalData*> datas)
{
if (datas.size() != 2){
throw std::runtime_error("AND need 2 arg and get :" + datas.size());
}
auto a = datas[0];
auto b = datas[1];
std::vector<ConditionalData*> dataVector;
if (a->getType() != typeid(bool).name() || b->getType() != typeid(bool).name()){
throw std::runtime_error("AND Unknown type encountered need bool get :" + a->getType() );
}
ConditionalData* data = new ConditionalData;
data->setValue<bool>( a->getValue<bool>() && b->getValue<bool>());
dataVector.push_back(data);
datas.clear();
return dataVector;
}
std::vector<ConditionalData*> ConditionalInterpreter::fOr(std::vector<ConditionalData*> datas)
{
if (datas.size() != 2){
throw std::runtime_error("OR need 2 arg and get :" + datas.size());
}
auto a = datas[0];
auto b = datas[1];
std::vector<ConditionalData*> dataVector;
if (a->getType() != typeid(bool).name() || b->getType() != typeid(bool).name()){
throw std::runtime_error("OR Unknown type encountered need bool get :" + a->getType() );
}
ConditionalData* data = new ConditionalData;
data->setValue<bool>( a->getValue<bool>() || b->getValue<bool>());
dataVector.push_back(data);
datas.clear();
return dataVector;
}
std::vector<ConditionalData*> ConditionalInterpreter::fNot(std::vector<ConditionalData*> datas)
{
if (datas.size() != 1){
throw std::runtime_error("not need 1 arg and get :" + datas.size());
}
auto a = datas[0];
std::vector<ConditionalData*> dataVector;
if (a->getType() != typeid(bool).name()){
throw std::runtime_error("NOT Unknown type encountered need bool get :" + a->getType() );
}
ConditionalData* data = new ConditionalData;
data->setValue<bool>( !a->getValue<bool>() );
dataVector.push_back(data);
datas.clear();
return dataVector;
}
#include "nodeTester/ConditionalLexer.hpp"
using namespace Aidge;
//////////////////
//ConditionalToken
//////////////////
ConditionalToken::ConditionalToken(const ConditionalTokenTypes type , const std::string lexeme ):
mLexeme(lexeme),
mType(type)
{
}
const std::string ConditionalToken::getLexeme(void){
return mLexeme;
}
const ConditionalTokenTypes ConditionalToken::getType(void){
return mType;
}
std::shared_ptr<Aidge::ConditionalToken> ConditionalToken::copy(){
auto newToken = std::make_shared<ConditionalToken>(mType,mLexeme);
return newToken;
}
std::ostringstream ConditionalToken::rep(void){
std::ostringstream out;
switch (mType){
case ConditionalTokenTypes::AND:
out << "AND" ;
break;
case ConditionalTokenTypes::OR:
out << "OR" ;
break;
case ConditionalTokenTypes::EQ:
out << "EQ" ;
break;
case ConditionalTokenTypes::NEQ:
out << "NEQ" ;
break;
case ConditionalTokenTypes::KEY:
out << "KEY" ;
break;
case ConditionalTokenTypes::INTEGER:
out << "INTEGER" ;
break;
case ConditionalTokenTypes::FLOAT:
out << "FLOAT" ;
break;
case ConditionalTokenTypes::STRING:
out << "STRING" ;
break;
case ConditionalTokenTypes::LAMBDA:
out << "LAMBDA" ;
break;
case ConditionalTokenTypes::ARGSEP:
out << "ARGSEP" ;
break;
case ConditionalTokenTypes::NODE:
out << "NODE" ;
break;
case ConditionalTokenTypes::LPAREN:
out << "LPAREN" ;
break;
case ConditionalTokenTypes::RPAREN:
out << "RPAREN" ;
break;
case ConditionalTokenTypes::STOP:
out << "STOP" ;
break;
default:
out << "???" ;
}
out << " (" << mLexeme <<")" << "\n";
return out;
}
//////////////////
//ConditionalLexer
//////////////////
ConditionalLexer::ConditionalLexer( const std::string ConditionalExpressions):
mConditionalExpressions(ConditionalExpressions)
{
mPosition = 0;
}
std::shared_ptr<ConditionalToken> ConditionalLexer::getNextToken(void){
std::string currentChars = "";
while (mPosition < mConditionalExpressions.length())
{
//erase all space
if (mConditionalExpressions[mPosition] != ' ')
{
currentChars += mConditionalExpressions[mPosition];
}
else
{
mPosition++;
continue;
}
//performe tokenisation, find a regex and make a new token
if (std::regex_match(currentChars,std::regex("\\&\\&")))// the AND TOKEN
{
mPosition++;
return std::make_shared<ConditionalToken>(ConditionalTokenTypes::AND,"");
}
else if (std::regex_match(currentChars,std::regex("\\|\\|")))// the OR TOKEN
{
mPosition++;
return std::make_shared<ConditionalToken>(ConditionalTokenTypes::OR,"");
}
else if (std::regex_match(currentChars,std::regex("\\!")))// the Not and not equ
{
mPosition++;
if ( mPosition < mConditionalExpressions.length()){
currentChars += mConditionalExpressions[mPosition];
if(std::regex_match(currentChars,std::regex("!="))){
mPosition++;
return std::make_shared<ConditionalToken>(ConditionalTokenTypes::NEQ,"");
}else{
return std::make_shared<ConditionalToken>(ConditionalTokenTypes::NOT,"");
}
}
//a not at the end not ok but it's the parseur work
return std::make_shared<ConditionalToken>(ConditionalTokenTypes::NOT,"");
}
else if (std::regex_match(currentChars,std::regex("==")))// the EQ TOKEN
{
mPosition++;
return std::make_shared<ConditionalToken>(ConditionalTokenTypes::EQ,"");
}
// else if (std::regex_match(currentChars,std::regex("!=")))// the NEQ TOKEN
// {
// mPosition++;
// return std::make_shared<ConditionalToken>(ConditionalTokenTypes::NEQ,"");
// }
else if (std::regex_match(currentChars,std::regex("\\(")))// the LPAREN TOKEN
{
mPosition++;
return std::make_shared<ConditionalToken>(ConditionalTokenTypes::LPAREN,"");
}
else if (std::regex_match(currentChars,std::regex("\\)")))// the RPAREN TOKEN
{
mPosition++;
return std::make_shared<ConditionalToken>(ConditionalTokenTypes::RPAREN,"");
}
else if (std::regex_match(currentChars,std::regex(",")))// the RPAREN TOKEN
{
mPosition++;
return std::make_shared<ConditionalToken>(ConditionalTokenTypes::ARGSEP,"");
}
else if (std::regex_match(currentChars,std::regex("\\$")))// the ACTNode TOKEN
{
mPosition++;
return std::make_shared<ConditionalToken>(ConditionalTokenTypes::NODE,"");
}
/////
//non const lent token
/////
//LAMBDA, KEY , bool //the fuction TAG
else if (std::regex_match(currentChars,std::regex("[A-Za-z_]")))// the KEY TOKEN (a char next )
{
//read all the key
bool isLambda = false;
std::regex keyRegex("[A-Za-z_0-9]+");
std::regex LambdaRegex("[A-Za-z_0-9]+\\(");
while ( mPosition < mConditionalExpressions.length()) {
if(!std::regex_match(currentChars,keyRegex) && !std::regex_match(currentChars,LambdaRegex))
{
currentChars.pop_back(); //the last char is the problemes
break;
}
else if (std::regex_match(currentChars,LambdaRegex)){
isLambda = true;
}
mPosition++;
currentChars += mConditionalExpressions[mPosition];
}
//we end the match 2 posibility
//we are at the end of the mConditionalExpressions and we need to ensure the match
//we are not we can continu
if (mPosition == mConditionalExpressions.length()-1)
{
if (!std::regex_match(currentChars,keyRegex) && !std::regex_match(currentChars,LambdaRegex))
{
throw badTokenError(currentChars,mPosition);
}
//mPosition++; // we stop all by going pos > lengt
}
if (std::regex_match(currentChars,std::regex("(true|false)"))){
return std::make_shared<ConditionalToken>(ConditionalTokenTypes::BOOL,currentChars);
} else if (isLambda){
currentChars.pop_back();//pop the ( of the lambda
return std::make_shared<ConditionalToken>(ConditionalTokenTypes::LAMBDA,currentChars);
} else{
return std::make_shared<ConditionalToken>(ConditionalTokenTypes::KEY,currentChars);
}
}
//numeric value
else if (std::regex_match(currentChars,std::regex("[0-9]")))// the KEY TOKEN (a char next )
{
//read all the key
bool isFloat = false;
std::regex integerRegex("[0-9]+$");
std::regex floatRegex("[0-9]+\\.[0-9]*$");
while ( mPosition < mConditionalExpressions.length()) {
if(!std::regex_match(currentChars,integerRegex) && !std::regex_match(currentChars,floatRegex))
{
currentChars.pop_back(); // the last char match is not a good one
break;
}
else if (std::regex_match(currentChars,floatRegex)){
isFloat = true;
}
mPosition++;
currentChars += mConditionalExpressions[mPosition];
}
//we end the match 2 posibility
//we are at the end of the mConditionalExpressions and we need to ensure the match
//we are not we can continu
if (mPosition == mConditionalExpressions.length()-1)
{
if (!std::regex_match(currentChars,integerRegex) && !std::regex_match(currentChars,floatRegex))
{
throw badTokenError(currentChars,mPosition);
}
}
if(isFloat){
return std::make_shared<ConditionalToken>(ConditionalTokenTypes::FLOAT,currentChars);
}else{
return std::make_shared<ConditionalToken>(ConditionalTokenTypes::INTEGER,currentChars);
}
}
//string TODO
else if (std::regex_match(currentChars,std::regex("\'"))) // TODO ' or \'
{
std::regex strRegex("\'[A-Za-z_0-9\\s]*\'$");
while ( mPosition < mConditionalExpressions.length()) {
if(std::regex_match(currentChars,strRegex)){
break;
}
mPosition++;
currentChars += mConditionalExpressions[mPosition];
}
//test the end condition
if (mPosition == mConditionalExpressions.length()-1 ){
if (!std::regex_match(currentChars,strRegex)){
throw badTokenError(currentChars,mPosition);
}
//mPosition++; // we stop all by going pos > lengt
}
mPosition++; // go after the last "
//erase the " char
currentChars.pop_back();
currentChars.erase(0,1);
return std::make_shared<ConditionalToken>(ConditionalTokenTypes::STRING,currentChars);
}
//Array TODO
mPosition++;
}
//no more to find no one match the currentChars
if (currentChars.empty()) {
return std::make_shared<ConditionalToken>(ConditionalTokenTypes::STOP,""); // Null shared pointer ;
}else{
//std::ostringstream errorMessage;
//errorMessage << "\nBad syntax " << currentChars << " :\n" << mConditionalExpressions;
throw badTokenError(currentChars,mPosition);
}
}
void ConditionalLexer::rstPosition(void){
if (isEnd()){
mPosition = 0;
}else{
throw badTokenError("end rst",mPosition);
}
}
bool ConditionalLexer::isEnd(void){
return mPosition >= mConditionalExpressions.length();
}
std::runtime_error ConditionalLexer::badTokenError(const std::string& currentChars,std::size_t position){
std::ostringstream errorMessage;
errorMessage << "\nBad syntax " << currentChars << " :\n" << mConditionalExpressions << "\n";
for (std::size_t i = 0; i < position; i++) {
errorMessage << ' ';
}
errorMessage << "^\n";
return std::runtime_error(errorMessage.str());
}
\ No newline at end of file
#include "nodeTester/ConditionalParser.hpp"
using namespace Aidge;
AstConditionalNode::AstConditionalNode(std::shared_ptr<ConditionalToken> token,ASTNodeCh child )
:mToken(token),mChild(child){}
std::string AstConditionalNode::getValue() const{
return mToken->getLexeme();
}
ConditionalTokenTypes AstConditionalNode::getType() const{
return mToken->getType();
}
bool AstConditionalNode::isLeaf() const {
return mChild.size() == 0;
}
const ASTNodeCh& AstConditionalNode::getChilds() const {
return mChild;
}
std::size_t AstConditionalNode::nbChild() const{
return mChild.size();
}
//////////////////////////////
//ConditionalParser
//////////////////////////////
ConditionalParser::ConditionalParser(const std::string ConditionalExpressions):mLexer(ConditionalExpressions){
mCurrentToken = mLexer.getNextToken();
}
void ConditionalParser::rstParser(void){
mLexer.rstPosition();
mCurrentToken = mLexer.getNextToken();
}
void ConditionalParser::ackToken(ConditionalTokenTypes tokenType){
if(mCurrentToken->getType() == tokenType ){
try {
mCurrentToken = mLexer.getNextToken();
} catch (const std::runtime_error& e) {
std::ostringstream errorMessage;
errorMessage << "Conditional Lexer error in Parser :\n"<< e.what() << std::endl;
throw std::runtime_error(errorMessage.str());
}
}else{
std::ostringstream errorMessage;
errorMessage << "Bad syntax ConditionalParser " << static_cast<int>(mCurrentToken->getType()) <<"!="<< static_cast<int>(tokenType) << "\n";
errorMessage << mLexer.rep();
throw std::runtime_error(errorMessage.str());
}
}
std::shared_ptr<AstConditionalNode> ConditionalParser::constructAstVal(void){
/*
val : (KEY|INTEGER|FOAT|STRING|LAMBDA)
*/
std::shared_ptr<Aidge::ConditionalToken> token = mCurrentToken->copy();
if (token->getType() == ConditionalTokenTypes::KEY){
ackToken(ConditionalTokenTypes::KEY);
return std::make_shared<AstConditionalNode>(token);
}
else if(token->getType() == ConditionalTokenTypes::INTEGER){
ackToken(ConditionalTokenTypes::INTEGER);
return std::make_shared<AstConditionalNode>(token);
}
else if(token->getType() == ConditionalTokenTypes::FLOAT){
ackToken(ConditionalTokenTypes::FLOAT);
return std::make_shared<AstConditionalNode>(token);
}
else if(token->getType() == ConditionalTokenTypes::BOOL){
ackToken(ConditionalTokenTypes::BOOL);
return std::make_shared<AstConditionalNode>(token);
}
else if(token->getType() == ConditionalTokenTypes::STRING){
ackToken(ConditionalTokenTypes::STRING);
return std::make_shared<AstConditionalNode>(token);
}else if(token->getType() == ConditionalTokenTypes::NODE){
ackToken(ConditionalTokenTypes::NODE);
return std::make_shared<AstConditionalNode>(token);
}else if(token->getType() == ConditionalTokenTypes::LAMBDA){
return constructAstLambda();
}
throw std::runtime_error("ConditionalParser unknow val type "+ token->rep().str() + "\n" + mLexer.rep());
}
std::shared_ptr<AstConditionalNode> ConditionalParser::constructAstLambda(void){
/*
AstLambda : LAMBDA val (ARGSEP val)* RPAREN
*/
std::shared_ptr<Aidge::ConditionalToken> tokenLdb = mCurrentToken->copy();
ackToken(ConditionalTokenTypes::LAMBDA);
ASTNodeCh paramLambda;
//AT LEAST ONE VALUE AS INPUT OF A LAMBDA
paramLambda.push_back(constructAstVal());
while (mCurrentToken->getType() != ConditionalTokenTypes::RPAREN)
{
ackToken(ConditionalTokenTypes::ARGSEP);
paramLambda.push_back(constructAstVal());
}
ackToken(ConditionalTokenTypes::RPAREN);
return std::make_shared<AstConditionalNode>(tokenLdb,paramLambda);
}
std::shared_ptr<AstConditionalNode> ConditionalParser::constructAstCmpr(void){
/*
cmpr : val (EQ|NEQ) val | LPAREN expr RPAREN
NOT ir ?
*/
std::shared_ptr<Aidge::ConditionalToken> token = mCurrentToken->copy();
//we can check the type relation ir key (EQ|NEQ) val | val (EQ|NEQ) key , but val (EQ|NEQ) val is valid ?
if (token->getType() == ConditionalTokenTypes::LPAREN)
{
ackToken(ConditionalTokenTypes::LPAREN);
std::shared_ptr<AstConditionalNode> node = constructAstExpr();
ackToken(ConditionalTokenTypes::RPAREN);
return node;
}else{
std::shared_ptr<AstConditionalNode> node = constructAstVal();
token = mCurrentToken->copy();
if (token->getType() == ConditionalTokenTypes::EQ){
ackToken(ConditionalTokenTypes::EQ);
return std::make_shared<AstConditionalNode>(token,ASTNodeCh{node,constructAstVal()});
}else if(token->getType() == ConditionalTokenTypes::NEQ){
ackToken(ConditionalTokenTypes::NEQ);
return std::make_shared<AstConditionalNode>(token,ASTNodeCh{node,constructAstVal()});
}
}
}
std::shared_ptr<AstConditionalNode> ConditionalParser::constructAstExpr(std::size_t precLimit /*= 0*/){
/*
expr : cmpr ((AND | OR) cmpr)*
the NOT is not binary OP can be use in pratt
precedence H to L: TODO
AND
OR
*/
//the not
std::shared_ptr<AstConditionalNode> left;
std::shared_ptr<Aidge::ConditionalToken> token = mCurrentToken->copy();
if (mCurrentToken->getType() == ConditionalTokenTypes::NOT ){
ackToken(ConditionalTokenTypes::NOT );
left= std::make_shared<AstConditionalNode>(token,ASTNodeCh{constructAstCmpr()});
}else{
left= constructAstCmpr();
}
//pratt
while (mCurrentToken->getType() != ConditionalTokenTypes::STOP ) //security
{
std::shared_ptr<Aidge::ConditionalToken> token = mCurrentToken->copy();
//if the token is not in the map is not a operator so we consider a prec of 0
if (ConditionalPrec.find(token->getType()) ==ConditionalPrec.end() ){
return left;
}
//if my actual operator have a prec <= of the last operator
std::size_t prec = ConditionalPrec.at(token->getType());
if (prec <= precLimit){
return left;
}
//Act all AND and OR
ackToken(token->getType());
std::shared_ptr<AstConditionalNode> right = constructAstExpr(prec);
//i'm not sur what append to newNode
//std::shared_ptr<AstConditionalNode> newNode = std::make_shared<AstConditionalNode>(token,ASTNodeCh{left,constructAstCmpr()});
std::shared_ptr<AstConditionalNode> newNode = std::make_shared<AstConditionalNode>(token,ASTNodeCh{left,right});
left = newNode;
}
return left;
}
std::shared_ptr<AstConditionalNode> ConditionalParser::parse(void){
/*
expr : cmpr ((AND | OR) cmpr)*
cmpr : val (EQ|NEQ) val | LPAREN expr RPAREN | BOOL | LAMBDA
val : (KEY|INTEGER|FOAT|STRING|LAMBDA)
lambda : LAMBDA val (ARGSEP val)* RPAREN
*/
std::shared_ptr<AstConditionalNode> astTree = constructAstExpr();
rstParser();
return astTree;
}
\ No newline at end of file
#include <catch2/catch_test_macros.hpp>
#include "nodeTester/ConditionalInterpreter.hpp"
#include "operator/GenericOperator.hpp"
using namespace Aidge;
TEST_CASE("ConditionalInterpreter", "ConditionalInterpreter") {
SECTION("custom Lambda") {
const std::string test = " !toto($) == true " ;
ConditionalInterpreter conditionalParser = ConditionalInterpreter(test);
conditionalParser.insertLambda("toto",+[](NodePtr NodeOp){return false;});
std::shared_ptr<Node> nodeOp = GenericOperator("conv", 0, 0, 0, "Gop1");
bool result = conditionalParser.test(nodeOp);
REQUIRE(result == true);
}
SECTION("syntax error") {
const std::string test = "'A' == 'A' ,&& ";
REQUIRE_THROWS_AS( ConditionalInterpreter(test), std::runtime_error);
}
}
\ No newline at end of file
#include <catch2/catch_test_macros.hpp>
#include "nodeTester/ConditionalLexer.hpp"
#include <iostream>
#include <map>
#include <functional>
using namespace Aidge;
TEST_CASE("nodeTester", "Lexer") {
SECTION("RandomGenerateTest") {
std::map<ConditionalTokenTypes, std::function<std::pair<std::string, std::string>()>> LexerTestMap{
{ConditionalTokenTypes::AND, +[](){return std::pair<std::string, std::string>("&& ","");}},
{ConditionalTokenTypes::OR, +[](){return std::pair<std::string, std::string>("|| ","");}},
{ConditionalTokenTypes::EQ, +[](){return std::pair<std::string, std::string>("== ","");}},
{ConditionalTokenTypes::NEQ, +[](){return std::pair<std::string, std::string>("!= ","");}},
{ConditionalTokenTypes::KEY, +[](){return std::pair<std::string, std::string>("A ","A");}},
{ConditionalTokenTypes::BOOL, +[](){
std::size_t keyLen = (std::rand() % 2);
const std::vector<std::string> characters = {"true","false"};
return std::pair<std::string, std::string>(characters[keyLen]+" ",characters[keyLen]);}
},
{ConditionalTokenTypes::INTEGER, +[](){
std::size_t keyLen = (std::rand() % 20)+1;
const std::string characters = "1234567890";
std::size_t randomIndex = std::rand() % characters.size();
std::string key;
for (std::size_t i = 0; i < keyLen; ++i) {
key += characters[randomIndex];
randomIndex = std::rand() % characters.size();
}
return std::pair<std::string, std::string>(key+" ",key);}
},
{ConditionalTokenTypes::FLOAT, +[](){
std::size_t keyLen = (std::rand() % 20)+2;
const std::string characters = "1234567890";
std::size_t randomIndex = std::rand() % characters.size();
std::string key;
for (std::size_t i = 0; i < keyLen/2; ++i) {
key += characters[randomIndex];
randomIndex = std::rand() % characters.size();
}
key += ".";
for (std::size_t i = 0; i < keyLen/2; ++i) {
key += characters[randomIndex];
randomIndex = std::rand() % characters.size();
}
return std::pair<std::string, std::string>(key+" ",key);}
},
{ConditionalTokenTypes::STRING, +[](){
std::size_t keyLen = (std::rand() % 20)+1;
const std::string characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 ";
std::size_t randomIndex = std::rand() % characters.size();
std::string key;
for (std::size_t i = 0; i < keyLen; ++i) {
key += characters[randomIndex];
randomIndex = std::rand() % characters.size();
}
return std::pair<std::string, std::string>("'"+key+"' ",key);}
},
{ConditionalTokenTypes::LAMBDA, +[](){
std::size_t keyLen = (std::rand() % 20)+1;
const std::string characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
const std::string Startchar = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
std::size_t randomIndex = std::rand() % characters.size();
std::size_t randomStartIndex = std::rand() % Startchar.size();
std::string key;
key += Startchar[randomStartIndex];
for (std::size_t i = 0; i < keyLen; ++i) {
key += characters[randomIndex];
randomIndex = std::rand() % characters.size();
}
return std::pair<std::string, std::string>(key+"( ",key);}
},
{ConditionalTokenTypes::ARGSEP, +[](){return std::pair<std::string, std::string>(", ","");}},
{ConditionalTokenTypes::NODE, +[](){return std::pair<std::string, std::string>("$ ","");}},
{ConditionalTokenTypes::LPAREN, +[](){return std::pair<std::string, std::string>("( ","");}},
{ConditionalTokenTypes::RPAREN, +[](){return std::pair<std::string, std::string>(") ","");}}
//{ConditionalTokenTypes::STOP, +[](){return std::pair<std::string, std::string>("","");}}
};
//////////////////
//TEST GENERATOR
//////////////////
const std::size_t numRandomElements = 100;
std::vector<std::tuple<ConditionalTokenTypes, std::string>> testVector;
std::string testString;
for (std::size_t i = 0; i < numRandomElements; ++i) {
int randomIndex = std::rand() % LexerTestMap.size();
// Get an iterator to the random element in the map
auto it = std::next(LexerTestMap.begin(), randomIndex);
// Access the random key and lambda value separately using structured binding
ConditionalTokenTypes randomKey = it->first;
std::function<std::pair<std::string, std::string>()> randomValue = it->second;
std::pair<std::string, std::string> result = randomValue();
testString += result.first;
testVector.emplace_back(randomKey, result.second);
}
ConditionalLexer conditionalLexer = ConditionalLexer(testString);
for (std::tuple<ConditionalTokenTypes, std::string> testToken : testVector) {
ConditionalTokenTypes tokenToFind = std::get<0>(testToken);
std::string lexemToFind = std::get<1>(testToken);
std::shared_ptr<Aidge::ConditionalToken> token = conditionalLexer.getNextToken();
std::ostringstream errorMessage;
errorMessage << "\n we whant :"<< lexemToFind << "\n we get : "<< token->getLexeme() <<"\n"<< "on \n" << testString << " :\n " ;
CAPTURE(errorMessage.str());
REQUIRE(token->getLexeme() == lexemToFind);
REQUIRE(token->getType() == tokenToFind);
}
std::shared_ptr<Aidge::ConditionalToken> token = conditionalLexer.getNextToken();
REQUIRE(token->getType() == ConditionalTokenTypes::STOP);
}
}
\ No newline at end of file
#include <catch2/catch_test_macros.hpp>
#include "nodeTester/ConditionalParser.hpp"
using namespace Aidge;
std::string gVal() {
int randomValue = std::rand() % 5;
switch (randomValue) {
case 0:
return std::to_string(std::rand() % 101);
case 1:
return std::to_string(std::rand() % 101)+"."+std::to_string(std::rand() % 101);
case 2:
return " 'toto' ";
case 3:
return " A ";
case 4:
return " A(10) ";
default:
return " true ";
}
}
std::string gExpr() ;
std::string gCmpr() {
int randomValue = std::rand() % 3;
switch (randomValue) {
case 0:
return gVal() + " == " +gVal();
case 1:
return "("+ gExpr() +")";
default:
return gVal() + " != " +gVal();
}
return gVal() + " == " +gVal();
}
std::string gExpr() {
std::string out = gCmpr();
int iterations = std::rand() % 100;
for (int i = 0; i < iterations; ++i) {
int randomValue = std::rand() % 2;
switch (randomValue) {
case 0:
return out +" && " + gCmpr();
break;
default:
return out +" || " + gCmpr();
break;
}
}
return out;
}
TEST_CASE("ConditionalParser", "ConditionalParser") {
SECTION("Empty") {
for (int i = 0; i < 1000; ++i) {
const std::string test = gExpr();
ConditionalParser conditionalParser = ConditionalParser(test);
std::shared_ptr<Aidge::AstConditionalNode> tree = conditionalParser.parse();
}
}
}
\ No newline at end of file
This diff is collapsed.
...@@ -10,9 +10,9 @@ BUILDDIR = build ...@@ -10,9 +10,9 @@ BUILDDIR = build
# Internal variables. # Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others # the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help .PHONY: help
help: help:
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
# documentation root, use os.path.abspath to make it absolute, like shown here. # documentation root, use os.path.abspath to make it absolute, like shown here.
# #
import os import os
import subprocess
import sys import sys
import pathlib import pathlib
sys.path.insert(0, os.path.abspath('../python')) sys.path.insert(0, os.path.abspath('../python'))
...@@ -26,7 +27,7 @@ author = u'CEA LIST' ...@@ -26,7 +27,7 @@ author = u'CEA LIST'
aidge_root = pathlib.Path().absolute() aidge_root = pathlib.Path().absolute()
version_file = open(aidge_root / "../../version.txt", "r").read().strip() version_file = open(aidge_root / "../version.txt", "r").read().strip()
# The short X.Y version # The short X.Y version
version = version_file version = version_file
...@@ -64,14 +65,20 @@ extensions = [ ...@@ -64,14 +65,20 @@ extensions = [
'sphinx_copybutton' 'sphinx_copybutton'
] ]
bibtex_bibfiles = ['_static/refs.bib']
graphviz_output_format = 'svg' graphviz_output_format = 'svg'
# Mermaid Configuration # Mermaid Configuration
mermaid_version = "9.3.0" mermaid_version = "9.3.0"
# Breathe Configuration # Breathe Configuration
breathe_default_project = "Aidge"
# Doxygen
subprocess.call('doxygen Doxyfile.in', shell=True)
breathe_projects = {
"aidge": "xml/"
}
breathe_default_project = "aidge"
breathe_default_members = ('members', 'undoc-members') breathe_default_members = ('members', 'undoc-members')
#Sphinx-gallery config #Sphinx-gallery config
...@@ -96,7 +103,7 @@ source_suffix = ['.rst', '.md'] ...@@ -96,7 +103,7 @@ source_suffix = ['.rst', '.md']
# source_suffix = '.rst' # source_suffix = '.rst'
# The master toctree document. # The master toctree document.
master_doc = 'index' master_doc = 'source/index'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.
...@@ -185,7 +192,9 @@ html_context = { ...@@ -185,7 +192,9 @@ html_context = {
# Add any paths that contain custom static files (such as style sheets) here, # Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files, # relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css". # so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static'] html_static_path = ['source/_static']
bibtex_bibfiles = [html_static_path[0] + '/refs.bib']
html_css_files = [ html_css_files = [
'css/custom.css', 'css/custom.css',
......
Data
====
C++ API for tensor class :
.. doxygenclass:: Aidge::Tensor
Aidge C++ API
=============
.. toctree::
data.rst
\ No newline at end of file
Aidge Python API
================
.. toctree::
Aidge API
=========
.. toctree::
Cpp/index.rst
Python/index.rst
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment