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 rule_graph;
38pub mod runtime;
39pub mod span;
40pub mod token;
41
42pub use ast::{
43 ExampleDecl, Expr, Grammar, GrammarItem, ImportDecl, RuleDecl, TokenBody, TokenDecl,
44};
45pub use diagnostic::{Diagnostic, DiagnosticKind, Severity};
46pub use error::{ErrorKind, RantlrError};
47pub use fix_hint::FixHint;
48pub use lexer::{lex, Lexer, LexerError};
49pub use linter::{lint, lint_all};
50pub use parser::parse;
51pub use rule_graph::{rule_graph, RuleEdge, RuleGraph, RuleNode};
52pub use runtime::{
53 analyze_and_parse, diagnose, parse_input, AnalyzeResult, DiagnosticJson, ParseTree,
54};
55pub use span::{BytePos, Span};
56pub use token::{BuiltinType, Keyword, Token, TokenKind};
57
58/// Parse a `.gr` grammar and run the smart linter.
59pub fn analyze(source: &str) -> Result<Grammar, RantlrError> {
60 let grammar = parse(source)?;
61 lint(source, &grammar)?;
62 Ok(grammar)
63}