syntax_parser_generator/lib.rs
1//! Independent library for generating lexical-analyzers and LALR parsers.
2//!
3//! This library offers a simple API for generating parsers of syntactically-structured text. As
4//! such, it can generate 2 types of engines - for the 2 phases of syntax parsing, which naturally
5//! fit on top of each other:
6//!
7//! * [_Lexical analyzers_](https://en.wikipedia.org/wiki/Lexical_analysis): for tokenizing input
8//! text by regular expressions.
9//! * [_Syntax-directed translators_](https://en.wikipedia.org/wiki/Syntax-directed_translation):
10//! for reconstructing the input's syntax-tree by a context-free grammar (using the
11//! [LALR](https://en.wikipedia.org/wiki/LALR_parser) algorithm), and translating it into some
12//! user-defined representation, such as an abstract syntax-tree (AST) or a sequence of
13//! intermediate code representation (IR).
14//!
15//! Check out the [lex] and [parsing] modules, respectively, for these purposes.
16//!
17//! Note that the crate is independent: its entire API and logic is designed and implemented
18//! in-house.
19//!
20//! # Example
21//!
22//! ```rust
23//! # use syntax_parser_generator::handles::specials::AutomaticallyHandled;
24//! # use syntax_parser_generator::lex::{LexemeDescriptor, LexicalAnalyzer, Regex};
25//! # use syntax_parser_generator::parsing::{Associativity, SyntaxDirectedTranslator, SyntaxDirectedTranslatorBuilder};
26//! # use syntax_parser_generator::readers::ByteArrayReader;
27//! # #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
28//! enum LexemeType { Plus, Star, Integer }
29//! # impl AutomaticallyHandled for LexemeType {
30//! # type HandleCoreType = u8;
31//! # fn serial(&self) -> usize { *self as usize }
32//! # }
33//!
34//! fn build_lexer() -> LexicalAnalyzer<LexemeType> {
35//! LexicalAnalyzer::new(vec![
36//! LexemeDescriptor::special_char(LexemeType::Plus, '+'),
37//! LexemeDescriptor::special_char(LexemeType::Star, '*'),
38//! LexemeDescriptor::new(
39//! LexemeType::Integer,
40//! Regex::plus_from(Regex::character_range('0', '9')),
41//! ),
42//! ])
43//! }
44//!
45//! struct ParsingContext {
46//! integer_count: usize,
47//! op_count: usize,
48//! }
49//! impl ParsingContext {
50//! fn new() -> Self {
51//! Self {
52//! integer_count: 0,
53//! op_count: 0,
54//! }
55//! }
56//! fn integer(&mut self, lexeme: String) -> Option<i32> {
57//! self.integer_count += 1;
58//! Some(lexeme.parse().ok()?)
59//! }
60//! fn sum(&mut self, satellites: Vec<Option<i32>>) -> Option<i32> {
61//! self.op_count += 1;
62//! Some(satellites[0]? + satellites[2]?)
63//! }
64//! fn mult(&mut self, satellites: Vec<Option<i32>>) -> Option<i32> {
65//! self.op_count += 1;
66//! Some(satellites[0]? * satellites[2]?)
67//! }
68//! }
69//!
70//! fn build_parser() -> SyntaxDirectedTranslator<LexemeType, ParsingContext, Option<i32>> {
71//! let mut builder = SyntaxDirectedTranslatorBuilder::new();
72//!
73//! builder.dub_lexeme_types(vec![
74//! (LexemeType::Integer, "INTEGER"),
75//! (LexemeType::Plus, "+"),
76//! (LexemeType::Star, "*"),
77//! ].into_iter());
78//! builder.new_nonterminal("expression");
79//! builder.set_start_nonterminal("expression");
80//!
81//! builder.new_binding(
82//! vec!["*"],
83//! Associativity::Left,
84//! "multiplicative",
85//! );
86//! builder.new_binding(
87//! vec!["+"],
88//! Associativity::Left,
89//! "additive",
90//! );
91//!
92//! builder.set_leaf_satellite_builder("INTEGER", ParsingContext::integer);
93//! builder.set_default_leaf_satellite_builder(|_, _| None);
94//!
95//! builder.register_identity_rule("expression", "INTEGER");
96//! builder.register_bound_rule(
97//! "expression",
98//! vec!["expression", "+", "expression"],
99//! "additive",
100//! ParsingContext::sum,
101//! );
102//! builder.register_bound_rule(
103//! "expression",
104//! vec!["expression", "*", "expression"],
105//! "multiplicative",
106//! ParsingContext::mult,
107//! );
108//! builder.build()
109//! }
110//!
111//! fn main() {
112//! let lexer = build_lexer();
113//! let parser = build_parser();
114//! let mut context = ParsingContext::new();
115//!
116//! let mut input = ByteArrayReader::from_string_slice("12+4*5+8");
117//! assert_eq!(parser.translate(&mut context, lexer.analyze(&mut input)), Some(Some(40)));
118//! assert_eq!(context.integer_count, 4);
119//! assert_eq!(context.op_count, 3);
120//! }
121//! ```
122
123#![warn(missing_docs)]
124
125mod automata;
126pub mod handles;
127pub mod lex;
128pub mod parsing;
129pub mod readers;