• Stars
    star
    226
  • Rank 176,514 (Top 4 %)
  • Language
    Elm
  • License
    BSD 3-Clause "New...
  • Created over 7 years ago
  • Updated 10 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A parsing library, focused on simplicity and great error messages

Parser

Regular expressions are quite confusing and difficult to use. This library provides a coherent alternative that handles more cases and produces clearer code.

The particular goals of this library are:

  • Make writing parsers as simple and fun as possible.
  • Produce excellent error messages.
  • Go pretty fast.

This is achieved with a couple concepts that I have not seen in any other parser libraries: parser pipelines, backtracking, and tracking context.

Parser Pipelines

To parse a 2D point like ( 3, 4 ), you might create a point parser like this:

import Parser exposing (Parser, (|.), (|=), succeed, symbol, float, spaces)

type alias Point =
  { x : Float
  , y : Float
  }

point : Parser Point
point =
  succeed Point
    |. symbol "("
    |. spaces
    |= float
    |. spaces
    |. symbol ","
    |. spaces
    |= float
    |. spaces
    |. symbol ")"

All the interesting stuff is happening in point. It uses two operators:

  • (|.) means “parse this, but ignore the result”
  • (|=) means “parse this, and keep the result”

So the Point function only gets the result of the two float parsers.

The theory is that |= introduces more “visual noise” than |., making it pretty easy to pick out which lines in the pipeline are important.

I recommend having one line per operator in your parser pipeline. If you need multiple lines for some reason, use a let or make a helper function.

Backtracking

To make fast parsers with precise error messages, all of the parsers in this package do not backtrack by default. Once you start going down a path, you keep going down it.

This is nice in a string like [ 1, 23zm5, 3 ] where you want the error at the z. If we had backtracking by default, you might get the error on [ instead. That is way less specific and harder to fix!

So the defaults are nice, but sometimes the easiest way to write a parser is to look ahead a bit and see what is going to happen. It is definitely more costly to do this, but it can be handy if there is no other way. This is the role of backtrackable parsers. Check out the semantics page for more details!

Tracking Context

Most parsers tell you the row and column of the problem:

Something went wrong at (4:17)

That may be true, but it is not how humans think. It is how text editors think! It would be better to say:

I found a problem with this list:

    [ 1, 23zm5, 3 ]
         ^
I wanted an integer, like 6 or 90219.

Notice that the error messages says this list. That is context! That is the language my brain speaks, not rows and columns.

Once you get comfortable with the Parser module, you can switch over to Parser.Advanced and use inContext to track exactly what your parser thinks it is doing at the moment. You can let the parser know “I am trying to parse a "list" right now” so if an error happens anywhere in that context, you get the hand annotation!

This technique is used by the parser in the Elm compiler to give more helpful error messages.

Comparison with Prior Work

More Repositories

1

compiler

Compiler for Elm, a functional language for reliable webapps.
Haskell
7,493
star
2

core

Elm's core libraries
Elm
2,791
star
3

elm-lang.org

Server and client code for the Elm website.
Elm
1,987
star
4

projects

Curated collection of projects for folks looking to collaborate within the Elm ecosystem.
423
star
5

html

Use HTML in Elm!
Elm
395
star
6

browser

Create Elm programs that run in browsers!
Elm
311
star
7

package.elm-lang.org

website for browsing packages and exploring documentation
Haskell
293
star
8

virtual-dom

The foundation of HTML and SVG in Elm.
JavaScript
208
star
9

error-message-catalog

A catalog of broken Elm programs / data to improve error messages
Elm
173
star
10

http

Make HTTP requests in Elm
Elm
155
star
11

svg

Fast SVG in Elm
Elm
146
star
12

file

Select files. Download files. Work with file content.
Elm
106
star
13

time

A simplified approach to working with dates, times, and time zones.
Elm
92
star
14

json

Work with JSON in Elm
Elm
90
star
15

bytes

Work with bytes and implement network protocols
Elm
80
star
16

url

Build and parse URLs. Useful for HTTP and "routing" in single-page apps (SPAs)
Elm
75
star
17

expectations

Trying to set expectations about @elm processes
53
star
18

editor-plugins

List of editor plugins for Elm.
50
star
19

random

Generate random values in Elm
Elm
45
star
20

regex

If you really need regex in Elm, it is possible.
Elm
33
star
21

color

Standard representation of colors, encouraging sharing between packages.
Elm
24
star
22

foundation.elm-lang.org

Source code for the ESF website
Elm
17
star
23

project-metadata-utils

Work with elm.json and docs.json files in Elm
Elm
16
star
24

forum-rules

Rules for Elm forums
9
star