Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/crusso/mo-parsec

A parsec parser combinator library for Motoko
https://github.com/crusso/mo-parsec

Last synced: 3 months ago
JSON representation

A parsec parser combinator library for Motoko

Awesome Lists containing this project

README

        

# mo-parsec

A Parsec based parser combinator library for Motoko.

This is a minimal parsec implementation based directly on a port, from OCaml, of
[Opal](0), which is itself derived from Haskell's influential [Parsec](1) library.

The library and example was implemented primarily to exercise Motoko new type argument inference, but may be of more general use.

* [src](src) contains the [`Parsec`](src/Parsec.mo) library.
* [test](test) contains a sample lambda calculus lexer and parser that you can run with wasmtime.

## API Documentation

API documentation for this library can be found at https://crusso.github.io/mo-parsec/.

## Testing

```bash
make test
```

## Example

```bash
make example
```

## Documentation

There is currently no documentation, but see
Opal's [README](https://github.com/pyrocat101/opal/README.md) for a good overview of the available combinators, whose names
and types are largely preserved (modulo naming conventions and uncurrying).

Since Motoko does not have symbolic identifiers, symbolic Opal combinators are explicitly named in `Parsec.mo`. Here's a rough guide:

| Opal | Parsec |
|------|---------|
| `>>=` | `bind` |
| `<\|>` | `choose` |
| `=>` | `map` |
| `>>` | `right` |
| `<<` | `left` |
| `<~>` | `cons` |

Opal functions that rely on OCaml's polymorphic equality and comparison require additional arguments in Parsec. Some Opal combinators taking OCaml lists
take Motoko immutable arrays instead (e.g. `choice`).

## Disclaimer

The library is not well-tested, use at your own risk.

## References & Credits

[0] https://github.com/pyrocat101/opal

[1] https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/parsec-paper-letter.pdf

Thanks to Christoph Hegemann for the lambda calculus sample and feedback.

## API

```swift
module {

Lazy : module {

type t = {force : () -> A};

t : (() -> A) -> t
};

LazyStream : module {
type t
= ?(A, Lazy.t>);

ofFunc : (() -> ?A) -> LazyStream.t;

ofIter : Iter -> LazyStream.t;

ofText : Text -> LazyStream.t
};

type Input = LazyStream.t;

type Monad = ?(Result, Input);

type Parser = Input -> Monad;

any : Input -> Monad;

between : (Parser, Parser, Parser) -> Parser;

bind : (Parser, A -> Parser) -> Parser;

chainl : (Parser, Parser A>, A) -> Parser;

chainl1 : (Parser, Parser A>) -> Parser;

chainr : (Parser, Parser A>, A) -> Parser;

chainr1 : (Parser, Parser A>) -> Parser;

choice : [Parser] -> Parser;

choose : (Parser, Parser) -> Parser;

cons : (Parser, Parser>) -> Parser>;

count : (Nat, Parser) -> Parser>;

delay : (() -> Parser) -> Parser;

endBy : (Parser, Parser) -> Parser>;

endBy1 : (Parser, Parser) -> Parser>;

eof : A -> Parser;

exactly : ((Token, Token) -> Bool, Token) -> Parser;

explode : Text -> List;

implode : List -> Text;

left : (Parser, Parser) -> Parser;

many : Parser -> Parser>;

many1 : Parser -> Parser>;

map : (Parser, A -> B) -> Parser;

mzero : () -> Parser;

noneOf : ((Token, Token) -> Bool, [Token]) -> Parser;

oneOf : ((Token, Token) -> Bool, [Token]) -> Parser;

option : (A, Parser) -> Parser;

optional : Parser -> Parser;

pair : (Parser, Parser) -> Parser;

parse : (Parser, LazyStream.t) -> ?A;

range : ((Token, Token) -> Bool, Token, Token) -> Parser;

ret : A -> Parser;

right : (Parser, Parser) -> Parser;

satisfy : (Token -> Bool) -> Parser;

sepBy : (Parser, Parser) -> Parser>;

sepBy1 : (Parser, Parser) -> Parser>;

skipMany : Parser -> Parser;

skipMany1 : Parser -> Parser;

token : (Token -> ?A) -> Parser

type CharParsers = {

alphaNum : Input -> Monad;

digit : Input -> Monad;

hexDigit : Input -> Monad;

letter : Input -> Monad;

lexeme : Parser -> Parser;

lower : Input -> Monad;

newline : Input -> Monad;

octDigit : Input -> Monad;

space : Input -> Monad;

spaces : Input -> Monad;

tab : Input -> Monad;

token : Text -> Parser;

upper : Input -> Monad
};

CharParsers : () -> CharParsers;
}
```