2012-11-05 61 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