2012-10-28 105 views
0

我正在尋求關於定製構建的Lexer類的幫助,並使用它來解析輸入。我們的教授爲我們的項目提供了一些框架代碼,我們必須使用它。 我的問題是這樣的,我們需要能夠一次調用多個函數來對錶進行排序併合並/排序單獨的表的列。舉例來說,我們的投入會是這樣的:解析器問題與自定義Lexer

顯示<「FILE_NAME> sortedby <」列2>

其中‘顯示’和‘sortedby’有幾分關鍵字和列2將被數字順序排序或按字母順序 - 取決於內容。

我們給出了用於排序的算法,我目前的問題並不在於實現,但能夠讓我們的詞法分析器/解析器讀取多個輸入。 目前,我只能使'顯示'位工作。更多的只是吐出一條錯誤消息。

我已經查看了代碼,試圖將一些邏輯切換語句從真到假,交換& &和||,甚至嘗試了一些沒有運氣的if-else語句。

我真的可以使用一些建議!一些代碼,我們給,它的原始格式:

Lexer.h:

#ifndef _LEXER_H 
#define _LEXER_H 
#include <string> 

enum token_types_t { 
IDENT, // a sequence of alphanumeric characters and _, starting with alpha 
TAG, // sequence of characters between < >, no escape 
ENDTOK, // end of string/file, no more token 
ERRTOK // unrecognized token 
}; 

struct Token { 
token_types_t type; 
std::string value; 
// constructor for Token 
Token(token_types_t tt=ENDTOK, std::string val="") : type(tt), value(val) {} 
}; 

class Lexer { 
public: 
// constructor 
Lexer(std::string str="") : input_str(str), cur_pos(0), in_err(false), 
    separators(" \t\n\r") { } 

//modifiers 
void set_input(std::string); // set a new input, 
void restart();    // move cursor to the beginning, restart 

Token next_token(); // returns the next token 
bool has_more_token(); // are there more token(s)? 

private: 
std::string input_str; // the input string to be scanned 
size_t  cur_pos; // current position in the input string 
bool  in_err;  // are we in the error state? 
std::string separators; // set of separators; *not* the best option! 
}; 
#endif 

Lexer.cpp:

#include "Lexer.h" 
#include <iostream> 
using namespace std; 

Token Lexer::next_token() { 
Token ret; 
size_t last; 

if (in_err) { 
    ret.type = ERRTOK; 
    ret.value = ""; 
    return ret; 
} 

// if not in error state, the default token is the ENDTOK 
ret.type = ENDTOK; 
ret.value = ""; 

if (has_more_token()) { 
    last = cur_pos; // input_str[last] is a non-space char 
    if (input_str[cur_pos] == '<') { 
     cur_pos++; 
     while (cur_pos < input_str.length() && input_str[cur_pos] != '>') 
      cur_pos++; 
     if (cur_pos < input_str.length()) { 
      ret.type = TAG; 
      ret.value = input_str.substr(last+1, cur_pos-last-1); 
      cur_pos++; // move past the closing " 
     } else { 
      in_err = true; 
      ret.type = ERRTOK; 
      ret.value = ""; 
     } 
    } else { 
     while (cur_pos < input_str.length() && 
       separators.find(input_str[cur_pos]) == string::npos && 
       input_str[cur_pos] != '<') { 
      cur_pos++; 
     } 
     ret.type = IDENT; 
     ret.value = input_str.substr(last, cur_pos-last); 
    } 
} 
return ret; 
} 

void Lexer::set_input(string str) { 
input_str = str; 
restart(); 
} 

bool Lexer::has_more_token() { 
while (cur_pos < input_str.length() && 
     separators.find(input_str[cur_pos]) != string::npos) { 
    cur_pos++; 
} 
return (cur_pos < input_str.length()); 
} 

void Lexer::restart() { 
cur_pos = 0; 
in_err = false; 
} 

我們的分析器(一個更大的.cpp文件的一部分) :

bool parse_input(Lexer lexer, string& file_name) {  
Token file_name_tok; 

if (!lexer.has_more_token() || 
    (file_name_tok = lexer.next_token()).type != TAG) 
    return false; 

if (lexer.has_more_token()) 
    return false; 

file_name = file_name_tok.value; 
return true; 
} 

顯示功能(相同cpp文件的一部分,解析器):

void display(Lexer cmd_lexer) { 
string file_name, line; 

if (!parse_input(cmd_lexer, file_name)) { 
    error_return("Syntax error: display <filename>"); 
    return; 
} 

ifstream ifs(file_name.c_str()); 
string error_msg; 
if (ifs) { 
     if (!is_well_formed(ifs, error_msg)) { 
     error_return(error_msg); 
    } else { 
      ifs.clear();   
     ifs.seekg(0, ios::beg); 
     print_well_formed_file(ifs); 
    } 
    while (ifs.good()) { 
    getline (ifs, line); 
    cout << line << endl; 
} 

} else { 
    error_return("Can't open " + file_name + " for reading"); 
} 
ifs.close(); 
} 
+0

應該顯示''命令「讀取一個源文件或其他特殊文件? –

回答

0

似乎很容易。要閱讀多個輸入,您需要多個Lexer/Parser。只需爲每個您必須閱讀的輸入創建一個。

1

根據不同的答案,我的意見,這些都是我會解決這個問題的辦法:

  • 如果display命令應該讀一個源文件並解析它,你可以實現它雖然堆棧。只要找到並解析了display指令,就可以在堆棧上推送新的詞法分析器實例。使用「當前」詞法分析器的堆棧頂部。

  • 如果display命令應該讀取和執行與實際解析無關的文件的某些操作,則考慮將指令存儲爲固定形式的中間形式,並在解析完成後執行此中間格式。這就是現代腳本語言幾乎可以做到的全部

+0

謝謝,這是非常有幫助的。我們使用與所有源代碼位於同一目錄中的文件 - 因此,現在我們不需要創建或訪問新文件。 – mossy367