<div align="center">
<h1><code>reed-parser</code></h1>
<img src="https://raw.githubusercontent.com/Necrass-Dev/NecrassRs/main/logo/reed.svg" alt="Reed logo" width="180">
<p>
<strong>A parser for the GraphQL language.</strong>
</p>
<p>
<a href="https://crates.io/crates/reed-parser">
<img src="https://img.shields.io/crates/v/reed-parser.svg?style=flat-square" alt="Crates.io version" />
</a>
<a href="https://crates.io/crates/reed-parser">
<img src="https://img.shields.io/crates/d/reed-parser.svg?style=flat-square" alt="Download" />
</a>
<a href="https://docs.rs/reed-parser/">
<img src="https://img.shields.io/static/v1?label=docs&message=reed-parser&color=blue&style=flat-square" alt="docs.rs docs" />
</a>
</p>
</div>
## Features
* Typed GraphQL concrete syntax tree
* Error resilience
* lexing and parsing does not fail or `panic` if a lexical or a syntax error is found
* GraphQL lexer
* GraphQL parser
## Getting started
Add the dependency to start using `reed-parser`:
```bash
cargo add reed-parser
```
Or add this to your `Cargo.toml` for a manual installation:
```toml
# Just an example, change to the necessary package version.
[dependencies]
reed-parser = "0.1.0"
```
## Rust versions
`reed-parser` is tested on the latest stable version of Rust.
Older version may or may not be compatible.
## Usage
`reed-parser` parses GraphQL schemas and executable documents into a typed syntax
tree that can be walked to extract the required information. You can quick start
with:
```rust
use reed_parser::Parser;
let cst = parser.parse();
```
`reed-parser` is built to be error-resilient. This means we don't abort parsing (or lexing) if an error occurs. That means `parser.parse()` will always produce a CST (Concrete Syntax Tree), and it will be accompanied by any errors that are encountered:
```rust
use reed_parser::Parser;
let cst = parser.parse();
// cst.errors() returns an iterator with the errors encountered during lexing and parsing
assert_eq!(0, cst.errors().len());
// cst.document() gets the Document, or root node, of the tree that you can
// start iterating on.
let doc = cst.document();
```
### Examples
Two examples outlined here:
* [Get field names in an object]
* [Get variables used in a query]
The [examples directory] in this repository has a few more useful
implementations such as:
* [using apollo-rs with miette to display error diagnostics]
* [using apollo-rs with annotate_snippets to display error diagnostics]
* [checking for unused variables]
#### Get field names in an object
```rust
use reed_parser::{cst, Parser};
let input = "
type ProductDimension {
size: String
weight: Float @tag(name: \"hi from inventory value type field\")
}
";
let parser = Parser::new(input);
let cst = parser.parse();
assert_eq!(0, cst.errors().len());
let doc = cst.document();
for def in doc.definitions() {
if let cst::Definition::ObjectTypeDefinition(object_type) = def {
assert_eq!(object_type.name().unwrap().text(), "ProductDimension");
for field_def in object_type.fields_definition().unwrap().field_definitions() {
println!("{}", field_def.name().unwrap().text()); // size weight
}
}
}
```
#### Get variables used in a query
```rust
use reed_parser::{cst, Parser};
let input = "
query GraphQuery($graph_id: ID!, $variant: String) {
service(id: $graph_id) {
schema(tag: $variant) {
document
}
}
}
";
let parser = Parser::new(input);
let cst = parser.parse();
assert_eq!(0, cst.errors().len());
let doc = cst.document();
for def in doc.definitions() {
if let cst::Definition::OperationDefinition(op_def) = def {
assert_eq!(op_def.name().unwrap().text(), "GraphQuery");
let variable_defs = op_def.variable_definitions();
let variables: Vec<String> = variable_defs
.iter()
.map(|v| v.variable_definitions())
.flatten()
.filter_map(|v| Some(v.variable()?.text().to_string()))
.collect();
assert_eq!(
variables.as_slice(),
["graph_id".to_string(), "variant".to_string()]
);
}
}
```
## License
Licensed under either of
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or <https://www.apache.org/licenses/LICENSE-2.0>)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or <https://opensource.org/licenses/MIT>)
at your option.
## Upstream provenance
Reed Parser 0.1.0 is derived from Apollo Parser 0.8.6 at upstream revision
[`e36ca6dceb668b4b0c703449beea39e75c16ead5`](https://github.com/apollographql/apollo-rs/tree/e36ca6dceb668b4b0c703449beea39e75c16ead5/crates/apollo-parser).
The source corrections used to establish Reed are maintained in this crate and
its regression tests. Package naming, documentation paths, fixture discovery,
source item order needed by workspace lints, and regression tests are adapted
for the Reed package; the parser module organization is retained. The
restored upstream fixture corpus reclassifies operation descriptions and empty
selection sets and updates Unicode diagnostics to match the maintained September
2025 language corrections.
[apollo-rs: spec-compliant GraphQL Tools in Rust]: https://www.apollographql.com/blog/announcement/tooling/apollo-rs-graphql-tools-in-rust/
[examples directory]: https://github.com/apollographql/apollo-rs/tree/main/crates/apollo-parser/examples
[Get field names in an object]: https://github.com/apollographql/apollo-rs#get-field-names-in-an-object
[Get variables used in a query]: https://github.com/apollographql/apollo-rs#get-variables-used-in-a-query
[using apollo-rs with miette to display error diagnostics]: https://github.com/apollographql/apollo-rs/blob/a7f616454a53dcb8496725ceac6c63eacddefb2c/crates/apollo-parser/examples/miette.rs
[using apollo-rs with annotate_snippets to display error diagnostics]: https://github.com/apollographql/apollo-rs/blob/a7f616454a53dcb8496725ceac6c63eacddefb2c/crates/apollo-parser/examples/annotate_snippet.rs
[checking for unused variables]: https://github.com/apollographql/apollo-rs/blob/a7f616454a53dcb8496725ceac6c63eacddefb2c/crates/apollo-parser/examples/unused_vars.rs
[October 2021 specification]: https://spec.graphql.org/October2021