oak_core/parser/
session.rs1use crate::{
2 Language,
3 lexer::{LexOutput, LexerCache, Token},
4 memory::arena::SyntaxArena,
5 tree::GreenNode,
6};
7use std::{cell::Cell, ptr::NonNull};
8
9pub trait ParseCache<L: Language>: LexerCache<L> {
11 fn arena(&self) -> &SyntaxArena;
13
14 fn old_tree(&self) -> Option<&GreenNode<'_, L>>;
16
17 fn lex_output(&self) -> Option<&LexOutput<L>>;
19
20 fn prepare_generation(&mut self);
22
23 fn commit_generation(&self, root: &GreenNode<L>);
25}
26
27pub struct ParseSession<L: Language + Send + Sync> {
32 arena_active: SyntaxArena,
34 arena_old: Option<SyntaxArena>,
36 last_root: Cell<Option<NonNull<()>>>,
38 last_lex: Option<LexOutput<L>>,
40}
41
42unsafe impl<L: Language + Send + Sync> Send for ParseSession<L> {}
43unsafe impl<L: Language + Send + Sync> Sync for ParseSession<L> {}
44
45impl<L: Language + Send + Sync> Default for ParseSession<L> {
46 fn default() -> Self {
47 Self::new(16)
48 }
49}
50
51impl<L: Language + Send + Sync> ParseSession<L> {
52 pub fn new(capacity: usize) -> Self {
54 Self { arena_active: SyntaxArena::new(capacity), arena_old: None, last_root: Cell::new(None), last_lex: None }
55 }
56
57 pub fn last_root(&self) -> Option<&GreenNode<'_, L>> {
59 let ptr = self.last_root.get()?;
60 unsafe { Some(&*(ptr.as_ptr() as *const GreenNode<'_, L>)) }
62 }
63}
64
65impl<L: Language + Send + Sync> ParseCache<L> for ParseSession<L> {
66 fn arena(&self) -> &SyntaxArena {
67 &self.arena_active
68 }
69
70 fn old_tree(&self) -> Option<&GreenNode<'_, L>> {
71 let ptr = self.last_root.get()?;
72 if self.arena_old.is_some() {
73 unsafe { Some(&*(ptr.as_ptr() as *const GreenNode<'_, L>)) }
75 }
76 else {
77 None
78 }
79 }
80
81 fn lex_output(&self) -> Option<&LexOutput<L>> {
82 self.last_lex.as_ref()
83 }
84
85 fn prepare_generation(&mut self) {
86 self.arena_old = Some(std::mem::replace(&mut self.arena_active, SyntaxArena::new(16)));
88
89 self.last_lex = None
92 }
93
94 fn commit_generation(&self, root: &GreenNode<L>) {
95 unsafe { self.last_root.set(Some(NonNull::new_unchecked(root as *const _ as *mut ()))) }
97 }
98}
99
100impl<L: Language + Send + Sync> LexerCache<L> for ParseSession<L> {
101 fn set_lex_output(&mut self, output: LexOutput<L>) {
102 self.last_lex = Some(output)
103 }
104
105 fn get_token(&self, index: usize) -> Option<Token<L::TokenType>> {
106 self.last_lex.as_ref()?.result.as_ref().ok()?.get(index).cloned()
107 }
108
109 fn count_tokens(&self) -> usize {
110 self.last_lex.as_ref().and_then(|out| out.result.as_ref().ok()).map(|tokens| tokens.len()).unwrap_or(0)
111 }
112
113 fn has_tokens(&self) -> bool {
114 self.last_lex.as_ref().and_then(|out| out.result.as_ref().ok()).map(|tokens| !tokens.is_empty()).unwrap_or(false)
115 }
116
117 fn get_tokens(&self) -> Option<&[Token<L::TokenType>]> {
118 self.last_lex.as_ref()?.result.as_ref().ok().map(|tokens| &**tokens)
119 }
120}
121
122impl<'a, L: Language, C: ParseCache<L> + ?Sized> ParseCache<L> for &'a mut C {
123 fn arena(&self) -> &SyntaxArena {
124 (**self).arena()
125 }
126
127 fn old_tree(&self) -> Option<&GreenNode<'_, L>> {
128 (**self).old_tree()
129 }
130
131 fn lex_output(&self) -> Option<&LexOutput<L>> {
132 (**self).lex_output()
133 }
134
135 fn prepare_generation(&mut self) {
136 (**self).prepare_generation()
137 }
138
139 fn commit_generation(&self, root: &GreenNode<L>) {
140 (**self).commit_generation(root)
141 }
142}