2014-09-12 46 views
1

編輯:正如在對sehe的答案的評論中所提到的,事實證明下面的代碼工作得很好;這是我對錯誤的迭代器(這裏沒有顯示)的處理。對不起這是我的錯。投票結束的話題/不可重現。提升精神(經典):內嵌解析器,工作除了跳過評論

EDIT2:精...... 如果你使用boost::spirit::istream_iterator養活ifstream的解析函數(像我一樣),不要忘記調用unsetf(std::ios::skipws)ifstream第一,或者您解析會失敗...


我有一個DSL(領域特定語言)文件,該文件看起來像這樣:

# Comment (optional) 

codepage = "ISO-8859-2"; 
... 

即,codepage規範是文件中的第一個非註釋語句,或者該文件被認爲是默認的代碼頁。

我徵用升壓精神的任務。由於技術原因,我不得不留在Spirit Classic(咳嗽 AIX/XLC 咳嗽),並且在經歷了一些頭疼的教程之後 - 這些教程總是以更多涉及的設置爲目標,比我想要的要複雜得多這是 - 我想出了這個小小的一段代碼:

#include <boost/spirit/include/support_istream_iterator.hpp> 
#include <boost/spirit/include/classic_core.hpp> 
#include <boost/spirit/include/classic_rule.hpp> 
#include <boost/spirit/include/classic_utility.hpp> 

#include <string> 

namespace spirit_classic = boost::spirit::classic; 

template< typename Iterator > 
static std::string getCodepage(Iterator first, Iterator last) 
{ 
    std::string codepage; 

    spirit_classic::parse(
     first, 
     last, 
     spirit_classic::as_lower_d[ "codepage" ] 
      >> spirit_classic::ch_p('=') 
      >> spirit_classic::lexeme_d[ spirit_classic::ch_p('"') 
       >> (+(spirit_classic::anychar_p - spirit_classic::ch_p('"')))[spirit_classic::assign_a(codepage)] 
       >> spirit_classic::ch_p('"') ] 
     >> spirit_classic::ch_p(';'), 
     spirit_classic::space_p | spirit_classic::comment_p('#') 
     ); 

    if (codepage.empty()) 
    { 
     codepage = "UTF-8"; 
    } 

    return codepage; 
} 

這工作得很好...除了船長:

... 
spirit_classic::space_p | spirit_classic::comment_p('#') 
... 

此跳過空格好吧 - 但完全失敗在跳過評論(即任何從'#'到行尾),我理解`comment_p('#')來實現。

因此很明顯,我已經明白了什麼。我無法弄清楚什麼。幫幫我?

+0

Hrm ...我很驚訝XlC++仍然無法處理這些精神。我實際上是在XlC++上做了我的第一個Spirit步驟(但是,那可能是Spirit Classic)。但從那以後,我們已經看到了一些XlC版本的改進。 – sehe 2014-09-12 13:28:16

+0

Anyhoops。我可以充分宣佈自己一個精神buff,但不適合經典:(我不確定你會發現很多人支持這個舊東西(它甚至在1_66中被刪除,IIRC) – sehe 2014-09-12 13:29:13

+0

@sehe:有點受公司的約束提供給我的就是XLC v11.1,而男孩,我有沒有樂趣讓Boost跳舞,因爲Boost團隊沒有一個AIX盒子可以測試,但是我得到了印象中,Classic和v2之間API的「簡單」層沒有發生太多變化,那麼,你的v2 buff-eye在這裏看到什麼不合適的地方? – DevSolar 2014-09-12 13:36:25

回答

1

我沒有太多的洞察力這裏,而且我用MSVC/GCC這裏只測試,但也許問題是comment_p試圖消耗eol(這是由space_p船長吃,而不是)?

所以,要麼你可以使用spirit_classic::blank_p(並明確說明你的EOLS),你可能有運氣扭轉了隊長的分支:

spirit_classic::comment_p('#') | spirit_classic::space_p 

看到它Live On Coliru

#include <boost/spirit/include/support_istream_iterator.hpp> 
#include <boost/spirit/include/classic_core.hpp> 
#include <boost/spirit/include/classic_rule.hpp> 
#include <boost/spirit/include/classic_utility.hpp> 

#include <string> 

namespace spirit_classic = boost::spirit::classic; 

template< typename Iterator > 
static std::string getCodepage(Iterator first, Iterator last) 
{ 
    std::string codepage; 

    spirit_classic::parse(
     first, 
     last, 
     spirit_classic::as_lower_d[ "codepage" ] 
      >> spirit_classic::ch_p('=') 
      >> spirit_classic::lexeme_d[ spirit_classic::ch_p('"') 
       >> (+(spirit_classic::anychar_p - spirit_classic::ch_p('"')))[spirit_classic::assign_a(codepage)] 
       >> spirit_classic::ch_p('"') ] 
     >> spirit_classic::ch_p(';'), 
     spirit_classic::comment_p('#') | spirit_classic::space_p 
     ); 

    if (codepage.empty()) 
    { 
     codepage = "UTF-8"; 
    } 

    return codepage; 
} 

int main() 
{ 
    std::string input = "# Comment (optional)\n" 
     "\n" 
     "\n" 
     "\n" 
     "codepage = \"ISO-8859-2\"; \n"; 

    std::cout << getCodepage(input.begin(), input.end()); 
} 

打印

ISO-8859-2 
+0

嗯,我能說什麼......轉身我的語法一直工作,這是我對Boost的istream_iterator的處理,這是錯誤的......無賴,對不起浪費你的時間。 – DevSolar 2014-09-12 13:47:00