2

そのため、このファイルの文字を入力として解析する精神を取得しようとしています。可能であれば、文字列全体をメモリに読み込まないようにしたいと思います。

これは私の現在の関連コードです。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 を返すだけです。

現在のファイルの内容は、int と文字列の繰り返しです。

45 ブリー 23 バタースコッチ

よく読んで受け入れる必要があります。のような文字列

「45りんごりんごりんご」

あってはなりません。ただし、この文字列を考えると、パーサーは失敗するはずです。代わりに、「45 Apple」に対してアクションを実行し、解析に対して true を返します。イテレータに問題があると思いますが、よくわかりません。上記の投稿されたコードでは、パーサーとして qi::int_ があり、入力データに関係なく常に成功します。したがって、私の文法ファイルがここの問題に関連しているとは思いません。これまでに失敗したデータを取得した唯一の方法は、パーサー入力として !qi::eps を使用することです。

誰かが私に与えることができる助けをありがとう!

編集: もう少し調べてみたところ、実際にはスキッパーが何らかの理由で問題になっていると思います。私の理解では、phrase_parse には 2 つの反復子、ある種の文法、およびスキップ パーサーが渡されます。スキップパーサーに基づいて入力をトークン化し、それらのトークンを文法で使用します。

イテレータ型の空白のスキップを無効にしないと、私の結果は「45 appleappleapple」を解析し、「45 apple」のみで成功します。

4

1 に答える 1

2

あなたが投稿していないため、文法を見ることができません。

入力が完全に消費されたかどうかを確認していないことわかります。

    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);

最後に、セマンティック アクションの副作用は、バックトラックの場合には元に戻せないことに注意してください。以下も参照してください。

于 2013-12-11T19:54:02.157 に答える