1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//! Parce is a parser and lexer generator, where the grammar and the parse tree are the same
//! data structure. It is similar to ANTLR, but the grammar is written in Rust code, not a
//! special DSL.
//!
//! # Quick Links to Documentation
//!
//! If you're new to Parce, read the example below, then go to these links to learn more.
//!
//! - [Lexer Attribute Macro](parce_macros::lexer)
//! - [Parser Attribute Macro](parce_macros::parser)
//! - [Lexer Trait](crate::lexer::Lexer)
//! - [Parse Trait](crate::parser::Parse)
//!
//! # Basic Example
//!
//! Parce is used in three steps:
//! - Create a lexer
//! - Create a parser that uses the lexer
//! - Parse things with the parser!
//!
//! ## Creating a lexer
//!
//! A lexer is a single enum with the [lexer attribute macro](macro@parce_macros::lexer) applied to it. Rules for each
//! lexeme are written as a string literal discriminant which get turned into matching logic by the
//! macro. The example below is just to give you a feel for the syntax; the real docs for lexer creation
//! are under the [lexer attribute macro](macro@parce_macros::lexer).
//!
//! ```
//! use parce::prelude::*;
//!
//! #[lexer(MyLexer)]
//! enum MyLexemes {
//! Bool = " 'true' | 'false' ", // match string literals, use | for multiple possible patterns
//! Digit = "[0-9]", // use Regex-like character classes
//! And = '&', // can omit double quotes if pattern is a single character
//! #[skip] Whitespace = "[ \n\r\t]" // skippable lexemes
//! }
//!
//! // The macro generates an enum "MyLexer" that implements the Lexer trait.
//! ```
//!
//! ## Creating a parser
//!
//! A parser is a collection of enums with the [parser attribute macro](macro@parce_macros::parser) applied to it.
//! Each enum is a grammar rule, and the variants of the enum are productions. Again, the rules for
//! each production are written as a string literal discriminant which is processed by the parser macro.
//! The example below is just to give you a feel for the syntax; the real docs for parser creation are
//! under the [parser attribute macro](macro@parce_macros::parser).
//!
//! TODO after left-recursion rewriting
//!
//! # Features
//!
//! ## Lexer Features
//!
//! - Regex-like repetition operators
//! - The usual `*`, `+`, and `?`
//! - And also `{n}` (exactly n), `{n,}` (n or more), and `{n,m}` (between n and m inclusive) <- ANTLR doesn't have those :)
//! - Lexeme nesting
//! - Regex-like character classes
//! - Skipped lexemes
//! - Fragment lexemes
//! - Modal lexers
//! - unlike ANTLR, lexemes can be active in multiple modes
//!
//! ## Parser Features
//!
//! # Comparison to ANTLR
//!
//! Since Parce and ANTLR serve very similar purposes, here are the pros and cons of using Parce over ANTLR:
//!
//! **Pros:**
//! - Parce operates directly on the syntax tree enums that you create. ANTLR generates it's own
//! tree, and if you don't want to use that one, you have to convert it to your own.
//! - Rust's enums make Parce's usage more intuitive for people who are unfamiliar with ANTLR.
//! - ANTLR currently doesn't have a stable Rust target.
//!
//! **Cons:**
//! - ANTLR's runtime performance is faster.
//! - I haven't actually benchmarked it, but Parce is extremely unlikely to be faster, given how
//! much smarter the ANTLR devs are than me ;)
//! - ANTLR's grammars are language-independent, as long as you don't embed code in your grammars.
//! - ANTLR has more features.
//! - Mixed lexer/parse grammars.
//! - (there are others, but I don't know what they are off the top of my head.)
//!
//! # Future plans
//!
//! - Semantic predicates
//! - left-recursive grammar re-writing like ANTLR, using semantic predicates
//! - Data post-processors
//! - multi-threaded lexing and parsing.
//!
//! # Contributing
//!
//! If you find a bug or want a new feature, please create an issue or pull request on [GitHub](https://github.com/JoelCourtney/parce)!