Parsing Expression Grammar (PEG) parser generator for Rust

Overview

Parsing Expression Grammars in Rust

Documentation | Release Notes

rust-peg is a simple yet flexible parser generator that makes it easy to write robust parsers. Based on the Parsing Expression Grammar formalism, it provides a Rust macro that builds a recursive descent parser from a concise definition of the grammar.

Features

  • Parse input from &str, &[u8], &[T] or custom types implementing traits
  • Customizable reporting of parse errors
  • Rules can accept arguments to create reusable rule templates
  • Precedence climbing for prefix/postfix/infix expressions
  • Helpful rustc error messages for errors in the grammar definition or the Rust code embedded within it
  • Rule-level tracing to debug grammars

Example

Parse a comma-separated list of numbers surrounded by brackets into a Vec<u32>:

peg::parser!{
  grammar list_parser() for str {
    rule number() -> u32
      = n:$(['0'..='9']+) { n.parse().unwrap() }
    
    pub rule list() -> Vec<u32>
      = "[" l:number() ** "," "]" { l }
  }
}

pub fn main() {
    assert_eq!(list_parser::list("[1,1,2,3,5,8]"), Ok(vec![1, 1, 2, 3, 5, 8]));
}

See the tests for more examples
Grammar rule syntax reference in rustdoc

Comparison with similar parser generators

crate parser type action code integration input type precedence climbing parameterized rules streaming input
peg PEG in grammar proc macro (block) &str, &[T], custom Yes Yes No
pest PEG external proc macro (file) &str Yes No No
nom combinators in source library &[u8], custom No Yes Yes
lalrpop LR(1) in grammar build script &str No Yes No
Comments
  • Look into syntex to make the library work on 1.0 stable

    Look into syntex to make the library work on 1.0 stable

    $ git rev-parse --abbrev-ref HEAD ; git rev-parse HEAD
    master
    7a4ddb202cb457103827bab91a0bb2f745440b07
    
    $ cargo build
       Compiling peg v0.2.2 (file:///home/n/3p/github.com/kevinmehall/rust-peg)
    src/grammar.rs:4:5: 4:29 warning: use of deprecated item: use e.g. i32::from_str_radix, #[warn(deprecated)] on by default
    src/grammar.rs:4 use std::num::from_str_radix;
                         ^~~~~~~~~~~~~~~~~~~~~~~~
    src/grammar.rs:3970:73: 3970:94 warning: use of deprecated item: use e.g. i32::from_str_radix, #[warn(deprecated)] on by default
    src/grammar.rs:3970                                                                         from_str_radix::<u32>(match_str,
                                                                                                ^~~~~~~~~~~~~~~~~~~~~
    src/grammar.rs:4046:61: 4046:82 warning: use of deprecated item: use e.g. i32::from_str_radix, #[warn(deprecated)] on by default
    src/grammar.rs:4046                                                             from_str_radix::<u32>(match_str,
                                                                                    ^~~~~~~~~~~~~~~~~~~~~
    src/grammar.rs:4134:97: 4134:118 warning: use of deprecated item: use e.g. i32::from_str_radix, #[warn(deprecated)] on by default
    src/grammar.rs:4134                                                                                                 from_str_radix::<u32>(match_str,
                                                                                                                        ^~~~~~~~~~~~~~~~~~~~~
    src/grammar.rs:4271:145: 4271:166 warning: use of deprecated item: use e.g. i32::from_str_radix, #[warn(deprecated)] on by default
    src/grammar.rs:4271                                                                                                                                                 from_str_radix::<u32>(match_str,
                                                                                                                                                                        ^~~~~~~~~~~~~~~~~~~~~
    src/peg_syntax_ext.rs:1:1: 1:107 error: unstable feature
    src/peg_syntax_ext.rs:1 #![feature(plugin_registrar, quote, box_syntax, core, collections, rustc_private, box_patterns, str_char)]
                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    note: this feature may not be used in the beta release channel
    error: aborting due to previous error
    Could not compile `peg`.
    
    To learn more, run the command again with --verbose.
    
    $ rustc --version
    rustc 1.0.0-beta (9854143cb 2015-04-02) (built 2015-04-02)
    
    opened by nejucomo 19
  • Span capture with precedence climbing

    Span capture with precedence climbing

    When inside a precedence!{} block, if you define a rule like this:

    l:position!() lhs:(@) "+" rhs:@ r:position!() { /* ... */ }
    

    Instead of:

    lhs:(@) "+" rhs:@ { /* ... */ }
    

    It complains with the following error: `@` is only allowed in `precedence!{}`

    Span capture is useful when your grammar generates an AST, when each node should have source mapping information, that can be used when validating the semantics of the AST after parsing.

    opened by linkdd 10
  • infinite loop

    infinite loop

    When I try to use the following contents cargo test never returns:

    #![feature(plugin)]
    #![plugin(peg_syntax_ext)]
    
    peg! line(r#"
    
    #[pub]
    line -> Vec<&'input str>
      = line_parts* 
    
    line_parts -> &'input str
      = literal
      / command
    
    #[pub]
    literal -> &'input str
      = l:(!"$(" .)* { match_str }
    
    command -> &'input str
      = "$(" c:inside_command ")" { c }
    
    inside_command -> &'input str
      = [a-zA-Z0-9_-]+ { match_str }
    
    "#);
    
    #[test]
    fn main() {
      assert_eq!(line::literal("foo ").ok().unwrap(), "foo ");
      assert_eq!(line::literal("foo \n").ok().unwrap(), "foo \n");
      assert_eq!(line::line("foo $(a)").ok().unwrap(), vec!["foo ", "a"]);
    }
    

    I think the problem is using the .* expression.

    Edit: The example was simplified based on @jonas-schievink 's suggestions.

    opened by ihrwein 10
  • Error: Expected HashSet

    Error: Expected HashSet

    I'm hitting an error with rust-peg. It's expecting a newline in a statement that shouldn't need one:

    main.rs:56:1: 123:5 error: Error at Line 58:12: Expected HashSet {"\u{2029}", "\r\n", "\u{2028}", "\n", "\r"}
    main.rs:56 peg! dot(r#"
    main.rs:57 #[pub]
    main.rs:58 graph -> DotGraph
    main.rs:59  = __ "strict"? __ gt:GraphType __ id:ID? __ "{" __ stmts:stmt_list __ "}" __
    main.rs:60  {
    main.rs:61      DotGraph::new(id, gt, stmts)
               ...
    
    opened by alexchandel 9
  • Support for threading a context object through to action code

    Support for threading a context object through to action code

    Allow an object passed to the top-level parse call to be threaded through all parse functions and accessible to the action code.

    ~~~With a #![context(T)] at the top of the grammar source, all exposed parse functions gain an extra argument of type T, which is exposed to actions as the context variable~~~.

    Use cases: string interners, source mapping.

    feature 
    opened by kevinmehall 8
  • Add nested elements PEG example

    Add nested elements PEG example

    This example shows how to parse nested elements using enum. It's basically a very simple XML/HTML parser. The existing examples don't really show how to do this.

    opened by bartolsthoorn 8
  • Parsing f32 in a single rule

    Parsing f32 in a single rule

    I'm trying to describe this regex \d+(\.\d+)? within a single rule, so I can support floats. I can't figure out how to express this without creating an entirely separate rule.

    The primary issue seems to be the lack of expression groups, which would enable this: integer() ("." integer())?

    Without expression groups, I thought maybe a delimiter with a restriction of a single repetition (integer() ** . but limited to two elements).

    If there's an existing solution, that would be ideal.

    opened by khionu 7
  • Repeat expression that doesn't consume input should be a compile time error

    Repeat expression that doesn't consume input should be a compile time error

    I found this issue porting from 0.5.0 to 0.6.0.

    When I run my parser test, it get stuck in an infinite loop (ie it never terminate).

    This is the reduced test case:

    extern crate peg;
    
    peg::parser!{grammar p() for str {
    
    pub rule string_literal() -> String
            = "\"" s:$((!['"'])*) "\"" { println!("literal {}", s); s.to_owned() }
    
    }}
    
    fn main() {
    
        let r = p::string_literal("\"literal\"");
    
        if let Ok(l) = r {
            println!("Parsed {}", l);
        } else {
            println!("Parse failed {:?}", r);
        }
    }
    

    Expected:

    • either it doesn't compile because it's a syntax error (i.e. I'm doing the rule wrong with the update syntax)
    • or it is a parse error

    Instead it just get stuck when I cargo run.

    diagnostics 
    opened by hfiguiere 7
  • Expose pos_to_line to consumer code

    Expose pos_to_line to consumer code

    https://github.com/kevinmehall/rust-peg/blob/8098fab1515dc38ca25cdebda9b17655aa5554e1/src/translate.rs#L337

    It'd be great to be able to get the line and column of tokens (my AST diagnostics makes heavy use of this).

    Is this already exposed in some way?

    #position isn't quite what I'm looking as that is just the (byte?) offset into the source string.

    This is the only thing I have seen so far that is preventing me from moving from pest to rust-peg. pest exposes this via input().line_col().

    #85 is possibly related.

    Example grammar:

    peg! tsql_grammar(r#"
    use ast;
    
    whitespace0 = [ \t\r\n]*
    whitespace1 = [ \t\r\n]+
    
    #[pub]
    top -> ast::TopStatement
        = kw_top:$("top"i)
          whitespace1
          paren_open:tok_paren_open?
          whitespace0
          lit:lit_i32
          whitespace0
          paren_close:tok_paren_close? {
              if (paren_open.is_some() && paren_close.is_none()) ||
                 (paren_open.is_none() && paren_close.is_some()) {
                     return Err(ParseError {
                         // need to be able to create these fields
                     });
              }
    
              ast::TopStatement {
                  top_keyword_pos: ast::Position::from((1, 1)),
                  expr: ast::Node {
                      pos: ast::Position::from((1, 1)), // also need position (line, col) here
                      value: ast::Expression::Literal { lit: ast::Literal::Int(lit) },
                  },
    
                  paren_open: paren_open,
                  paren_close: paren_close,
              }
          }"#);
    
    opened by phrohdoh 7
  • Grammar ambiguity between {action} and {count}.

    Grammar ambiguity between {action} and {count}.

    Actions that consist of returning a single integer are ambiguous with the repetition count syntax introduced by #20.

    number -> u32
      = "one" {1}
      / "two" {2}
      / "three" {3}
    

    Those should be actions, but are parsed as repeat counts.

    One option that minimally solves the problem is to simply drop x {5} in favor of x {5, 5}. A bare comma is not valid Rust, but the distinction between actions and the remaining { , } forms may be hard for humans to parse.

    Does anyone have ideas for a new syntax for the bounded-repeat functionality?

    opened by kevinmehall 7
  • Matching Lua's

    Matching Lua's "long strings"

    I'm trying to write a parser that matches Lua's long string syntax. Basically, "[" followed by any number of "=" (including 0) followed by "[" opens the string, and "]" followed by the same number of "=" followed by "]" closes it.

    Examples of long strings:

    • [[simple long string]]
    • [=["level 1" long string]]this is still part of the string]==]as is this]=]

    I didn't come up with a parser that works, it's probably not even possible. This is what I currently have:

    mlstring_char -> char
        = [^\]] { match_str.char_at(0) }
    
    mlstring_inner -> String
        = "=" s:mlstring_inner "="      { s }
        / "[" chars:mlstring_char* "]"  { chars.into_iter().collect() }
    
    string -> String
        = "[" s:mlstring_inner "]" { s }
    

    This obviously doesn't work: Long strings end with the first "]" inside of them. If PEG wasn't greedy, I could just match any char inside mlstring_inner, but rust-peg doesn't seem to have any non-greedy mode. Another way to solve this would be to reference captured strings in the pattern (like some Regex implementations allow). That way, I could just capture "="* in the opening braces, and reference it in the closing brace. The match would only succeed if both strings are the same, ie. if both braces use the same number of "="s. The third way I've come up with is the most flexible solution: Run arbitrary rust code to determine if a rule should match. This way, I could just compare the number of "="s, and match the end of the long string if it has an equal number of "="s.

    Is this somehow possible without modifying rust-peg?

    question 
    opened by jonas-schievink 7
  • Support binding token literals in rules

    Support binding token literals in rules

    The tokens I'm using in my grammar include info like text range, line, column, etc. It would be nice if I could match some of these tokens via the literal syntax and bind the resulting token to a variable for use within the rule's action expression.

    Something like:

    rule foo() -> u32
        = t:"blah" { t.line }
    

    but when I try something like the above I get "cannot find value `t` in this scope".

    I can work around this in a couple ways right now:

    // I can use a rule like this:
    rule nt() -> Token<'input> = ##next_token()
    
    // using the undocumented ##member() syntax, with a suitable implementation on my impl Parser type:
    
    impl<'input> TokenSlice<'input> {
        pub fn next_token(&self, pos: usize) -> RuleResult<Token<'input>> {
            match self.tokens.get(pos) {
                Some(t) => RuleResult::Matched(pos, *t),
                _ => RuleResult::Failed,
            }
        }
    }
    
    // and now I can do like so:
    rule foo() -> u32
        = t:nt() "blah" { t.line }
    

    (the above is what I'm using for now)

    or

    // I could create rules for each token kind:
    rule BLAH() -> Token<'input>
        = token:[Token{ kind: TokenKind::Blah, .. }] { token }
    
    rule foo() -> u32
        = t:BLAH() { t.line }
    
    // But that gets tedious as I add new tokens, and I'd rather use the "blah" literal syntax instead of BLAH()
    
    opened by cstrahan-blueshift 1
  • Docs: add note on how to 'negate' rule

    Docs: add note on how to 'negate' rule

    Context

    I am writing a basic latex parser. For this I need to parse patterns such as: \textit{some text \texbft{some other text}}. I decided to recognize text by matching any character that is not syntax. With syntax I mean: \textit{ \textbf{and}`.

    "Problem"

    I was stuck on how to collect characters that are not syntax. Eventually I realized that putting a negative non consuming look-ahead in front of a match anything would get me any char that did not follow the rule.

    I now use:

    rule char() 
    = !(syntax() / eof()) c:[_] { c }
    

    This might be obvious to most users of rust-peg, I have limited exposure writing parsers.

    Solution

    I think a short example on how to match characters that do not follow some rule could be added to the docs under Pattern expressions. It would fit nicely after the idiom on matching <eof>

    Alternatively a dedicated test/example could work. I prefer the first as I think this is an idiom. I am not a domain expert however. I can imagine you want to keep the docs as short as possible. In that case a clearly named test could be a good alternative.

    Next steps

    Let me know what you think, I am more then happy to open a draft PR for one or both of these options. I will probably need some help to get the terminology correct.

    opened by dvdsk 2
  • Improve documentation and examples how to handle strings properly

    Improve documentation and examples how to handle strings properly

    The documentation only shows examples of parsing numbers and single characters. Almost all the tests also don't parse strings, which makes it hard to know what one needs to do, especially if one is a bit of a beginner in Rust and rust-peg.

    The information about the 'input lifetime annotation is a bit elusive (not documented), and it is not clear how this affects the lifetime annotations needed for any structs receiving the parsed str or Vec of str.

    It would also be great if there were some recommendations as to how strings should be parsed, and if zero-copy can be achieved in any way.

    Some proper documentation with a few examples of parsing singular or vec of strings (with operators such as ** and ++) would be really helpful.

    opened by jbx1 3
  • `&mut` rule argument doesn't work with `precedence!{}`

    `&mut` rule argument doesn't work with `precedence!{}`

    Minimal example:

        pub rule mut_prec(a: &mut ()) -> () = precedence! {
            "a" { a; () }
        }
    
    ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
    error[E0507]: cannot move out of `a`, a captured variable in an `Fn` closure
      --> $DIR/rule_args.rs:31:13
       |
    30 |     pub rule mut_prec(a: &mut ()) -> () = precedence! {
       |                       -                   ---------- captured by this `Fn` closure
       |                       |
       |                       captured outer variable
    31 |         "a" { a; () }
       |             ^^-^^^^^^
       |             | |
       |             | move occurs because `a` has type `&mut ()`, which does not implement the `Copy` trait
       |             move out of `a` occurs here
    ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
    

    Discussed in https://github.com/kevinmehall/rust-peg/discussions/312

    Originally posted by lfnoise July 17, 2022 I created a working parser for a non-trivial language syntax in a few hours, so that was pretty neat, thanks.

    I needed to pass a &mut symbol table struct down the tree of parsing rules. This worked fine for all but precedence climbing and left recursive rules. The left recursion gave me an error message that arguments weren't supported.. fair enough. Precedence climbing just wouldn't compile. It gave an error about not being able to capture a mutable in the rule closure and needing a FnMut instead of a Fn. Left recursion was easy to solve, but creating separate nested rules for a dozen levels of precedence by hand was not so nice. My parser works, but is not as simple it would be with the precedence! macro.

    Did I do something wrong? Is there a way to pass an argument down into the @ (next lower precedence rule) somehow? Here's the code. Thank you.

    opened by kevinmehall 0
  • Add a way to specify a parser stack limit

    Add a way to specify a parser stack limit

    TODO:

    • [ ] documentation
    • [ ] change placeholder STACK OVERFLOW expected string to something nicer
    • [ ] test failure case: non integer stack limit given

    This PR implements a new stack_limit directive in the meta grammar. When specified, the generated parser will keep track of rule invocation depth and error out when the depth is beyond the specified maximum.

    I'm not married to any of the naming and syntax here, feel free to suggest better alternatives.

    A better way of raising errors from this might be to introduce a new RuleResult variant that immediately terminates parsing instead of carrying on with alternatives. I think that's a great future improvement, but didn't consider for this PR because it would expand the scope quite a bit.

    Fixes #282. This PR depends on #307.

    opened by zsol 1
  • Bootstrap-Based Cargo `fmt`

    Bootstrap-Based Cargo `fmt`

    This PR introduces the following changes:

    • replaces the rustfmt with a project wide cargo fmt
    • updates missing formatted source code files from the path peg-macros

    Background of this PR:

    • I've noticed that some files are not corresponding to the rust format and I want to provide some additions and changes to your project in the near future and in order to keep the change set at minimal level IMHO the current master state should be updated.
    opened by ppaulweber 0
Releases(0.8.1)
  • 0.8.1(Sep 26, 2022)

    Fixes

    • Fix type inference for generic argument in rule's return position (#317)
    • Fix parsing of &'a mut T in type grammar (#304)

    Improvements

    • Made LineCol Copy (#298)

    Contributors

    @kevinmehall @plaflamme @zsol @Kile-Asmussen @kw217

    Source code(tar.gz)
    Source code(zip)
  • 0.8.0(Jan 4, 2022)

    New Features

    • #[cache_left_rec] annotation to allow left recursion (#266)
    • Return matched token/character from [ ] pattern expression (#234)

    Fixes

    • Fix Rust grammar for arguments (#261) and type bounds (#279)
    • Fix trace feature when using infix!{} (#277)
    • Fix #[cache] with grammar lifetime parameters
    • Allow clippy::redundant_closure_call lint in generated grammar (#258)

    Breaking changes

    Most users will not require changes to upgrade from 0.7 to 0.8; these only affect advanced use cases.

    • Allow only lifetime, not type, parameters at the grammar level. (type parameters were never properly supported)
    • Add 'input lifetime parameter to ParseElem trait so implementations can return tokens by reference. (#268)
    • Require Copy on ParseElem::Element to better represent the expectation that they are cheap to copy/move.

    Contributors: @kevinmehall @zsol @neunenak @fgasperij

    Source code(tar.gz)
    Source code(zip)
  • 0.7.0(Apr 10, 2021)

    New features

    • Significantly improved compile-time error messages for invalid grammars
    • Support [MyToken(x)] syntax for capturing variables from pattern expressions (#245)
    • Restore support for [^ ] inverted pattern syntax
    • Add #[no_eof] pub rule() = ... syntax to allow matching a prefix of the input rather than reporting a parse error if the rule does not reach end-of-file (#233)
    • Allow rule _ = without parentheses when defining special underscore rule (#243)
    • Add grammar-level type and lifetime parameters (#254)
    • Compile-time check for repeat expressions that infinite-loop without consuming input (#210)
    • Implement PartialEq, PartialOrd, Eq, Ord, Debug, Hash for RuleResult (#217)

    Fixes

    • Extend detection of infinite-loop left recursion to check inside precedence!() (#238)
    • Wrap user-supplied code in immediately-invoked closure so that return and ? behave as expected (#246)
    • Remove overzealous error checks to allow passing rule closure arguments as parameters to another call (#226)

    Breaking changes

    • Add required is_eof() method to Parse trait (#252)
    • Certain patterns that would infinite-loop or stack overflow if executed are now a compile-time error
    • mixed_site hygiene prevents action code from accessing internal parser state variables such as __input, __pos, etc.

    Contributors

    @kevinmehall @dario23 @bgw @adrianwn

    Source code(tar.gz)
    Source code(zip)
  • 0.6.3(Jul 22, 2020)

  • 0.6.2(Feb 15, 2020)

  • 0.6.1(Jan 18, 2020)

    • Use fully qualified Result path to avoid problems if Result is shadowed (#214)
    • Update to 2018 edition for more consistent behavior when the peg name is shadowed
    • Allow crate-relative imports in grammars (#213)
    • Documentation improvements
    • Fix rule arguments on pub rule
    • Forbid #[cache] on rules with arguments

    Contributors: @dario23 @kevinmehall

    Source code(tar.gz)
    Source code(zip)
  • 0.6.0(Oct 6, 2019)

    Major improvements

    • Replaced build script integration and nightly-only syntax extension with a procedural macro that works on stable Rust. This means that errors both in the PEG grammar and the Rust code embedded from it are reported with source position by rustc. It even works with RLS!
    • Add the ability to parse non-str input by implementing traits. It comes with an implementation for [T] (including [u8]), but you can define the traits for your own types. In fact, the rust-peg grammar is parsed with rust-peg via an implementation for token trees from proc-macro2.
    • Add precedence!{} block for adding a precedence-climbing expression parser integrated with the surrounding PEG source.
    • Report errors in left-recursive rules that would cause infinte loops.
    • Allow rules to accept value and type parameters, including passing closures to replace the template syntax.
    • Significant performance improvement for input that parses successfully by deferring error handling until parsing has failed.

    Upgrade from 0.5.x

    1. Remove peg = "0.5" from [build_dependencies] in Cargo.toml, and add peg = "0.6" under [dependencies].
    2. If nothing else is in build.rs, delete it and remove build = "build.rs" from Cargo.toml
    3. If using the 2015 edition of Rust, add extern crate peg; to your crate root.
    4. Move your grammar from a separate .rustpeg file into a Rust source file. Remove the mod somename { include!(...) } and replace it with:
    peg::parser!{grammar somename() for str {
        // grammar goes here
    }}
    
    1. Add the rule keyword and parentheses to rule declarations.
      • foo = ... becomes rule foo() = ...
      • pub bar -> X = ... becomes pub rule bar() -> X = ....
    2. Add parentheses to expressions that invoke another rule.
      • name:ident becomes name:ident().
    3. Replace the character set syntax with the pattern matching syntax.
      • [a-zA-Z] becomes ['a'..='z' | 'A'..='Z'].
      • [^X] becomes (!['X'][_]) -- the inverted character set syntax was removed, but can be substituted with a negative lookahead followed by [_] to match and consume the character.
    4. If your grammar used templates, replace them with rule arguments.
    5. Replace
      • . with [_].
      • #position with position!()
      • #quiet<e> with quiet!{e}
      • #expected("foo") with expected!("foo").
    Source code(tar.gz)
    Source code(zip)
  • 0.5.7(Oct 6, 2018)

    • Use ? instead of try!() for compatibility with Rust 2018.
    • Add support for dyn and impl in rule return types
    • Fix peg-syntax-ext for changes in Rust nightly (0.6 will replace peg-syntax-ext with a proc-macro for stable Rust)
    Source code(tar.gz)
    Source code(zip)
  • 0.5.6(Aug 21, 2018)

  • 0.5.5(Dec 16, 2017)

  • 0.5.4(Jun 24, 2017)

  • 0.5.3(May 9, 2017)

  • 0.5.2(Apr 29, 2017)

  • 0.5.1(Jan 29, 2017)

  • 0.5.0(Jan 15, 2017)

    Changes

    • Change #[pub] rule_name = ... syntax to pub rule_name = .... The old syntax is retained for backwards compatibility, but pub is now a reserved keyword and cannot be used as an identifier.

    New features

    • Add rule templates
    • Add experimental #infix syntax for parsing binary infix expressions by precedence climbing.
    • Allow delimited-repeat with range bounds **<n,m>.
    • Add x*<{count}> syntax for a repeat bounded by a Rust expression.
    • Add #quiet<e> and #expected("msg") expressions for improved error reporting.
    • Allow as in use statements to match Rust syntax.

    Fixes

    • Fix a bug in error reporting of & and ! expressions.
    • Avoid type errors if a rule returns a result, but the result is not used.
    • Error when using a nonexistent rule, rather than generating Rust code that doesn't compile.
    Source code(tar.gz)
    Source code(zip)
  • 0.4.0(Nov 20, 2016)

    Migrating from 0.3

    • If you were using the syntax extension, replace peg = "0.3.0" with peg-syntax-ext = "0.4.0" in your Cargo.toml's [dependencies] section. The library name in #![plugin(peg_syntax_ext)] remains the same. Consider moving to the build script for compatibility with Rust stable.
    • The match_str variable has been removed in favor of the $(expr) syntax. Replace [0-9]+ { match_str.parse().unwrap() } with n:$([0-9]+) { n.parse().unwrap() }
    • start_pos and pos variables have been removed. Use #position as an expression, which returns a usize offset into the source string. Replace foo:x { Span(start_pos, pos, foo) } with start:#position foo:x end:#position { Span(start, end, foo) }
    • The \u2029 unicode hex escape syntax has been removed, as it has long-since been removed from Rust. Use \u{2029} instead.
    • The previously-undocumented foo{x,y} bounded-repeat syntax was replaced with foo*<x,y> to avoid a grammar ambiguity (#74).
    Source code(tar.gz)
    Source code(zip)
Owner
Kevin Mehall
Kevin Mehall
LR(1) grammar parser of simple expression

LR(1)语法分析程序 实验内容 编写LR(1)语法分析程序,实现对算术表达式的语法分析。要求所分析算数表达式由如下的文法产生: E -> E+T | E-T | T T -> T*F | T/F | F F -> (E) | num 程序设计与实现 使用方式:运行.\lr1-parser.exe

Gao Keyong 1 Nov 24, 2021
PEG parser for YAML written in Rust 🦀

yaml-peg PEG parser (pest) for YAML written in Rust ?? Quick Start ⚡️ # Run cargo run -- --file example_files/test.yaml # Output { "xmas": "true",

Visarut Phusua 4 Sep 17, 2022
PEG parser combinators using operator overloading without macros.

pom PEG parser combinators created using operator overloading without macros. Document Tutorial API Reference Learning Parser Combinators With Rust -

Junfeng Liu 412 Dec 31, 2022
Yet Another Parser library for Rust. A lightweight, dependency free, parser combinator inspired set of utility methods to help with parsing strings and slices.

Yap: Yet another (rust) parsing library A lightweight, dependency free, parser combinator inspired set of utility methods to help with parsing input.

James Wilson 117 Dec 14, 2022
Extensible inline parser engine, the backend parsing engine for Lavendeux.

Lavendeux Parser - Extensible inline parser engine lavendeux-parser is an exensible parsing engine for mathematical expressions. It supports variable

Richard Carson 10 Nov 3, 2022
A parser combinator for parsing &[Token].

PickTok A parser combinator like nom but specialized in parsing &[Token]. It has similar combinators as nom, but also provides convenient parser gener

Mikuto Matsuo 6 Feb 24, 2023
Rust grammar tool libraries and binaries

Grammar and parsing libraries for Rust grmtools is a suite of Rust libraries and binaries for parsing text, both at compile-time, and run-time. Most u

Software Development Team 318 Dec 26, 2022
Parse BNF grammar definitions

bnf A library for parsing Backus–Naur form context-free grammars. What does a parsable BNF grammar look like? The following grammar from the Wikipedia

Shea Newton 188 Dec 26, 2022
LR(1) parser generator for Rust

LALRPOP LALRPOP is a Rust parser generator framework with usability as its primary goal. You should be able to write compact, DRY, readable grammars.

null 2.4k Jan 7, 2023
An LR parser generator, implemented as a proc macro

parsegen parsegen is an LR parser generator, similar to happy, ocamlyacc, and lalrpop. It currently generates canonical LR(1) parsers, but LALR(1) and

Ömer Sinan Ağacan 5 Feb 28, 2022
Website for Microformats Rust parser (using 'microformats-parser'/'mf2')

Website for Microformats Rust parser (using 'microformats-parser'/'mf2')

Microformats 5 Jul 19, 2022
A Rust library for zero-allocation parsing of binary data.

Zero A Rust library for zero-allocation parsing of binary data. Requires Rust version 1.6 or later (requires stable libcore for no_std). See docs for

Nick Cameron 45 Nov 27, 2022
Parsing and inspecting Rust literals (particularly useful for proc macros)

litrs: parsing and inspecting Rust literals litrs offers functionality to parse Rust literals, i.e. tokens in the Rust programming language that repre

Lukas Kalbertodt 31 Dec 26, 2022
Rust library for parsing configuration files

configster Rust library for parsing configuration files Config file format The 'option' can be any string with no whitespace. arbitrary_option = false

The Impossible Astronaut 19 Jan 5, 2022
A Rust crate for RDF parsing and inferencing.

RDF-rs This crate provides the tools necessary to parse RDF graphs. It currently contains a full (with very few exceptions) Turtle parser that can par

null 2 May 29, 2022
rbdt is a python library (written in rust) for parsing robots.txt files for large scale batch processing.

rbdt ?? ?? ?? ?? rbdt is a work in progress, currently being extracted out of another (private) project for the purpose of open sourcing and better so

Knuckleheads' Club 0 Nov 9, 2021
A Rust crate for hassle-free Corosync's configuration file parsing

corosync-config-parser A Rust crate for hassle-free Corosync's configuration file parsing. Inspired by Kilobyte22/config-parser. Usage extern crate co

Alessio Biancalana 2 Jun 10, 2022
This crate provide parsing fontconfig file but not yet complete all features

This crate provide parsing fontconfig file but not yet complete all features

null 4 Dec 27, 2022
A native Rust port of Google's robots.txt parser and matcher C++ library.

robotstxt A native Rust port of Google's robots.txt parser and matcher C++ library. Native Rust port, no third-part crate dependency Zero unsafe code

Folyd 72 Dec 11, 2022