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