Skip to content

Navigation Menu

Sign in
Sign up

Repository files navigation

Glindo

Package Version
Hex Docs

Glindo is a functional parser-combinator library for Gleam that makes it easy to build powerful, composable parsers for context-free grammars: JSON, CSV, small DSLs, YAML, and more. Glindo uses familiar FP abstractions—functors, monads, lazy evaluation—to thread parsing state and errors in a purely functional way.


🔑 Key Features

  • Core Combinators

    • map, bind (monadic sequencing)
    • seq_of (sequence), chc_of (choice), chc_opt (greedy choice)
    • mny_of, mny_chc (zero-or-more repetition)
    • opt_of (optional), sep_by (separated lists), btwn (between), peek_fwd, lazy, tok (token with whitespace)
  • Rich Type Safety

    • Parser(a) wraps fn(ParserState) -> Result(ParseResult(a), String)
    • ParseResult(a) bundles (res, rem, idx)
    • ParserState(str, idx) tracks the remaining input & position
  • Out-of-the-box Grammars

    • JSON: full support for null, boolean, number, string, array, object
    • CSV: handles quoted strings (with "" escapes), unquoted fields, line breaks, and trimming
  • Pure-FP Style

    • No mutable state—everything is threaded through combinators
    • Lazy parsing for recursive grammars
    • Distinct error messages

📦 Installation

gleam add glindo

In your gleam.toml

[dependencies] glindo = ">= 1.0.0"

🚀 Quick Start

import glindo/parser.{
 map, 
 btwn, 
 num, 
 sat_pred, 
 tok, 
 prefix_str, 
 chc_of, 
 sep_by
}
import glindo/types.{type Parser}
import glindo/csv 
pub fn main() {
// A simple parser naive CSV parser
pub type CSVal {
 CSVInt(Int)
 CSVStr(String)
 CSVBool(Bool)
}
pub type CSVRecord {
 Field(line: Int, records: List(CSVal))
}
pub type CSV {
 CSV(value: List(CSVRecord))
}
fn csv_quoted_string() -> Parser(CSVal) {
 btwn(
 tok(prefix_str("\"")),
 chc_of([
 sat_pred(chr_grab(), fn(x) { x != "\"" }),
 map(prefix_str("\"\""), fn(x) { [x] }),
 ]),
 tok(prefix_str("\"")),
 )
 |> map(string.concat)
 |> map(string.trim)
 |> map(fn(x) { CSVStr(x) })
}
fn csv_unquoted_string() -> Parser(CSVal) {
 chr_grab()
 |> sat_pred(fn(x) { x != "," && x != "\r\n" && x != "\n" })
 |> map(string.concat)
 |> map(string.trim)
 |> map(fn(x) { CSVStr(x) })
}
fn csv_string() -> Parser(CSVal) {
 [csv_quoted_string(), csv_unquoted_string()]
 |> chc_of()
}
fn csv_num() -> Parser(CSVal) {
 use num <- map(num())
 CSVInt(num)
}
fn filter_csval(val: CSVal) -> Bool {
 val != CSVStr("\r\n")
}
fn csv_record() -> Parser(CSVRecord) {
 [csv_string(), csv_num()]
 |> chc_of()
 |> sep_by(prefix_str(","))
 |> map(fn(x) { list.filter(x, filter_csval) })
 |> map(fn(rec) { Field(1, rec) })
}
fn csv() -> Parser(CSV) {
 csv_record()
 |> sep_by(
 [tok(prefix_str("\r\n")), tok(prefix_str("\n"))]
 |> chc_of()
 |> tok(),
 )
 |> map(fn(csv) { CSV(csv) })
 }
}

📚 Core API Overview

Combinator Type Signature Description
map (Parser(a), fn(a) -> b) -> Parser(b) Transform parsed result
bind (Parser(a), fn(a) -> Parser(b)) -> Parser(b) Sequence two parsers
seq_of List(Parser(a)) -> Parser(List(a)) Run parsers in order; fail if any fails
chc_of List(Parser(a)) -> Parser(a) Try parsers until one succeeds
chc_opt List(Parser(a)) -> Parser(a) Greedy choice: pick the one that consumes the most input
mny_of Parser(a) -> Parser(List(a)) Zero-or-more repetition
mny_chc List(Parser(a)) -> Parser(List(a)) Zero-or-more choice
opt_of Parser(a) -> Parser(Option(a)) Optional parser
sep_by (Parser(a), Parser(b)) -> Parser(List(a)) Parse a list separated by a delimiter
btwn (Parser(a), Parser(b), Parser(c)) -> Parser(b) Between two delimiters
peek_fwd Parser(a) -> Parser(a) Look ahead without consuming input
lazy (fn() -> Parser(a)) -> Parser(a) Deferred parser for recursion
tok Parser(a) -> Parser(a) Skip leading/trailing whitespace around a parser

See the HexDocs API Reference for full details and examples.

🛠️ Development

Glindo is under active development. To run tests and play with the library locally:

git clone https://github.com/daniel-shunom/glindo.git
cd glindo
gleam run # Run examples or REPL
gleam test # Execute the test suite

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b my-feature)
  3. Write tests for new functionality
  4. Submit a pull request

Please follow the Gleam style guide and include documentation comments for any new public API.

📞 Contact Information

If you’d like to reach out, feel free to connect via:

About

A simple parser combinator library that just works

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

19 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

AltStyle によって変換されたページ (->オリジナル) /