James Moore
James Moore

Reputation: 457

Run-time User Input Parsing

I'm trying to create a runtime parser that can recognize keywords of a given language or be used for syntax highlighting. I know how to design and implement a simple finite state machine, but the problem is parsing the users input in real time. From a console its simple, I would just call getline() after the user presses enter and iterate through the string, character by character. But in a GUI environment I cant figure out how to parse in real time. For now, I started by creating a simple text box in a metro style app and by triggering a textchanged event I would get the users input, store it into a string, and send it to the lexer for parsing.

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

Inside my lexer I do the following:

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

Inside my scan function I have a simple finite state machine implemented by a switch statement

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

The major problems I'm having are when I call the function NextCharacter() to determine if its a > or >=, the character goes through the switch and bypasses the nextcharacter function because its not waiting for the next input. But I can't figure out how to fix this. Here's my NextCharacter() function:

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

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

I've been searching for a solution on how to gather users input in real time and iterate through it for use in a run time parser in a text editor like environment. Everything I find is console based, but GUI based is much different. Can anybody point me in the right direction, in what is the best way to go about this? Is there a better way to get users input in a runtime parser? Am I completely wrong in the way I'm going about this?

Upvotes: 2

Views: 668

Answers (1)

WhozCraig
WhozCraig

Reputation: 66254

The only thing I see wrong with your NextCharacter() is that is scans the entire input string, returning the last character always. You would be better off storing a 'current' iterator in the lexer, and stopping when it reaches the end() of the input string.

In class Lexer:

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

Something like that. Keep an iterator of the current input along side your input string copy. I hammered this on a web page, so there are bound to be errors, but I hope you get the idea.

Upvotes: 2

Related Questions