<p align="center">
<img src="assets/logo.svg" alt="surql-parser" width="120" />
</p>
<h1 align="center">surql-parser</h1>
<p align="center">
Standalone SurrealQL parser extracted from <a href="https://surrealdb.com">SurrealDB</a>.<br/>
Parse SurrealQL queries into an AST without depending on the SurrealDB engine.
</p>
<p align="center">
<a href="https://github.com/overrealdb/surql-parser/actions/workflows/ci.yml"><img src="https://github.com/overrealdb/surql-parser/actions/workflows/ci.yml/badge.svg" alt="CI" /></a>
<a href="https://github.com/overrealdb/surql-parser/actions/workflows/security.yml"><img src="https://github.com/overrealdb/surql-parser/actions/workflows/security.yml/badge.svg" alt="Security" /></a>
<a href="https://crates.io/crates/surql-parser"><img src="https://img.shields.io/crates/v/surql-parser.svg" alt="crates.io" /></a>
<a href="https://docs.rs/surql-parser"><img src="https://docs.rs/surql-parser/badge.svg" alt="docs.rs" /></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-blue.svg" alt="License" /></a>
</p>
## Use Cases
- Migration tools and schema analyzers
- Linters and formatters for `.surql` files
- IDE extensions (Zed, VS Code) with syntax analysis
- Code generation from SurrealQL definitions
- CI validation of SurrealQL files
## Quick Start
```rust
use surql_parser::parse;
let ast = parse("SELECT name, age FROM user WHERE age > 18 ORDER BY name").unwrap();
assert_eq!(ast.expressions.len(), 1);
```
### Parse DDL
```rust
let ast = surql_parser::parse(
"DEFINE FUNCTION fn::greet($name: string) { RETURN 'Hello, ' + $name; }"
).unwrap();
```
### Parse type annotations
```rust
let kind = surql_parser::parse_kind("option<record<user>>").unwrap();
```
### Extract schema definitions
```rust
let defs = surql_parser::extract_definitions("
DEFINE TABLE user SCHEMAFULL;
DEFINE FIELD name ON user TYPE string;
DEFINE FIELD age ON user TYPE int DEFAULT 0;
DEFINE INDEX email_idx ON user FIELDS email UNIQUE;
DEFINE FUNCTION fn::greet($name: string) { RETURN 'Hello, ' + $name; };
").unwrap();
assert_eq!(defs.tables.len(), 1);
assert_eq!(defs.fields.len(), 2);
assert_eq!(defs.indexes.len(), 1);
assert_eq!(defs.functions.len(), 1);
```
### Check reserved keywords
```rust
assert!(surql_parser::is_reserved_keyword("SELECT"));
assert!(!surql_parser::is_reserved_keyword("username"));
```
## Compile-Time Tools
### `surql-macros` — proc-macro crate
Validate SurrealQL at compile time:
```toml
[dependencies]
surql-macros = "0.1"
```
```rust
use surql_macros::{surql_check, surql_function};
// Compile-time validated query — typo here is a compile error
const QUERY: &str = surql_check!("SELECT * FROM user WHERE age > 18");
// Compile-time validated function name
#[surql_function("fn::get_user")]
fn get_user_call(id: &str) -> String {
format!("fn::get_user('{id}')")
}
```
Errors show both the SurrealQL location and the Rust source location:
```
error: Invalid SurrealQL: Unexpected token `WHERE`, expected FROM
--> [1:10]
|
```
### `build.rs` helper (feature `build`)
Validate `.surql` files and generate typed constants at build time:
```toml
[build-dependencies]
surql-parser = { version = "0.1", features = ["build"] }
```
```rust
// build.rs
fn main() {
let out_dir = std::env::var("OUT_DIR").unwrap();
surql_parser::build::validate_schema("surql/");
surql_parser::build::generate_typed_functions(
"surql/",
format!("{out_dir}/surql_functions.rs"),
);
}
```
This generates constants like `FN_GET_USER: &str = "fn::get_user"` with doc comments showing parameter types and return types. See `examples/sample-project/` for a complete working example.
## CLI Tool
```sh
cargo install surql-parser --features cli
surql check schema/**/*.surql # validate .surql files
surql schema schema/ # extract full schema
surql fmt file.surql # format SurrealQL
surql functions schema/ # list fn::* definitions
surql tables schema/ # list table definitions
```
## Testing
```sh
cargo test # parser tests (instant)
cargo test --features build # + build helper tests
cargo test -p surql-macros # proc-macro tests (trybuild)
cargo test -p surql-sample-project # e2e: build.rs + macros
cargo test --features validate-mem # + in-memory SurrealDB
cargo test --features validate-docker # + real SurrealDB in Docker
```
Validation deps (surrealdb, testcontainers) are dev-dependencies only — they don't leak to library consumers.
## SurrealDB Compatibility
| 0.1.x | 3.x | Active |
Parser source is auto-synced from SurrealDB via an automated pipeline. See [UPSTREAM_SYNC.md](UPSTREAM_SYNC.md) for details.
## How It Works
The parser source code is **extracted from SurrealDB** using an AST-level Rust transformer (`tools/transform/`). This ensures 100% compatibility with SurrealDB's parser while removing engine-specific execution code.
The sync pipeline:
1. Copies `syn/` (lexer, parser) and `sql/` (AST types) from SurrealDB source
2. Rewrites imports via declarative rules (`mappings.toml`)
3. Strips execution-layer code (318 impl blocks removed automatically)
4. Validates compilation
## License
Apache 2.0 — same as SurrealDB.