• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

bench/H09-Aug-2017-286253

lib/H09-Aug-2017-1,6621,445

test/H09-Aug-2017-3,5713,270

.gitignoreH A D09-Aug-201754 76

.travis.ymlH A D09-Aug-2017163 1312

LICENSEH A D09-Aug-20171.1 KiB2317

README.mdH A D09-Aug-20174 KiB170132

mix.exsH A D09-Aug-2017859 3126

mix.lockH A D09-Aug-2017717 65

README.md

1## Combine
2
3A parser combinator library for Elixir projects.
4
5[![Master](https://travis-ci.org/bitwalker/combine.svg?branch=master)](https://travis-ci.org/bitwalker/combine)
6[![Hex.pm Version](http://img.shields.io/hexpm/v/combine.svg?style=flat)](https://hex.pm/packages/combine)
7
8## How to Use
9
10First add it to your dependency list like so:
11
12```elixir
13def deps do
14  [{:combine, "~> x.x.x"}, ...]
15end
16```
17
18Documentation is [located here](http://hexdocs.pm/combine).
19
20From there the API is fairly straightforward, the docs cover what
21parser combinators are available, but here's a quick taste of how you
22use it:
23
24```elixir
25defmodule DateTimeParser do
26  use Combine
27
28  def parse(datetime), do: Combine.parse(datetime, parser)
29
30  defp parser, do: date |> ignore(char("T")) |> time
31
32  defp date do
33    label(integer, "year")
34    |> ignore(char("-"))
35    |> label(integer, "month")
36    |> ignore(char("-"))
37    |> label(integer, "day")
38  end
39
40  defp time(previous) do
41    previous
42    |> label(integer, "hour")
43    |> ignore(char(":"))
44    |> label(integer, "minute")
45    |> ignore(char(":"))
46    |> label(float, "seconds")
47    |> either(
48      map(char("Z"), fn _ -> "UTC" end),
49      pipe([either(char("-"), char("+")), word], &(Enum.join(&1)))
50    )
51  end
52end
53
54...> datetime = "2014-07-22T12:30:05.0002Z"
55...> datetime_zoned = "2014-07-22T12:30:05.0002+0200"
56...> DateTimeParser.parse(datetime)
57[2014, 7, 22, 12, 30, 5.0002, "UTC"]
58...> DateTimeParser.parse(datetime_zoned)
59[2014, 7, 22, 12, 30, 5.0002, "+0200"]
60
61```
62
63## Why Combine vs ExParsec?
64
65Combine is a superset of ExParsec's API for the most part and it's performance is significantly
66better in the one benchmark I've run with a very simple parser. Benchfella was used to run the
67benchmarks, and the benchmarks used for comparison are present in both Combine and ExParsec's
68`bench` directories with the exception of the datetime parsing one, which is easily replicated
69in ExParsec if you wish to double check yourself. For reference, here's what I'm seeing on my machine:
70
71```
72# ExParsec
73
74Settings:
75  duration:      1.0 s
76
77## Bench.ExParsec.Binary
78[19:01:54] 1/2: many bits
79## Bench.ExParsec.Text
80[19:01:56] 2/2: many any_char
81
82Finished in 5.67 seconds
83
84## Bench.ExParsec.Binary
85many bits            1000   1731.83 µs/op
86
87## Bench.ExParsec.Text
88many any_char                  5000   616.02 µs/op
89parse ISO 8601 datetime        2000   964.48 µs/op
90
91# Combine
92
93Settings:
94  duration:      1.0 s
95
96## Combine.Bench
97[15:21:21] 1/5: parse ISO 8601 datetime
98[15:21:22] 2/5: many bits
99[15:21:25] 3/5: many any_char
100[15:21:27] 4/5: large set of choices (one_of/word)
101[15:21:30] 5/5: large set of choices (choice/parsers)
102
103Finished in 12.08 seconds
104
105## Combine.Bench
106large set of choices (one_of/word)         100000   25.60 µs/op
107many any_char                               50000   32.98 µs/op
108many bits                                   50000   43.90 µs/op
109parse ISO 8601 datetime                     10000   139.45 µs/op
110large set of choices (choice/parsers)       10000   265.04 µs/op
111```
112
113ExParsec also appears to be falling behind on maintenace, even with PRs being submitted,
114so rather than forking I decided to write my own from scratch that met my needs.
115
116## Parsers
117
118You should look at the docs for usage on each parser combinator, but the following
119lists which ones are available in each module.
120
121### Combine.Parsers.Base
122--------
123```
124between         both
125choice          either
126eof             fail
127fatal           ignore
128label           many
129map             none_of
130one_of          option
131pair_both       pair_left
132pair_right      pipe
133satisfy         sep_by
134sep_by1         sequence
135skip            skip_many
136skip_many1      times
137zero
138```
139
140### Combine.Parsers.Text
141--------
142```
143alphanumeric      bin_digit
144char              digit
145float             fixed_integer
146hex_digit         integer
147letter            lower
148newline           octal_digit
149space             spaces
150string            tab
151upper             word
152word_of
153```
154
155### Combine.Parsers.Binary
156--------
157```
158bits       bytes
159float      int
160uint
161```
162
163## Roadmap
164
165- Streaming parsers
166
167## License
168
169MIT
170