glsl_lang_pp/parser/
syntax.rs1use rowan::Checkpoint;
2
3use lang_util::{SmolStr, TextRange};
4
5use crate::lexer;
6
7use super::{ErrorKind, ExpectAny, ParserRun, SyntaxKind::*};
8
9type InputToken = lexer::Token;
10
11pub fn file(parser: &mut ParserRun) {
12 loop {
13 parser.buffer_trivia();
15
16 if let Some(token) = parser.peek() {
17 match *token {
18 InputToken::HASH => if_section_or_control_line(parser),
19 InputToken::NEWLINE => {
20 parser.eat_trivia();
23 parser.bump();
24 }
25 _ => {
26 parser.eat_trivia();
27
28 while let Some(token) = parser.peek() {
29 parser.bump();
31
32 if *token == InputToken::NEWLINE {
33 break;
35 }
36 }
37 }
38 }
39 } else {
40 parser.eat_trivia();
41 break;
42 }
43 }
44}
45
46pub fn define_body(parser: &mut ParserRun) {
47 parser.eat_trivia();
49
50 parser.start_node(PP_DEFINE_BODY);
51 pp_tokens(parser);
52 parser.finish_node();
53
54 parser.eat_trivia();
56}
57
58fn if_section_or_control_line(parser: &mut ParserRun) {
60 let checkpoint = parser.checkpoint();
61
62 parser.eat_trivia();
63
64 parser.bump();
66
67 parser.skip_trivia();
69
70 let mut pp_type_name = None;
72 let pp_type = if let Some(token) = parser.peek() {
73 if *token == InputToken::NEWLINE {
74 Some(PP_EMPTY)
76 } else {
77 let mut error = None;
78 let name = SmolStr::from(parser.text(token));
79 pp_type_name = Some(name.clone());
80 let result = match name.as_ref() {
81 "include" => {
82 parser.bump();
83 pp_include(parser);
84 Some(PP_INCLUDE)
85 }
86 "define" => {
87 parser.bump();
88 pp_define(parser);
89 Some(PP_DEFINE)
90 }
91 "undef" => {
92 parser.bump();
93 pp_if_ident(parser);
94 Some(PP_UNDEF)
95 }
96 "line" => {
97 parser.bump();
98 pp_line(parser);
99 Some(PP_LINE)
100 }
101 "error" => {
102 parser.bump();
103 pp_error(parser);
104 Some(PP_ERROR)
105 }
106 "pragma" => {
107 parser.bump();
108 pp_pragma(parser);
109 Some(PP_PRAGMA)
110 }
111 "version" => {
112 parser.bump();
113 pp_version(parser);
114 Some(PP_VERSION)
115 }
116 "if" => {
117 parser.bump();
118 pp_if_expr(parser);
119 Some(PP_IF)
120 }
121 "ifdef" => {
122 parser.bump();
123 pp_if_ident(parser);
124 Some(PP_IFDEF)
125 }
126 "ifndef" => {
127 parser.bump();
128 pp_if_ident(parser);
129 Some(PP_IFNDEF)
130 }
131 "elif" => {
132 parser.bump();
133 pp_if_expr(parser);
135 Some(PP_ELIF)
136 }
137 "else" => {
138 parser.bump();
139 Some(PP_ELSE)
141 }
142 "endif" => {
143 parser.bump();
144 Some(PP_ENDIF)
146 }
147 "extension" => {
148 parser.bump();
149 pp_extension(parser);
150 Some(PP_EXTENSION)
151 }
152 "(" => {
153 parser.bump();
154 match pp_rs_ident(parser, token) {
155 Ok(()) => {
156 return;
158 }
159 Err(err) => {
160 error = err.into();
161 }
162 }
163 None
164 }
165 other => {
166 error = Some((
167 ErrorKind::UnknownPreprocessorDirective { name: other.into() },
168 token.range,
169 ));
170 None
171 }
172 };
173
174 if let Some(error) = error {
175 parser.push_error(error.0, error.1);
176 }
177
178 result
179 }
180 } else {
181 None
182 };
183
184 parser.skip_trivia();
186
187 match parser.peek() {
189 Some(token) if *token == InputToken::NEWLINE => {
190 parser.bump();
191 }
192 None => {
193 }
195 Some(other) => {
196 let mut start = other.range;
198
199 parser.start_node(ERROR);
201
202 while let Some(token) = parser.peek() {
203 if *token == InputToken::NEWLINE {
205 break;
206 }
207
208 start = TextRange::new(start.start(), token.range.end());
210 parser.bump();
211 }
212
213 parser.finish_node();
215
216 if let Some(InputToken::NEWLINE) = parser.peek().as_deref() {
218 parser.bump();
219 }
220
221 if pp_type.is_some() {
224 parser.push_error(
225 ErrorKind::ExtraTokensInPreprocessorDirective {
226 name: pp_type_name.unwrap(),
227 },
228 start,
229 );
230 }
231 }
232 }
233
234 match pp_type {
236 Some(t) => {
237 parser.start_node_at(checkpoint, t);
238 parser.finish_node();
239 }
240 None => {
241 parser.start_node_at(checkpoint, ERROR);
242 parser.finish_node();
243 }
244 }
245}
246
247fn pp_rs_ident(
248 parser: &mut ParserRun,
249 token: lexer::TextToken,
250) -> Result<(), (ErrorKind, TextRange)> {
251 let mut level = 1;
252 while level > 0 {
253 parser.skip_trivia();
255
256 let peeked = parser.peek().map(|tt| SmolStr::from(parser.text(tt)));
257 match peeked.as_deref() {
258 Some("(") => {
259 level += 1;
260 parser.bump();
261 }
262 Some(")") => {
263 level -= 1;
264 parser.bump();
265 }
266 Some(_) => {
267 parser.bump();
268 }
269 None => {
270 return Err((
271 ErrorKind::EndOfInput {
272 expected: Box::new([lexer::Token::RPAREN]),
273 },
274 token.range,
275 ));
276 }
277 }
278 }
279
280 Ok(())
281}
282
283fn pp_include(parser: &mut ParserRun) {
284 parser.input.set_expect_angle_string(true);
286
287 parser.skip_trivia();
288
289 parser.start_node(PP_INCLUDE_PATH);
291 pp_tokens(parser);
292 parser.finish_node();
293
294 parser.eat_trivia();
295}
296
297fn pp_define(parser: &mut ParserRun) {
298 parser.skip_trivia();
299
300 ident(parser);
302
303 if let Some(InputToken::LPAREN) = parser.peek().as_deref() {
305 let mut checkpoint = Some(parser.checkpoint());
307
308 parser.bump();
310
311 loop {
313 parser.skip_trivia();
314
315 let arg_checkpoint = parser.checkpoint();
316 match parser.expect_any(
317 &[InputToken::IDENT_KW, InputToken::RPAREN],
318 &[InputToken::NEWLINE],
319 ) {
320 ExpectAny::Found(found) => {
321 match *found {
322 InputToken::IDENT_KW => {
323 parser.start_node_at(arg_checkpoint, PP_DEFINE_ARG);
325 parser.finish_node();
326 }
327 InputToken::RPAREN => {
328 break;
330 }
331 _ => {
332 unreachable!()
333 }
334 }
335 }
336
337 ExpectAny::Unexpected(other) => {
338 if let Some(checkpoint) = checkpoint.take() {
340 parser.start_node_at(checkpoint, ERROR);
341 }
342
343 if *other == InputToken::NEWLINE {
344 break;
345 }
346 }
347
348 ExpectAny::EndOfInput => {
349 if let Some(checkpoint) = checkpoint.take() {
350 parser.start_node_at(checkpoint, ERROR);
351 }
352
353 break;
354 }
355 }
356
357 parser.skip_trivia();
358
359 match parser.expect_any(
360 &[InputToken::COMMA, InputToken::RPAREN],
361 &[InputToken::NEWLINE],
362 ) {
363 ExpectAny::Found(found) => {
364 match *found {
365 InputToken::COMMA => {
366 }
368 InputToken::RPAREN => {
369 break;
371 }
372 _ => {
373 unreachable!()
374 }
375 }
376 }
377
378 ExpectAny::Unexpected(other) => {
379 if let Some(checkpoint) = checkpoint.take() {
381 parser.start_node_at(checkpoint, ERROR);
382 }
383
384 if *other == InputToken::NEWLINE {
385 break;
386 }
387 }
388
389 ExpectAny::EndOfInput => {
390 if let Some(checkpoint) = checkpoint.take() {
391 parser.start_node_at(checkpoint, ERROR);
392 }
393
394 break;
395 }
396 }
397 }
398
399 if let Some(checkpoint) = checkpoint.take() {
401 parser.start_node_at(checkpoint, PP_DEFINE_ARGS);
402 }
403
404 parser.finish_node();
405 } else {
406 }
408
409 parser.skip_trivia();
411
412 parser.start_node(PP_DEFINE_BODY);
414 pp_tokens(parser);
415 parser.finish_node();
416
417 parser.eat_trivia();
419}
420
421fn pp_line(parser: &mut ParserRun) {
422 parser.skip_trivia();
423
424 parser.start_node(PP_LINE_BODY);
426 pp_tokens(parser);
427 parser.finish_node();
428
429 parser.eat_trivia();
431}
432
433fn pp_error(parser: &mut ParserRun) {
434 parser.skip_trivia();
435
436 parser.start_node(PP_ERROR_BODY);
438 pp_tokens(parser);
439 parser.finish_node();
440
441 parser.eat_trivia();
443}
444
445fn pp_pragma(parser: &mut ParserRun) {
446 parser.skip_trivia();
447
448 parser.start_node(PP_PRAGMA_BODY);
450 pp_tokens(parser);
451 parser.finish_node();
452
453 parser.eat_trivia();
455}
456
457fn pp_version(parser: &mut ParserRun) {
458 parser.skip_trivia();
459
460 parser.start_node(PP_VERSION_NUMBER);
462 digits(parser);
463 parser.finish_node();
464
465 parser.skip_trivia();
466
467 if let Some(InputToken::IDENT_KW) = parser.peek().as_deref() {
469 parser.start_node(PP_VERSION_PROFILE);
470 parser.bump();
471 parser.finish_node();
472 }
473}
474
475fn pp_if_expr(parser: &mut ParserRun) {
476 parser.skip_trivia();
477
478 parser.start_node(PP_IF_EXPR);
481 pp_tokens(parser);
482 parser.finish_node();
483
484 parser.eat_trivia();
485}
486
487fn pp_if_ident(parser: &mut ParserRun) {
488 parser.skip_trivia();
489
490 parser.start_node(PP_IDENT);
491 ident(parser);
492 parser.finish_node();
493}
494
495fn pp_extension(parser: &mut ParserRun) {
496 parser.skip_trivia();
497
498 ident(parser);
500
501 parser.skip_trivia();
502
503 if let ExpectAny::Found(_) = parser.expect_any(&[InputToken::COLON], &[InputToken::NEWLINE]) {
504 parser.skip_trivia();
505
506 ident(parser);
508 } else {
509 }
511}
512
513fn digits(parser: &mut ParserRun) {
514 let checkpoint = parser.checkpoint();
515
516 match parser.expect_one(InputToken::DIGITS) {
517 ExpectAny::Found(_) => {}
518 ExpectAny::Unexpected(_) | ExpectAny::EndOfInput => {
519 parser.start_node_at(checkpoint, ERROR);
520 parser.finish_node();
521 }
522 }
523}
524
525fn ident(parser: &mut ParserRun) {
526 let checkpoint = parser.checkpoint();
527
528 match parser.expect_one(InputToken::IDENT_KW) {
529 ExpectAny::Found(_) => {}
530 ExpectAny::Unexpected(_) | ExpectAny::EndOfInput => {
531 parser.start_node_at(checkpoint, ERROR);
532 parser.finish_node();
533 }
534 }
535}
536
537fn pp_concat(parser: &mut ParserRun, checkpoint: Checkpoint) {
538 parser.start_node_at(checkpoint, PP_CONCAT);
540
541 parser.bump();
543
544 loop {
546 parser.buffer_trivia();
547
548 if let Some(current) = parser.peek() {
549 match *current {
550 InputToken::NEWLINE => {
551 break;
553 }
554 InputToken::PP_CONCAT => {
555 parser.eat_trivia();
557 let checkpoint = parser.checkpoint();
558 pp_concat(parser, checkpoint);
559 }
560 _ => {
561 parser.eat_trivia();
563 parser.bump();
564 }
565 }
566 }
567 }
568
569 parser.finish_node();
571}
572
573fn pp_tokens(parser: &mut ParserRun) {
574 let mut checkpoint = parser.checkpoint();
578
579 loop {
580 parser.buffer_trivia();
582
583 if let Some(current) = parser.peek() {
585 match *current {
586 InputToken::NEWLINE => {
587 break;
589 }
590 InputToken::PP_CONCAT => {
591 parser.eat_trivia();
593
594 let checkpoint = std::mem::replace(&mut checkpoint, parser.checkpoint());
596 pp_concat(parser, checkpoint);
597 }
598 _ => {
599 parser.eat_trivia();
602
603 checkpoint = parser.checkpoint();
605
606 parser.bump();
607 }
608 }
609 } else {
610 break;
612 }
613 }
614}