我是OCaml的新手。我有一个如下语法定义:
<program>::=
| <instruction <program>>
| "end"
<instruction>::=
| "move"
| "left"
| "right"
| "repeat" <program>
我如何为它编写OCaml定义?类似的事情:“让p = ......”
答案 0 :(得分:4)
通常,当你给某人一个语法时,你应该用它所用的语言来指定,例如,EBNF。您的示例对我来说看起来不是有效的BNF。
虽然如果我理解了您的定义,那么program
和instruction
将映射到以下OCaml类型:
type program =
| Instruction of instruction
| End
and instruction =
| Move
| Left
| Right
| Repeat of program
为了将任意字符串转换为上面定义的程序类型的值,您需要编写一个解析器。 OCaml编写解析器的常用方法是使用ocamllex
和ocamlyacc
工具。但是这个简单的语法可以手动解析。以下函数将解析标记列表并输出程序:
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";;