2

特定の言語のキーワードを認識したり、構文の強調表示に使用したりできるランタイム パーサーを作成しようとしています。単純な有限状態マシンを設計および実装する方法は知っていますが、問題はユーザー入力をリアルタイムで解析することです。コンソールから簡単に言えば、ユーザーが Enter キーを押した後に getline() を呼び出すだけで、文字列を 1 文字ずつ反復処理できます。しかし、GUI 環境では、リアルタイムで解析する方法がわかりません。今のところ、metro スタイル アプリで単純なテキスト ボックスを作成することから始め、textchanged イベントをトリガーして、ユーザー入力を取得し、それを文字列に格納して、解析のためにレクサーに送信します。

void InterpreterMetro::MainPage::EditWindow_TextChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::TextChangedEventArgs^ e)
{
    String ^ input = "";
    input = EditWindow -> Text;

    // Send the string to the lexer for parsing
    m_lexer.Initialize( input )
}

私のレクサーの中で私は次のことを行います:

void Lexer::Initialize( std::wstring input )
{
    // Store the current input string
    m_input = input;

    // Get the next character in the input
    NextCharacter();

    // Analyze the current input character
    Scan();
}

スキャン関数内には、switch ステートメントによって実装された単純な有限ステート マシンがあります。

Token Lexer::Scan()
{
    State = Initial;

    while( State != Exit )
    {
        switch( State )
        {
            case Initial:
                {
                    if( m_peek == '>' ){ State = Greater; }
                    else{ State = Exit; }
                } break;

            case Greater:
                {
                    NextCharacter();
                    if( m_peek == '='){ State = GreaterEqual; }
                    else{ return m_token.GREATER; }
                } break;

            case GreaterEqual:
                {
                    NextCharacter();
                    return m_token.GREATEREQUAL;
                } break;
        }
    }
}

私が抱えている主な問題は、関数 NextCharacter() を呼び出して > または >= かどうかを判断するときに、次の入力を待っていないため、文字がスイッチを通過して nextcharacter 関数をバイパスすることです。しかし、これを修正する方法がわかりません。ここに私の NextCharacter() 関数があります:

void Lexer::NextCharacter()
{
    std::wstring::iterator iterator = m_input.begin();

    for( iterator; iterator != m_input.end(); ++iterator )
    {
        m_peek = *iterator;
    }
}

ユーザー入力をリアルタイムで収集し、テキスト エディターのような環境のランタイム パーサーで使用するために反復処理する方法に関するソリューションを探していました。私が見つけたものはすべてコンソール ベースですが、GUI ベースは大きく異なります。これについて最善の方法は何ですか? ランタイムパーサーでユーザー入力を取得するより良い方法はありますか? 私がこれについて行っている方法は完全に間違っていますか?

4

1 に答える 1

2

あなたの NextCharacter() で唯一間違っていると思うのは、入力文字列全体をスキャンし、常に最後の文字を返すことです。「現在の」イテレータをレクサーに格納し、入力文字列の end() に達したときに停止する方がよいでしょう。

クラスレクサーでは:

class Lexer
{
   ... your current code...

private:
    std::wstring m_input;
    std::wstring::iterator m_it;
};


Lexer::Lexer()
   : m_input("")
   , m_it(m_input.end())
{
}


void Lexer::Initialize(const std::wstring& input)
{
    m_input = input;
    m_it = m_input.begin();
}

bool Lexer::NextCharacter()
{
    if (m_it != m_input.end())
    {
        m_peek = *m_it++;
        return true;
    }
    return false;
}

そんな感じ。入力文字列のコピーと一緒に現在の入力の反復子を保持します。これをウェブページで叩いたので、エラーがあるに違いありませんが、理解していただければ幸いです。

于 2012-11-06T01:00:45.200 に答える