1pub mod element_type;
2
3pub use element_type::BashElementType;
4
5use crate::{
6 language::BashLanguage,
7 lexer::{BashLexer, BashTokenType},
8};
9use oak_core::{
10 OakError, TextEdit,
11 parser::{ParseCache, Parser, ParserState},
12 source::Source,
13};
14
15pub(crate) type State<'a, S> = ParserState<'a, BashLanguage, S>;
16
17pub struct BashParser<'config> {
18 pub(crate) _config: &'config BashLanguage,
19}
20
21impl<'config> BashParser<'config> {
22 pub fn new(config: &'config BashLanguage) -> Self {
23 Self { _config: config }
24 }
25
26 pub(crate) fn parse_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
27 if state.at(BashTokenType::Keyword) {
28 let checkpoint = state.checkpoint();
31 state.bump();
32 while state.not_at_end() && !state.at(BashTokenType::Newline) && !state.at(BashTokenType::Delimiter) {
33 state.bump();
34 }
35 state.finish_at(checkpoint, BashElementType::CommandStatement);
36 }
37 else {
38 self.parse_command(state)?;
39 }
40 Ok(())
41 }
42
43 pub(crate) fn parse_command<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
44 let checkpoint = state.checkpoint();
45 while state.not_at_end() && !state.at(BashTokenType::Newline) && !state.at(BashTokenType::Delimiter) {
46 state.bump();
47 }
48 state.finish_at(checkpoint, BashElementType::CommandStatement);
49 Ok(())
50 }
51}
52
53impl<'config> Parser<BashLanguage> for BashParser<'config> {
54 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<BashLanguage>) -> oak_core::ParseOutput<'a, BashLanguage> {
55 let lexer = BashLexer::new(self._config);
56 oak_core::parser::parse_with_lexer(&lexer, text, edits, cache, |state| {
57 let checkpoint = state.checkpoint();
58
59 while state.not_at_end() && !state.at(BashTokenType::Eof) {
60 if state.at(BashTokenType::Newline) || state.at(BashTokenType::Delimiter) {
61 state.bump();
62 }
63 else {
64 self.parse_statement(state).ok();
65 }
66 }
67
68 Ok(state.finish_at(checkpoint, BashElementType::Root))
69 })
70 }
71}