Angstrom Parser-Combinator Library

repository·master·Indexed 20 days ago

https://github.com/inhabitedtype/angstrom

A high-performance parser-combinator library for OCaml optimized for network protocols and serialization. It features monadic and applicative interfaces, default backtracking, unbounded lookahead, and non-blocking incremental IO compatible with Async and Lwt.

Tokens
781
Snippets
4
Records
5
Agent score
22%

What's inside Angstrom

  1. Core concepts of Angstrom parsers

    master

    Angstrom is a high-performance parser-combinator library designed for network protocols and serialization formats.

    Key characteristics include:

    • Monadic and Applicative interfaces: Allows for expressive and reusable parser composition.
    • Backtracking by default: Unlike many other OCaml parser libraries (like Parsec derivatives), you do not need an explicit try combinator to backtrack; it is the default behavior.
    • Unbounded lookahead: Supports looking ahead in the input stream without limits.
    • Incremental Input: Supports both buffered and unbuffered interfaces. The unbuffered interface enables zero-copy IO.
    • Concurrency Support: Unlike libraries that rely on lazy character streams, Angstrom provides non-blocking incremental interfaces that are compatible with monadic concurrency libraries like Async and Lwt.
  2. Example: Parsing arithmetic expressions

    master

    The following example demonstrates how to build a parser for a simple arithmetic expression language. It uses combinators to handle parentheses, basic operators (+, -, *, /), and integers, computing the result during the parsing process.

    open Angstrom
    
    let parens p = char '(' *> p <* char ')'
    let add = char '+' *> return (+)
    let sub = char '-' *> return (-)
    let mul = char '*' *> return (*)
    let div = char '/' *> return (/)
    let integer =
      take_while1 (function '0' .. '9' -> true | _ -> false) >>| int_of_string
    
    let chainl1 e op =
      let rec go acc =
        (lift2 (fun f x -> f acc x) op e >>= go) <|> return acc in
      e >>= fun init -> go init
    
    let expr : int t =
      fix (fun expr ->
        let factor = parens expr <|> integer in
        let term   = chainl1 factor (mul <|> div) in
        chainl1 term (add <|> sub))
    
    let eval (str:string) : int =
      match parse_string ~consume:All expr str with
      | Ok v      -> v
      | Error msg -> failwith msg