regex - 如何在 OCaml 中将字符串解析为正则表达式类型

标签 regex ocaml

我们像这样定义一个正则表达式类型:

type regex_t =
    | Empty_String
    | Char of char
    | Union of regex_t * regex_t 
    | Concat of regex_t * regex_t 
    | Star of regex_t 

我们想写一个函数string_to_regex: string -> regex_t

  • Empty_string 的唯一字符是“E”
  • Char 的唯一字符是 'a'..'z'
  • '|'用于 Union
  • '*' 代表 Star
  • Concat 假定用于连续解析。
  • '('/')' 具有最高的优先级,然后是星号,然后是 concat,然后是 union

例如,

(a|E)*(a|b) 将是

Concat(Star(Union(Char 'a',Empty_String)),Union(Char 'a',Char 'b'))

如何实现string_to_regex

最佳答案

Ocamllex 和 menhir 是编写词法分析器和解析器的绝佳工具

ast.mli

type regex_t =
| Empty
| Char of char
| Concat of regex_t * regex_t
| Choice of regex_t * regex_t
| Star of regex_t

词法分析器.mll

{ open Parser }

rule token = parse
| ['a'-'z'] as c { CHAR c }
| 'E' { EMPTY }
| '*' { STAR }
| '|' { CHOICE }
| '(' { LPAR }
| ')' { RPAR }
| eof { EOF }

解析器.mly

%{ open Ast %}

%token <char> CHAR
%token EMPTY STAR CHOICE LPAR RPAR CONCAT
%token EOF

%nonassoc LPAR EMPTY CHAR

%left CHOICE
%left STAR
%left CONCAT

%start main
%type <Ast.regex_t> main

%%

main: r = regex EOF { r }

regex:
| EMPTY { Empty }
| c = CHAR { Char c }
| LPAR r = regex RPAR { r }
| a = regex CHOICE b = regex { Choice(a, b) }
| r = regex STAR { Star r }
| a = regex b = regex { Concat(a, b) } %prec CONCAT

ma​​in.ml

open Ast

let rec format_regex = function
| Empty -> "Empty"
| Char c -> "Char " ^ String.make 1 c
| Concat(a, b) -> "Concat("^format_regex a^", "^format_regex b^")"
| Choice(a, b) -> "Choice("^format_regex a^", "^format_regex b^")"
| Star(a) -> "Star("^format_regex a^")"

let () =
  let s = read_line () in
  let r = Parser.main Lexer.token (Lexing.from_string s) in
  print_endline (format_regex r)

并编译

ocamllex lexer.mll
menhir parser.mly
ocamlc -c ast.mli
ocamlc -c parser.mli
ocamlc -c parser.ml
ocamlc -c lexer.ml
ocamlc -c main.ml
ocamlc -o regex parser.cmo lexer.cmo main.cmo

然后

$ ./regex
(a|E)*(a|b)
Concat(Star(Choice(Char a, Empty)), Choice(Char a, Char b))

关于regex - 如何在 OCaml 中将字符串解析为正则表达式类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23891077/

相关文章:

recursion - 相互递归数据类型

ocaml - 多态变体子类型实现与签名不匹配

Python Regex 替换 - 是否可以进行有条件的替换?

javascript - 无法使用 PHP 从 CollegeBoard 获取内容

Python 用字典值替换字符串

javascript - RegEx - 从逗号分隔的字符串中提取包含子字符串的单词

OCaml 二次根的部分应用

emacs - 如何在 tuareg-mode emacs 中指定注释文件的自定义路径?

ocaml - 如何通过类型构造函数比较相等值?

php - 正则表达式/DOM 解析用缩略图替换 YouTube iframe,同时保留字符串