解析中的2个方向(字符串< - >标记)的表

时间:2013-10-15 21:54:20

标签: parsing ocaml lexer ocamlyacc ocamllex

我已经定义了一个哈希表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"返回令牌CALL(在lexer.mll中使用)和find_1 table CALL返回"Call"(在parser.mly中使用)

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

1 个答案:

答案 0 :(得分:2)

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

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

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