oak_clojure/parser/
mod.rs1pub mod element_type;
3pub use element_type::ClojureElementType;
4
5use crate::{language::ClojureLanguage, lexer::token_type::ClojureTokenType};
6use oak_core::{
7 OakError,
8 parser::{ParseCache, ParseOutput, Parser, ParserState, parse_with_lexer},
9 source::{Source, TextEdit},
10};
11
12pub(crate) type State<'a, S> = ParserState<'a, ClojureLanguage, S>;
13
14pub struct ClojureParser<'config> {
16 pub(crate) config: &'config ClojureLanguage,
17}
18
19impl<'config> ClojureParser<'config> {
20 pub fn new(config: &'config ClojureLanguage) -> Self {
22 Self { config }
23 }
24
25 fn parse_form<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
26 match state.peek_kind() {
27 Some(ClojureTokenType::ListStart) => self.parse_list(state),
28 Some(ClojureTokenType::VectorStart) => self.parse_vector(state),
29 Some(ClojureTokenType::MapStart) => self.parse_map(state),
30 Some(ClojureTokenType::SetStart) => self.parse_set(state),
31 Some(ClojureTokenType::AnonFnStart) => self.parse_anon_fn(state),
32 Some(ClojureTokenType::Quote) => {
33 let cp = state.checkpoint();
34 state.bump();
35 self.parse_form(state)?;
36 state.finish_at(cp, ClojureElementType::Quotation);
37 Ok(())
38 }
39 Some(ClojureTokenType::Meta) => {
40 let cp = state.checkpoint();
41 state.bump();
42 self.parse_form(state)?;
43 state.finish_at(cp, ClojureElementType::Meta);
44 Ok(())
45 }
46 Some(_) => {
47 state.bump();
48 Ok(())
49 }
50 None => Ok(()),
51 }
52 }
53
54 fn parse_list<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
55 let cp = state.checkpoint();
56 state.expect(ClojureTokenType::ListStart).ok();
57 while state.not_at_end() && !state.at(ClojureTokenType::ListEnd) {
58 self.parse_form(state)?;
59 }
60 state.expect(ClojureTokenType::ListEnd).ok();
61 state.finish_at(cp, ClojureElementType::List);
62 Ok(())
63 }
64
65 fn parse_vector<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
66 let cp = state.checkpoint();
67 state.expect(ClojureTokenType::VectorStart).ok();
68 while state.not_at_end() && !state.at(ClojureTokenType::VectorEnd) {
69 self.parse_form(state)?;
70 }
71 state.expect(ClojureTokenType::VectorEnd).ok();
72 state.finish_at(cp, ClojureElementType::Vector);
73 Ok(())
74 }
75
76 fn parse_map<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
77 let cp = state.checkpoint();
78 state.expect(ClojureTokenType::MapStart).ok();
79 while state.not_at_end() && !state.at(ClojureTokenType::MapEnd) {
80 self.parse_form(state)?;
81 }
82 state.expect(ClojureTokenType::MapEnd).ok();
83 state.finish_at(cp, ClojureElementType::Map);
84 Ok(())
85 }
86
87 fn parse_set<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
88 let cp = state.checkpoint();
89 state.expect(ClojureTokenType::SetStart).ok();
90 while state.not_at_end() && !state.at(ClojureTokenType::MapEnd) {
91 self.parse_form(state)?;
92 }
93 state.expect(ClojureTokenType::MapEnd).ok();
94 state.finish_at(cp, ClojureElementType::Set);
95 Ok(())
96 }
97
98 fn parse_anon_fn<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
99 let cp = state.checkpoint();
100 state.expect(ClojureTokenType::AnonFnStart).ok();
101 while state.not_at_end() && !state.at(ClojureTokenType::ListEnd) {
102 self.parse_form(state)?;
103 }
104 state.expect(ClojureTokenType::ListEnd).ok();
105 state.finish_at(cp, ClojureElementType::AnonFn);
106 Ok(())
107 }
108}
109
110impl<'config> Parser<ClojureLanguage> for ClojureParser<'config> {
111 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<ClojureLanguage>) -> ParseOutput<'a, ClojureLanguage> {
112 let lexer = crate::lexer::ClojureLexer::new(self.config);
113 parse_with_lexer(&lexer, text, edits, cache, |state| {
114 let checkpoint = state.checkpoint();
115
116 while state.not_at_end() {
117 self.parse_form(state)?
118 }
119
120 Ok(state.finish_at(checkpoint, ClojureElementType::SourceFile))
121 })
122 }
123}