1#![doc = include_str!("readme.md")]
2
3pub mod pratt;
5pub mod session;
7pub mod state;
9
10pub use self::{
11 pratt::{Associativity, OperatorInfo, Pratt, PrattParser, binary, postfix, unary},
12 session::{ParseCache, ParseSession},
13 state::{ParserState, deep_clone_node},
14};
15
16pub use triomphe::Arc;
17
18pub use crate::{
19 Language, Lexer,
20 errors::{OakDiagnostics, OakError},
21 source::{Source, TextEdit},
22 tree::GreenNode,
23};
24
25pub type ParseOutput<'a, L: Language> = OakDiagnostics<&'a GreenNode<'a, L>>;
27
28pub trait Parser<L: Language + Send + Sync>
30where
31 L::ElementType: From<L::TokenType>,
32{
33 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<L>) -> ParseOutput<'a, L>;
43}
44
45pub fn parse<'a, L, P, Lex, S>(parser: &P, _lexer: &Lex, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<L>) -> ParseOutput<'a, L>
50where
51 L: Language + Send + Sync,
52 L::ElementType: From<L::TokenType>,
53 P: Parser<L>,
54 Lex: Lexer<L>,
55 S: Source + ?Sized,
56{
57 parser.parse(text, edits, cache)
58}
59
60pub fn parse_one_pass<'a, L, P, S>(parser: &P, text: &'a S, cache: &'a mut impl ParseCache<L>) -> ParseOutput<'a, L>
64where
65 L: Language + Send + Sync,
66 L::ElementType: From<L::TokenType>,
67 P: Parser<L>,
68 S: Source + ?Sized,
69{
70 parser.parse(text, &[], cache)
71}
72
73pub fn parse_with_lexer<'a, L, S, Lex>(lexer: &Lex, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<L>, run: impl FnOnce(&mut ParserState<'a, L, S>) -> Result<&'a GreenNode<'a, L>, OakError>) -> ParseOutput<'a, L>
78where
79 L: Language + Send + Sync,
80 L::ElementType: From<L::TokenType>,
81 S: Source + ?Sized,
82 Lex: Lexer<L>,
83{
84 cache.prepare_generation();
86
87 let lex_out = match cache.lex_output() {
89 Some(out) => out.clone(),
90 None => {
91 let out = lexer.lex(text, edits, cache);
92 cache.set_lex_output(out.clone());
93 out
94 }
95 };
96
97 let capacity_hint = cache.old_tree().map(|old| old.children.len().max(1024)).unwrap_or(1024);
98
99 let arena: &'a crate::memory::arena::SyntaxArena = unsafe { std::mem::transmute(cache.arena()) };
103 let mut st = ParserState::new(arena, lex_out, text, capacity_hint);
104
105 if let Some(old) = cache.old_tree() {
106 let old: &'a GreenNode<'a, L> = unsafe { std::mem::transmute(old) };
107 st.set_incremental(old, edits);
108 }
109
110 let result = run(&mut st);
112 let output = st.finish(result);
113
114 if let Ok(root) = output.result {
116 cache.commit_generation(root)
117 }
118
119 output
120}