如何为给定的语法定义制作OCaml定义?

时间:2014-12-12 04:21:20

标签: syntax ocaml definition

我是OCaml的新手。我有一个如下语法定义:

<program>::= 
| <instruction <program>>
| "end"
<instruction>::=
| "move"
| "left"
| "right"
| "repeat" <program>

我如何为它编写OCaml定义?类似的事情:“让p = ......”

1 个答案:

答案 0 :(得分:4)

通常,当你给某人一个语法时,你应该用它所用的语言来指定,例如,EBNF。您的示例对我来说看起来不是有效的BNF。

虽然如果我理解了您的定义,那么programinstruction将映射到以下OCaml类型:

type program = 
  | Instruction of instruction
  | End
and instruction = 
  | Move
  | Left
  | Right
  | Repeat of program

为了将任意字符串转换为上面定义的程序类型的值,您需要编写一个解析器。 OCaml编写解析器的常用方法是使用ocamllexocamlyacc工具。但是这个简单的语法可以手动解析。以下函数将解析标记列表并输出程序:

let rec parse = function
  | ["instruction"; "move" ]  -> Instruction Move
  | ["instruction"; "left" ]  -> Instruction Left
  | ["instruction"; "right"]  -> Instruction Right
  | "instruction" :: "repeat" :: tokens  -> Instruction (Repeat (parse tokens))
  | ["end"] -> End
  | [] -> invalid_arg "Unexpected end of stream"
  | token :: _ -> invalid_arg ("Unexpected token: " ^ token)

标记列表应该由如此命名的标记生成器(或词法分析器)生成,这是一个接受字符串并将其拆分为标记列表的函数。可以使用Str库编写简单的标记化器:

let tokenizer = Str.(split (regex " +"))

作为旁注:默认情况下,Str库未加载到顶层。要加载它,您需要向顶层发出以下指令(包括#符号):

#use "topfind";;
#require "str";;