Skip to main content

oak_ada/parser/
mod.rs

1#![doc = include_str!("readme.md")]
2/// Ada 语法元素类型定义。
3pub 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
16/// Ada 语言的语法分析器。
17pub struct AdaParser<'config> {
18    pub(crate) config: &'config AdaLanguage,
19}
20
21impl<'config> AdaParser<'config> {
22    /// 使用给定的语言配置创建新的 `AdaParser`。
23    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        // Parameters
89        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}