# GLL parsing framework [![Build Status](https://travis-ci.com/lykenware/gll.svg?branch=master)](https://travis-ci.com/lykenware/gll) [![Latest Version](https://img.shields.io/crates/v/gll.svg)](https://crates.io/crates/gll) [![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/gll) ## Usage Easiest way to get started is through `gll-macros`: ```toml [dependencies] gll = "0.0.2" gll-macros = "0.0.2" ``` ```rust extern crate gll; extern crate gll_macros; ``` As an example, this is what you might write for a JSON-like syntax, that uses plain identifiers instead of string literals for field names, and allows values to be parenthesized Rust expressions: ```rust mod json_like { ::gll_macros::proc_macro_parser! { Value = Null:"null" | False:"false" | True:"true" | Literal:LITERAL | Array:{ "[" elems:Value* % "," "]" } | Object:{ "{" fields:Field* % "," "}" } | InterpolateRust:{ "(" TOKEN_TREE+ ")" }; Field = name:IDENT ":" value:Value; } } ``` You can also use a build script to generate the parser (**TODO**: document). To parse a string with that grammar: ```rust let tokens = string.parse().unwrap(); json_like::Value::parse_with(tokens, |parser, result| { let value = result.unwrap(); // ... }); ``` ## Grammar All grammars contain a set of named rules, with the syntax `Name = rule;`. (the order between the rules doesn't matter) Rules are made out of: * **grouping**, using `{...}` * **string literals**, matching input characters / tokens exactly * **character ranges**: `'a'..='d'` is equivalent to `"a"|"b"|"c"|"d"` * only in scannerless mode * **builtin rules**: `IDENT`, `PUNCT`, `LITERAL`, `TOKEN_TREE` * only in proc macro mode * **named rules**, referred to by their name * **concatenation**: `A B` - "`A` followed by `B`" * **alternation**: `A | B` - "either `A` or `B`" * **optionals**: `A?` - "either `A` or nothing" * **lists**: `A*` - "zero or more `A`s", `A+` - "one or more `A`s" * optional separator: `A* % ","` - "comma-separated `A`s" Parts of a rule can be labeled with **field names**, to allow later access to them: `LetDecl = "let" pat:Pat { "=" init:Expr }? ";";` produces: ```rust // Note: generic parameters omitted for brevity. struct LetDecl { pat: Handle, init: Option>, } ``` One Rust-specific convention is that alternation fields are enum variants. `Expr = Lit:LITERAL | Add:{ a:Expr "+" b:Expr };` produces: ```rust enum Expr { Lit(Handle), Add { a: Handle, b: Handle, }, } ``` ## License Licensed under either of * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.