I'm trying to write a parser for the following BNF rules using boost spirit
(Boost v1.64)
The rules are:
<numeric-literal>::= integer
<type-name> ::= "in" | "out" | "in_out"
<array-type-spec> ::= <type-spec> "[" [<numeric-literal>] "]"
<tuple-type-spec> ::= "(" <type-spec> ("," <type-spec>)+ ")"
<type-spec> ::= <type-name> | <array-type-spec> | <tuple-type-spec>
Below is my attempt, using boost::make_recursive_variant
It seems to work ok on the string in
But it fails on in[2].
Where is my mistake?
What would be an elegant solution?
namespace Ast {
enum class TypeName { IN, OUT, INOUT};
using NumericLiteral = int;
using TypeSpec = boost::make_recursive_variant
<
TypeName,
std::pair<boost::recursive_variant_, NumericLiteral>,
std::vector < boost::recursive_variant_ >
>::type;
}
//grammar:
namespace myGrammar {
namespace qi = boost::spirit::qi;
template <typename Iterator = char const*,typename Signature = Ast::TypeSpec()>
struct myRules : qi::grammar < Iterator, Signature> {
myRules() : myRules::base_type(start) {
fillSymbols();
rNumericLiteral = qi::int_;
rTypeName = sTypeName;
rTypeSpec = rTypeName | (rTypeSpec >> '[' >> rNumericLiteral >> ']') | ('(' >> qi::repeat(2, qi::inf)[(rTypeSpec % ',')] >> ')');
start = qi::skip(qi::space)[rTypeSpec];
}
private:
using Skipper = qi::space_type;
qi::rule<Iterator, Ast::TypeSpec()> start;
qi::rule<Iterator, Ast::NumericLiteral(), Skipper> rNumericLiteral;
qi::rule<Iterator, Ast::TypeName(), Skipper> rTypeName;
qi::rule<Iterator, Ast::TypeSpec(), Skipper> rTypeSpec;
//symbols
qi::symbols<char, Ast::TypeName>sTypeName;
void fillSymbols()
{
using namespace Ast;
sTypeName.add
("in", TypeName::IN)
("out", TypeName::OUT)
("in_out", TypeName::INOUT)
}
};
}