cas_parser/parser/
keyword.rs1use crate::{
2 parser::{error::{kind, Error}, garbage::Garbage, Parser, Parse},
3 tokenizer::TokenKind,
4};
5use std::ops::Range;
6
7macro_rules! keywords {
11 ($(($name:ident, $lexeme:tt))*) => {
12 $(
13 #[derive(Clone, Debug, PartialEq)]
14 pub struct $name<'source> {
15 pub lexeme: &'source str,
16 pub span: Range<usize>,
17 }
18
19 impl<'source> Parse<'source> for $name<'source> {
20 fn std_parse(
21 input: &mut Parser<'source>,
22 _: &mut Vec<Error>
23 ) -> Result<Self, Vec<Error>> {
24 let token = input.next_token().map_err(|e| vec![e])?;
25
26 if token.kind == TokenKind::Keyword {
27 if token.lexeme != stringify!($lexeme) {
28 return Err(vec![Error::new(vec![token.span], kind::UnexpectedToken {
34 expected: &[TokenKind::Keyword],
35 found: token.kind,
36 })]);
37 }
38 Ok(Self {
39 lexeme: token.lexeme,
40 span: token.span,
41 })
42 } else {
43 Err(vec![Error::new(vec![token.span], kind::UnexpectedToken {
44 expected: &[TokenKind::Keyword],
45 found: token.kind,
46 })])
47 }
48 }
49 }
50
51 impl<'source> Garbage for $name<'source> {
52 fn garbage() -> Self {
53 Self { lexeme: "", span: 0..0 }
54 }
55 }
56 )*
57 };
58}
59
60keywords!(
61 (If, if)
62 (Then, then)
63 (Else, else)
64 (Loop, loop)
65 (While, while)
66 (Break, break)
67 (Continue, continue)
68);