2013-10-15 30 views
1

我已經定義了一個散列表keyword_table來存儲我的語言的所有關鍵字。這裏是代碼的一部分:解析中的2個方向(字符串<->標記)表

(* parser.mly *) 
%token CALL CASE CLOSE CONST 
... 
reserved_identifier: 
| CALL { "Call" } 
| CASE { "Case" } 
| CLOSE { "Close" } 
| CONST { "Const" } 
... 

(* lexer.mll *) 
{let hash_table list = 
    let tbl = Hashtbl.create (List.length list) in 
    List.iter (fun (s, t) -> Hashtbl.add tbl (lowercase s) t) list; 
    tbl 

let keyword_table = hash_table [ 
    "Call", CALL; "Case", CASE; "Close", CLOSE; "Const", CONST; 
    ... ]} 

rule token = parse 
    | lex_identifier as li 
    { try Hashtbl.find keyword_table (lowercase li) 
     with Not_found -> IDENTIFIER li } 

由於有很多的關鍵字,我真的很想避免重複的代碼。

parser.mly,似乎%token CALL CASE ...不能簡化,因爲每個標記必須明確定義。但是,對於reserved_identifier部分,是否可以調用函數來從令牌返回字符串,而不是對每個字符串進行硬編碼?

所以,這表明哈希表可能不適合這個目的。哪種數據結構是雙方搜索的最佳選擇(我們假設雙方的每個密鑰都是唯一的)?因此,我們想要實現find_0 table "Call"返回令牌CALL(用於lexer.mll)和find_1 table CALL返回"Call"(用於parser.mly)。

另外,如果這個table可以定義,我應該把它放在哪裏,以便parser.mly可以使用它?

回答

2

當您處於詞法分析器中時,可能會得到字符串,正好在與令牌匹配的位置(例如,Lexing.lexeme)。嘗試在解析器中獲取它已經太晚了。我們不希望令牌流將所有字符串保留在內存中,因爲它會增加內存消耗(實際上大多數令牌從不需要它們的字符串表示)。

爲什麼不建立一個從關鍵字值(或標記值)到字符串的反轉表,同時你建立第一個映射? hash_table可以重命名爲hash_tables並返回兩個反向映射。

如果您希望解析器和詞法分析器都可見,那麼可能需要在解析器中定義它。

相關問題