2013-12-11 50 views
2

所以我試圖讓精神來解析這個文件中的字符,因爲它是輸入。如果可能的話,我寧願不把完整的字符串讀入內存。助推精神istream迭代器給出誤報

這是我目前的相關代碼,Rosters_Grammar是一個語法文件,我用它來指定我想要的語法。

#include "StdAfx.h" 
#include "Interpreter.h" 
#include "Rosters_Grammar.h" 
#include <boost\spirit\include\qi.hpp> 
#include <fstream> 

bool Interpreter::invoke(std::string path) 
{ 
    //Define our parser type and iterator types. 
    typedef boost::spirit::istream_iterator iter_type; 
    typedef Rosters_Grammar<iter_type> parser_type; 

    //Create an instance of our grammar parser and pass it an appropriate project. 
    parser_type grammar_parser(project); 

    //Open the target file and wrap ifstream into the iterator. 
    std::ifstream in = std::ifstream(path); 
    if(in.is_open()){ 

    //Disable Whitespace Skipping 
    in.unsetf(std::ios::skipws); 

    iter_type begin(in); 
    iter_type end; 

    //Phrase parse the grammar 
    return boost::spirit::qi::phrase_parse(begin, 
              end, 
             qi::int_ , 
             boost::spirit::qi::space); 
    } 
    else{ 
    return false; 
    } 
} 

出現的問題是我的解析總是成功的原因。鑑於名冊語法,我可以告訴它正在讀取輸入的一部分,因爲它正在執行相應的操作,並且正確地按照預期正確輸入。然而,解析器在錯誤輸入時不會失敗,它只是通過文件停止部分並返回true。

我現在的文件內容是整數和字符串的重複,這樣

45布里 23 butter_scotch

應該讀罰款和接受。像

琴絃 「45蘋果蘋果蘋果」

不應該。然而,考慮到這種情況,解析器應該會失敗。相反,它執行「45 Apple」的操作,然後爲解析返回true。我認爲這是我的迭代器的東西,但我不能確定。 在上面的發佈代碼中,我有qi :: int_作爲我的分析器,並且無論我的輸入數據如何,它都會成功。所以我不相信我的語法文件不應該與這裏的問題相關。 我得到數據失敗的唯一方法是使用!qi :: eps作爲我的分析器輸入。

感謝任何人可以給我的幫助!

編輯: 經過深入研究,我確實認爲我的船長出於某種原因是個問題。 我的理解是,phrase_parse傳遞了2個迭代器,某種語法和一個跳過解析器。它基於跳過解析器標記輸入,並在語法中使用這些標記。

在不禁用迭代器類型的空白跳過的情況下,我的結果解析出「45 appleappleapple」,並且只有「45蘋果」才能成功。

回答

2

我們無法看到語法,因爲您沒有發佈它。

可以看到你DONOT檢查wheter輸入已被完全消耗:

return boost::spirit::qi::phrase_parse(
      begin, end, 
      grammar_parser , 
      qi::space); 

您可以修復,通過任一要求qi::eoi

return boost::spirit::qi::phrase_parse(
      begin, end, 
      grammar_parser >> qi::eoi, 
      qi::space); 

或者你可以檢查迭代器:

bool ok = boost::spirit::qi::phrase_parse(
      begin, end, 
      grammar_parser , 
      qi::space); 

    if (begin != end) 
     std::cerr << "Remaining unparsed: '" << std::string(begin, end) << "'\n"; 

    return ok && (begin == end); 

Finall y,注意在回溯的情況下,的語義動作的副作用永遠不能撤銷。另請參見:

+0

哇。我在這裏根本不對。我曾認爲只有在整個輸入被消耗的情況下,解析才被認爲是成功的。這整個時間我都在想。感謝現實檢查。這應該有很大幫助! – Rabidsheep