rantlr_core/lib.rs
1//! # rantlr-core
2//!
3//! Architecture
4//!
5//! ```text
6//! .gr source
7//! │
8//! ▼
9//! ┌─────────┐ Token stream + Spans ┌──────────┐
10//! │ Lexer │ ──────────────────────────► │ Parser │
11//! └─────────┘ └────┬─────┘
12//! │
13//! ▼
14//! ┌──────────┐
15//! │ AST │ Grammar / Rule / TokenDecl
16//! └────┬─────┘
17//! ┌───────────────────┼───────────────────┐
18//! ▼ ▼ ▼
19//! ┌────────┐ ┌──────────┐ ┌──────────┐
20//! │ Linter │ │ rantlr-gen│ │ runtime │
21//! └────────┘ └──────────┘ └──────────┘
22//! ```
23//!
24//! Design choices:
25//! - Hand-written lexer + recursive-descent parser for clear diagnostics / auto-fixes.
26//! - Keywords over operators: `rule`, `token`, `match`, `repeat`, `optional`.
27//! - `repeat` / `optional` are first-class AST nodes (not desugared away).
28//! - Built-in types (`Number`, `QuotedString`, …) are recognized as dedicated tokens.
29
30pub mod ast;
31pub mod diagnostic;
32pub mod error;
33pub mod fix_hint;
34pub mod lexer;
35pub mod linter;
36pub mod parser;
37pub mod runtime;
38pub mod span;
39pub mod token;
40
41pub use ast::{
42 ExampleDecl, Expr, Grammar, GrammarItem, ImportDecl, RuleDecl, TokenBody, TokenDecl,
43};
44pub use diagnostic::{Diagnostic, DiagnosticKind, Severity};
45pub use error::{ErrorKind, RantlrError};
46pub use fix_hint::FixHint;
47pub use lexer::{lex, Lexer, LexerError};
48pub use linter::{lint, lint_all};
49pub use parser::parse;
50pub use runtime::{
51 analyze_and_parse, diagnose, parse_input, AnalyzeResult, DiagnosticJson, ParseTree,
52};
53pub use span::{BytePos, Span};
54pub use token::{BuiltinType, Keyword, Token, TokenKind};
55
56/// Parse a `.gr` grammar and run the smart linter.
57pub fn analyze(source: &str) -> Result<Grammar, RantlrError> {
58 let grammar = parse(source)?;
59 lint(source, &grammar)?;
60 Ok(grammar)
61}