forgedb_parser/lib.rs
1//! ForgeDB Parser
2//!
3//! Parser and lexer for ForgeDB's schema definition language.
4//!
5//! # Overview
6//!
7//! This crate provides parsing capabilities for ForgeDB's schema language, converting
8//! schema files (.forge) into an Abstract Syntax Tree (AST) that can be used for code
9//! generation, validation, and other tooling.
10//!
11//! # Architecture
12//!
13//! The parser is implemented as a traditional two-stage compiler frontend:
14//!
15//! 1. **Lexer** - Tokenizes input source code into a stream of tokens
16//! 2. **Parser** - Converts token stream into an Abstract Syntax Tree (AST)
17//!
18//! ## Supported Constructs
19//!
20//! - **Models** - Database table definitions with fields and constraints
21//! - **Structs** - Composite data types
22//! - **Fields** - Typed fields with constraints
23//! - **Constraints** - Directive validation rules (@email, @min, @pattern, etc.)
24//! - **Relations** - Model relationships (`[Model]`, `*Model`, `?Model`)
25//! - **Components** - Reusable field groups with protocols
26//!
27//! # Examples
28//!
29//! ## Parsing a Schema File
30//!
31//! ```rust
32//! use forgedb_parser::Parser;
33//!
34//! let source = r#"
35//! User {
36//! id: +uuid
37//! email: &string @email
38//! age: i32 @min(18)
39//! }
40//! "#;
41//!
42//! // Parser::new returns Result<Parser, String>
43//! let mut parser = Parser::new(source).expect("parse error");
44//! match parser.parse() {
45//! Ok(schema) => {
46//! println!("Parsed {} models", schema.models.len());
47//! for model in &schema.models {
48//! println!("Model: {}", model.name);
49//! }
50//! }
51//! Err(error) => {
52//! eprintln!("Parse error: {}", error);
53//! }
54//! }
55//! ```
56//!
57//! ## Working with the AST
58//!
59//! ```rust
60//! use forgedb_parser::{Parser, Model, FieldType};
61//!
62//! let source = r#"
63//! Post {
64//! id: +uuid
65//! title: string
66//! content: string
67//! }
68//! "#;
69//!
70//! let mut parser = Parser::new(source).expect("parse error");
71//! let schema = parser.parse().unwrap();
72//!
73//! for model in &schema.models {
74//! println!("Model: {}", model.name);
75//! for field in &model.fields {
76//! println!(" Field: {} : {:?}", field.name, field.field_type);
77//! }
78//! }
79//! ```
80//!
81//! ## Tokenization
82//!
83//! ```rust
84//! use forgedb_parser::{Lexer, Token};
85//!
86//! let source = "User { id: +uuid }";
87//! let mut lexer = Lexer::new(source);
88//!
89//! // Lexer::tokenize() collects all tokens into a Vec
90//! let tokens: Vec<Token> = lexer.tokenize().expect("lex error");
91//! println!("Tokenized into {} tokens", tokens.len());
92//! ```
93//!
94//! # Public API
95//!
96//! ## Core Types
97//!
98//! - [`Parser`] - Main parser interface
99//! - [`Lexer`] - Tokenizer for schema source code
100//! - [`Schema`] - Root AST node containing all definitions
101//!
102//! ## AST Nodes
103//!
104//! - [`Model`] - Database table definition
105//! - [`Struct`] - Composite data type
106//! - [`Field`] - Field definition with type and constraints
107//! - [`FieldType`] - Field data type (i32, string, uuid, etc.)
108//! - [`Constraint`] - Directive constraint (@email, @min, @pattern, etc.)
109//! - [`RelationType`] - Relationship type (OneToMany, RequiredReference, OptionalReference, ManyToMany)
110//!
111//! ## Component System
112//!
113//! - [`ComponentProtocol`] - Interface definition for components
114//! - [`ComponentReference`] - Reference to a component in a model
115//!
116//! # Schema Language Features
117//!
118//! ## Field Types
119//!
120//! - **Integers**: `u32`, `u64`, `i32`, `i64`
121//! - **Floating Point**: `f64`
122//! - **Decimal**: `decimal` (exact fixed-point)
123//! - **Boolean**: `bool`
124//! - **String**: `string`, `char(N)` (fixed-size)
125//! - **JSON**: `json`
126//! - **UUID**: `uuid`
127//! - **Timestamp**: `timestamp`
128//! - **Enum**: a bare reference to a top-level `enum Name { ... }`
129//!
130//! ## Field Modifiers (prefix, before the type)
131//!
132//! - `+field` - Auto-generate (`u32`/`u64`/`uuid`/`timestamp` only)
133//! - `&field` - Unique
134//! - `^field` - Index
135//! - `?field` / `field?` - Optional (nullable)
136//!
137//! ## Constraints (directives)
138//!
139//! - `@email` - Email validation
140//! - `@min(value)` / `@max(value)` - Numeric bounds
141//! - `@length(n)` / `@length(min, max)` - String length
142//! - `@pattern("…")` / `@regex("…")` - Regex validation (enforced)
143//! - `@index(a, b)` - Composite index (model level)
144//! - `@on_delete(restrict|cascade|set_null)` - FK on-delete policy (enforced)
145//!
146//! ## Relations
147//!
148//! - `[Model]` - One-to-many
149//! - `*Model` - Required reference (belongs-to)
150//! - `?Model` - Optional reference
151//! - `[Model]` on both sides - Many-to-many
152//!
153//! # Error Handling
154//!
155//! The parser returns detailed error messages with line and column information:
156//!
157//! ```text
158//! Parse error at line 5, column 12: Expected '}', found 'field'
159//! ```
160//!
161//! # Related Crates
162//!
163//! - [`forgedb-validation`](../forgedb_validation) - Schema validation
164//! - [`forgedb-types`](../forgedb_types) - Runtime type definitions
165//! - [`forgedb`](../../) - Main ForgeDB CLI using this parser
166//!
167//! # See Also
168//!
169//! - [ForgeDB Schema Language Guide](../../docs/schema-language.md)
170//! - [SPRINT1_SUMMARY.md](../../archive/sprint-summaries/SPRINT1_SUMMARY.md) - Parser implementation
171
172pub mod ast;
173pub mod lexer;
174pub mod parser;
175pub mod validate;
176
177// Re-export main types for convenience
178pub use ast::{
179 ComponentProtocol, ComponentReference, Constraint, ConstraintParam, EnumDef, Field, FieldType,
180 Model, Projection, RelationType, Schema, Struct,
181};
182pub use lexer::{Lexer, Token};
183pub use parser::{ParsedSchema, Parser};
184// The single positioned schema-validation authority (consumed by the CLI + LSP).
185pub use validate::{collect_naming_errors, collect_structure_errors, validate_schema};