1

我已经定义了一个哈希表keyword_table来存储我的语言的所有关键字。以下是部分代码:

(* 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"returns token CALL(用于lexer.mll)和find_1 table CALLreturns "Call"(用于parser.mly)。

另外,如果table可以定义,我应该把它放在哪里以便parser.mly可以使用它?

4

1 回答 1

2

当您在词法分析器中时,可以在与标记匹配的点(例如。Lexing.lexeme)中获取字符串。试图在解析器中获取它为时已晚。我们不希望令牌流将所有字符串保留在内存中,因为这会大大增加内存消耗(实际上大多数令牌从不需要它们的字符串表示)。

为什么不构建一个从关键字值(或标记值)到字符串的反向表,同时构建第一个映射?hash_table可以重命名为hash_tables并返回两个反向映射。

如果您希望它在解析器和词法分析器中都可见,它可能需要在解析器中定义。

于 2013-10-16T12:47:45.697 回答