2

我已经实现了 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_turnstilein lexer.ml。我什至无法在lexer.mll.

有没有办法做到这一点?

4

2 回答 2

4

最后,我选择了我从ocamllex自身来源中窃取的以下风格(所以我猜这是标准做法)。从字符串到标记的映射(这里是关联列表)在序言中定义lexer.mll

let symbols =
  [ 
    ...
    (Symb.turnstile, TURNSTILE); 
    ...
  ]

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

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

wherepunctuation是匹配符号序列的正则表达式。

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

let pp fmt (l,r) = 
  Format.fprintf fmt "@[%a %s@ %a@]" Form.pp Symb.turnstile l Form.pp r
于 2012-08-05T10:26:11.423 回答
1

尽管这两个标记在符号上看起来都像字符串,但它们确实非常不同。我认为没有一种方便的类型可以共享它们以供 ocamllex 和 Printf.printf 使用。这可能是 ocamllex 不支持此类外部定义的原因。使用宏工具(文本包含)可能会获得您想要的效果。

于 2012-08-03T15:31:09.263 回答