| Crates.io | rowan-peg |
| lib.rs | rowan-peg |
| version | 0.2.9 |
| created_at | 2025-09-12 09:03:22.097062+00 |
| updated_at | 2025-09-18 15:37:52.963695+00 |
| description | Convert ABNF like grammar to rust-peg build `rowan` lossless syntax tree |
| homepage | |
| repository | https://github.com/A4-Tacks/rowan-peg-rs |
| max_upload_size | |
| id | 1835381 |
| size | 65,594 |
Convert ABNF like grammar to rust-peg build rowan lossless syntax tree
Using rowan library lossless syntax tree
Add dependencies:
char-classes = "0.3.4"
peg = "0.8.5"
rowan = "0.15.15"
rowan-peg-utils = "0.2.3"
Edit your grammar declaration:
exports [ pair-list ]
pair-list = whitespace *pair
pair = key whitespace "=" whitespace val whitespace
key = text
val = number / text
number = int ["." int]
int = $(+<0-9>) @int ; Add `int` to the expected set when parsing fails
text = $(+<a-zA-Z_->) @text
whitespace = $(*< \t\r\n>)
Generate grammar from your grammar declaration:
rowan-peg your-lang.abnf > src/grammar.rs
If you want to use cargo to build grammar, you can use rowan-peg-macro
#[rowan_peg_macro::build(path = "grammar.abnf")]
mod grammar {}
A simple json parser example-json
cd examples/example-json
cargo run -- example.json
[examples/example-json/src/main.rs:23:5] &json = JsonText(
JSON_TEXT@0..476
WS@0..0 ""
VALUE@0..476
OBJECT@0..476
BEGIN_OBJECT@0..6
WS@0..0 ""
L_CURLY@0..1 "{"
WS@1..6 "\n "
MEMBER@6..136
STRING@6..15
QUOTATION_MARK@6..7 "\""
CHAR@7..8
UNESCAPED@7..8 "s"
CHAR@8..9
UNESCAPED@8..9 "t"
CHAR@9..10
...
...
cargo run -- examples/example-json/json.abnf
Export or rename rules using exports []
Such as exports [ foo ], export foo rule (public it)
Such as exports [ bar = foo ], export bar rule (public and renamed into bar)
Define a rule using my-rule = "rule"
When a rule belongs to the following situations, it is a token rule:
rule body only exist a slice and optional expected
such as: a = $"x", a = $("a" ["b"]), a = $("a" ["b"]) @a
Hard matched content cannot be escaped, such as "a" "+"
{name}_kw, such as "if" -> if_kw"!" -> bang[!NOTE] Because it cannot be escaped, double quotes are represented by
<">
Match a some of characters or character ranges, can only be used in slice
Escaping equivalent rust string-literal
Syntax equivalent char-classes::any!() macro
Such as <a-z> matches lowercase alpha, <^0-9> matches non number
Collect any parsing range as a token, must be used in token rule
Such as: a-or-ab = $("a" ["b"]), it can parsing a, ab
Sequential choice, from PEG
Such as: x = "a" "b" / "c", it can parser ab, c
When a branch fails, it will return to the beginning to try parsing the next branch
If no branch is successful, the this rule fails
Repeat parsing specified number of times
+x: Repeat x 1 to more times
*x: Repeat x 0 to more times
233*x: Repeat x 233 to more times
*6x: Repeat x 0 to 6 times
2*6x: Repeat x 2 to 6 times
6x: Repeat x 6 times
6(x y): Repeat x y 6 times
Positive lookahead and Negative lookahead, from PEG
Positive lookahead: Parsing, but success also returns to the beginning, which is a non consumption parsing
Negative lookahead: Similar to positive lookahead, but fails upon success and succeeds upon failure
Map to rust-peg quiet! {}, will not add any expecteds from the target to the error message
Such as: x = "x" ~" " "y", quiet space token expecteds message
Use semicolons for comment, such as:
x = "a" ; this is a comment