1pub mod element_type;
3
4use crate::language::GsglLanguage;
5use oak_core::{
6 parser::{ParseCache, ParseOutput, Parser, ParserState, parse_with_lexer},
7 source::{Source, TextEdit},
8};
9
10pub(crate) type State<'a, S> = ParserState<'a, GsglLanguage, S>;
11
12pub struct GsglParser {
14 pub(crate) config: GsglLanguage,
16}
17
18impl GsglParser {
19 pub fn new(config: GsglLanguage) -> Self {
21 Self { config }
22 }
23}
24
25impl Parser<GsglLanguage> for GsglParser {
26 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<GsglLanguage>) -> ParseOutput<'a, GsglLanguage> {
27 let lexer = crate::lexer::GsglLexer::new(&self.config);
28 parse_with_lexer(&lexer, text, edits, cache, |state| {
29 let checkpoint = state.checkpoint();
30
31 while state.not_at_end() {
32 self.skip_trivia(state);
33 if state.at(crate::lexer::token_type::GsglTokenType::Struct) {
34 self.parse_struct(state);
35 }
36 else if self.is_at_type(state) {
37 self.parse_declaration_or_function(state);
38 }
39 else {
40 state.advance();
41 }
42 self.skip_trivia(state);
43 }
44
45 Ok(state.finish_at(checkpoint, crate::parser::element_type::GsglElementType::Root))
46 })
47 }
48}
49
50impl GsglParser {
51 fn skip_trivia<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
52 while state.at(crate::lexer::token_type::GsglTokenType::Whitespace) || state.at(crate::lexer::token_type::GsglTokenType::Newline) || state.at(crate::lexer::token_type::GsglTokenType::Comment) {
53 state.bump();
54 }
55 }
56
57 fn is_at_type<'a, S: Source + ?Sized>(&self, state: &State<'a, S>) -> bool {
58 match state.current().map(|t| t.kind) {
59 Some(k) => {
60 let val = k as u8;
61 (val >= 84 && val <= 107) || k == crate::lexer::token_type::GsglTokenType::Identifier
63 }
64 None => false,
65 }
66 }
67
68 fn parse_struct<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
69 let cp = state.checkpoint();
70 state.expect(crate::lexer::token_type::GsglTokenType::Struct).ok();
71 self.skip_trivia(state);
72
73 if state.at(crate::lexer::token_type::GsglTokenType::Identifier) {
74 state.bump();
75 }
76 self.skip_trivia(state);
77
78 if state.at(crate::lexer::token_type::GsglTokenType::LeftBrace) {
79 state.bump();
80 while state.not_at_end() && !state.at(crate::lexer::token_type::GsglTokenType::RightBrace) {
81 if self.is_at_type(state) {
82 self.parse_variable_declaration(state);
83 }
84 else {
85 state.advance();
86 }
87 self.skip_trivia(state);
88 }
89 if state.at(crate::lexer::token_type::GsglTokenType::RightBrace) {
90 state.bump();
91 }
92 }
93
94 if state.at(crate::lexer::token_type::GsglTokenType::Semicolon) {
95 state.bump();
96 }
97
98 state.finish_at(cp, crate::parser::element_type::GsglElementType::StructDecl);
99 }
100
101 fn parse_declaration_or_function<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
102 let cp = state.checkpoint();
103
104 state.bump();
106 self.skip_trivia(state);
107
108 if state.at(crate::lexer::token_type::GsglTokenType::Identifier) {
110 state.bump();
111 }
112 self.skip_trivia(state);
113
114 if state.at(crate::lexer::token_type::GsglTokenType::LeftParen) {
115 self.parse_parameter_list(state);
117 self.skip_trivia(state);
118
119 if state.at(crate::lexer::token_type::GsglTokenType::LeftBrace) {
120 self.parse_block(state);
121 }
122 else if state.at(crate::lexer::token_type::GsglTokenType::Semicolon) {
123 state.bump();
124 }
125 state.finish_at(cp, crate::parser::element_type::GsglElementType::FunctionDecl);
126 }
127 else {
128 while state.not_at_end() && !state.at(crate::lexer::token_type::GsglTokenType::Semicolon) {
130 state.bump();
131 }
132 if state.at(crate::lexer::token_type::GsglTokenType::Semicolon) {
133 state.bump();
134 }
135 state.finish_at(cp, crate::parser::element_type::GsglElementType::VariableDecl);
136 }
137 }
138
139 fn parse_variable_declaration<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
140 let cp = state.checkpoint();
141 state.bump(); self.skip_trivia(state);
143 if state.at(crate::lexer::token_type::GsglTokenType::Identifier) {
144 state.bump();
145 }
146 self.skip_trivia(state);
147 if state.at(crate::lexer::token_type::GsglTokenType::Semicolon) {
148 state.bump();
149 }
150 state.finish_at(cp, crate::parser::element_type::GsglElementType::VariableDecl);
151 }
152
153 fn parse_parameter_list<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
154 state.expect(crate::lexer::token_type::GsglTokenType::LeftParen).ok();
155 self.skip_trivia(state);
156
157 while state.not_at_end() && !state.at(crate::lexer::token_type::GsglTokenType::RightParen) {
158 self.parse_parameter(state);
159 self.skip_trivia(state);
160 if state.at(crate::lexer::token_type::GsglTokenType::Comma) {
161 state.bump();
162 self.skip_trivia(state);
163 }
164 }
165
166 if state.at(crate::lexer::token_type::GsglTokenType::RightParen) {
167 state.bump();
168 }
169 }
170
171 fn parse_parameter<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
172 let cp = state.checkpoint();
173 if self.is_at_type(state) {
174 state.bump(); self.skip_trivia(state);
176 }
177 if state.at(crate::lexer::token_type::GsglTokenType::Identifier) {
178 state.bump(); }
180 state.finish_at(cp, crate::parser::element_type::GsglElementType::Parameter);
181 }
182
183 fn parse_block<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
184 let cp = state.checkpoint();
185 state.expect(crate::lexer::token_type::GsglTokenType::LeftBrace).ok();
186 self.skip_trivia(state);
187
188 while state.not_at_end() && !state.at(crate::lexer::token_type::GsglTokenType::RightBrace) {
189 self.parse_statement(state);
190 self.skip_trivia(state);
191 }
192
193 if state.at(crate::lexer::token_type::GsglTokenType::RightBrace) {
194 state.bump();
195 }
196 state.finish_at(cp, crate::parser::element_type::GsglElementType::Block);
197 }
198
199 fn parse_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
200 let cp = state.checkpoint();
201 if state.at(crate::lexer::token_type::GsglTokenType::LeftBrace) {
202 self.parse_block(state);
203 }
204 else {
205 while state.not_at_end() && !state.at(crate::lexer::token_type::GsglTokenType::Semicolon) && !state.at(crate::lexer::token_type::GsglTokenType::RightBrace) {
206 state.bump();
207 }
208 if state.at(crate::lexer::token_type::GsglTokenType::Semicolon) {
209 state.bump();
210 }
211 }
212 state.finish_at(cp, crate::parser::element_type::GsglElementType::Statement);
213 }
214}