【问题标题】:A table of 2 directions (string <-> token) in parsing解析中包含 2 个方向(字符串 <-> 标记)的表
【发布时间】:2013-10-23 21:10:18
【问题描述】:

我已经定义了一个哈希表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可以使用它?

【问题讨论】:

    标签: parsing ocaml lexer ocamlyacc ocamllex


    【解决方案1】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-09
      • 2016-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-21
      • 1970-01-01
      • 2012-05-04
      相关资源
      最近更新 更多