ocamllex正则表达式的外部定义

时间:2012-08-03 12:04:52

标签: ocaml pretty-print lexer ocamlyacc ocamllex

我已经实现了lexer / parser / pretty-printer的常用组合,用于在我的代码中读入/打印一个类型。我发现词法分析器和漂亮的打印机在普通字符串正则表达式中有冗余,通常用于符号,标点符号或分隔符。

例如我现在有

rule token = parse
  | "|-" { TURNSTILE }

在我的lexer.mll文件中,以及如下函数:

let pp fmt (l,r) = 
  Format.fprintf fmt "@[%a |-@ %a@]" Form.pp l Form.pp r

漂亮印刷。如果我决定更改TURNSTILE的字符串,我必须编辑代码中的两个位置,我发现它不太理想。

显然,OCaml词法分析器支持定义正则表达式的某种能力,然后在mll文件中引用它们。所以lexer.mll可以写成

let symb_turnstile = "|-"

rule token = parse
  | symb_turnstile { TURNSTILE }

但这不会让我从外部访问symb_turnstile,从我漂亮的打印功能说起。事实上,在运行ocamllex之后,symb_turnstile中没有lexer.ml的出现。我甚至不能在lexer.mll的OCaml结尾中引用这些标识符。

有没有办法实现这个目标?

2 个答案:

答案 0 :(得分:4)

最后,我采用了以下风格,我从ocamllex本身的来源偷走了(所以我猜它是标准做法)。从lexer.mll

的序言中定义了从字符串到标记的映射(此处为关联列表)
let symbols =
  [ 
    ...
    (Symb.turnstile, TURNSTILE); 
    ...
  ]

其中Symb是将turnstile定义为字符串的模块。然后,lexer.mll的lexing部分故意过于笼统:

rule token = parse
  ...
  | punctuation
    {
      try 
        List.assoc (Lexing.lexeme lexbuf) symbols
      with Not_found -> lex_error lexbuf  
    }
  ...

其中punctuation是匹配符号序列的正则表达式。

漂亮的打印机现在可以像这样写。

let pp fmt (l,r) = 
  Format.fprintf fmt "@[%a %s@ %a@]" Form.pp Symb.turnstile l Form.pp r

答案 1 :(得分:1)

虽然这两个令牌看起来都是符号字符串,但它们确实非常不同。我认为没有一种方便的类型可以共享它们以供ocamllex和Printf.printf使用。这可能是ocamllex不支持此类外部定义的原因。您可以通过宏工具获得所需的效果(文本包含)。