2012-11-05 60 views
2

我正在尝试创建一个运行时分析器,它可以识别给定语言的关键字或用于语法高亮显示。我知道如何设计和实现一个简单的有限状态机,但问题是实时解析用户输入。从简单的控制台开始,我会在用户按下Enter键并按字符遍历字符串之后调用getline()。但在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()来确定它的a>或> =时,字符通过开关并绕过下一个字符函数,因为它不等待下一个输入。但我无法弄清楚如何解决这个问题。这是我的NextCharacter()函数:

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

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

我一直在寻找如何收集用户输入的实时性和遍历它在像环境中的文本编辑器在运行时解析器使用的解决方案。我发现的所有东西都是基于控制台的,但基于GUI的差别很大。任何人都可以指引我朝着正确的方向发展,最好的方式是什么?有没有更好的方式让用户在运行时解析器中输入?我在这方面的做法完全错误吗?

回答

2

我唯一看到你的NextCharacter()错误的是它扫描整个输入字符串,总是返回最后一个字符。你最好将一个'current'迭代器存储在词法分析器中,当它到达输入字符串的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; 
} 

类似的东西。在输入字符串副本的旁边保留当前输入的迭代器。我在网页上敲了这个,所以肯定会有错误,但我希望你明白。

+0

这绝对是更高效,谢谢。但我仍然遇到下一个字符函数被绕过的问题。例如,假设输入字符是一个'>',State Initial将字符发送到State Greater,但由于用户还没有输入另一个输入,所以当前字符被注册为大于标记而不是等待检查如果下一个字符是等号。我想我需要一种方法来保持当前的状态,所以下一个角色从那里开始而不是初始状态。 –

+0

您遇到的问题是您的词法分析器的确定性有限自动机的一个障碍。两个标记('>','> =')具有相同的起始标记。如果字符'='不符合'>',你可以用一个“push_back”(对于你来说本质上只是一个'm_it - ',使用上面提供的示例或类似的东西)来解释。注意:词法分析器并不像人们认为的那样微不足道。但至少你有一个如何正确地走你的输入字符串的想法。乐趣还没到(滑雪空白,但只在适当的时候=)。 – WhozCraig