diff options
Diffstat (limited to 'host/lib/rfnoc/nocscript')
-rw-r--r-- | host/lib/rfnoc/nocscript/block_iface.cpp | 176 | ||||
-rw-r--r-- | host/lib/rfnoc/nocscript/block_iface.hpp | 38 | ||||
-rw-r--r-- | host/lib/rfnoc/nocscript/expression.cpp | 189 | ||||
-rw-r--r-- | host/lib/rfnoc/nocscript/expression.hpp | 112 | ||||
-rw-r--r-- | host/lib/rfnoc/nocscript/function_table.cpp | 72 | ||||
-rw-r--r-- | host/lib/rfnoc/nocscript/function_table.hpp | 43 | ||||
-rw-r--r-- | host/lib/rfnoc/nocscript/parser.cpp | 414 | ||||
-rw-r--r-- | host/lib/rfnoc/nocscript/parser.hpp | 12 |
8 files changed, 499 insertions, 557 deletions
diff --git a/host/lib/rfnoc/nocscript/block_iface.cpp b/host/lib/rfnoc/nocscript/block_iface.cpp index f0a4e89b5..48adc8ab2 100644 --- a/host/lib/rfnoc/nocscript/block_iface.cpp +++ b/host/lib/rfnoc/nocscript/block_iface.cpp @@ -18,108 +18,81 @@ using namespace uhd::rfnoc; using namespace uhd::rfnoc::nocscript; -block_iface::block_iface(block_ctrl_base *block_ptr) - : _block_ptr(block_ptr) +block_iface::block_iface(block_ctrl_base* block_ptr) : _block_ptr(block_ptr) { function_table::sptr ft = function_table::make(); // Add the SR_WRITE() function - expression_function::argtype_list_type sr_write_args = boost::assign::list_of - (expression::TYPE_STRING) - (expression::TYPE_INT) - ; - ft->register_function( - "SR_WRITE", + expression_function::argtype_list_type sr_write_args = + boost::assign::list_of(expression::TYPE_STRING)(expression::TYPE_INT); + ft->register_function("SR_WRITE", boost::bind(&block_iface::_nocscript__sr_write, this, _1), expression::TYPE_BOOL, - sr_write_args - ); + sr_write_args); // Add read access to arguments ($foo) - expression_function::argtype_list_type arg_set_args_wo_port = boost::assign::list_of - (expression::TYPE_STRING) - (expression::TYPE_INT) - ; - expression_function::argtype_list_type arg_set_args_w_port = boost::assign::list_of - (expression::TYPE_STRING) - (expression::TYPE_INT) - (expression::TYPE_INT) - ; -#define REGISTER_ARG_SETTER(noctype, setter_func) \ - arg_set_args_wo_port[1] = expression::noctype; \ - arg_set_args_w_port[1] = expression::noctype; \ - ft->register_function( \ - "SET_ARG", \ + expression_function::argtype_list_type arg_set_args_wo_port = + boost::assign::list_of(expression::TYPE_STRING)(expression::TYPE_INT); + expression_function::argtype_list_type arg_set_args_w_port = boost::assign::list_of( + expression::TYPE_STRING)(expression::TYPE_INT)(expression::TYPE_INT); +#define REGISTER_ARG_SETTER(noctype, setter_func) \ + arg_set_args_wo_port[1] = expression::noctype; \ + arg_set_args_w_port[1] = expression::noctype; \ + ft->register_function("SET_ARG", \ boost::bind(&block_iface::setter_func, this, _1), \ - expression::TYPE_BOOL, \ - arg_set_args_wo_port \ - ); \ - ft->register_function( \ - "SET_ARG", \ + expression::TYPE_BOOL, \ + arg_set_args_wo_port); \ + ft->register_function("SET_ARG", \ boost::bind(&block_iface::setter_func, this, _1), \ - expression::TYPE_BOOL, \ - arg_set_args_w_port \ - ); - REGISTER_ARG_SETTER(TYPE_INT, _nocscript__arg_set_int); - REGISTER_ARG_SETTER(TYPE_STRING, _nocscript__arg_set_string); - REGISTER_ARG_SETTER(TYPE_DOUBLE, _nocscript__arg_set_double); + expression::TYPE_BOOL, \ + arg_set_args_w_port); + REGISTER_ARG_SETTER(TYPE_INT, _nocscript__arg_set_int); + REGISTER_ARG_SETTER(TYPE_STRING, _nocscript__arg_set_string); + REGISTER_ARG_SETTER(TYPE_DOUBLE, _nocscript__arg_set_double); REGISTER_ARG_SETTER(TYPE_INT_VECTOR, _nocscript__arg_set_intvec); // Add read/write access to local variables - expression_function::argtype_list_type set_var_args = boost::assign::list_of - (expression::TYPE_STRING) - (expression::TYPE_INT) - ; - const expression_function::argtype_list_type get_var_args = boost::assign::list_of - (expression::TYPE_STRING) - ; -#define REGISTER_VAR_ACCESS(noctype, typestr) \ - set_var_args[1] = expression::noctype; \ - ft->register_function( \ - "SET_VAR", \ + expression_function::argtype_list_type set_var_args = + boost::assign::list_of(expression::TYPE_STRING)(expression::TYPE_INT); + const expression_function::argtype_list_type get_var_args = + boost::assign::list_of(expression::TYPE_STRING); +#define REGISTER_VAR_ACCESS(noctype, typestr) \ + set_var_args[1] = expression::noctype; \ + ft->register_function("SET_VAR", \ boost::bind(&block_iface::_nocscript__var_set, this, _1), \ - expression::TYPE_BOOL, \ - set_var_args \ - ); \ - ft->register_function( \ - "GET_"#typestr, \ + expression::TYPE_BOOL, \ + set_var_args); \ + ft->register_function("GET_" #typestr, \ boost::bind(&block_iface::_nocscript__var_get, this, _1), \ - expression::noctype, \ - get_var_args \ - ); + expression::noctype, \ + get_var_args); REGISTER_VAR_ACCESS(TYPE_INT, INT); REGISTER_VAR_ACCESS(TYPE_STRING, STRING); REGISTER_VAR_ACCESS(TYPE_DOUBLE, DOUBLE); REGISTER_VAR_ACCESS(TYPE_INT_VECTOR, INT_VECTOR); // Create the parser - _parser = parser::make( - ft, + _parser = parser::make(ft, boost::bind(&block_iface::_nocscript__arg_get_type, this, _1), - boost::bind(&block_iface::_nocscript__arg_get_val, this, _1) - ); + boost::bind(&block_iface::_nocscript__arg_get_val, this, _1)); } -void block_iface::run_and_check(const std::string &code, const std::string &error_message) +void block_iface::run_and_check(const std::string& code, const std::string& error_message) { boost::mutex::scoped_lock local_interpreter_lock(_lil_mutex); - UHD_NOCSCRIPT_LOG() << "[NocScript] Executing and asserting code: " << code ; - expression::sptr e = _parser->create_expr_tree(code); + UHD_NOCSCRIPT_LOG() << "[NocScript] Executing and asserting code: " << code; + expression::sptr e = _parser->create_expr_tree(code); expression_literal result = e->eval(); if (not result.to_bool()) { if (error_message.empty()) { - throw uhd::runtime_error(str( - boost::format("[NocScript] Code returned false: %s") - % code - )); + throw uhd::runtime_error( + str(boost::format("[NocScript] Code returned false: %s") % code)); } else { - throw uhd::runtime_error(str( - boost::format("[NocScript] Error: %s") - % error_message - )); + throw uhd::runtime_error( + str(boost::format("[NocScript] Error: %s") % error_message)); } } @@ -127,25 +100,26 @@ void block_iface::run_and_check(const std::string &code, const std::string &erro } -expression_literal block_iface::_nocscript__sr_write(expression_container::expr_list_type args) +expression_literal block_iface::_nocscript__sr_write( + expression_container::expr_list_type args) { const std::string reg_name = args[0]->eval().get_string(); - const uint32_t reg_val = uint32_t(args[1]->eval().get_int()); - bool result = true; + const uint32_t reg_val = uint32_t(args[1]->eval().get_int()); + bool result = true; try { - UHD_NOCSCRIPT_LOG() << "[NocScript] Executing SR_WRITE() " ; + UHD_NOCSCRIPT_LOG() << "[NocScript] Executing SR_WRITE() "; _block_ptr->sr_write(reg_name, reg_val); - } catch (const uhd::exception &e) { - UHD_LOGGER_ERROR("RFNOC") << boost::format("[NocScript] Error while executing SR_WRITE(%s, 0x%X):\n%s") - % reg_name % reg_val % e.what() - ; + } catch (const uhd::exception& e) { + UHD_LOGGER_ERROR("RFNOC") + << boost::format("[NocScript] Error while executing SR_WRITE(%s, 0x%X):\n%s") + % reg_name % reg_val % e.what(); result = false; } return expression_literal(result); } -expression::type_t block_iface::_nocscript__arg_get_type(const std::string &varname) +expression::type_t block_iface::_nocscript__arg_get_type(const std::string& varname) { const std::string var_type = _block_ptr->get_arg_type(varname); if (var_type == "int") { @@ -161,7 +135,7 @@ expression::type_t block_iface::_nocscript__arg_get_type(const std::string &varn } } -expression_literal block_iface::_nocscript__arg_get_val(const std::string &varname) +expression_literal block_iface::_nocscript__arg_get_val(const std::string& varname) { const std::string var_type = _block_ptr->get_arg_type(varname); if (var_type == "int") { @@ -177,46 +151,50 @@ expression_literal block_iface::_nocscript__arg_get_val(const std::string &varna } } -expression_literal block_iface::_nocscript__arg_set_int(const expression_container::expr_list_type &args) +expression_literal block_iface::_nocscript__arg_set_int( + const expression_container::expr_list_type& args) { const std::string var_name = args[0]->eval().get_string(); const int val = args[1]->eval().get_int(); - size_t port = 0; + size_t port = 0; if (args.size() == 3) { port = size_t(args[2]->eval().get_int()); } - UHD_NOCSCRIPT_LOG() << "[NocScript] Setting $" << var_name ; + UHD_NOCSCRIPT_LOG() << "[NocScript] Setting $" << var_name; _block_ptr->set_arg<int>(var_name, val, port); return expression_literal(true); } -expression_literal block_iface::_nocscript__arg_set_string(const expression_container::expr_list_type &args) +expression_literal block_iface::_nocscript__arg_set_string( + const expression_container::expr_list_type& args) { const std::string var_name = args[0]->eval().get_string(); const std::string val = args[1]->eval().get_string(); - size_t port = 0; + size_t port = 0; if (args.size() == 3) { port = size_t(args[2]->eval().get_int()); } - UHD_NOCSCRIPT_LOG() << "[NocScript] Setting $" << var_name ; + UHD_NOCSCRIPT_LOG() << "[NocScript] Setting $" << var_name; _block_ptr->set_arg<std::string>(var_name, val, port); return expression_literal(true); } -expression_literal block_iface::_nocscript__arg_set_double(const expression_container::expr_list_type &args) +expression_literal block_iface::_nocscript__arg_set_double( + const expression_container::expr_list_type& args) { const std::string var_name = args[0]->eval().get_string(); - const double val = args[1]->eval().get_double(); - size_t port = 0; + const double val = args[1]->eval().get_double(); + size_t port = 0; if (args.size() == 3) { port = size_t(args[2]->eval().get_int()); } - UHD_NOCSCRIPT_LOG() << "[NocScript] Setting $" << var_name ; + UHD_NOCSCRIPT_LOG() << "[NocScript] Setting $" << var_name; _block_ptr->set_arg<double>(var_name, val, port); return expression_literal(true); } -expression_literal block_iface::_nocscript__arg_set_intvec(const expression_container::expr_list_type &) +expression_literal block_iface::_nocscript__arg_set_intvec( + const expression_container::expr_list_type&) { UHD_THROW_INVALID_CODE_PATH(); } @@ -226,20 +204,22 @@ block_iface::sptr block_iface::make(uhd::rfnoc::block_ctrl_base* block_ptr) return sptr(new block_iface(block_ptr)); } -expression_literal block_iface::_nocscript__var_get(const expression_container::expr_list_type &args) +expression_literal block_iface::_nocscript__var_get( + const expression_container::expr_list_type& args) { expression_literal expr = _vars[args[0]->eval().get_string()]; - //std::cout << "[NocScript] Getting var " << args[0]->eval().get_string() << " == " << expr ; - //std::cout << "[NocScript] Type " << expr.infer_type() ; - //return _vars[args[0]->eval().get_string()]; + // std::cout << "[NocScript] Getting var " << args[0]->eval().get_string() << " == " + // << expr ; std::cout << "[NocScript] Type " << expr.infer_type() ; return + // _vars[args[0]->eval().get_string()]; return expr; } -expression_literal block_iface::_nocscript__var_set(const expression_container::expr_list_type &args) +expression_literal block_iface::_nocscript__var_set( + const expression_container::expr_list_type& args) { _vars[args[0]->eval().get_string()] = args[1]->eval(); - //std::cout << "[NocScript] Set var " << args[0]->eval().get_string() << " to " << _vars[args[0]->eval().get_string()] ; - //std::cout << "[NocScript] Type " << _vars[args[0]->eval().get_string()].infer_type() ; + // std::cout << "[NocScript] Set var " << args[0]->eval().get_string() << " to " << + // _vars[args[0]->eval().get_string()] ; std::cout << "[NocScript] Type " << + // _vars[args[0]->eval().get_string()].infer_type() ; return expression_literal(true); } - diff --git a/host/lib/rfnoc/nocscript/block_iface.hpp b/host/lib/rfnoc/nocscript/block_iface.hpp index 3fafcb4d0..9d13fd4ab 100644 --- a/host/lib/rfnoc/nocscript/block_iface.hpp +++ b/host/lib/rfnoc/nocscript/block_iface.hpp @@ -11,7 +11,7 @@ #include <boost/thread/mutex.hpp> #ifndef INCLUDED_LIBUHD_NOCSCRIPT_BLOCK_IFACE_HPP -#define INCLUDED_LIBUHD_NOCSCRIPT_BLOCK_IFACE_HPP +# define INCLUDED_LIBUHD_NOCSCRIPT_BLOCK_IFACE_HPP namespace uhd { namespace rfnoc { namespace nocscript { @@ -22,14 +22,14 @@ namespace uhd { namespace rfnoc { namespace nocscript { * NocScript function calls that require access to the original block * controller class. */ -class block_iface { +class block_iface +{ +public: + typedef boost::shared_ptr<block_iface> sptr; - public: - typedef boost::shared_ptr<block_iface> sptr; + static sptr make(uhd::rfnoc::block_ctrl_base* block_ptr); - static sptr make(uhd::rfnoc::block_ctrl_base* block_ptr); - - block_iface(uhd::rfnoc::block_ctrl_base* block_ptr); + block_iface(uhd::rfnoc::block_ctrl_base* block_ptr); /*! Execute \p code and make sure it returns 'true'. * @@ -39,9 +39,9 @@ class block_iface { * \throws uhd::runtime_error if the expression returns false. * \throws uhd::syntax_error if the expression is invalid. */ - void run_and_check(const std::string &code, const std::string &error_message=""); + void run_and_check(const std::string& code, const std::string& error_message = ""); - private: +private: //! For the local interpreter lock (lil) boost::mutex _lil_mutex; @@ -49,22 +49,26 @@ class block_iface { expression_literal _nocscript__sr_write(expression_container::expr_list_type); //! Argument type getter that can be used within NocScript - expression::type_t _nocscript__arg_get_type(const std::string &argname); + expression::type_t _nocscript__arg_get_type(const std::string& argname); //! Argument value getter that can be used within NocScript - expression_literal _nocscript__arg_get_val(const std::string &argname); + expression_literal _nocscript__arg_get_val(const std::string& argname); //! Argument value setters: - expression_literal _nocscript__arg_set_int(const expression_container::expr_list_type &); - expression_literal _nocscript__arg_set_string(const expression_container::expr_list_type &); - expression_literal _nocscript__arg_set_double(const expression_container::expr_list_type &); - expression_literal _nocscript__arg_set_intvec(const expression_container::expr_list_type &); + expression_literal _nocscript__arg_set_int( + const expression_container::expr_list_type&); + expression_literal _nocscript__arg_set_string( + const expression_container::expr_list_type&); + expression_literal _nocscript__arg_set_double( + const expression_container::expr_list_type&); + expression_literal _nocscript__arg_set_intvec( + const expression_container::expr_list_type&); //! Variable value getter - expression_literal _nocscript__var_get(const expression_container::expr_list_type &); + expression_literal _nocscript__var_get(const expression_container::expr_list_type&); //! Variable value setter - expression_literal _nocscript__var_set(const expression_container::expr_list_type &); + expression_literal _nocscript__var_set(const expression_container::expr_list_type&); //! Raw pointer to the block class. Note that since block_iface may // only live as a member of a block_ctrl_base, we don't really need diff --git a/host/lib/rfnoc/nocscript/expression.cpp b/host/lib/rfnoc/nocscript/expression.cpp index 1a7f3ee94..32065bda1 100644 --- a/host/lib/rfnoc/nocscript/expression.cpp +++ b/host/lib/rfnoc/nocscript/expression.cpp @@ -8,121 +8,110 @@ #include "expression.hpp" #include "function_table.hpp" #include <uhd/utils/cast.hpp> -#include <boost/format.hpp> #include <boost/algorithm/string.hpp> +#include <boost/format.hpp> using namespace uhd::rfnoc::nocscript; -std::map<expression::type_t, std::string> expression::type_repr{ - {TYPE_INT, "INT"}, +std::map<expression::type_t, std::string> expression::type_repr{{TYPE_INT, "INT"}, {TYPE_DOUBLE, "DOUBLE"}, {TYPE_STRING, "STRING"}, {TYPE_BOOL, "BOOL"}, - {TYPE_INT_VECTOR, "INT_VECTOR"} -}; + {TYPE_INT_VECTOR, "INT_VECTOR"}}; /******************************************************************** * Literal expressions (constants) *******************************************************************/ expression_literal::expression_literal( - const std::string token_val, - expression::type_t type -) : _bool_val(false) - , _int_val(0) - , _double_val(0.0) - , _val(token_val) - , _type(type) + const std::string token_val, expression::type_t type) + : _bool_val(false), _int_val(0), _double_val(0.0), _val(token_val), _type(type) { switch (_type) { - case expression::TYPE_STRING: - // Remove the leading and trailing quotes: - _val = _val.substr(1, _val.size()-2); - break; - - case expression::TYPE_INT: - if (_val.substr(0, 2) == "0x") { - _int_val = uhd::cast::hexstr_cast<int>(_val); - } else { - _int_val = std::stoi(_val); - } - break; - - case expression::TYPE_DOUBLE: - _double_val = std::stod(_val); - break; - - case expression::TYPE_BOOL: - if (boost::to_upper_copy(_val) == "TRUE") { - _bool_val = true; - } else { - // lexical cast to bool is too picky - _bool_val = bool(std::stoi(_val)); - } - break; - - case expression::TYPE_INT_VECTOR: - { - std::string str_vec = _val.substr(1, _val.size()-2); - std::vector<std::string> subtoken_list; - boost::split(subtoken_list, str_vec, boost::is_any_of(", "), boost::token_compress_on); - for(const std::string &t: subtoken_list) { - _int_vector_val.push_back(std::stoi(t)); - } - break; + case expression::TYPE_STRING: + // Remove the leading and trailing quotes: + _val = _val.substr(1, _val.size() - 2); + break; + + case expression::TYPE_INT: + if (_val.substr(0, 2) == "0x") { + _int_val = uhd::cast::hexstr_cast<int>(_val); + } else { + _int_val = std::stoi(_val); + } + break; + + case expression::TYPE_DOUBLE: + _double_val = std::stod(_val); + break; + + case expression::TYPE_BOOL: + if (boost::to_upper_copy(_val) == "TRUE") { + _bool_val = true; + } else { + // lexical cast to bool is too picky + _bool_val = bool(std::stoi(_val)); + } + break; + + case expression::TYPE_INT_VECTOR: { + std::string str_vec = _val.substr(1, _val.size() - 2); + std::vector<std::string> subtoken_list; + boost::split( + subtoken_list, str_vec, boost::is_any_of(", "), boost::token_compress_on); + for (const std::string& t : subtoken_list) { + _int_vector_val.push_back(std::stoi(t)); + } + break; } - default: - UHD_THROW_INVALID_CODE_PATH(); + default: + UHD_THROW_INVALID_CODE_PATH(); } } expression_literal::expression_literal(bool b) - : _bool_val(b) - , _int_val(0) - , _double_val(0.0) - , _val("") - , _type(expression::TYPE_BOOL) + : _bool_val(b), _int_val(0), _double_val(0.0), _val(""), _type(expression::TYPE_BOOL) { // nop } expression_literal::expression_literal(int i) - : _bool_val(false) - , _int_val(i) - , _double_val(0.0) - , _val("") - , _type(expression::TYPE_INT) + : _bool_val(false) + , _int_val(i) + , _double_val(0.0) + , _val("") + , _type(expression::TYPE_INT) { // nop } expression_literal::expression_literal(double d) - : _bool_val(false) - , _int_val(0) - , _double_val(d) - , _val("") - , _type(expression::TYPE_DOUBLE) + : _bool_val(false) + , _int_val(0) + , _double_val(d) + , _val("") + , _type(expression::TYPE_DOUBLE) { // nop } -expression_literal::expression_literal(const std::string &s) - : _bool_val(false) - , _int_val(0) - , _double_val(0.0) - , _val(s) - , _type(expression::TYPE_STRING) +expression_literal::expression_literal(const std::string& s) + : _bool_val(false) + , _int_val(0) + , _double_val(0.0) + , _val(s) + , _type(expression::TYPE_STRING) { // nop } expression_literal::expression_literal(const std::vector<int> v) - : _bool_val(false) - , _int_val(0) - , _double_val(0.0) - , _int_vector_val(v) - , _val("") - , _type(expression::TYPE_INT_VECTOR) + : _bool_val(false) + , _int_val(0) + , _double_val(0.0) + , _int_vector_val(v) + , _val("") + , _type(expression::TYPE_INT_VECTOR) { // nop } @@ -201,8 +190,7 @@ std::string expression_literal::repr() const return std::to_string(_double_val); case TYPE_BOOL: return _bool_val ? "TRUE" : "FALSE"; - case TYPE_INT_VECTOR: - { + case TYPE_INT_VECTOR: { std::stringstream sstr; sstr << "["; for (size_t i = 0; i < _int_vector_val.size(); i++) { @@ -213,13 +201,13 @@ std::string expression_literal::repr() const } sstr << "]"; return sstr.str(); - } + } default: UHD_THROW_INVALID_CODE_PATH(); } } -bool expression_literal::operator==(const expression_literal &rhs) const +bool expression_literal::operator==(const expression_literal& rhs) const { if (rhs.infer_type() != _type) { return false; @@ -287,7 +275,7 @@ expression_literal expression_container::eval() } expression_literal ret_val; - for(const expression::sptr &sub_expr: _sub_exprs) { + for (const expression::sptr& sub_expr : _sub_exprs) { ret_val = sub_expr->eval(); if (_combiner == COMBINE_AND and ret_val.to_bool() == false) { return ret_val; @@ -303,11 +291,12 @@ expression_literal expression_container::eval() /******************************************************************** * Functions *******************************************************************/ -std::string expression_function::to_string(const std::string &name, const argtype_list_type &types) +std::string expression_function::to_string( + const std::string& name, const argtype_list_type& types) { std::string s = name; int arg_count = 0; - for(const expression::type_t type: types) { + for (const expression::type_t type : types) { if (arg_count == 0) { s += "("; } else { @@ -322,17 +311,12 @@ std::string expression_function::to_string(const std::string &name, const argtyp } expression_function::expression_function( - const std::string &name, - const function_table::sptr func_table -) : _name(name) - , _func_table(func_table) + const std::string& name, const function_table::sptr func_table) + : _name(name), _func_table(func_table) { _combiner = COMBINE_ALL; if (not _func_table->function_exists(_name)) { - throw uhd::syntax_error(str( - boost::format("Unknown function: %s") - % _name - )); + throw uhd::syntax_error(str(boost::format("Unknown function: %s") % _name)); } } @@ -359,21 +343,18 @@ std::string expression_function::repr() const } expression_function::sptr expression_function::make( - const std::string &name, - const function_table::sptr func_table -) { + const std::string& name, const function_table::sptr func_table) +{ return sptr(new expression_function(name, func_table)); } /******************************************************************** * Variables *******************************************************************/ -expression_variable::expression_variable( - const std::string &token_val, +expression_variable::expression_variable(const std::string& token_val, type_getter_type type_getter, - value_getter_type value_getter -) : _type_getter(type_getter) - , _value_getter(value_getter) + value_getter_type value_getter) + : _type_getter(type_getter), _value_getter(value_getter) { // We can assume this is true because otherwise, it's not a valid token: UHD_ASSERT_THROW(not token_val.empty() and token_val[0] == '$'); @@ -391,11 +372,9 @@ expression_literal expression_variable::eval() return _value_getter(_varname); } -expression_variable::sptr expression_variable::make( - const std::string &token_val, - type_getter_type type_getter, - value_getter_type value_getter -) { +expression_variable::sptr expression_variable::make(const std::string& token_val, + type_getter_type type_getter, + value_getter_type value_getter) +{ return sptr(new expression_variable(token_val, type_getter, value_getter)); } - diff --git a/host/lib/rfnoc/nocscript/expression.hpp b/host/lib/rfnoc/nocscript/expression.hpp index 69b5198bb..becc329f0 100644 --- a/host/lib/rfnoc/nocscript/expression.hpp +++ b/host/lib/rfnoc/nocscript/expression.hpp @@ -6,14 +6,14 @@ // #include <uhd/exception.hpp> -#include <boost/shared_ptr.hpp> #include <boost/function.hpp> #include <boost/make_shared.hpp> -#include <vector> +#include <boost/shared_ptr.hpp> #include <map> +#include <vector> #ifndef INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_EXPR_HPP -#define INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_EXPR_HPP +# define INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_EXPR_HPP namespace uhd { namespace rfnoc { namespace nocscript { @@ -24,17 +24,11 @@ class expression_literal; */ class expression { - public: +public: typedef boost::shared_ptr<expression> sptr; //! All the possible return types for expressions within Noc-Script - enum type_t { - TYPE_INT, - TYPE_DOUBLE, - TYPE_STRING, - TYPE_BOOL, - TYPE_INT_VECTOR - }; + enum type_t { TYPE_INT, TYPE_DOUBLE, TYPE_STRING, TYPE_BOOL, TYPE_INT_VECTOR }; // TODO make this a const and fix the [] usage static std::map<type_t, std::string> type_repr; @@ -53,29 +47,28 @@ class expression */ class expression_literal : public expression { - public: +public: typedef boost::shared_ptr<expression_literal> sptr; - template <typename expr_type> - static sptr make(expr_type x) { return boost::make_shared<expression_literal>(x); }; + template <typename expr_type> static sptr make(expr_type x) + { + return boost::make_shared<expression_literal>(x); + }; /*! Generate the literal expression from its token string representation. * This includes markup, e.g. a string would still have the quotes, and * a hex value would still have leading 0x. */ - expression_literal( - const std::string token_val, - expression::type_t type - ); + expression_literal(const std::string token_val, expression::type_t type); //! Create a boolean literal expression from a C++ bool. - expression_literal(bool b=false); + expression_literal(bool b = false); //! Create an integer literal expression from a C++ int. expression_literal(int i); //! Create a double literal expression from a C++ double. expression_literal(double d); //! Create a string literal expression from a C++ string. - expression_literal(const std::string &s); + expression_literal(const std::string& s); //! Create an int vector literal expression from a C++ vector<int>. expression_literal(std::vector<int> v); @@ -149,9 +142,9 @@ class expression_literal : public expression //! String representation std::string repr() const; - bool operator==(const expression_literal &rhs) const; + bool operator==(const expression_literal& rhs) const; - private: +private: //! For TYPE_BOOL bool _bool_val; @@ -171,13 +164,13 @@ class expression_literal : public expression expression::type_t _type; }; -UHD_INLINE std::ostream& operator<< (std::ostream& out, const expression_literal &l) +UHD_INLINE std::ostream& operator<<(std::ostream& out, const expression_literal& l) { out << l.repr(); return out; } -UHD_INLINE std::ostream& operator<< (std::ostream& out, const expression_literal::sptr &l) +UHD_INLINE std::ostream& operator<<(std::ostream& out, const expression_literal::sptr& l) { out << l->repr(); return out; @@ -187,7 +180,7 @@ UHD_INLINE std::ostream& operator<< (std::ostream& out, const expression_literal */ class expression_container : public expression { - public: +public: typedef boost::shared_ptr<expression_container> sptr; typedef std::vector<expression::sptr> expr_list_type; @@ -195,15 +188,10 @@ class expression_container : public expression static sptr make(); //! List of valid combination types (see expression_container::eval()). - enum combiner_type { - COMBINE_ALL, - COMBINE_AND, - COMBINE_OR, - COMBINE_NOTSET - }; + enum combiner_type { COMBINE_ALL, COMBINE_AND, COMBINE_OR, COMBINE_NOTSET }; //! Create an empty container - expression_container() : _combiner(COMBINE_NOTSET) {}; + expression_container() : _combiner(COMBINE_NOTSET){}; virtual ~expression_container(){}; /*! Type-deduction rules for containers are: @@ -222,9 +210,15 @@ class expression_container : public expression void set_combiner_safe(const combiner_type c); - void set_combiner(const combiner_type c) { _combiner = c; }; + void set_combiner(const combiner_type c) + { + _combiner = c; + }; - combiner_type get_combiner() const { return _combiner; }; + combiner_type get_combiner() const + { + return _combiner; + }; /*! Evaluate a container by evaluating its sub-expressions. * @@ -243,7 +237,7 @@ class expression_container : public expression */ virtual expression_literal eval(); - protected: +protected: //! Store all the sub-expressions, in order expr_list_type _sub_exprs; combiner_type _combiner; @@ -273,23 +267,19 @@ class function_table; */ class expression_function : public expression_container { - public: +public: typedef boost::shared_ptr<expression_function> sptr; typedef std::vector<expression::type_t> argtype_list_type; //! Return an sptr to a function object without args static sptr make( - const std::string &name, - const boost::shared_ptr<function_table> func_table - ); + const std::string& name, const boost::shared_ptr<function_table> func_table); - static std::string to_string(const std::string &name, const argtype_list_type &types); + static std::string to_string(const std::string& name, const argtype_list_type& types); expression_function( - const std::string &name, - const boost::shared_ptr<function_table> func_table - ); - ~expression_function(){} + const std::string& name, const boost::shared_ptr<function_table> func_table); + ~expression_function() {} //! Add an argument expression virtual void add(expression::sptr new_expr); @@ -309,7 +299,7 @@ class expression_function : public expression_container //! String representation std::string repr() const; - private: +private: std::string _name; const boost::shared_ptr<function_table> _func_table; std::vector<expression::type_t> _arg_types; @@ -324,42 +314,38 @@ class expression_function : public expression_container */ class expression_variable : public expression { - public: +public: typedef boost::shared_ptr<expression_variable> sptr; - typedef boost::function<expression::type_t(const std::string &)> type_getter_type; - typedef boost::function<expression_literal(const std::string &)> value_getter_type; + typedef boost::function<expression::type_t(const std::string&)> type_getter_type; + typedef boost::function<expression_literal(const std::string&)> value_getter_type; - static sptr make( - const std::string &token_val, - type_getter_type type_getter, - value_getter_type value_getter - ); + static sptr make(const std::string& token_val, + type_getter_type type_getter, + value_getter_type value_getter); /*! Create a variable object from its token value * (e.g. '$spp', i.e. including the '$' symbol). The variable * does not have to exist at this point. */ - expression_variable( - const std::string &token_val, - type_getter_type type_getter, - value_getter_type value_getter - ); + expression_variable(const std::string& token_val, + type_getter_type type_getter, + value_getter_type value_getter); /*! Looks up the variable type in the variable table. * - * \throws Depending on \p type_getter, this may throw when the variable does not exist. - * Recommended behaviour is to throw uhd::syntax_error. + * \throws Depending on \p type_getter, this may throw when the variable does not + * exist. Recommended behaviour is to throw uhd::syntax_error. */ expression::type_t infer_type() const; /*! Look up a variable's value in the variable table. * - * \throws Depending on \p value_getter, this may throw when the variable does not exist. - * Recommended behaviour is to throw uhd::syntax_error. + * \throws Depending on \p value_getter, this may throw when the variable does not + * exist. Recommended behaviour is to throw uhd::syntax_error. */ expression_literal eval(); - private: +private: std::string _varname; type_getter_type _type_getter; value_getter_type _value_getter; diff --git a/host/lib/rfnoc/nocscript/function_table.cpp b/host/lib/rfnoc/nocscript/function_table.cpp index 621cd5809..57e32363d 100644 --- a/host/lib/rfnoc/nocscript/function_table.cpp +++ b/host/lib/rfnoc/nocscript/function_table.cpp @@ -15,18 +15,21 @@ using namespace uhd::rfnoc::nocscript; class function_table_impl : public function_table { - public: - struct function_info { +public: + struct function_info + { expression::type_t return_type; function_ptr function; - function_info(): return_type(expression::TYPE_INT) {}; - function_info(const expression::type_t return_type_, const function_ptr &function_) - : return_type(return_type_), function(function_) - {}; + function_info() : return_type(expression::TYPE_INT){}; + function_info( + const expression::type_t return_type_, const function_ptr& function_) + : return_type(return_type_), function(function_){}; }; // Should be an unordered_map... sigh, we'll get to C++11 someday. - typedef std::map<std::string, std::map<expression_function::argtype_list_type, function_info> > table_type; + typedef std::map<std::string, + std::map<expression_function::argtype_list_type, function_info>> + table_type; /************************************************************************ * Structors @@ -36,63 +39,58 @@ class function_table_impl : public function_table _REGISTER_ALL_FUNCS(); } - ~function_table_impl() {}; + ~function_table_impl(){}; /************************************************************************ * Interface implementation ***********************************************************************/ - bool function_exists(const std::string &name) const { + bool function_exists(const std::string& name) const + { return bool(_table.count(name)); } - bool function_exists( - const std::string &name, - const expression_function::argtype_list_type &arg_types - ) const { + bool function_exists(const std::string& name, + const expression_function::argtype_list_type& arg_types) const + { table_type::const_iterator it = _table.find(name); return (it != _table.end()) and bool(it->second.count(arg_types)); } - expression::type_t get_type( - const std::string &name, - const expression_function::argtype_list_type &arg_types - ) const { + expression::type_t get_type(const std::string& name, + const expression_function::argtype_list_type& arg_types) const + { table_type::const_iterator it = _table.find(name); if (it == _table.end() or (it->second.find(arg_types) == it->second.end())) { - throw uhd::syntax_error(str( - boost::format("Unable to retrieve return value for function %s") - % expression_function::to_string(name, arg_types) - )); + throw uhd::syntax_error( + str(boost::format("Unable to retrieve return value for function %s") + % expression_function::to_string(name, arg_types))); } return it->second.find(arg_types)->second.return_type; } - expression_literal eval( - const std::string &name, - const expression_function::argtype_list_type &arg_types, - expression_container::expr_list_type &arguments - ) { + expression_literal eval(const std::string& name, + const expression_function::argtype_list_type& arg_types, + expression_container::expr_list_type& arguments) + { if (not function_exists(name, arg_types)) { - throw uhd::syntax_error(str( - boost::format("Cannot eval() function %s, not a known signature") - % expression_function::to_string(name, arg_types) - )); + throw uhd::syntax_error( + str(boost::format("Cannot eval() function %s, not a known signature") + % expression_function::to_string(name, arg_types))); } return _table[name][arg_types].function(arguments); } - void register_function( - const std::string &name, - const function_table::function_ptr &ptr, - const expression::type_t return_type, - const expression_function::argtype_list_type &sig - ) { + void register_function(const std::string& name, + const function_table::function_ptr& ptr, + const expression::type_t return_type, + const expression_function::argtype_list_type& sig) + { _table[name][sig] = function_info(return_type, ptr); } - private: +private: table_type _table; }; diff --git a/host/lib/rfnoc/nocscript/function_table.hpp b/host/lib/rfnoc/nocscript/function_table.hpp index 6d7ef4202..63125ab1b 100644 --- a/host/lib/rfnoc/nocscript/function_table.hpp +++ b/host/lib/rfnoc/nocscript/function_table.hpp @@ -6,48 +6,45 @@ // #include "expression.hpp" -#include <boost/shared_ptr.hpp> #include <boost/function.hpp> +#include <boost/shared_ptr.hpp> #include <vector> #ifndef INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_FUNCTABLE_HPP -#define INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_FUNCTABLE_HPP +# define INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_FUNCTABLE_HPP namespace uhd { namespace rfnoc { namespace nocscript { class function_table { - public: +public: typedef boost::shared_ptr<function_table> sptr; - typedef boost::function<expression_literal(expression_container::expr_list_type&)> function_ptr; + typedef boost::function<expression_literal(expression_container::expr_list_type&)> + function_ptr; static sptr make(); - virtual ~function_table() {}; + virtual ~function_table(){}; /*! Check if any function with a given name exists * * \returns True, if any function with name \p name is registered. */ - virtual bool function_exists(const std::string &name) const = 0; + virtual bool function_exists(const std::string& name) const = 0; /*! Check if a function with a given name and list of argument types exists * * \returns True, if such a function is registered. */ - virtual bool function_exists( - const std::string &name, - const expression_function::argtype_list_type &arg_types - ) const = 0; + virtual bool function_exists(const std::string& name, + const expression_function::argtype_list_type& arg_types) const = 0; /*! Get the return type of a function with given name and argument type list * * \returns The function's return type * \throws uhd::syntax_error if no such function is registered */ - virtual expression::type_t get_type( - const std::string &name, - const expression_function::argtype_list_type &arg_types - ) const = 0; + virtual expression::type_t get_type(const std::string& name, + const expression_function::argtype_list_type& arg_types) const = 0; /*! Calls the function \p name with the argument list \p arguments * @@ -56,11 +53,9 @@ class function_table * \returns The return value of the called function * \throws uhd::syntax_error if no such function is found */ - virtual expression_literal eval( - const std::string &name, - const expression_function::argtype_list_type &arg_types, - expression_container::expr_list_type &arguments - ) = 0; + virtual expression_literal eval(const std::string& name, + const expression_function::argtype_list_type& arg_types, + expression_container::expr_list_type& arguments) = 0; /*! Register a new function * @@ -69,12 +64,10 @@ class function_table * \param return_type The function's return value * \param sig The function signature (list of argument types) */ - virtual void register_function( - const std::string &name, - const function_ptr &ptr, - const expression::type_t return_type, - const expression_function::argtype_list_type &sig - ) = 0; + virtual void register_function(const std::string& name, + const function_ptr& ptr, + const expression::type_t return_type, + const expression_function::argtype_list_type& sig) = 0; }; }}} /* namespace uhd::rfnoc::nocscript */ diff --git a/host/lib/rfnoc/nocscript/parser.cpp b/host/lib/rfnoc/nocscript/parser.cpp index 71bb7b028..f34d475ba 100644 --- a/host/lib/rfnoc/nocscript/parser.cpp +++ b/host/lib/rfnoc/nocscript/parser.cpp @@ -7,11 +7,11 @@ #include "parser.hpp" #include <uhd/utils/cast.hpp> -#include <boost/spirit/include/lex_lexertl.hpp> -#include <boost/format.hpp> -#include <boost/bind.hpp> #include <boost/assign.hpp> +#include <boost/bind.hpp> +#include <boost/format.hpp> #include <boost/make_shared.hpp> +#include <boost/spirit/include/lex_lexertl.hpp> #include <sstream> #include <stack> @@ -20,30 +20,28 @@ namespace lex = boost::spirit::lex; class parser_impl : public parser { - public: +public: /****************************************************************** * Structors TODO make them protected *****************************************************************/ - parser_impl( - function_table::sptr ftable, + parser_impl(function_table::sptr ftable, expression_variable::type_getter_type var_type_getter, - expression_variable::value_getter_type var_value_getter - ) : _ftable(ftable) - , _var_type_getter(var_type_getter) - , _var_value_getter(var_value_getter) + expression_variable::value_getter_type var_value_getter) + : _ftable(ftable) + , _var_type_getter(var_type_getter) + , _var_value_getter(var_value_getter) { // nop } - ~parser_impl() {}; + ~parser_impl(){}; /****************************************************************** * Parsing *****************************************************************/ //! List of parser tokens - enum token_ids - { + enum token_ids { ID_WHITESPACE = lex::min_token_id + 42, ID_KEYWORD, ID_ARG_SEP, @@ -58,29 +56,21 @@ class parser_impl : public parser }; //! The Lexer object used for NocScript - template <typename Lexer> - struct ns_lexer : lex::lexer<Lexer> + template <typename Lexer> struct ns_lexer : lex::lexer<Lexer> { ns_lexer() { - this->self.add - ("\\s+", ID_WHITESPACE) - (",", ID_ARG_SEP) - ("[A-Z][A-Z0-9_]*", ID_KEYWORD) - ("\\(", ID_PARENS_OPEN) - ("\\)", ID_PARENS_CLOSE) - ("\\$[a-z][a-z0-9_]*", ID_VARIABLE) - ("-?\\d+\\.\\d+", ID_LITERAL_DOUBLE) - ("-?\\d+", ID_LITERAL_INT) - ("0x[0-9A-F]+", ID_LITERAL_HEX) - ("\\\"[^\\\"]*\\\"", ID_LITERAL_STR) - ("'[^']*'", ID_LITERAL_STR) // both work - ("\\[[0-9]\\]", ID_LITERAL_VECTOR_INT) - ; + this->self.add("\\s+", ID_WHITESPACE)(",", ID_ARG_SEP)( + "[A-Z][A-Z0-9_]*", ID_KEYWORD)("\\(", ID_PARENS_OPEN)( + "\\)", ID_PARENS_CLOSE)("\\$[a-z][a-z0-9_]*", ID_VARIABLE)( + "-?\\d+\\.\\d+", ID_LITERAL_DOUBLE)("-?\\d+", ID_LITERAL_INT)( + "0x[0-9A-F]+", ID_LITERAL_HEX)("\\\"[^\\\"]*\\\"", ID_LITERAL_STR)( + "'[^']*'", ID_LITERAL_STR) // both work + ("\\[[0-9]\\]", ID_LITERAL_VECTOR_INT); } }; - private: +private: struct grammar_props { function_table::sptr ftable; @@ -92,12 +82,13 @@ class parser_impl : public parser std::string error; std::stack<expression_container::sptr> expr_stack; - grammar_props( - function_table::sptr ftable_, + grammar_props(function_table::sptr ftable_, expression_variable::type_getter_type var_type_getter_, - expression_variable::value_getter_type var_value_getter_ - ) : ftable(ftable_), var_type_getter(var_type_getter_), var_value_getter(var_value_getter_), - function_name("") + expression_variable::value_getter_type var_value_getter_) + : ftable(ftable_) + , var_type_getter(var_type_getter_) + , var_value_getter(var_value_getter_) + , function_name("") { UHD_ASSERT_THROW(expr_stack.empty()); // Push an empty container to the stack to hold the result @@ -124,11 +115,11 @@ class parser_impl : public parser static const int VALID_PARENS_OPEN = 0x2; static const int VALID_PARENS_CLOSE = 0x4; static const int VALID_EXPRESSION = 0x8 + 0x02; - static const int VALID_OPERATOR = 0x10; + static const int VALID_OPERATOR = 0x10; // !This function operator gets called for each of the matched tokens. template <typename Token> - bool operator()(Token const& t, grammar_props &P, int &next_valid_state) const + bool operator()(Token const& t, grammar_props& P, int& next_valid_state) const { //! This is totally not how Boost::Spirit is meant to be used, // as there's token types etc. But for now let's just convert @@ -136,218 +127,231 @@ class parser_impl : public parser std::stringstream sstr; sstr << t.value(); std::string val = sstr.str(); - //std::cout << "VAL: " << val << std::endl; - //std::cout << "Next valid states:\n" - //<< boost::format("VALID_COMMA [%s]\n") % ((next_valid_state & 0x1) ? "x" : " ") - //<< boost::format("VALID_PARENS_OPEN [%s]\n") % ((next_valid_state & 0x2) ? "x" : " ") - //<< boost::format("VALID_PARENS_CLOSE [%s]\n") % ((next_valid_state & 0x4) ? "x" : " ") - //<< boost::format("VALID_EXPRESSION [%s]\n") % ((next_valid_state & (0x8 + 0x02)) ? "x" : " ") - //<< boost::format("VALID_OPERATOR [%s]\n") % ((next_valid_state & 0x10) ? "x" : " ") - //<< std::endl; + // std::cout << "VAL: " << val << std::endl; + // std::cout << "Next valid states:\n" + //<< boost::format("VALID_COMMA [%s]\n") % ((next_valid_state & 0x1) ? + //"x" : " ") + //<< boost::format("VALID_PARENS_OPEN [%s]\n") % ((next_valid_state & 0x2) ? + //"x" : " ") + //<< boost::format("VALID_PARENS_CLOSE [%s]\n") % ((next_valid_state & 0x4) ? + //"x" : " ") + //<< boost::format("VALID_EXPRESSION [%s]\n") % ((next_valid_state & (0x8 + + //0x02)) ? "x" : " ") + //<< boost::format("VALID_OPERATOR [%s]\n") % ((next_valid_state & 0x10) + //? "x" : " ") + //<< std::endl; switch (t.id()) { + case ID_WHITESPACE: + // Ignore + break; - case ID_WHITESPACE: - // Ignore - break; - - case ID_KEYWORD: - // Ambiguous, could be an operator (AND, OR) or a function name (ADD, MULT...). - // So first, check which it is: - if (val == "AND" or val == "OR") { - if (not (next_valid_state & VALID_OPERATOR)) { - P.error = str(boost::format("Unexpected operator: %s") % val); + case ID_KEYWORD: + // Ambiguous, could be an operator (AND, OR) or a function name (ADD, + // MULT...). So first, check which it is: + if (val == "AND" or val == "OR") { + if (not(next_valid_state & VALID_OPERATOR)) { + P.error = str(boost::format("Unexpected operator: %s") % val); + return false; + } + next_valid_state = VALID_EXPRESSION; + try { + if (val == "AND") { + P.expr_stack.top()->set_combiner_safe( + expression_container::COMBINE_AND); + } else if (val == "OR") { + P.expr_stack.top()->set_combiner_safe( + expression_container::COMBINE_OR); + } + } catch (const uhd::syntax_error& e) { + P.error = str(boost::format("Operator %s is mixing operator " + "types within this container.") + % val); + } + // Right now, we can't have multiple operator types within a + // container. We might be able to change that, if there's enough + // demand. Either we keep track of multiple operators, or we open + // a new container. In the latter case, we'd need a way of keeping + // track of those containers, so it's a bit tricky. + break; + } + // If it's not a keyword, it has to be a function, so check the + // function table: + if (not(next_valid_state & VALID_EXPRESSION)) { + P.error = str(boost::format("Unexpected expression: %s") % val); return false; } - next_valid_state = VALID_EXPRESSION; - try { - if (val == "AND") { - P.expr_stack.top()->set_combiner_safe(expression_container::COMBINE_AND); - } else if (val == "OR") { - P.expr_stack.top()->set_combiner_safe(expression_container::COMBINE_OR); - } - } catch (const uhd::syntax_error &e) { - P.error = str(boost::format("Operator %s is mixing operator types within this container.") % val); + if (not P.ftable->function_exists(val)) { + P.error = str(boost::format("Unknown function: %s") % val); + return false; } - // Right now, we can't have multiple operator types within a container. - // We might be able to change that, if there's enough demand. Either - // we keep track of multiple operators, or we open a new container. - // In the latter case, we'd need a way of keeping track of those containers, - // so it's a bit tricky. + P.function_name = val; + next_valid_state = VALID_PARENS_OPEN; break; - } - // If it's not a keyword, it has to be a function, so check the - // function table: - if (not (next_valid_state & VALID_EXPRESSION)) { - P.error = str(boost::format("Unexpected expression: %s") % val); - return false; - } - if (not P.ftable->function_exists(val)) { - P.error = str(boost::format("Unknown function: %s") % val); - return false; - } - P.function_name = val; - next_valid_state = VALID_PARENS_OPEN; - break; - // Every () creates a new container, either a raw container or - // a function. - case ID_PARENS_OPEN: - if (not (next_valid_state & VALID_PARENS_OPEN)) { - P.error = str(boost::format("Unexpected parentheses.")); - return false; - } - if (not P.function_name.empty()) { - // We've already checked the function name exists - P.expr_stack.push(expression_function::make(P.function_name, P.ftable)); - P.function_name.clear(); - } else { + // Every () creates a new container, either a raw container or + // a function. + case ID_PARENS_OPEN: + if (not(next_valid_state & VALID_PARENS_OPEN)) { + P.error = str(boost::format("Unexpected parentheses.")); + return false; + } + if (not P.function_name.empty()) { + // We've already checked the function name exists + P.expr_stack.push( + expression_function::make(P.function_name, P.ftable)); + P.function_name.clear(); + } else { + P.expr_stack.push(expression_container::make()); + } + // Push another empty container to hold the first element/argument + // in this container: P.expr_stack.push(expression_container::make()); - } - // Push another empty container to hold the first element/argument - // in this container: - P.expr_stack.push(expression_container::make()); - next_valid_state = VALID_EXPRESSION | VALID_PARENS_CLOSE; - break; - - case ID_PARENS_CLOSE: - { - if (not (next_valid_state & VALID_PARENS_CLOSE)) { - P.error = str(boost::format("Unexpected parentheses.")); - return false; - } - if (P.expr_stack.size() < 2) { - P.error = str(boost::format("Unbalanced closing parentheses.")); - return false; - } - // First pop the last expression inside the parentheses, - // if it's not empty, add it to the top container (this also avoids - // adding arguments to functions if none were provided): - expression_container::sptr c = P.expr_stack.top(); - P.expr_stack.pop(); - if (not c->empty()) { - P.expr_stack.top()->add(c); - } - // At the end of (), either a function or container is complete, - // so pop that and add it to its top container: - expression_container::sptr c2 = P.expr_stack.top(); - P.expr_stack.pop(); - P.expr_stack.top()->add(c2); - next_valid_state = VALID_OPERATOR | VALID_COMMA | VALID_PARENS_CLOSE; - } - break; - - case ID_ARG_SEP: - { - if (not (next_valid_state & VALID_COMMA)) { - P.error = str(boost::format("Unexpected comma.")); - return false; - } - next_valid_state = VALID_EXPRESSION; - // If stack size is 1, we're on the base container, which means we - // simply string stuff. - if (P.expr_stack.size() == 1) { + next_valid_state = VALID_EXPRESSION | VALID_PARENS_CLOSE; break; - } - // Otherwise, a ',' always means we add the previous expression to - // the current container: - expression_container::sptr c = P.expr_stack.top(); - P.expr_stack.pop(); - P.expr_stack.top()->add(c); - // It also means another expression is following, so create another - // empty container for that: - P.expr_stack.push(expression_container::make()); - } - break; - // All the atomic expressions just get added to the current container: + case ID_PARENS_CLOSE: { + if (not(next_valid_state & VALID_PARENS_CLOSE)) { + P.error = str(boost::format("Unexpected parentheses.")); + return false; + } + if (P.expr_stack.size() < 2) { + P.error = str(boost::format("Unbalanced closing parentheses.")); + return false; + } + // First pop the last expression inside the parentheses, + // if it's not empty, add it to the top container (this also avoids + // adding arguments to functions if none were provided): + expression_container::sptr c = P.expr_stack.top(); + P.expr_stack.pop(); + if (not c->empty()) { + P.expr_stack.top()->add(c); + } + // At the end of (), either a function or container is complete, + // so pop that and add it to its top container: + expression_container::sptr c2 = P.expr_stack.top(); + P.expr_stack.pop(); + P.expr_stack.top()->add(c2); + next_valid_state = VALID_OPERATOR | VALID_COMMA | VALID_PARENS_CLOSE; + } break; + + case ID_ARG_SEP: { + if (not(next_valid_state & VALID_COMMA)) { + P.error = str(boost::format("Unexpected comma.")); + return false; + } + next_valid_state = VALID_EXPRESSION; + // If stack size is 1, we're on the base container, which means we + // simply string stuff. + if (P.expr_stack.size() == 1) { + break; + } + // Otherwise, a ',' always means we add the previous expression to + // the current container: + expression_container::sptr c = P.expr_stack.top(); + P.expr_stack.pop(); + P.expr_stack.top()->add(c); + // It also means another expression is following, so create another + // empty container for that: + P.expr_stack.push(expression_container::make()); + } break; - case ID_VARIABLE: - { - if (not (next_valid_state & VALID_EXPRESSION)) { - P.error = str(boost::format("Unexpected expression.")); - return false; - } - expression_variable::sptr v = expression_variable::make(val, P.var_type_getter, P.var_value_getter); - P.expr_stack.top()->add(v); - next_valid_state = VALID_OPERATOR | VALID_COMMA | VALID_PARENS_CLOSE; - } - break; + // All the atomic expressions just get added to the current container: - default: - // If we get here, we assume it's a literal expression - { - if (not (next_valid_state & VALID_EXPRESSION)) { - P.error = str(boost::format("Unexpected expression.")); - return false; - } - expression::type_t token_type; - switch (t.id()) { // A map lookup would be more elegant, but we'd need a nicer C++ for that - case ID_LITERAL_DOUBLE: token_type = expression::TYPE_DOUBLE; break; - case ID_LITERAL_INT: token_type = expression::TYPE_INT; break; - case ID_LITERAL_HEX: token_type = expression::TYPE_INT; break; - case ID_LITERAL_STR: token_type = expression::TYPE_STRING; break; - case ID_LITERAL_VECTOR_INT: token_type = expression::TYPE_INT_VECTOR; break; - default: UHD_THROW_INVALID_CODE_PATH(); - } - P.expr_stack.top()->add(boost::make_shared<expression_literal>(val, token_type)); - next_valid_state = VALID_OPERATOR | VALID_COMMA | VALID_PARENS_CLOSE; - break; - } + case ID_VARIABLE: { + if (not(next_valid_state & VALID_EXPRESSION)) { + P.error = str(boost::format("Unexpected expression.")); + return false; + } + expression_variable::sptr v = expression_variable::make( + val, P.var_type_getter, P.var_value_getter); + P.expr_stack.top()->add(v); + next_valid_state = VALID_OPERATOR | VALID_COMMA | VALID_PARENS_CLOSE; + } break; + + default: + // If we get here, we assume it's a literal expression + { + if (not(next_valid_state & VALID_EXPRESSION)) { + P.error = str(boost::format("Unexpected expression.")); + return false; + } + expression::type_t token_type; + switch (t.id()) { // A map lookup would be more elegant, but we'd + // need a nicer C++ for that + case ID_LITERAL_DOUBLE: + token_type = expression::TYPE_DOUBLE; + break; + case ID_LITERAL_INT: + token_type = expression::TYPE_INT; + break; + case ID_LITERAL_HEX: + token_type = expression::TYPE_INT; + break; + case ID_LITERAL_STR: + token_type = expression::TYPE_STRING; + break; + case ID_LITERAL_VECTOR_INT: + token_type = expression::TYPE_INT_VECTOR; + break; + default: + UHD_THROW_INVALID_CODE_PATH(); + } + P.expr_stack.top()->add( + boost::make_shared<expression_literal>(val, token_type)); + next_valid_state = VALID_OPERATOR | VALID_COMMA + | VALID_PARENS_CLOSE; + break; + } } // end switch return true; } }; - public: - expression::sptr create_expr_tree(const std::string &code) +public: + expression::sptr create_expr_tree(const std::string& code) { // Create empty stack and keyword states grammar_props P(_ftable, _var_type_getter, _var_value_getter); int next_valid_state = grammar::VALID_EXPRESSION; // Create a lexer instance - ns_lexer<lex::lexertl::lexer<> > lexer_functor; + ns_lexer<lex::lexertl::lexer<>> lexer_functor; // Tokenize the string char const* first = code.c_str(); - char const* last = &first[code.size()]; - bool r = lex::tokenize( - first, last, // Iterators + char const* last = &first[code.size()]; + bool r = lex::tokenize(first, + last, // Iterators lexer_functor, // Lexer - boost::bind(grammar(), _1, boost::ref(P), boost::ref(next_valid_state)) // Function object + boost::bind(grammar(), + _1, + boost::ref(P), + boost::ref(next_valid_state)) // Function object ); // Check the parsing worked: if (not r or P.expr_stack.size() != 1) { std::string rest(first, last); - throw uhd::syntax_error(str( - boost::format("Parsing stopped at: %s\nError message: %s") - % rest % P.error - )); + throw uhd::syntax_error( + str(boost::format("Parsing stopped at: %s\nError message: %s") % rest + % P.error)); } // Clear stack and return result return P.get_result(); } - private: - +private: function_table::sptr _ftable; expression_variable::type_getter_type _var_type_getter; expression_variable::value_getter_type _var_value_getter; }; -parser::sptr parser::make( - function_table::sptr ftable, +parser::sptr parser::make(function_table::sptr ftable, expression_variable::type_getter_type var_type_getter, - expression_variable::value_getter_type var_value_getter -) { - return sptr(new parser_impl( - ftable, - var_type_getter, - var_value_getter - )); + expression_variable::value_getter_type var_value_getter) +{ + return sptr(new parser_impl(ftable, var_type_getter, var_value_getter)); } - diff --git a/host/lib/rfnoc/nocscript/parser.hpp b/host/lib/rfnoc/nocscript/parser.hpp index 139082515..e9d9f0820 100644 --- a/host/lib/rfnoc/nocscript/parser.hpp +++ b/host/lib/rfnoc/nocscript/parser.hpp @@ -10,20 +10,18 @@ #include <boost/shared_ptr.hpp> #ifndef INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_PARSER_HPP -#define INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_PARSER_HPP +# define INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_PARSER_HPP namespace uhd { namespace rfnoc { namespace nocscript { class parser { - public: +public: typedef boost::shared_ptr<parser> sptr; - static sptr make( - function_table::sptr ftable, + static sptr make(function_table::sptr ftable, expression_variable::type_getter_type var_type_getter, - expression_variable::value_getter_type var_value_getter - ); + expression_variable::value_getter_type var_value_getter); /*! The main parsing call: Turn a string of code into an expression tree. * @@ -31,7 +29,7 @@ class parser * * \throws uhd::syntax_error if \p code contains syntax errors */ - virtual expression::sptr create_expr_tree(const std::string &code) = 0; + virtual expression::sptr create_expr_tree(const std::string& code) = 0; }; }}} /* namespace uhd::rfnoc::nocscript */ |