Skip to content

Commit

Permalink
✨ working example parser
Browse files Browse the repository at this point in the history
  • Loading branch information
nabeelvalley committed Jul 19, 2024
1 parent 9a762f7 commit dd6e8f1
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 19 deletions.
23 changes: 20 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,36 @@
# parz

> Learning about Parser Combinators using [The YouTube Series by Low Byte Productions](https://www.youtube.com/playlist?list=PLP29wDx6QmW5yfO1LAgO8kU3aQEj8SIrU)
A simple parser combinator library

> Trying to learn [Gleam]() while also Learning about Parser Combinators using
> [The YouTube Series by Low Byte Productions](https://www.youtube.com/playlist?list=PLP29wDx6QmW5yfO1LAgO8kU3aQEj8SIrU)
> and [Understanding Parser Combinators](https://fsharpforfunandprofit.com/posts/understanding-parser-combinators/)
[![Package Version](https://img.shields.io/hexpm/v/parz)](https://hex.pm/packages/parz)
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/parz/)

The project exposes the following modules:

1. `parz.` - contains the `run` method which is used for executing a parser
2. `parz/combinators` - the parser combinator library
3. `pars/parsers` - some simple, prmiitive parsers

## Usage

```sh
gleam add parz
```

```gleam
import parz
import parz.{run}
import pars/combinators
import pars/parsers
pub fn main() {
// TODO: An example of the project in use
// For an example usage look at the `tests/sample_parser_test.gleam` file
let parser = // .. define a parser
let result = run(parser, content_to_parse)
}
```

Expand Down
1 change: 0 additions & 1 deletion src/parz/combinators.gleam
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import gleam/list
import gleam/string
import parz/types.{type Parser, type ParserState, ParserState}
import parz/util.{tap}

fn sequence_rec(
parsers: List(Parser(a)),
Expand Down
15 changes: 0 additions & 15 deletions src/parz/util.gleam

This file was deleted.

89 changes: 89 additions & 0 deletions test/simple_parser_test.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import gleeunit/should
import parz.{run}
import parz/combinators.{label_error, left, map, separator1, sequence}
import parz/parsers.{letters, regex, str}
import parz/types.{ParserState}

type Kind {
StringKind
BooleanKind
NumberKind
UnknownKind
}

type Identifier {
Identifier(name: String)
}

type Node {
UnknownNode
Node(name: Identifier, kind: Kind)
}

type NodePart {
K(kind: Kind)
I(identifier: Identifier)
}

type AST {
AST(List(Node))
}

const input = "name:string;
age:number;
active:boolean;"

const custom_error = "Expected : but found something else"

fn parser() {
let name =
left(letters(), str(":") |> label_error(custom_error))
|> map(Identifier)
|> map(I)

let kind =
left(letters(), str(";"))
|> map(fn(ok) {
case ok {
"string" -> StringKind
"number" -> NumberKind
"boolean" -> BooleanKind
_ -> UnknownKind
}
})
|> map(K)

let node =
sequence([name, kind])
|> map(fn(ok) {
case ok {
[I(i), K(k)] -> Node(i, k)
_ -> UnknownNode
}
})

let whitespace = regex("\\s*")

let parser = separator1(node, whitespace) |> map(AST)

parser
}

pub fn simple_parser_test() {
run(parser(), input)
|> should.be_ok
|> should.equal(ParserState(
AST([
Node(Identifier("name"), StringKind),
Node(Identifier("age"), NumberKind),
Node(Identifier("active"), BooleanKind),
]),
"",
))
}

pub fn simple_parser_error_test() {
run(parser(), "name;number")
|> should.be_error
|> should.equal(custom_error)
}

0 comments on commit dd6e8f1

Please sign in to comment.