aiken_lang/parser/
utils.rs1use super::{error::ParseError, token::Token};
2use chumsky::prelude::*;
3
4pub fn optional_flag(token: Token) -> impl Parser<Token, bool, Error = ParseError> {
5 just(token).ignored().or_not().map(|v| v.is_some())
6}
7
8pub fn type_name_with_args() -> impl Parser<Token, (String, Option<Vec<String>>), Error = ParseError>
9{
10 just(Token::Type).ignore_then(
11 select! {Token::UpName { name } => name}.then(
12 select! {Token::Name { name } => name}
13 .separated_by(just(Token::Comma))
14 .allow_trailing()
15 .delimited_by(just(Token::Less), just(Token::Greater))
16 .or_not(),
17 ),
18 )
19}
20
21#[macro_export]
22macro_rules! assert_expr {
23 ($code:expr) => {
24 use chumsky::Parser;
25
26 match $crate::parser::lexer::run(indoc::indoc! { $code }) {
27 Ok($crate::parser::lexer::LexInfo { tokens, .. }) => {
28 let stream = chumsky::Stream::from_iter($crate::ast::Span::create(tokens.len(), 1), tokens.into_iter());
29
30 let result = $crate::parser::expr::sequence().parse(stream);
31
32 match result {
33 Ok(expr) => {
34 insta::with_settings!({
35 description => concat!("Code:\n\n", indoc::indoc! { $code }),
36 prepend_module_to_snapshot => false,
37 omit_expression => true
38 }, {
39 insta::assert_debug_snapshot!(expr);
40 })
41 },
42 Err(err) => {
43 insta::with_settings!({
44 description => concat!("Invalid code (parse error):\n\n", indoc::indoc! { $code }),
45 prepend_module_to_snapshot => false,
46 omit_expression => true
47 }, {
48 insta::assert_snapshot!(err.into_iter().map(|e| e.to_string()).collect::<Vec<_>>().join("\n"));
49 })
50 }
51 }
52 }
53 Err(err) => {
54 insta::with_settings!({
55 description => concat!("Invalid code (lexer error):\n\n", indoc::indoc! { $code }),
56 prepend_module_to_snapshot => false,
57 omit_expression => true
58 }, {
59 insta::assert_snapshot!(err.into_iter().map(|e| e.to_string()).collect::<Vec<_>>().join("\n"));
60 })
61 }
62 }
63 };
64}
65
66#[macro_export]
67macro_rules! assert_annotation {
68 ($code:expr) => {
69 use chumsky::Parser;
70
71 let $crate::parser::lexer::LexInfo { tokens, .. } = $crate::parser::lexer::run(indoc::indoc! { $code }).unwrap();
72
73 let stream = chumsky::Stream::from_iter($crate::ast::Span::create(tokens.len(), 1), tokens.into_iter());
74
75 let result = $crate::parser::annotation().parse(stream).unwrap();
76
77 insta::with_settings!({
78 description => concat!("Code:\n\n", indoc::indoc! { $code }),
79 prepend_module_to_snapshot => false,
80 omit_expression => true
81 }, {
82 insta::assert_debug_snapshot!(result);
83 });
84 };
85}
86
87#[macro_export]
88macro_rules! assert_pattern {
89 ($code:expr) => {
90 use chumsky::Parser;
91
92 let $crate::parser::lexer::LexInfo { tokens, .. } = $crate::parser::lexer::run(indoc::indoc! { $code }).unwrap();
93
94 let stream = chumsky::Stream::from_iter($crate::ast::Span::create(tokens.len(), 1), tokens.into_iter());
95
96 let result = $crate::parser::pattern().parse(stream).unwrap();
97
98 insta::with_settings!({
99 description => concat!("Code:\n\n", indoc::indoc! { $code }),
100 prepend_module_to_snapshot => false,
101 omit_expression => true
102 }, {
103 insta::assert_debug_snapshot!(result);
104 });
105 };
106}
107
108#[macro_export]
109macro_rules! assert_module {
110 ($code:expr) => {
111 let (module, _) =
112 $crate::parser::module(indoc::indoc!{ $code }, $crate::ast::ModuleKind::Validator).expect("Failed to parse code");
113
114 insta::with_settings!({
115 description => concat!("Code:\n\n", indoc::indoc! { $code }),
116 prepend_module_to_snapshot => false,
117 omit_expression => true
118 }, {
119 insta::assert_debug_snapshot!(module);
120 });
121 };
122}
123
124#[macro_export]
125macro_rules! assert_definition {
126 ($code:expr) => {
127 use chumsky::Parser;
128
129 let $crate::parser::lexer::LexInfo { tokens, .. } = $crate::parser::lexer::run(indoc::indoc! { $code }).unwrap();
130
131 let stream = chumsky::Stream::from_iter($crate::ast::Span::create(tokens.len(), 1), tokens.into_iter());
132
133 let result = $crate::parser::definition().parse(stream);
134
135 match result {
136 Ok(expr) => {
137 insta::with_settings!({
138 description => concat!("Code:\n\n", indoc::indoc! { $code }),
139 prepend_module_to_snapshot => false,
140 omit_expression => true
141 }, {
142 insta::assert_debug_snapshot!(expr);
143 })
144 },
145 Err(err) => {
146 insta::with_settings!({
147 description => concat!("Invalid code (parse error):\n\n", indoc::indoc! { $code }),
148 prepend_module_to_snapshot => false,
149 omit_expression => true
150 }, {
151 insta::assert_snapshot!(err.into_iter().map(|e| e.to_string()).collect::<Vec<_>>().join("\n"));
152 })
153 }
154 }
155 };
156}
157
158#[macro_export]
159macro_rules! assert_import {
160 ($code:expr) => {
161 use chumsky::Parser;
162
163 let $crate::parser::lexer::LexInfo { tokens, .. } = $crate::parser::lexer::run(indoc::indoc! { $code }).unwrap();
164
165 let stream = chumsky::Stream::from_iter($crate::ast::Span::create(tokens.len(), 1), tokens.into_iter());
166
167 let result = $crate::parser::import().parse(stream).unwrap();
168
169 insta::with_settings!({
170 description => concat!("Code:\n\n", indoc::indoc! { $code }),
171 prepend_module_to_snapshot => false,
172 omit_expression => true
173 }, {
174 insta::assert_debug_snapshot!(result);
175 });
176 };
177}
178
179#[macro_export]
180macro_rules! assert_format {
181 ($code:expr) => {
182 let src = indoc::indoc! { $code };
183
184 let (module, extra) =
185 $crate::parser::module(src, $crate::ast::ModuleKind::Lib).expect("Failed to parse code");
186
187 let mut out = String::new();
188 $crate::format::pretty(&mut out, module, extra, &src);
189
190 insta::with_settings!({
191 description => concat!("Code:\n\n", indoc::indoc! { $code }),
192 prepend_module_to_snapshot => false,
193 omit_expression => true
194 }, {
195 insta::assert_snapshot!(out);
196 });
197
198 let (module2, extra2) = $crate::parser::module(&out, $crate::ast::ModuleKind::Lib).unwrap();
200 let mut out2 = String::new();
201 $crate::format::pretty(&mut out2, module2, extra2, &out);
202 pretty_assertions::assert_eq!(out, out2, "formatting isn't idempotent");
203 };
204}