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