package orsetto

  1. Overview
  2. Docs
Legend:
Library
Module
Module type
Parameter
Class
Class type

JavaScript Object Notation (JSON) input scanner.

Overview

Functions that scan Unicode text for JSON interchange language syntax. A low-level lexical token scanner is provided for monadic parsing of any valid JSON text, including infinite streams. Higher-level scanners are provided for composing bespoke parsers according to a required schema. A scanner is also provided for input of arbitrary finite JSON values.

Lexical Analyzer
module Annot = Ucs_scan.UTF8.Annot

A convenient alias for the UTF-8 text annotation system.

The lexical analyzer that recognizes JSON events.

Parser

Include the scanner profile. The first stage scanner is the lexical analyzer augmented to raise Bad_syntax on failure to recognize a valid event.

include Cf_scan.Staging.Profile with type symbol := Uchar.t and type token := Json_event.t and type position := Cf_annot.Textual.position and type 'a form := 'a Annot.form
include Cf_scan.Profile with type symbol := Json_event.t with type position := Cf_annot.Textual.position with type 'a form := 'a Annot.form
type +'r t

The monad type.

include Cf_monad.Unary.Profile with type +'r t := 'r t

Module inclusions from Cf_monad_core and Cf_seqmonad.

include Cf_monad.Core.Unary.Profile with type 'r t := 'r t
val return : 'r -> 'r t

Use return a to apply the binding to a.

val bind : 'a t -> ('a -> 'b t) -> 'b t

Use bind m f to bind f to the value returned by m.

val map : 'a t -> f:('a -> 'b) -> 'b t

Use map m f to return the result of applying f to the value returned by m.

module Infix : Cf_monad_core.Unary.Infix with type 'r t := 'r t

Open Infix to include the infix monad operators.

val disregard : 'r t -> unit t

Use disregard m to ignore the value returned by m and apply the unit value to the bound function.

include Cf_seqmonad.Functor.Unary with type 'r t := 'r t
val collect : 'r t Seq.t -> (int * 'r list) t

Use collect s to bind in sequence every monad value in the finite sequence s and collect all the returned values. Returns (n, s) where n is the number of values collected and s is the list of values in reverse order, i.e. from last collected to first collected. Never returns and exhausts all memory if s never terminates.

val serial : unit t Seq.t -> unit t

Use serial s to bind in sequence every monad value in the sequence s.

val nil : 'r t

A scanner that never produces any value.

val fin : bool t

A scanner that returns true at the end of the input sequence, otherwise returns false.

Backtracking
type mark

The abstract type representing a resumption point in the input.

val cur : mark t

A scanner that produces a mark captured at the current position.

val mov : mark -> unit t

Use mov mark to resume scanning at the captured mark.

val pos : mark -> unit Annot.form

Use pos mark to make a unit value attributed with the position of captured mark. Raises Not_found if mark was captured at the end of the input stream.

Terminal Scanner

The universal symbol scanner. Recognizes any symbol in the input stream and produces its form. Does not produce anything at the end of input.

The literal symbol scanner. Use one symbol to make a scanner that recognizes symbol in the input stream and produces its form.

val sat : (Json_event.t -> bool) -> Json_event.t Annot.form t

The symbol satisfier scanner. Use sat f to make a scanner that recognizes any symbol for which applying f returns true and produces its form.

val ign : (Json_event.t -> bool) -> unit Annot.form t

The ignore scanner. Use ign f to make a scanner that scans the input while applying f to each symbol returns true, then produces a unit form that annotates the span of ignored symbols. Produces an implicit unit form if the end of input has already been reached.

val tok : (Json_event.t -> 'r option) -> 'r Annot.form t

The symbolic token scanner. Use tok f to make a scanner that recognizes any symbol for which applying f returns Some v, then produces the form of v.

Scanner Composers

The opaque value form scanner composer. Use ntyp n p to make a scanner that encloses the value contained in the form produced by p in an opaque value with the runtime type indicated by n and returns its form in the same position.

val dflt : 'r -> 'r t -> 'r t

The default value scanner. Use dflt v p to produce the output of p or the default value v if p does not produce output.

val opt : 'r t -> 'r option t

The optional scanner composer. Use opt p to make a scanner that produces either Some v if p produces v otherwise None.

val vis : ?a:int -> ?b:int -> ('r -> 'r t) -> 'r -> 'r t

The visitor scanner composer. Use vis ?a ?b f v to compose a scanner that recognizes a sequence of elements in the input stream by applying a visitor function f at each element to obtain its scanner. The first element is visited with the initializer v, and each following element is visited with the value returned by the preceding scanner.

If ~a is used, then it specifies the minimum number of elements to visit. If ~b is used then it specifies the maximum number of elements to visit. Composition raises Invalid_argument if a < 0 or b < a.

val seq : ?a:int -> ?b:int -> 'r t -> 'r list t

The homogenous list scanner composer. Use seq ?a ?b p to create a new scanner that uses p to recognize and produce, in order, each element in a sequence of elements in the input stream.

If ~a is used, then it specifies the minimum number of elements that must be recognized and produced in the output. If ~b is used then it specifies the maximum number of elements to recognize. Composition raises Invalid_argument if a < 0 or b < a.

val alt : 'r t list -> 'r t

The bounded multiple choice scanner. Use alt ps to create a scanner that produces the output from the first scanner ps that produces. If no scanner in ps produces output, then the resulting scanner does not produce.

val altz : 'r t Seq.t -> 'r t

The unbounded multiple choice scanner. Use alt ps to create a scanner that produces the output from the first scanner ps that produces. If no scanner in ps produces output, then the resulting scanner does not produce.

Error Parsers
type exn +=
  1. | Bad_syntax of string Annot.form

A distinguished syntax failure exception.

val fail : string -> 'r t

Use fail msg to raise Bad_syntax with msg optionally annotated with the current position.

val or_fail : string -> 'r t -> 'r t

Use or_fail msg p to make a scanner that raises Bad_syntax with msg if p does not recognize its input. It may be convenient to call this function with a pipeline operator, i.e. p |> or_fail "reasons".

val err : ?x:exn -> unit -> 'r t

Use err ~x () to make a scanner that raises x. If ?x is not provided, then it raises Not_found.

val errf : ?xf:(mark -> 'x) -> unit -> 'r t

Use errf ~xf () to make a scanner that captures a mark and applies it to xf to raise an exception. If ?xf is not provided, then raises Not_found.

val req : ?x:exn -> 'r t -> 'r t

Use req ~x p to make a scanner that either produces the output of p or raises x. If p does not produce and ?x is not provided, then it raises Not_found.

val reqf : ?xf:(mark -> 'x) -> 'r t -> 'r t

Use reqf ~xf p to make a scanner that either produces the output of p or captures a mark at the current input and applies it to xf to raise an exception. If ?xf is not provided, then raises Not_found.

val ck : 'r t -> ('r, exn) result t

The error check scanner. Use ck p to create a new scanner that either produces either Ok v if p produces v or Error x if scanning the input with p raises the exception x.

val sync : 'r t -> 'r option t

The error recovery scanner. Use sync p to scan the input with p until it produces or reaches the end of input. Produces Some v if p ever produces v, otherwise produces None if the end of input is reached without p producing a value.

Elaboration
val lift : ?start:Cf_annot.Textual.position -> 'r t -> Json_event.t Seq.t -> 'r Seq.t

Use lift p s to map s into a persistent sequence of the values produced by p. If ~start is provided, then it specifies the starting position of the first symbol in s.

val of_seq : ?start:Cf_annot.Textual.position -> 'r t -> Json_event.t Seq.t -> 'r

Use of_seq p s to parse s with p and return the result. Raises Not_found if p does not recognize the entire sequence of s. If ~start is provided, then it specifies the starting position of the first symbol in s.

module Affix : sig ... end

Combinator operators

val lift_staged : ?start:Cf_annot.Textual.position -> 'r t -> Uchar.t Seq.t -> 'r Seq.t

Use lift_staged p s to lift s into the first stage token sequence, then map it into a persistent sequence of the values produced by p. If ~start is provided, then it specifies the starting position of the first symbol in s.

val of_seq_staged : ?start:Cf_annot.Textual.position -> 'r t -> Uchar.t Seq.t -> 'r

Use of_seq_staged p s to lift s into the first stage token sequence, then parse it with p, and return the result. Raises Not_found if p does not recognize the entire sequence of s. If ~start is provided, then it specifies the starting position of the first symbol in s.

The parser that returns the next annotated event that is not space.

val space : unit Annot.form t

The parser that recognizes a space event.

Scalar Values

The following parsers all ignore any white space encountered in the input before recognizing the scalar value.

val null : unit Annot.form t

A parser that recognizes the null literal.

val boolean : bool Annot.form t

The parser that recognizes either the true or false literal and returns the value of annotated boolean value accordingly.

val integer : int Annot.form t

The parser that recognizes an integer number within the range of Ocaml and returns the annotated integer value accordingly.

val float : float Annot.form t

The parser that recognizes a number within the range of Ocaml floating point numbers and returns the annotated float value accordingly.

val string : Ucs_text.t Annot.form t

The parser that recognizes a string literal and returns the annotated Unicode text with all the escaped sequences converted.

val signal : [< Json_event.signal ] -> unit Annot.form t

Use signal x to make a parser that recognizes the event signal x.

Aggregate Values

The following interfaces are provided to facilitate various strategies for scanning arrays and objects.

module Chain : Cf_chain_scan.Profile with type symbol := Json_event.t Annot.form and type mark := mark and type 'a t := 'a t and type 'a form := 'a

The chain scanner module.

val chain : ?xf:(mark -> 'x) -> unit -> Chain.chain

Use chain () to make a chain discipline for array and object content, which is a list of elements separated by semi-colon characters.

module Object : Cf_record_scan.Profile with type index := Ucs_text.t and type 'a form := 'a Annot.form and type 'a t := 'a t

The record scanner module for JSON object content.

val group : [< `Array | `Object ] -> 'r t -> 'r Annot.form t

Use group kind content to make a parser that recognizes an array or an object form according to kind with content that must be recognized by content.

For example, use float |> seq ~a:1 ?b |> group `Array to scan an array of one or more floating point numbers.

Alternatively, use Object.scan schema |> group `Object to scan an object according to schema.

A parser that recognizes any JSON encoded value and produces an annotated opaque value with encapsulated runtime type indication. The following table describes the runtime type indications produced for values decoded.

  • null: Cf_type.Unit
  • boolean: Cf_type.Bool
  • number: Cf_type.Int or Cf_type.Float
  • string: Ucs_type.Text
  • array: Cf_type.Seq Cf_type.Opaque
  • object: Cf_type.(Seq (Pair (Ucs_type.Text, Cf_type.Opaque))

Use the Ucs_type module for unpacking.

Note well: the array and object containers are sequences of untyped values, which must be unpacked recursively. Exceeding a maximum recursion depth of 1000 raises Bad_syntax.

Conveniences
val of_text : 'a t -> Ucs_text.t -> 'a

Use of_text p t to parse the Unicode text s with p.