Skip to main content

oak_ada/parser/
mod.rs

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