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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
//! ForgeDB Parser
//!
//! Parser and lexer for ForgeDB's schema definition language.
//!
//! # Overview
//!
//! This crate provides parsing capabilities for ForgeDB's schema language, converting
//! schema files (.forge) into an Abstract Syntax Tree (AST) that can be used for code
//! generation, validation, and other tooling.
//!
//! # Architecture
//!
//! The parser is implemented as a traditional two-stage compiler frontend:
//!
//! 1. **Lexer** - Tokenizes input source code into a stream of tokens
//! 2. **Parser** - Converts token stream into an Abstract Syntax Tree (AST)
//!
//! ## Supported Constructs
//!
//! - **Models** - Database table definitions with fields and constraints
//! - **Structs** - Composite data types
//! - **Fields** - Typed fields with constraints
//! - **Constraints** - Directive validation rules (@email, @min, @pattern, etc.)
//! - **Relations** - Model relationships (`[Model]`, `*Model`, `?Model`)
//! - **Components** - Reusable field groups with protocols
//!
//! # Examples
//!
//! ## Parsing a Schema File
//!
//! ```rust
//! use forgedb_parser::Parser;
//!
//! let source = r#"
//! User {
//! id: +uuid
//! email: &string @email
//! age: i32 @min(18)
//! }
//! "#;
//!
//! // Parser::new returns Result<Parser, String>
//! let mut parser = Parser::new(source).expect("parse error");
//! match parser.parse() {
//! Ok(schema) => {
//! println!("Parsed {} models", schema.models.len());
//! for model in &schema.models {
//! println!("Model: {}", model.name);
//! }
//! }
//! Err(error) => {
//! eprintln!("Parse error: {}", error);
//! }
//! }
//! ```
//!
//! ## Working with the AST
//!
//! ```rust
//! use forgedb_parser::{Parser, Model, FieldType};
//!
//! let source = r#"
//! Post {
//! id: +uuid
//! title: string
//! content: string
//! }
//! "#;
//!
//! let mut parser = Parser::new(source).expect("parse error");
//! let schema = parser.parse().unwrap();
//!
//! for model in &schema.models {
//! println!("Model: {}", model.name);
//! for field in &model.fields {
//! println!(" Field: {} : {:?}", field.name, field.field_type);
//! }
//! }
//! ```
//!
//! ## Tokenization
//!
//! ```rust
//! use forgedb_parser::{Lexer, Token};
//!
//! let source = "User { id: +uuid }";
//! let mut lexer = Lexer::new(source);
//!
//! // Lexer::tokenize() collects all tokens into a Vec
//! let tokens: Vec<Token> = lexer.tokenize().expect("lex error");
//! println!("Tokenized into {} tokens", tokens.len());
//! ```
//!
//! # Public API
//!
//! ## Core Types
//!
//! - [`Parser`] - Main parser interface
//! - [`Lexer`] - Tokenizer for schema source code
//! - [`Schema`] - Root AST node containing all definitions
//!
//! ## AST Nodes
//!
//! - [`Model`] - Database table definition
//! - [`Struct`] - Composite data type
//! - [`Field`] - Field definition with type and constraints
//! - [`FieldType`] - Field data type (i32, string, uuid, etc.)
//! - [`Constraint`] - Directive constraint (@email, @min, @pattern, etc.)
//! - [`RelationType`] - Relationship type (OneToMany, RequiredReference, OptionalReference, ManyToMany)
//!
//! ## Component System
//!
//! - [`ComponentProtocol`] - Interface definition for components
//! - [`ComponentReference`] - Reference to a component in a model
//!
//! # Schema Language Features
//!
//! ## Field Types
//!
//! - **Integers**: `u32`, `u64`, `i32`, `i64`
//! - **Floating Point**: `f64`
//! - **Decimal**: `decimal` (exact fixed-point)
//! - **Boolean**: `bool`
//! - **String**: `string`, `char(N)` (fixed-size)
//! - **JSON**: `json`
//! - **UUID**: `uuid`
//! - **Timestamp**: `timestamp`
//! - **Enum**: a bare reference to a top-level `enum Name { ... }`
//!
//! ## Field Modifiers (prefix, before the type)
//!
//! - `+field` - Auto-generate (`u32`/`u64`/`uuid`/`timestamp` only)
//! - `&field` - Unique
//! - `^field` - Index
//! - `?field` / `field?` - Optional (nullable)
//!
//! ## Constraints (directives)
//!
//! - `@email` - Email validation
//! - `@min(value)` / `@max(value)` - Numeric bounds
//! - `@length(n)` / `@length(min, max)` - String length
//! - `@pattern("…")` / `@regex("…")` - Regex validation (enforced)
//! - `@index(a, b)` - Composite index (model level)
//! - `@on_delete(restrict|cascade|set_null)` - FK on-delete policy (enforced)
//!
//! ## Relations
//!
//! - `[Model]` - One-to-many
//! - `*Model` - Required reference (belongs-to)
//! - `?Model` - Optional reference
//! - `[Model]` on both sides - Many-to-many
//!
//! # Error Handling
//!
//! The parser returns detailed error messages with line and column information:
//!
//! ```text
//! Parse error at line 5, column 12: Expected '}', found 'field'
//! ```
//!
//! # Related Crates
//!
//! - [`forgedb-validation`](../forgedb_validation) - Schema validation
//! - [`forgedb-types`](../forgedb_types) - Runtime type definitions
//! - [`forgedb`](../../) - Main ForgeDB CLI using this parser
//!
//! # See Also
//!
//! - [ForgeDB Schema Language Guide](../../docs/schema-language.md)
//! - [SPRINT1_SUMMARY.md](../../archive/sprint-summaries/SPRINT1_SUMMARY.md) - Parser implementation
// Re-export main types for convenience
pub use ;
pub use ;
pub use ;
// The single positioned schema-validation authority (consumed by the CLI + LSP).
pub use ;