【问题标题】:OCaml: Pattern matching on strings of variable lengthOCaml:可变长度字符串的模式匹配
【发布时间】:2014-03-01 10:38:00
【问题描述】:

我正在尝试编写一个接受用户输入(一次一行)并以某种方式评估此用户输入的程序。

我有一个函数getline : unit -> string 从标准输入读取一个字符串并返回它。命令格式如下:

#command1 arg1 arg2 arg3
#cmd2 arg1 arg2
#nextcommand arg1 arg2 arg3 arg4
#quit
#exit

对命令的示例调用如下所示:

#command1 2 6 3
#cmd2 6 3
#nextcommand a b3 2 3

主要问题是函数evalcommand : string -> unit 需要getline 获得的整行。我开始了

let evalcommand command = match command with
    | "#quit" | "#exit" -> () (* no problem; both length 4 and no arguments *)
    | (* how to capture arguments properly? *)

如何处理长度不同的命令(例如 command1cmd2)并且带有附加参数?

已经考虑过不太好的替代方案:

  • 使用解析器(可能由解析器生成器生成):这是我想到的第一件事,但由于我只想支持五六个命令,看起来对我来说有点矫枉过正。

  • 检查不同长度的前缀:当然,我可以只检查命令字符串不同长度的前缀,但这似乎涉及很多样板代码。

  • 字符串的列表表示:我知道我可以将每个String 转换为char list,然后执行类似的操作

    let evalcommand command = match String.to_list with
            | ['#';'e';'x';'i';'t'] -> () (* cumbersome for many commands *)
            | '#'::'c'::'m'::'d'::'2'::args -> consume_args args (* cumbersome *)
            | (* and so on *)
    
  • Mikmatch:我也看过Mikmatch,但如果可能的话,我更喜欢使用 OCaml 的内在特性。

  • 哈希表方法:当然,我可以使用将Strings 映射到String list -> unit 的哈希表(即函数将一定数量的字符串作为参数,返回()) .

所以这是最后一个问题:有没有什么优雅的方法可以以一种直接、易于维护的方式(最好用少量代码)来解决这个问题?

【问题讨论】:

  • 如果事情变得更复杂,您可以定义语法并使用Camlp4.Struct.Grammar 模块解析它们。或通过 Lex/Yacc。

标签: pattern-matching ocaml


【解决方案1】:

不是最优雅的解决方案,但为什么不简单地按空格分割?

open Str;;

let split_on_spaces s = split (regexp " ") s;;

let evalcmd cmd = match (split_on_spaces cmd) with
  | ["#quit"] | ["#exit"] -> ()
  (* match on a known number on arguments *)
  | ["#command";arg1;arg2;arg3] -> ()
  (* unknown number *)
  | "#cmd2" :: arg_list -> ()

【讨论】:

    【解决方案2】:

    按照 Marth 的建议,我已经编写了许多简单的命令解释器。我认为这是一个优雅的解决方案,可以让简单的命令行语法快速运行。

    如果您的命令行语法可能比您显示的更丰富(例如,如果您可能需要带引号的字符串),您可以只使用 ocamllex 编写解释器。除非你真的很喜欢嵌套分隔符,否则你的命令行可能可以用正则表达式来描述。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-12
      • 1970-01-01
      相关资源
      最近更新 更多