2013-10-26 60 views
2

我是Boost :: spirit的初學者,我想定義解析TTCN語言的語法。 (http://www.trex.informatik.uni-goettingen.de/trac/wiki/ttcn-3_4.5.1) 我試圖定義一些像'阿爾法,AlphaNum'的原始語法解析器的規則是一對一的原始語法faitful,但顯然我做錯了什麼,因爲語法定義這種方式不起作用。 但是當我用primite parsers代替TTCN時,它開始工作。Boost :: spirit(經典)原語vs自定義解析器

有人可以告訴爲什麼'手動'定義的規則不能按預期工作嗎? 如何解決它,因爲我想堅持接近原來的語法。 這是一個begginer的代碼錯誤或不同的東西?

#define BOOST_SPIRIT_DEBUG 

#include <boost/spirit/include/classic_symbols.hpp> 
#include <boost/spirit/include/classic_tree_to_xml.hpp> 
#include <boost/spirit/include/classic_position_iterator.hpp> 
#include <boost/spirit/include/classic_core.hpp> 
#include <boost/spirit/include/classic_parse_tree.hpp> 
#include <boost/spirit/include/classic_ast.hpp> 
#include <iostream> 
#include <string> 
#include <boost/spirit/home/classic/debug.hpp> 
using namespace boost::spirit::classic; 
using namespace std; 
using namespace BOOST_SPIRIT_CLASSIC_NS; 

typedef node_iter_data_factory<int> factory_t; 
typedef position_iterator<std::string::iterator> pos_iterator_t; 
typedef tree_match<pos_iterator_t, factory_t> parse_tree_match_t; 
typedef parse_tree_match_t::const_tree_iterator iter_t; 


struct ParseGrammar: public grammar<ParseGrammar> 
{ 
     template<typename ScannerT> 
     struct definition 
     { 
      definition(ParseGrammar const &) 
      { 
       KeywordImport = str_p("import"); 
       KeywordAll = str_p("all"); 
       SemiColon = ch_p(';'); 
       Underscore = ch_p('_'); 

       NonZeroNum = range_p('1','9'); 
       Num = ch_p('0') | NonZeroNum; 
       UpperAlpha = range_p('A', 'Z'); 
       LowerAlpha = range_p('a', 'z'); 
       Alpha = UpperAlpha | LowerAlpha; 
       AlphaNum = Alpha | Num; 

       //this does not! 
       Identifier = lexeme_d[Alpha >> *(AlphaNum | Underscore)]; 

       // Uncomment below line to make rule work 
       // Identifier = lexeme_d[alpha_p >> *(alnum_p | Underscore)]; 

       Module = KeywordImport >> Identifier >> KeywordAll >> SemiColon; 

       BOOST_SPIRIT_DEBUG_NODE(Module); 
       BOOST_SPIRIT_DEBUG_NODE(KeywordImport); 
       BOOST_SPIRIT_DEBUG_NODE(KeywordAll); 
       BOOST_SPIRIT_DEBUG_NODE(Identifier); 
       BOOST_SPIRIT_DEBUG_NODE(SemiColon); 
      } 

      rule<ScannerT> KeywordImport,KeywordAll,Module,Identifier,SemiColon; 
      rule<ScannerT> Alpha,UpperAlpha,LowerAlpha,Underscore,Num,AlphaNum; 
      rule<ScannerT> NonZeroNum; 
      rule<ScannerT> const& 
      start() const { return Module; } 
     }; 
}; 

int main() 
{ 
    ParseGrammar resolver; // Our parser 
    BOOST_SPIRIT_DEBUG_NODE(resolver); 

    string content = "import foobar all;"; 

    pos_iterator_t pos_begin(content.begin(), content.end()); 
    pos_iterator_t pos_end; 

    tree_parse_info<pos_iterator_t, factory_t> info; 
     info = ast_parse<factory_t>(pos_begin, pos_end, resolver, space_p); 

    std::cout << "\ninfo.length : " << info.length << std::endl; 
    std::cout << "info.full : " << info.full << std::endl; 

    if(info.full) 
    { 
     std::cout << "OK: Parsing succeeded\n\n"; 
    } 
    else 
    { 
     int line = info.stop.get_position().line; 
     int column = info.stop.get_position().column; 
     std::cout << "-------------------------\n"; 
     std::cout << "ERROR: Parsing failed\n"; 
     std::cout << "stopped at: " << line << ":" << column << "\n"; 
     std::cout << "-------------------------\n"; 
    } 
    return 0; 
} 

回答

1

我不會做精神經典(這已被棄用了幾年現在)。

我只能假設你已經和船長混在一起了。下面是翻譯成精神V2的東西:

#define BOOST_SPIRIT_DEBUG 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/support_line_pos_iterator.hpp> 

namespace qi = boost::spirit::qi; 

typedef boost::spirit::line_pos_iterator<std::string::const_iterator> pos_iterator_t; 

template <typename Iterator = pos_iterator_t, typename Skipper = qi::space_type> 
struct ParseGrammar: public qi::grammar<Iterator, Skipper> 
{ 
    ParseGrammar() : ParseGrammar::base_type(Module) 
    { 
     using namespace qi; 
     KeywordImport = lit("import"); 
     KeywordAll = lit("all"); 
     SemiColon  = lit(';'); 

#if 1 
     // this rule obviously works 
     Identifier = lexeme [alpha >> *(alnum | '_')]; 
#else 
     // this does too, but less efficiently 

     Underscore = lit('_'); 
     NonZeroNum = char_('1','9'); 
     Num   = char_('0') | NonZeroNum; 
     UpperAlpha = char_('A', 'Z'); 
     LowerAlpha = char_('a', 'z'); 
     Alpha   = UpperAlpha | LowerAlpha; 
     AlphaNum  = Alpha | Num; 

     Identifier = lexeme [Alpha >> *(AlphaNum | Underscore)]; 
#endif 

     Module = KeywordImport >> Identifier >> KeywordAll >> SemiColon; 

     BOOST_SPIRIT_DEBUG_NODES((Module)(KeywordImport)(KeywordAll)(Identifier)(SemiColon)) 
    } 

    qi::rule<Iterator, Skipper> Module; 
    qi::rule<Iterator> KeywordImport,KeywordAll,Identifier,SemiColon; 
    qi::rule<Iterator> Alpha,UpperAlpha,LowerAlpha,Underscore,Num,AlphaNum; 
    qi::rule<Iterator> NonZeroNum; 
}; 

int main() 
{ 
    std::string const content = "import \r\n\r\nfoobar\r\n\r\n all; bogus"; 

    pos_iterator_t first(content.begin()), iter=first, last(content.end()); 

    ParseGrammar<pos_iterator_t> resolver; // Our parser 
    bool ok = phrase_parse(iter, last, resolver, qi::space); 

    std::cout << std::boolalpha; 
    std::cout << "\nok : " << ok << std::endl; 
    std::cout << "full : " << (iter == last) << std::endl; 

    if(ok && iter==last) 
    { 
     std::cout << "OK: Parsing fully succeeded\n\n"; 
    } 
    else 
    { 
     int line = get_line(iter); 
     int column = get_column(first, iter); 
     std::cout << "-------------------------\n"; 
     std::cout << "ERROR: Parsing failed or not complete\n"; 
     std::cout << "stopped at: " << line << ":" << column << "\n"; 
     std::cout << "remaining: '" << std::string(iter, last) << "'\n"; 
     std::cout << "-------------------------\n"; 
    } 
    return 0; 
} 

我添加了一個有點「假」,在輸入的結束,所以輸出變成一個更好的展示:這一切都表示,這

<Module> 
    <try>import \r\n\r\nfoobar\r\n\r</try> 
    <KeywordImport> 
    <try>import \r\n\r\nfoobar\r\n\r</try> 
    <success> \r\n\r\nfoobar\r\n\r\n all;</success> 
    <attributes>[]</attributes> 
    </KeywordImport> 
    <Identifier> 
    <try>foobar\r\n\r\n all; bogu</try> 
    <success>\r\n\r\n all; bogus</success> 
    <attributes>[]</attributes> 
    </Identifier> 
    <KeywordAll> 
    <try>all; bogus</try> 
    <success>; bogus</success> 
    <attributes>[]</attributes> 
    </KeywordAll> 
    <SemiColon> 
    <try>; bogus</try> 
    <success> bogus</success> 
    <attributes>[]</attributes> 
    </SemiColon> 
    <success> bogus</success> 
    <attributes>[]</attributes> 
</Module> 

ok : true 
full : false 
------------------------- 
ERROR: Parsing failed or not complete 
stopped at: 3:8 
remaining: 'bogus' 
------------------------- 

就是我可能將其降低到:

template <typename Iterator, typename Skipper = qi::space_type> 
struct ParseGrammar: public qi::grammar<Iterator, Skipper> 
{ 
    ParseGrammar() : ParseGrammar::base_type(Module) 
    { 
     using namespace qi; 

     Identifier = alpha >> *(alnum | '_'); 
     Module  = "import" >> Identifier >> "all" >> ';'; 

     BOOST_SPIRIT_DEBUG_NODES((Module)(Identifier)) 
    } 

    qi::rule<Iterator, Skipper> Module; 
    qi::rule<Iterator> Identifier; 
}; 

正如你所看到的,Identifier規則是一個隱含語義因爲它沒有declar編輯使用船長。

看到它Live on Coliru

+2

sehe,thans很多!你幫了我一大筆錢。我試圖尋找精神V2,但看起來像文檔在一些問題上不那麼明確,因爲它是爲boost :: classic。感謝你的代碼,我已經很好地理解了一些阻礙我的概念。再次感謝! – Gregory81

+0

@ Gregory81乾杯!提示:從不害羞地解釋你真正想要達到的目標。我總是這樣推理:如果你打算讓別人花時間解釋一些事情,那麼你也可以問他們想得到的最好的方式,而不是僅僅停留在一個細節上。另請參見[XY-problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – sehe

+0

此外,現在您對Spirit V2的觀點有所變化,隨時提問由於許多信息已經存在,所以更多的問題(或者只是瀏覽[tag:boost-spirit]或[tag:boost-spirit-qi])。 – sehe

相關問題