oak_protobuf/parser/
mod.rs1use 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(); 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}