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