Assuming I have a BNF grammar as shown below. Now a 'List' will correspond to all terms before the '|' symbol. However, I want to read the very last number of every 'List' as an attribute of the 'List'.
<code> ::= <code> <line> 12 2 | <line> 24 4
<line> ::= <ifte> 13 23 | <loop> 24 34 | <action> 15 3
<ifte> ::= if <cond> {<code>} else {<code>} 12
Furthermore, this last number (List attribute) can be optional; I guess to make this easier I might have to maybe use some symbol to enclose the number for easier parsing e.g <<23>>.
The code from here compiles but it doesn't parse the grammar above:
//#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted.hpp>
/*#include <fmt/ranges.h>
#include <fmt/ostream.h>*/
#include <iomanip>
namespace AST {
struct Name : std::string {
using std::string::string;
using std::string::operator=;
friend std::ostream &operator<<(std::ostream &os, Name const &n) {
return os << '<' << n.c_str() << '>';
}
};
using Term = boost::variant<Name, std::string>;
struct List {
std::vector<Term> terms;
int number;
};
using Expression = std::vector<List>;
struct Rule {
Name name; //rhs
Expression rhs;
};
using Syntax = std::vector<Rule>;
}
BOOST_FUSION_ADAPT_STRUCT(AST::List, terms, number)
BOOST_FUSION_ADAPT_STRUCT(AST::Rule, name, rhs)
namespace Parser {
namespace qi = boost::spirit::qi;
template<typename Iterator>
class BNF : public qi::grammar<Iterator, AST::Syntax()> {
public:
BNF() : BNF::base_type(start) {
start = qi::skip(blank)[rule % +qi::eol];
_rule_name = qi::hold[qi::char_('<') >> (qi::alpha >> *(qi::alnum | qi::char_('-'))) >> qi::char_('>')];
_list = +term >> qi::uint_;
term = _literal | _rule_name;
_literal = qi::hold['"' >> *(character - '"') >> '"']
| qi::hold["'" >> *(character - "'") >> "'"]
| qi::hold[+(qi::graph - qi::char_("<|>") - "::=")];
character = qi::alnum | qi::char_("\"'| !#$%&()*+,./:;>=<?@]\\^_`{}~[-");
_expression = _list % '|';
rule = _rule_name >> "::=" >> _expression;
BOOST_SPIRIT_DEBUG_NODES((rule)(_expression)(_list)(term)(_literal)(
character)(_rule_name))
}
private:
qi::rule<Iterator> blank;
qi::rule<Iterator, AST::Syntax()> start;
qi::rule<Iterator, AST::Rule(), qi::rule<Iterator>> rule;
qi::rule<Iterator, AST::Expression(), qi::rule<Iterator>> _expression;
qi::rule<Iterator, AST::List(), qi::rule<Iterator>> _list;
qi::rule<Iterator, AST::Term()> term;
qi::rule<Iterator, AST::Name()> _rule_name;
qi::rule<Iterator, std::string()> _literal;
qi::rule<Iterator, char()> character;
};
}
int main() {
Parser::BNF<std::string::const_iterator> const parser;
}
How can I fix/modify the code link above to suit my needs.