OCamlLex不区分大小写

5
有没有办法在Ocamllex规范中实现不区分大小写的令牌? 我已经尝试过以下方法来使令牌不区分大小写:
let token = parser
    ...
   | ['C''c']['A''a']['S''s']['E''e'] { CASE }
    ...

但我正在寻找其他的东西,如果存在的话。


(但如果上下文更加清晰,翻译也会更加准确)

请展示你所尝试过的内容。 - johnny 5
2个回答

6

使用普通的令牌分析器,它接受大小写字母,并在表格中查找关键字,忽略大小写:

{
type token = Case | Test | Ident of string

let keyword_tbl = Hashtbl.create 64

let _ = List.iter (fun (name, keyword) ->
    Hashtbl.add keyword_tbl name keyword) [
    "case", Case;
    "test", Test;
  ]
}

let ident_char = ['a'-'z' 'A'-'Z' '_']

rule next_token = parse
  | ident_char+ as s {
      let canon = String.lowercase s in
      try Hashtbl.find keyword_tbl canon
      with Not_found ->
        (* `Ident canon` if you want case-insensitive vars as well
         * as keywords *)
        Ident s
    }

2
正如@gsg所提出的,解决这个问题的正确方法是使用一个普通的令牌词法分析器,它接受大小写,并在表格中查找关键字。实际上,为每个关键字编写一个正则表达式是一种反模式,在ocamllex文档中有提到:

12.7 常见错误

ocamllex: 转换表溢出,自动机太大 ocamllex生成的确定性自动机最多只能有32767个转换。上面的消息表示您的词法分析器定义过于复杂,超出了此限制。这通常是由于词法分析器定义具有语言中每个字母关键字的单独规则,如以下示例所示。[...]

http://caml.inria.fr/pub/docs/manual-ocaml-4.00/manual026.html#toc111

文档继续提供了一个明确的代码示例和使用查找表进行重写的方法。
查找表应该封装查找的“不区分大小写”,因此我们应该使用一个函数式的关联结构(即:Map或HashTbl),允许我们定义自己的比较函数。由于我们的查找表很可能是不可变的,所以我们选择使用Map。
{
type token = Case | Test | Ident of string

module KeywordTable =
  Map.Make(struct
    type t = string
    let compare a b =
      String.(compare (lowercase a) (lowercase b))
  end)

let keyword_table =
  List.fold_left
    (fun (k, v) -> KeywordTable.add k v))
    [
      "case", Case;
      "test", Test;
    ]
    KeywordTable.empty
}

let ident_char = ['a'-'z' 'A'-'Z' '_']

rule next_token = parse
  | ident_char+ as s {
      try KeywordTable.find keyword_table s
      with Not_found -> Ident s
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接