1

基本的なトークン化構造/アルゴリズムが用意されています。それはかなり複雑で、私のデザインの「欠陥」についてあなたに啓蒙するのに十分簡単に​​それを明確にできることを願っています。

クラスParserState

// bool functions return false if getline() or stream extraction '>>' fails
static bool nextLine(); // reads and tokenizes next line from file and puts it in m_buffer
static bool nextToken(); // gets next token from m_buffer, via fetchToken(), and puts it in m_token
static bool fetchToken( std::string &token ); // procures next token from file/buffer

static size_t m_lineNumber;
static std::ifstream m_fstream;
static std::string m_buffer;
static std::string m_token;

この設定の理由は、構文エラーが発生した場合に行番号を報告できるようにするためです。パーサーのフェーズ/状態に応じて、私のプログラムではさまざまなことが起こり、このParserStateのサブクラスはとを使用m_tokennextTokenて続行します。 が空の場合はをfetchToken呼び出し、引数に次のトークンを配置します。nextLinem_buffer

istringstream stream;

do // read new line until valid token can be extracted
{
    Debug(5) << "m_buffer contains: " << m_buffer << "\n";
    stream.str( m_buffer );

    if( stream >> token )
    {
        Debug(5) << "Token extracted: " << token << "\n";
        m_token = token;
        return true; // return when token found
    }
    stream.clear();
} while( nextLine() );
// if no tokens can be extracted from the whole file, return false
return false;

問題は、m_bufferから削除されたトークンが削除されず、を呼び出すたびに同じトークンが読み取られることnextToken()です。問題は、それm_bufferを変更できることです。したがって、istringstream::strループ内での呼び出しです。しかし、これが私の問題の原因であり、私が見る限り、それを回避することはできません。したがって、私の質問:stream >> token文字列ストリームによって内部的にポイントされた文字列から何かを削除するにはどうすればよいですか?おそらく私はを使用する必要はありませんstringstreamが、この状況ではもっと基本的なもの(最初の空白を見つけて文字列から最初のトークンを切り取るなど)ですか?

10億ありがとう!

PS:行番号を追跡できる限り、関数/クラス構造を変更する提案は問題ありません(したがって、完全なファイルが読み込まれm_bufferず、クラスメンバーistringstreamがあります。これは、行番号エラーの報告が必要になる前のことです)。

4

3 に答える 3

1

m_bufferstd::istringstream代わりに単純に作ってみませんstd::stringか?一時変数を削除するだけでなく、目的の効果を得ることができます。m_buffer次のようなステートメントを変更するたびに

m_buffer = ...

代わりにこれを書いてください:

m_buffer.str(...);
于 2010-11-07T20:55:30.287 に答える
0

stream同じトークンを何度も読み取らないようにするには、使用する位置を取得してから、を使用tellgして復元する必要があると思いますseekg(これらの方法についてはここで説明します)。ただしstd::istringstream、ここでの使用は私にとってやり過ぎだと思われます。私はむしろm_buffer直接働きたいです。

于 2010-11-07T21:03:27.457 に答える
0

行番号レポートを処理するための通常のスキームは、行数をインクリメントしながら、一度に1行ずつ読み取ることです。次に、トークナイザーがトークンの作成を開始すると、行番号のスナップショットを取得して、に格納します。トークンデータ構造(通常、行番号、トークンタイプ、およびトークン値(存在する場合)が含まれます)。

これにより、行番号を失うことなく、行の読み取りをトークンの作成から切り離すことができます。また、トークンをたくさん持つことができ、それらはすべて行番号(異なるものを含む)を持つことができ、トークンは1つの行で始まり、別の行で終わることができます。

于 2010-11-08T00:39:09.790 に答える