Я пытаюсь настроить базовый синтаксический анализатор для некоторых игровых данных, который использует знакомый и очень простой формат «C-style». В основном, называя фигурные скобки «структуры», затем помещая параметры и вложенные «структуры» внутрь. Он будет разбирать что-то вроде этого:
Name0
{
Name1
{
Param0 *= 2
Param2 = "lol"
}
Param0 = 1
Param1 = "test"
Name2 { }
}
Name3 {
Param0 = "test"
}
Тем не менее, он терпит неудачу даже при простом входном тесте «Test {}», не говоря уже о том, чтобы получить что-то настолько сложное, как в моем примере выше. Структуры настроены на использование слияния, и это кажется достаточно простым, поэтому я сомневаюсь, что это проблема. В настоящее время я не использую пару правил, и большинство моих правил не проверены, потому что они терпят неудачу, когда пытаются выполнить первое правило category
в root
. Это ошибка, которую я получаю при вводе «Test {}»:
Error! Expecting <sequence>"{"<node> here: ""
Вот класс Parser:
template<typename Iterator>
struct Parser : qi::grammar<Iterator, std::vector<Category>(), ascii::space_type>
{
qi::rule<Iterator, std::vector<Category>(), ascii::space_type> root;
qi::rule<Iterator, Category(), ascii::space_type> category;
qi::rule<Iterator, Param(), ascii::space_type> param;
qi::rule<Iterator, Node(), ascii::space_type> node;
qi::rule<Iterator, Value(), ascii::space_type> value;
qi::rule<Iterator, char()> escape;
qi::rule<Iterator, std::string()> quotedstring;
qi::rule<Iterator, std::string()> normalstring;
qi::rule<Iterator> comment;
qi::rule<Iterator> commentblock;
Parser() : Parser::base_type(root, "root")
{
using namespace qi;
using ascii::char_;
using phoenix::construct;
using phoenix::val;
escape %= '\\' > char_("\\\"");
quotedstring %= '"' >> *((char_ - '"') | escape) > '"';
normalstring %= *(char_ - qi::eol);
comment = "//" >> *(char_ - qi::eol);
commentblock = "/*" >> *(char_ - "*/") > "*/";
node %= category | param; //comment? comment block? holding off for now
value %= normalstring | float_;
param %=
lexeme[+(char_ - operators)]
> operators
> value
> qi::eol;
category %=
lexeme[+(char_ - '{')] //won't this grab all whitespace around the tag too?
> '{'
>> *node
> '}';
root %= *category;
root.name("root");
category.name("category");
param.name("param");
node.name("node");
value.name("value");
escape.name("escape");
quotedstring.name("quotedstring");
normalstring.name("normalstring");
comment.name("comment");
commentblock.name("commentblock");
debug(root);
debug(category);
debug(param);
debug(node);
debug(value);
debug(escape);
debug(quotedstring);
debug(normalstring);
debug(comment);
debug(commentblock);
on_error<fail>
(
root,
std::cout
<< val("Error! Expecting ")
<< _4
<< val(" here: \"")
<< construct<std::string>(_3, _2)
<< val("\"")
<< std::endl
);
}
};
И не связанная с этим вещь: можно ли использовать лямбда-выражения С++ 11 в вызовах on_success
и on_error
? Я просмотрел функцию on_error
, и, похоже, ее параметры шаблонизированы в соответствии с типом правила, а это означает, что лямбда должна быть определена для каждого отдельного типа правила (в основном для каждого правила). Это правильно? Очень жаль, эти лямбда-фэниксы настолько непрозрачны, что я понятия не имею, как даже вытащить номер строки и поместить его в структуру.
редактировать:
Вот таблица operators
:
struct Operators : qi::symbols<char, Operator>
{
Operators()
{
add
("=", Operator::equal)
("+=", Operator::plusequal)
("-=", Operator::minusequal)
("*=", Operator::timesequal)
("/=", Operator::divideequal)
;
}
} operators;