diff options
author | Martin Braun <martin.braun@ettus.com> | 2019-01-18 13:46:12 -0800 |
---|---|---|
committer | Brent Stapleton <brent.stapleton@ettus.com> | 2019-01-22 18:16:59 -0800 |
commit | 04722ba053fa6225c5a71d34316cbac093b87f66 (patch) | |
tree | 969b34beccf7a5a3c7de0ff73ac4490863c5da44 /host/lib/rfnoc/nocscript/parser.cpp | |
parent | 5f3058e401bcd15143fd1015f62087f662db1384 (diff) | |
download | uhd-04722ba053fa6225c5a71d34316cbac093b87f66.tar.gz uhd-04722ba053fa6225c5a71d34316cbac093b87f66.tar.bz2 uhd-04722ba053fa6225c5a71d34316cbac093b87f66.zip |
formatting: Apply clang-format to nocscript files
Diffstat (limited to 'host/lib/rfnoc/nocscript/parser.cpp')
-rw-r--r-- | host/lib/rfnoc/nocscript/parser.cpp | 414 |
1 files changed, 209 insertions, 205 deletions
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)); } - |