Передача строки пути к файлу в семантическое действие в Boost.Spirit
Я новичок в Boost.Spirit, и у меня есть вопрос, связанный с мини-интерпретатором, который я пытаюсь реализовать с помощью библиотеки. В качестве подзадачи анализа моего языка мне нужно извлечь путь к файлу из ввода в форме:
"path = \"/path/to/file\""
и передать его как строку (без кавычек) в семантическое действие.
Я написал некоторый код, который может анализировать этот тип ввода, но передача проанализированной строки не работает должным образом, вероятно, из-за моего отсутствия опыта работы с Boost.Spirit.
Кто-нибудь может помочь?
На самом деле моя грамматика более сложная, но я выделил проблему следующим образом:
#include <string>
#include "boost/spirit/include/qi.hpp"
#include "boost/spirit/include/phoenix_core.hpp"
#include "boost/spirit/include/phoenix_operator.hpp"
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace phoenix = boost::phoenix;
namespace parser {
// Semantic action (note: in reality, this would use file_path_string in non-trivial way)
void display_path(std::string file_path_string) {
std::cout << "Detected file-path: " << file_path_string << std::endl;
}
// Grammar
template <typename Iterator>
struct path_command : qi::grammar<Iterator, ascii::space_type> {
path_command() : path_command::base_type(path_specifier) {
using qi::string;
using qi::lit;
path = +(qi::char_("/") >> *qi::char_("a-zA-Z_0-9"));
quoted_path_string = lit('"') >> (path- lit('"')) >> lit('"');
path_specifier = lit("path") >> qi::lit("=")
>> quoted_path_string[&display_path];
}
qi::rule<Iterator, ascii::space_type> path_specifier;
qi::rule<Iterator, std::string()> path, quoted_path_string;
};
}
int main() {
using ascii::space;
typedef std::string::const_iterator iterator_type;
typedef parser::path_command<iterator_type> path_command;
bool parse_res;
path_command command_instance; // Instance of our Grammar
iterator_type iter, end;
std::string test_command1 = "path = \"/file1\"";
std::string test_command2 = "path = \"/dirname1/dirname2/file2\"";
// Testing example command 1
iter = test_command1.begin();
end = test_command1.end();
parse_res = phrase_parse(iter, end, command_instance, space);
std::cout << "Parse result for test 1: " << parse_res << std::endl;
// Testing example command 2
iter = test_command2.begin();
end = test_command2.end();
parse_res = phrase_parse(iter, end, command_instance, space);
std::cout << "Parse result for test 2: " << parse_res << std::endl;
return EXIT_SUCCESS;
}
Выход:
Detected file-path: /
Parse result for test 1: 1
Detected file-path: ///
Parse result for test 2: 1
но я хотел бы получить:
Detected file-path: /file1
Parse result for test 1: 1
Detected file-path: /dirname1/dirname2/file2
Parse result for test 2: 1
1 ответ
Почти все в порядке с вашим парсером. Проблема заключается в ошибке в Spirit (до Boost V1.46), препятствующей правильной обработке атрибута в подобных случаях. Это было недавно исправлено в SVN и будет доступно в Boost V1.47 (я попытался запустить вашу неизменную программу с этой версией, и все работает просто отлично).
Сейчас вы можете обойти эту проблему, используя директиву raw[] (см. Ниже).
Я сказал "почти" выше, потому что вы можете: а) упростить то, что у вас есть; б) вы должны использовать no_skip[], чтобы избежать вызова пропускающего парсера между квотами.
path = raw[+(qi::char_("/") >> *qi::char_("a-zA-Z_0-9"))];
quoted_path_string = no_skip['"' >> path >> '"'];
path_specifier = lit("path") >> qi::lit("=")
>> quoted_path_string[&display_path];
Вы можете опустить - lit('"')
часть, потому что ваш path
Парсер не распознает кавычки в первую очередь.