Skip to main content

oak_ada/parser/
mod.rs

1pub mod element_type;
2
3pub use element_type::AdaElementType;
4
5use crate::{language::AdaLanguage, lexer::AdaTokenType};
6use oak_core::{
7    OakError, TextEdit,
8    parser::{Parser, ParserState},
9    source::Source,
10};
11
12pub(crate) type State<'a, S> = ParserState<'a, AdaLanguage, S>;
13
14pub struct AdaParser<'config> {
15    pub(crate) config: &'config AdaLanguage,
16}
17
18impl<'config> AdaParser<'config> {
19    pub fn new(config: &'config AdaLanguage) -> Self {
20        Self { config }
21    }
22
23    pub(crate) fn parse_context_clause<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
24        let cp = state.checkpoint();
25        state.expect(AdaTokenType::With).ok();
26
27        while state.at(AdaTokenType::Identifier) {
28            state.advance();
29            if state.at(AdaTokenType::Dot) {
30                state.advance();
31            }
32            else {
33                break;
34            }
35        }
36
37        state.expect(AdaTokenType::Semicolon).ok();
38        state.finish_at(cp, AdaElementType::ContextClause);
39        Ok(())
40    }
41
42    pub(crate) fn parse_package_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
43        let cp = state.checkpoint();
44        state.expect(AdaTokenType::Package).ok();
45
46        if state.at(AdaTokenType::Body) {
47            state.advance();
48        }
49
50        state.expect(AdaTokenType::Identifier).ok();
51        state.expect(AdaTokenType::Is).ok();
52
53        while state.not_at_end() && !state.at(AdaTokenType::End) {
54            if state.at(AdaTokenType::Procedure) || state.at(AdaTokenType::Function) {
55                self.parse_subprogram_declaration(state)?;
56            }
57            else {
58                state.advance();
59            }
60        }
61
62        state.expect(AdaTokenType::End).ok();
63        if state.at(AdaTokenType::Identifier) {
64            state.advance();
65        }
66        state.expect(AdaTokenType::Semicolon).ok();
67
68        state.finish_at(cp, AdaElementType::PackageDeclaration);
69        Ok(())
70    }
71
72    pub(crate) fn parse_subprogram_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
73        let cp = state.checkpoint();
74
75        if state.at(AdaTokenType::Procedure) {
76            state.advance();
77        }
78        else {
79            state.expect(AdaTokenType::Function).ok();
80        }
81
82        state.expect(AdaTokenType::Identifier).ok();
83
84        // Parameters
85        if state.at(AdaTokenType::LeftParen) {
86            state.advance();
87            while state.not_at_end() && !state.at(AdaTokenType::RightParen) {
88                state.advance();
89            }
90            state.expect(AdaTokenType::RightParen).ok();
91        }
92
93        if state.at(AdaTokenType::Return) {
94            state.advance();
95            state.expect(AdaTokenType::Identifier).ok();
96        }
97
98        if state.at(AdaTokenType::Is) {
99            state.advance();
100            while state.not_at_end() && !state.at(AdaTokenType::End) {
101                state.advance();
102            }
103            state.expect(AdaTokenType::End).ok();
104            if state.at(AdaTokenType::Identifier) {
105                state.advance();
106            }
107        }
108
109        state.expect(AdaTokenType::Semicolon).ok();
110        state.finish_at(cp, AdaElementType::SubprogramDeclaration);
111        Ok(())
112    }
113
114    pub(crate) fn parse_pragma<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
115        let cp = state.checkpoint();
116        state.expect(AdaTokenType::Pragma).ok();
117        state.expect(AdaTokenType::Identifier).ok();
118
119        if state.at(AdaTokenType::LeftParen) {
120            state.advance();
121            while state.not_at_end() && !state.at(AdaTokenType::RightParen) {
122                state.advance();
123            }
124            state.expect(AdaTokenType::RightParen).ok();
125        }
126
127        state.expect(AdaTokenType::Semicolon).ok();
128        state.finish_at(cp, AdaElementType::Pragma);
129        Ok(())
130    }
131}
132
133impl<'config> Parser<AdaLanguage> for AdaParser<'config> {
134    fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl oak_core::ParseCache<AdaLanguage>) -> oak_core::ParseOutput<'a, AdaLanguage> {
135        let lexer = crate::lexer::AdaLexer::new(self.config);
136        oak_core::parser::parse_with_lexer(&lexer, text, edits, cache, |state| {
137            let checkpoint = state.checkpoint();
138
139            while state.not_at_end() && !state.at(AdaTokenType::Eof) {
140                if state.at(AdaTokenType::With) {
141                    self.parse_context_clause(state)?;
142                }
143                else if state.at(AdaTokenType::Package) {
144                    self.parse_package_declaration(state)?;
145                }
146                else if state.at(AdaTokenType::Procedure) || state.at(AdaTokenType::Function) {
147                    self.parse_subprogram_declaration(state)?;
148                }
149                else if state.at(AdaTokenType::Pragma) {
150                    self.parse_pragma(state)?;
151                }
152                else {
153                    state.bump();
154                }
155            }
156
157            Ok(state.finish_at(checkpoint, AdaElementType::Root))
158        })
159    }
160}