Skip to main content

oak_protobuf/parser/
mod.rs

1use crate::{kind::ProtobufSyntaxKind, language::ProtobufLanguage, lexer::ProtobufLexer};
2use oak_core::{
3    errors::OakError,
4    parser::{ParseCache, ParseOutput, Parser, ParserState},
5    source::{Source, TextEdit},
6    tree::GreenNode,
7};
8
9pub(crate) type State<'a, S> = ParserState<'a, ProtobufLanguage, S>;
10
11pub struct ProtobufParser<'a> {
12    language: &'a ProtobufLanguage,
13}
14
15impl<'a> ProtobufParser<'a> {
16    pub fn new(language: &'a ProtobufLanguage) -> Self {
17        Self { language }
18    }
19
20    fn parse_root_internal<'b, S: Source + ?Sized>(&self, state: &mut State<'b, S>) -> Result<&'b GreenNode<'b, ProtobufLanguage>, OakError> {
21        let checkpoint = state.checkpoint();
22        self.parse_program(state);
23        Ok(state.finish_at(checkpoint, ProtobufSyntaxKind::Root))
24    }
25
26    fn parse_program<S: Source + ?Sized>(&self, state: &mut State<'_, S>) {
27        while state.not_at_end() {
28            if state.at(ProtobufSyntaxKind::Syntax) {
29                self.parse_syntax(state);
30            }
31            else if state.at(ProtobufSyntaxKind::Package) {
32                self.parse_package(state);
33            }
34            else if state.at(ProtobufSyntaxKind::Import) {
35                self.parse_import(state);
36            }
37            else if state.at(ProtobufSyntaxKind::Option) {
38                self.parse_option(state);
39            }
40            else if state.at(ProtobufSyntaxKind::Message) {
41                self.parse_message(state);
42            }
43            else if state.at(ProtobufSyntaxKind::Enum) {
44                self.parse_enum(state);
45            }
46            else if state.at(ProtobufSyntaxKind::Service) {
47                self.parse_service(state);
48            }
49            else {
50                state.bump();
51            }
52        }
53    }
54
55    fn parse_syntax<S: Source + ?Sized>(&self, state: &mut State<'_, S>) {
56        let checkpoint = state.checkpoint();
57        state.expect(ProtobufSyntaxKind::Syntax).ok();
58        state.expect(ProtobufSyntaxKind::Assign).ok();
59        state.expect(ProtobufSyntaxKind::StringLiteral).ok();
60        state.expect(ProtobufSyntaxKind::Semicolon).ok();
61        state.finish_at(checkpoint, ProtobufSyntaxKind::SyntaxDef);
62    }
63
64    fn parse_package<S: Source + ?Sized>(&self, state: &mut State<'_, S>) {
65        let checkpoint = state.checkpoint();
66        state.expect(ProtobufSyntaxKind::Package).ok();
67        state.expect(ProtobufSyntaxKind::Identifier).ok();
68        state.expect(ProtobufSyntaxKind::Semicolon).ok();
69        state.finish_at(checkpoint, ProtobufSyntaxKind::PackageDef);
70    }
71
72    fn parse_import<S: Source + ?Sized>(&self, state: &mut State<'_, S>) {
73        let checkpoint = state.checkpoint();
74        state.expect(ProtobufSyntaxKind::Import).ok();
75        if state.at(ProtobufSyntaxKind::Public) || state.at(ProtobufSyntaxKind::Weak) {
76            state.bump();
77        }
78        state.expect(ProtobufSyntaxKind::StringLiteral).ok();
79        state.expect(ProtobufSyntaxKind::Semicolon).ok();
80        state.finish_at(checkpoint, ProtobufSyntaxKind::ImportDef);
81    }
82
83    fn parse_option<S: Source + ?Sized>(&self, state: &mut State<'_, S>) {
84        let checkpoint = state.checkpoint();
85        state.expect(ProtobufSyntaxKind::Option).ok();
86        state.expect(ProtobufSyntaxKind::Identifier).ok();
87        state.expect(ProtobufSyntaxKind::Assign).ok();
88        state.bump(); // value
89        state.expect(ProtobufSyntaxKind::Semicolon).ok();
90        state.finish_at(checkpoint, ProtobufSyntaxKind::OptionDef);
91    }
92
93    fn parse_message<S: Source + ?Sized>(&self, state: &mut State<'_, S>) {
94        let checkpoint = state.checkpoint();
95        state.expect(ProtobufSyntaxKind::Message).ok();
96        state.expect(ProtobufSyntaxKind::Identifier).ok();
97        state.expect(ProtobufSyntaxKind::LeftBrace).ok();
98        while !state.at(ProtobufSyntaxKind::RightBrace) && state.not_at_end() {
99            state.bump();
100        }
101        state.expect(ProtobufSyntaxKind::RightBrace).ok();
102        state.finish_at(checkpoint, ProtobufSyntaxKind::MessageDef);
103    }
104
105    fn parse_enum<S: Source + ?Sized>(&self, state: &mut State<'_, S>) {
106        let checkpoint = state.checkpoint();
107        state.expect(ProtobufSyntaxKind::Enum).ok();
108        state.expect(ProtobufSyntaxKind::Identifier).ok();
109        state.expect(ProtobufSyntaxKind::LeftBrace).ok();
110        while !state.at(ProtobufSyntaxKind::RightBrace) && state.not_at_end() {
111            state.bump();
112        }
113        state.expect(ProtobufSyntaxKind::RightBrace).ok();
114        state.finish_at(checkpoint, ProtobufSyntaxKind::EnumDef);
115    }
116
117    fn parse_service<S: Source + ?Sized>(&self, state: &mut State<'_, S>) {
118        let checkpoint = state.checkpoint();
119        state.expect(ProtobufSyntaxKind::Service).ok();
120        state.expect(ProtobufSyntaxKind::Identifier).ok();
121        state.expect(ProtobufSyntaxKind::LeftBrace).ok();
122        while !state.at(ProtobufSyntaxKind::RightBrace) && state.not_at_end() {
123            state.bump();
124        }
125        state.expect(ProtobufSyntaxKind::RightBrace).ok();
126        state.finish_at(checkpoint, ProtobufSyntaxKind::ServiceDef);
127    }
128}
129
130impl<'config> Parser<ProtobufLanguage> for ProtobufParser<'config> {
131    fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<ProtobufLanguage>) -> ParseOutput<'a, ProtobufLanguage> {
132        let lexer = ProtobufLexer::new(self.language);
133        oak_core::parser::parse_with_lexer(&lexer, text, edits, cache, |state| self.parse_root_internal(state))
134    }
135}