oxilean_parse/lib.rs
1#![forbid(unsafe_code)]
2#![allow(unused_imports)]
3#![allow(dead_code)]
4
5//! # OxiLean Parser — Surface Syntax to AST
6//!
7//! This crate converts concrete OxiLean source syntax (text) into abstract syntax trees (ASTs)
8//! that the elaborator can process into kernel-checkable terms.
9//!
10//! ## Quick Start
11//!
12//! ### Parsing an Expression
13//!
14//! ```ignore
15//! use oxilean_parse::{Lexer, Parser, SurfaceExpr};
16//!
17//! let source = "fun (x : Nat) => x + 1";
18//! let lexer = Lexer::new(source);
19//! let tokens = lexer.tokenize()?;
20//! let mut parser = Parser::new(tokens);
21//! let expr = parser.parse_expr()?;
22//! ```
23//!
24//! ### Parsing a Module
25//!
26//! ```ignore
27//! use oxilean_parse::Module;
28//!
29//! let source = "def double (n : Nat) : Nat := n + n";
30//! let module = Module::parse_source(source)?;
31//! ```
32//!
33//! ## Architecture Overview
34//!
35//! The parser is a three-stage pipeline:
36//!
37//! ```text
38//! Source Text (.oxilean file)
39//! │
40//! ▼
41//! ┌──────────────────────┐
42//! │ Lexer │ → Tokenizes text
43//! │ (lexer.rs) │ → Handles UTF-8, comments, strings
44//! └──────────────────────┘
45//! │
46//! ▼
47//! Token Stream
48//! │
49//! ▼
50//! ┌──────────────────────┐
51//! │ Parser │ → Builds AST from tokens
52//! │ (parser_impl.rs) │ → Handles precedence, associativity
53//! │ + Helpers │ → Pattern, macro, tactic parsers
54//! └──────────────────────┘
55//! │
56//! ▼
57//! Abstract Syntax Tree (AST)
58//! │
59//! └─→ SurfaceExpr, SurfaceDecl, Module, etc.
60//! └─→ Diagnostic information (errors, warnings)
61//! └─→ Source mapping (for IDE integration)
62//! ```
63//!
64//! ## Key Concepts & Terminology
65//!
66//! ### Tokens
67//!
68//! Basic lexical elements:
69//! - **Identifiers**: `x`, `Nat`, `add_comm`, etc.
70//! - **Keywords**: `fun`, `def`, `theorem`, `inductive`, etc.
71//! - **Operators**: `+`, `-`, `:`, `=>`, `|`, etc.
72//! - **Literals**: Numbers, strings, characters
73//! - **Delimiters**: `(`, `)`, `[`, `]`, `{`, `}`
74//!
75//! ### Surface Syntax (SurfaceExpr)
76//!
77//! Represents OxiLean code before elaboration:
78//! - **Applications**: `f x y` (function calls)
79//! - **Lambda**: `fun x => body`
80//! - **Pi types**: `(x : A) -> B`
81//! - **Matches**: `match x with | nil => ... | cons h t => ...`
82//! - **Tactics**: `by (tac1; tac2)`
83//! - **Attributes**: `@[simp] def foo := ...`
84//!
85//! ### AST vs Kernel Expr
86//!
87//! - **AST (this crate)**: Surface syntax with implicit info
88//! - Contains `?` (implicit args), `_` (placeholders)
89//! - No type annotations required
90//! - Represents user-written code
91//! - **Kernel Expr (oxilean-kernel)**: Type-checked terms
92//! - All types explicit
93//! - All implicit args resolved
94//! - Fully elaborated
95//!
96//! ## Module Organization
97//!
98//! ### Core Parsing Modules
99//!
100//! | Module | Purpose |
101//! |--------|---------|
102//! | `lexer` | Tokenization: text → tokens |
103//! | `tokens` | Token and TokenKind definitions |
104//! | `parser_impl` | Main parser: tokens → AST |
105//! | `command` | Command parsing (`def`, `theorem`, etc.) |
106//!
107//! ### AST Definition
108//!
109//! | Module | Purpose |
110//! |--------|---------|
111//! | `ast_impl` | Core AST types: `SurfaceExpr`, `SurfaceDecl`, etc. |
112//! | `pattern` | Pattern matching syntax |
113//! | `literal` | Number and string literals |
114//!
115//! ### Specialized Parsers
116//!
117//! | Module | Purpose |
118//! |--------|---------|
119//! | `tactic_parser` | Tactic syntax: `intro`, `apply`, `rw`, etc. |
120//! | `macro_parser` | Macro definition and expansion |
121//! | `notation_system` | Operator precedence and associativity |
122//!
123//! ### Diagnostics & Source Mapping
124//!
125//! | Module | Purpose |
126//! |--------|---------|
127//! | `diagnostic` | Error and warning collection |
128//! | `error_impl` | Parse error types and messages |
129//! | `sourcemap` | Source position tracking for IDE |
130//! | `span_util` | Source span utilities |
131//!
132//! ### Utilities
133//!
134//! | Module | Purpose |
135//! |--------|---------|
136//! | `prettyprint` | AST pretty-printing |
137//! | `module` | Module system and imports |
138//! | `repl_parser` | REPL command parsing |
139//!
140//! ## Parsing Pipeline Details
141//!
142//! ### Phase 1: Lexical Analysis (Lexer)
143//!
144//! Transforms character stream into token stream:
145//! - Handles Unicode identifiers (UTF-8)
146//! - Recognizes keywords vs identifiers
147//! - Tracks line/column positions (for error reporting)
148//! - Supports:
149//! - Single-line comments: `-- comment`
150//! - Multi-line comments: `/- -/`
151//! - String literals: `"hello"`
152//! - Number literals: `42`, `0xFF`, `3.14`
153//!
154//! ### Phase 2: Syntactic Analysis (Parser)
155//!
156//! Transforms token stream into AST:
157//! - **Recursive descent**: For statements and declarations
158//! - **Pratt parsing**: For expressions (handles precedence)
159//! - **Lookahead(1)**: LL(1) grammar for predictive parsing
160//! - **Error recovery**: Continues parsing after errors
161//!
162//! ### Phase 3: Post-Processing
163//!
164//! - **Notation expansion**: Apply infix/prefix operators
165//! - **Macro expansion**: Expand syntax sugar
166//! - **Span assignment**: Map AST nodes to source positions
167//!
168//! ## Usage Examples
169//!
170//! ### Example 1: Parse and Pretty-Print
171//!
172//! ```text
173//! use oxilean_parse::{Lexer, Parser, print_expr};
174//!
175//! let source = "(x : Nat) -> Nat";
176//! let mut parser = Parser::from_source(source)?;
177//! let expr = parser.parse_expr()?;
178//! println!("{}", print_expr(&expr));
179//! ```
180//!
181//! ### Example 2: Parse a Definition
182//!
183//! ```text
184//! use oxilean_parse::{Lexer, Parser, Decl};
185//!
186//! let source = "def double (n : Nat) : Nat := n + n";
187//! let mut parser = Parser::from_source(source)?;
188//! let decl = parser.parse_decl()?;
189//! assert!(matches!(decl, Decl::Def { .. }));
190//! ```
191//!
192//! ### Example 3: Collect Diagnostics
193//!
194//! ```text
195//! use oxilean_parse::DiagnosticCollector;
196//!
197//! let mut collector = DiagnosticCollector::new();
198//! // ... parse code ...
199//! for diag in collector.diagnostics() {
200//! println!("{:?}", diag);
201//! }
202//! ```
203//!
204//! ## Operator Precedence
205//!
206//! Operators are organized by precedence levels (0-100):
207//! - **Level 100** (highest): Projections, applications
208//! - **Level 90**: Power/exponentiation
209//! - **Level 70**: Multiplication, division
210//! - **Level 65**: Addition, subtraction
211//! - **Level 50**: Comparison (`<`, `>`, `=`, etc.)
212//! - **Level 40**: Conjunction (`and`)
213//! - **Level 35**: Disjunction (`or`)
214//! - **Level 25**: Implication (`->`)
215//! - **Level 0** (lowest): Binders (`fun`, `:`, etc.)
216//!
217//! Associativity (left/right/non-associative) is per-operator.
218//!
219//! ## Error Handling
220//!
221//! Parser errors include:
222//! - **Unexpected token**: Parser expected a different token
223//! - **Expected `type` token**: Specific token was expected but not found
224//! - **Unclosed delimiter**: Missing closing bracket/paren
225//! - **Undeclared operator**: Unknown infix operator
226//! - **Invalid pattern**: Malformed pattern in match/fun
227//!
228//! All errors carry:
229//! - **Source location** (span): File, line, column
230//! - **Error message**: Human-readable description
231//! - **Context**: Surrounding code snippet (for IDE tooltips)
232//!
233//! ## Source Mapping & IDE Integration
234//!
235//! The parser builds a **source map** tracking:
236//! - AST node → source location
237//! - Hover information (for IDE hover tooltips)
238//! - Semantic tokens (for syntax highlighting)
239//! - Reference locations (for "go to definition")
240//!
241//! This enables:
242//! - Accurate error reporting
243//! - IDE language server protocol (LSP) support
244//! - Refactoring tools
245//!
246//! ## Extensibility
247//!
248//! ### Adding New Operators
249//!
250//! Operators are registered in `notation_system`:
251//! ```ignore
252//! let notation = Notation {
253//! name: "my_op",
254//! kind: NotationKind::Infix,
255//! level: 60,
256//! associativity: Associativity::Left,
257//! };
258//! notation_table.insert(notation);
259//! ```
260//!
261//! ### Adding New Keywords
262//!
263//! Keywords are hardcoded in `lexer::keyword_of_string()`.
264//! Add new keyword, then handle in parser.
265//!
266//! ### Custom Macros
267//!
268//! Macros are parsed by `macro_parser` and expanded during parsing:
269//! ```text
270//! syntax "list" ["[", expr, (",", expr)*, "]"] => ...
271//! macro list_to_cons : list => (...)
272//! ```
273//!
274//! ## Integration with Other Crates
275//!
276//! ### With oxilean-elab
277//!
278//! The elaborator consumes this crate's AST:
279//! ```text
280//! Parser: Source → SurfaceExpr
281//! Elaborator: SurfaceExpr → Kernel Expr (with type checking)
282//! ```
283//!
284//! ### With oxilean-kernel
285//!
286//! Kernel types (Name, Level, Literal) are re-exported by parser for convenience.
287//!
288//! ## Performance Considerations
289//!
290//! - **Linear parsing**: O(n) where n = source length
291//! - **Minimal allocations**: AST nodes are typically smaller than source
292//! - **Single pass**: No tokenization+parsing phase, done in parallel
293//!
294//! ## Further Reading
295//!
296//! - [ARCHITECTURE.md](../../ARCHITECTURE.md) — System architecture
297//! - [BLUEPRINT.md](../../BLUEPRINT.md) — Formal syntax specification
298//! - Module documentation for specific subcomponents
299
300#![allow(missing_docs)]
301#![warn(clippy::all)]
302#![allow(clippy::collapsible_if)]
303
304// Module stubs for future implementation
305pub mod ast;
306pub mod error;
307pub mod parser;
308pub mod token;
309
310// Full implementations
311pub mod ast_impl;
312pub mod command;
313pub mod diagnostic;
314pub mod error_impl;
315pub mod expr_cache;
316/// Advanced formatter with Wadler-Lindig optimal layout.
317pub mod formatter_adv;
318pub mod incremental;
319pub mod indent_tracker;
320pub mod lexer;
321pub mod macro_parser;
322pub mod module;
323pub mod notation_system;
324pub mod parser_impl;
325pub mod pattern;
326pub mod prettyprint;
327pub mod repl_parser;
328pub mod roundtrip;
329pub mod sourcemap;
330pub mod span_util;
331pub mod tactic_parser;
332pub mod tokens;
333pub mod wasm_source_map;
334
335pub use ast::SurfaceExpr as OldSurfaceExpr;
336pub use ast_impl::{
337 AstNotationKind, AttributeKind, Binder, BinderKind, CalcStep as AstCalcStep, Constructor, Decl,
338 DoAction, FieldDecl, Literal, Located, MatchArm, Pattern, SortKind, SurfaceExpr, TacticRef,
339 WhereClause,
340};
341pub use command::{Command, CommandParser, NotationKind, OpenItem};
342pub use diagnostic::{Diagnostic, DiagnosticCollector, DiagnosticLabel, Severity};
343pub use error::ParseError as OldParseError;
344pub use error_impl::{ParseError, ParseErrorKind};
345pub use lexer::Lexer;
346pub use macro_parser::{
347 HygieneInfo, MacroDef, MacroError, MacroErrorKind, MacroExpander, MacroParser, MacroRule,
348 MacroToken, SyntaxDef, SyntaxItem, SyntaxKind,
349};
350pub use module::{Module, ModuleRegistry};
351pub use notation_system::{
352 Fixity, NotationEntry, NotationKind as NotationSystemKind, NotationPart, NotationTable,
353 OperatorEntry,
354};
355pub use parser_impl::Parser;
356pub use pattern::{MatchClause, PatternCompiler};
357pub use prettyprint::{print_decl, print_expr, ParensMode, PrettyConfig, PrettyPrinter};
358pub use repl_parser::{is_complete, ReplCommand, ReplParser};
359pub use sourcemap::{
360 EntryKind, HoverInfo, SemanticToken, SourceEntry, SourceMap, SourceMapBuilder,
361};
362pub use span_util::{dummy_span, merge_spans, span_contains, span_len};
363pub use tactic_parser::{
364 CalcStep, CaseArm, ConvSide, RewriteRule, SimpArgs, TacticExpr, TacticParser,
365};
366pub use tokens::{Span, StringPart, Token, TokenKind};
367
368pub mod core_types;
369pub use core_types::*;
370
371pub mod error_recovery;
372pub mod hygienic_macro;
373pub mod module_system;
374pub mod notation_elaboration;
375pub mod source_map;