package reparse

  1. Overview
  2. Docs
Recursive descent parsing library for ocaml

Install

Dune Dependency

Authors

Maintainers

Sources

reparse-unix-v2.1.0.tbz
sha256=51f7bb7087679e7e8dabf237a2e080094391bc626476c4c614515a14a3da6919
sha512=b886a2261131b7ccf5d38def08a57724a8eb1a8b95d299f452659b874f7d186aa1e25e77aebfa921b269804f1d9895c0e124c31bbd5d204af9c5dd9b1c720ebf

Description

Monadic, recursive descent based, parser construction library for ocaml. Comprehensively documented and tested.

Published: 07 Apr 2021

README

Reparse

Reparse is a monadic, recursive descent based, comprehensive parser construction library for ocaml.

Reparse Documentation

Getting Started

$ opam install reparse

Add reparse to dune,

(executable # or library
  (name hello_world)
  (public_name hello_world)
  (libraries reparse))

Example - Calculator

A calculator is the hello world of parsers. Here is an implementation in Reparse which supports +,-,* and / operations.

open Reparse

type expr =
  | Int of int
  | Add of expr * expr
  | Sub of expr * expr
  | Mult of expr * expr
  | Div of expr * expr

let skip_spaces = skip (ignore_m space)

let binop : 'a t -> char -> 'b t -> ('a -> 'b -> 'c) -> 'c t =
 fun exp1 op exp2 f ->
  map3 exp1 (skip_spaces *> char op <* skip_spaces) exp2 ~f:(fun e1 _ e2 -> f e1 e2)
;;

let integer : expr t =
  let+ d = digits in
  Int (int_of_string d)
;;

let factor : expr t -> expr t =
 fun expr ->
  any
    [ char '(' *> skip_spaces *> expr <* skip_spaces <* char ')'
    ; skip_spaces *> integer <* skip_spaces
    ]
;;

let term : expr t -> expr t =
 fun factor ->
  recur (fun term ->
      let mult = binop factor '*' term (fun e1 e2 -> Mult (e1, e2)) in
      let div = binop factor '/' term (fun e1 e2 -> Div (e1, e2)) in
      mult <|> div <|> factor)
;;

let expr : expr t =
  recur (fun expr ->
      let factor = factor expr in
      let term = term factor in
      let add = binop term '+' expr (fun e1 e2 -> Add (e1, e2)) in
      let sub = binop term '-' expr (fun e1 e2 -> Sub (e1, e2)) in
      any [ add; sub; term ])
;;

let rec eval : expr -> int = function
  | Int i -> i
  | Add (e1, e2) -> eval e1 + eval e2
  | Sub (e1, e2) -> eval e1 - eval e2
  | Mult (e1, e2) -> eval e1 * eval e2
  | Div (e1, e2) -> eval e1 / eval e2
;;

(* Test AST *)
let r =
  let actual = parse_string expr "1*2-4+3" in
  let expected = Sub (Mult (Int 1, Int 2), Add (Int 4, Int 3)) in
  Bool.equal (expected = actual) true
;;

(* Run and test the evaluator. *)
let exp_result =
  let v = eval (parse_string expr "12+1*10") in
  Int.equal 22 v
;;

The expression grammar is defined by the following BNF grammar:

<expr>   ::= <term>   "+" <expr>
           | <term>
<term>   ::= <factor> "*" <term>
           | <factor>
<factor> ::= "(" <expr> ")"
           | integer

More Examples

Credits

  • https://github.com/MLton/mlton/blob/master/lib/mlton/basic/parse.sig

  • https://github.com/c-cube/ocaml-containers/blob/master/src/core/CCParse.mli

Dependencies (3)

  1. base
  2. ocaml >= "4.10.0"
  3. dune >= "2.7"

Dev Dependencies (2)

  1. odoc with-doc
  2. alcotest with-test

Used by (2)

  1. http-multipart-formdata = "1.1.0"
  2. reparse-unix >= "2.1.0"

Conflicts

None

OCaml

Innovation. Community. Security.