2011-03-02 2 views
1

저는 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 [] 지시어 (아래 참조)를 사용하여이 문제를 해결할 수 있습니다.

당신이 갖고있는 것을 단순화 할 수 있기 때문에 위의 '거의'라고 말했습니다. b) no_skip []을 사용하여 qutoes 사이에서 건너 뛰기 구문 분석기를 호출하지 않아야합니다. 당신의 path 파서가 처음에 따옴표를 인식하지 못하기 때문에

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('"') 일부를 생략 할 수 있습니다.

+0

우수 감사합니다. – Dragos

관련 문제