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 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}