Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

X3: Recursive grammar: alternative container parses substitution issue #461

Closed
Xeverous opened this issue Feb 13, 2019 · 19 comments · Fixed by #606
Closed

X3: Recursive grammar: alternative container parses substitution issue #461

Xeverous opened this issue Feb 13, 2019 · 19 comments · Fixed by #606
Labels

Comments

@Xeverous
Copy link
Contributor

Xeverous commented Feb 13, 2019

I would like to parse such text:

config {
	foo: 0
	bar: 1 {
		bar_child: 11
		bar_child2: 12
	}
	quux: 2
}
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <string>
#include <vector>

namespace x3 = boost::spirit::x3;

namespace ast
{
	struct config_param
	{
		std::string name;
		int value;
		std::vector<config_param> child_params;
	};

	struct config
	{
		std::vector<config_param> params;
	};
}

BOOST_FUSION_ADAPT_STRUCT(
	ast::config_param,
	name, value, child_params)

BOOST_FUSION_ADAPT_STRUCT(
	ast::config,
	params)

using comment_type = x3::rule<class comment_class>;
BOOST_SPIRIT_DECLARE(comment_type)

using identifier_type = x3::rule<class identifier_class, std::string>;
BOOST_SPIRIT_DECLARE(identifier_type)

using whitespace_type = x3::rule<class whitespace_class>;
BOOST_SPIRIT_DECLARE(whitespace_type)

using config_param_type = x3::rule<class config_param_class, ast::config_param>;
BOOST_SPIRIT_DECLARE(config_param_type)

using config_type = x3::rule<class config_class, ast::config>;
BOOST_SPIRIT_DECLARE(config_type)

using grammar_type = x3::rule<class grammar_class, ast::config>;
BOOST_SPIRIT_DECLARE(grammar_type)

using skipper_type = whitespace_type;
using iterator_type = std::string::const_iterator;
using context_type = x3::phrase_parse_context<skipper_type>::type;

const comment_type comment = "comment";
const auto comment_def = x3::lexeme['#' >> *(x3::char_ - '\n')];
BOOST_SPIRIT_DEFINE(comment)

const identifier_type identifier = "identifier";
const auto identifier_def = x3::lexeme[(x3::alpha | '_') >> *(x3::alnum | '_')];
BOOST_SPIRIT_DEFINE(identifier)

const whitespace_type whitespace = "whitespace";
const auto whitespace_def = x3::space | comment;
BOOST_SPIRIT_DEFINE(whitespace)

const config_param_type config_param = "config param";
const auto config_param_def = identifier > ':' > x3::int_ > (('{' > *config_param > '}') /* | x3::attr(std::vector<ast::config_param>()) */ );
BOOST_SPIRIT_DEFINE(config_param)

const config_type config = "config";
const auto config_def = x3::lit("config") > '{' > *config_param > '}';
BOOST_SPIRIT_DEFINE(config)

const grammar_type grammar = "code";
const auto grammar_def = config;
BOOST_SPIRIT_DEFINE(grammar)

BOOST_SPIRIT_INSTANTIATE(grammar_type, iterator_type, context_type)

With comment enabled, every config param must have empty {} after it's value. I tried to remove this requirement by providing alternative that results in the same attribute (empty vector of childs). However, if you uncomment code, it does not compile.

Is this the same bug as #434 ? Any workaround?

@Xeverous Xeverous changed the title recursive grammar with attribute recursive grammar with (vector_attribute | x3::attr(vector{})) Feb 13, 2019
@Kojoley

This comment has been minimized.

@Xeverous

This comment has been minimized.

@Kojoley

This comment has been minimized.

@Xeverous

This comment has been minimized.

@Kojoley

This comment has been minimized.

@Xeverous

This comment has been minimized.

@Kojoley

This comment has been minimized.

@Xeverous

This comment has been minimized.

@Xeverous

This comment has been minimized.

@Kojoley

This comment has been minimized.

@Kojoley

This comment has been minimized.

@djowel

This comment has been minimized.

@Xeverous

This comment has been minimized.

@Kojoley

This comment has been minimized.

@djowel

This comment has been minimized.

@Xeverous

This comment has been minimized.

@Kojoley
Copy link
Collaborator

Kojoley commented Feb 14, 2019

I rechecked your example and found that I was wrong, I am sorry. Please provide MWE next time.

#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <vector>

namespace x3 = boost::spirit::x3;

struct Foo
{
    int value;
    std::vector<Foo> children;
};
BOOST_FUSION_ADAPT_STRUCT(Foo,
    value, children)

x3::rule<class foo_r, Foo> foo;
auto const foo_def = x3::int_ >> ('{' >> *foo >> '}' | '[' >> *foo >> ']');
BOOST_SPIRIT_DEFINE(foo)

BOOST_SPIRIT_INSTANTIATE(decltype(foo), char const*, x3::unused_type)

@Kojoley Kojoley reopened this Feb 14, 2019
@Kojoley Kojoley changed the title recursive grammar with (vector_attribute | x3::attr(vector{})) X3: Recursive grammar: alternative container parses substitution issue Feb 14, 2019
@Frkymhn
Copy link

Frkymhn commented Jan 9, 2020

i want to work on this issue please guide me

@Kojoley
Copy link
Collaborator

Kojoley commented Jan 9, 2020

i want to work on this issue please guide me

For some reason, the specialization

template <typename T, typename Attribute>
struct is_substitute_impl<T, Attribute,
typename enable_if<
mpl::and_<
fusion::traits::is_sequence<T>,
fusion::traits::is_sequence<Attribute>,
mpl::equal<T, Attribute, is_substitute<mpl::_1, mpl::_2>>
>
>::type>
: mpl::true_ {};
is offending, if I comment it out - the repro from my previous post will compile. Try to identify the reason.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants