I have pieced together a parser using boost libraries from various sources on the net. It works (although is not as clean as I would have liked) but I ran into a particular problem. In the first part of the parser I first parse the function name, then a set of arguments enclosed in parenthesis. Later on, when parsing the actual expression, in the parse factor I allow for numbers and variables to be parsed. However, I would like to only parse those variables that have been previously declared in the vars parser. Here is my grammar:
template<typename Iterator>
struct exp_parser : qi::grammar<Iterator, expression(), ascii::space_type>
{
exp_parser() : exp_parser::base_type(all)
{
using qi::_val;
using qi::_1;
using qi::char_;
using qi::double_;
using qi::lit;
using phoenix::at_c;
using phoenix::push_back;
using phoenix::bind;
all =
name [at_c<0>(_val) = _1] >> '(' >> vars [at_c<1>(_val) = _1] >> ')' >> '='
>> expr [at_c<2>(_val) = _1];
// Parsing of actual expression
expr =
term [_val = _1]
>> *( ('+' >> term [_val += _1])
| ('-' >> term [_val -= _1])
);
term =
factor [_val = _1]
>> *( ('*' >> factor [_val *= _1])
| ('/' >> factor [_val /= _1])
);
factor =
simple [_val = _1]
| '(' >> expr [_val = _1] >> ')'
| ('-' >> factor [_val = bind(make_unary, UN_OP::MIN, _1)])
| ("sin" >> factor [_val = bind(make_unary, UN_OP::SIN, _1)])
| ("cos" >> factor [_val = bind(make_unary, UN_OP::COS, _1)])
| ("tan" >> factor [_val = bind(make_unary, UN_OP::TAN, _1)])
| ('+' >> factor [_val = _1]);
// Prototyping of expression
prtctd %= lit("sin") | lit("cos") | lit("tan");
var %= !prtctd >> char_('a','z');
num %= double_;
simple %= var | num | ('(' >> expr >> ')');
name %= ((char_('a','z') | char_('A','Z') ) >> *(char_('a','z') | char_('A','Z') | char_('0','9') ));
vars %= (char_('a','z') >> *(',' >> char_('a','z')));
}
qi::rule<Iterator, ast(), ascii::space_type> expr, term, factor, simple;
qi::rule<Iterator, expression(), ascii::space_type> all;
qi::rule<Iterator, std::string(), ascii::space_type> name, prtctd;
qi::rule<Iterator, std::vector<char>(), ascii::space_type> vars;
qi::rule<Iterator, char(), ascii::space_type> var;
qi::rule<Iterator, double(), ascii::space_type> num;
};
And this is the struct that I use to store it all:
struct expression {
std::string name;
std::vector<char> arguments;
ast syntax_tree;
};
Now, how can I access the std::vector<char> in the factor parser so that I only parse the right variables.
Also, I am new to using boost and using this as an exercise to myself to start learning a little bit about. If anyone has any advice, please let me know on how I can clean up this code.
Thanks in advance!