1use crate::lexer::ClosingParen;
21use crate::Error;
22
23use super::lexer;
24use super::Str;
25use std::borrow::Cow;
26use std::collections::VecDeque;
27use std::fmt::Write;
28
29pub trait TreeIter<'a>: Iterator<Item = TreeItem<'a, Self::ArgsIter>> {
31 type ArgsIter: ArgsIter<'a, TreeIter = Self>;
33
34 fn remaining_source(&self) -> Str<'a>;
36}
37
38pub enum TreeItem<'a, A> {
40 FuncCall {
42 func_name: Str<'a>,
44 args: A,
46 },
47 Comment {
49 value: &'a str,
51 },
52}
53
54pub trait ArgsIter<'a>: Iterator<Item = ArgsItem<'a, Self::TreeIter>> {
56 type TreeIter: TreeIter<'a, ArgsIter = Self>;
58}
59
60pub enum ArgsItem<'a, F> {
62 Regular {
64 key: Option<Str<'a>>,
69 value: Value<'a>,
71 value_source: Str<'a>,
73 },
74 List {
76 key: Option<Str<'a>>,
81 square_open: Str<'a>,
83 tree: F,
87 },
88 Comment {
90 value: &'a str,
92 },
93}
94
95pub fn pretty_print<'a, W: std::fmt::Write>(
97 w: &mut W,
98 tree: impl TreeIter<'a>,
99) -> std::fmt::Result {
100 pretty_print_impl(w, tree, 0)?;
101 Ok(())
102}
103
104#[derive(Default)]
105struct ArgsPrinter<'a> {
106 indent: usize,
107 multiline: bool,
108 buf: Vec<(Option<Str<'a>>, Value<'a>)>,
109}
110
111impl<'a> ArgsPrinter<'a> {
112 fn activate_multiline<W: std::fmt::Write>(&mut self, w: &mut W) -> std::fmt::Result {
113 self.multiline = true;
114 for (key, value) in &self.buf {
115 self.print_multiline(w, key, value)?;
116 }
117 self.buf.clear();
118 Ok(())
119 }
120 fn print<W: std::fmt::Write>(
121 &mut self,
122 w: &mut W,
123 key: Option<Str<'a>>,
124 value: Value<'a>,
125 ) -> std::fmt::Result {
126 if self.buf.len() >= 4 {
127 self.activate_multiline(w)?;
128 }
129 if self.multiline {
130 self.print_multiline(w, &key, &value)?;
131 } else {
132 self.buf.push((key, value));
133 }
134 Ok(())
135 }
136 fn print_multiline<W: std::fmt::Write>(
137 &self,
138 w: &mut W,
139 key: &Option<Str<'a>>,
140 value: &Value<'a>,
141 ) -> std::fmt::Result {
142 let indent = Indent(self.indent);
143 write!(w, "\n{indent} ")?;
144 if let Some(key) = key {
145 write!(w, "{key}=")?;
146 }
147 write!(w, "{},", value)?;
148 Ok(())
149 }
150 fn flush<W: std::fmt::Write>(&mut self, w: &mut W) -> std::fmt::Result {
151 let mut remaining_args = self.buf.len();
152 for (keyword, arg) in &self.buf {
153 if let Some(keyword) = keyword {
154 write!(w, "{keyword}=")?;
155 }
156 write!(w, "{}", arg)?;
157 remaining_args = remaining_args.saturating_sub(1);
158 if remaining_args > 0 {
159 write!(w, ", ")?;
160 }
161 }
162 let indent = Indent(self.indent);
163 if self.multiline {
164 write!(w, "\n{indent}")?;
165 }
166 self.buf.clear();
167 self.multiline = false;
168 Ok(())
169 }
170}
171
172struct Indent(usize);
173
174impl std::fmt::Display for Indent {
175 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
176 for _ in 0..self.0 {
177 f.write_char(' ')?;
178 }
179 Ok(())
180 }
181}
182
183fn pretty_print_impl<'a, W: std::fmt::Write, T: TreeIter<'a>>(
184 w: &mut W,
185 tree: T,
186 depth: usize,
187) -> std::fmt::Result {
188 let indent = Indent(depth);
189 let mut ap: ArgsPrinter = ArgsPrinter {
190 indent: depth,
191 ..Default::default()
192 };
193 for item in tree {
194 match item {
195 TreeItem::FuncCall { func_name, args } => {
196 write!(w, "{indent}{func_name}(")?;
197 for item in args {
198 match item {
199 ArgsItem::Comment { value } => {
200 ap.activate_multiline(w)?;
201 write!(w, "\n{indent} #{value}")?;
202 }
203 ArgsItem::Regular {
204 key,
205 value,
206 value_source: _,
207 } => {
208 ap.print(w, key, value)?;
209 }
210 ArgsItem::List {
211 key,
212 square_open: _,
213 tree,
214 } => {
215 ap.activate_multiline(w)?;
216 write!(w, "\n{indent} ")?;
217 if let Some(key) = key {
218 write!(w, "{key}=")?;
219 }
220 writeln!(w, "[")?;
221 pretty_print_impl(w, tree, depth + 4)?;
222 write!(w, "{indent} ],")?;
223 }
224 }
225 }
226 ap.flush(w)?;
227 writeln!(w, ")")?;
228 }
229 TreeItem::Comment { value } => {
230 writeln!(w, "{indent}#{value}")?;
231 }
232 };
233 }
234 Ok(())
235}
236
237#[derive(Debug, Default, PartialEq, Clone)]
239pub struct Tree<'a> {
240 pub calls: Vec<FuncCall<'a>>,
241 pub trailing_comments: Vec<&'a str>,
242}
243
244impl<'a> Tree<'a> {
245 pub fn build(tree: impl TreeIter<'a>) -> Self {
247 Self::build_impl(tree)
248 }
249
250 fn build_impl<I: TreeIter<'a>>(tree: I) -> Self {
251 let mut comments = vec![];
252 let take_comments = |comments: &mut Vec<&'a str>| {
253 let mut v = vec![];
254 std::mem::swap(&mut v, comments);
255 v
256 };
257 let calls = tree
258 .filter_map(|item| match item {
259 TreeItem::FuncCall { func_name, args } => {
260 let func_comments = take_comments(&mut comments);
261 let args: Vec<Arg<'a>> = args
262 .filter_map(|item| match item {
263 ArgsItem::Regular {
264 key,
265 value,
266 value_source,
267 } => Some(Arg {
268 comments: take_comments(&mut comments),
269 key,
270 value,
271 value_source,
272 }),
273 ArgsItem::List {
274 key,
275 square_open: _,
276 tree,
277 } => {
278 let value_source = tree.remaining_source();
279 let inner_tree = Tree::build_impl(tree);
280 Some(Arg {
281 comments: take_comments(&mut comments),
282 key,
283 value: Value::List(inner_tree),
284 value_source,
285 })
286 }
287 ArgsItem::Comment { value } => {
288 comments.push(value);
289 None
290 }
291 })
292 .collect();
293 Some(FuncCall {
294 comments: func_comments,
295 func_name,
296 args,
297 trailing_comments: take_comments(&mut comments),
298 })
299 }
300 TreeItem::Comment { value } => {
301 comments.push(value);
302 None
303 }
304 })
305 .collect();
306 Self {
307 calls,
308 trailing_comments: comments,
309 }
310 }
311
312 pub fn iter<'b>(&'b self) -> impl TreeIter<'a> + 'b {
313 let mut iter = ExplicitIter { tree_stack: vec![] };
314 iter.push_tree(self);
315 iter
316 }
317}
318
319impl<'a> std::fmt::Display for Tree<'a> {
320 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
321 pretty_print(f, self.iter())
322 }
323}
324
325struct ExplicitIter<'a, 'b> {
327 tree_stack: Vec<TreeStackElem<'a, 'b>>,
328}
329
330enum TreeStackElem<'a, 'b> {
331 FuncCall(&'b FuncCall<'a>),
332 Comments(&'b [&'a str]),
333}
334
335struct ExplicitArgsIter<'a, 'b> {
337 args_stack: Vec<ArgsStackElem<'a, 'b>>,
338}
339
340enum ArgsStackElem<'a, 'b> {
341 Arg(&'b Arg<'a>),
342 Comments(&'b [&'a str]),
343}
344
345impl<'a, 'b> ExplicitIter<'a, 'b> {
346 fn push_tree(&mut self, t: &'b Tree<'a>) {
347 self.tree_stack
348 .push(TreeStackElem::Comments(&t.trailing_comments));
349 for call in t.calls.iter().rev() {
350 self.push_func_call(call);
351 }
352 }
353 fn push_func_call(&mut self, call: &'b FuncCall<'a>) {
354 self.tree_stack.push(TreeStackElem::FuncCall(call));
355 self.tree_stack
356 .push(TreeStackElem::Comments(&call.comments));
357 }
358}
359
360impl<'a, 'b> ExplicitArgsIter<'a, 'b> {
361 fn push_args(&mut self, call: &'b FuncCall<'a>) {
362 self.args_stack
363 .push(ArgsStackElem::Comments(&call.trailing_comments));
364 for a in call.args.iter().rev() {
365 self.args_stack.push(ArgsStackElem::Arg(a));
366 self.args_stack.push(ArgsStackElem::Comments(&a.comments));
367 }
368 }
369}
370
371impl<'a, 'b> TreeIter<'a> for ExplicitIter<'a, 'b> {
372 type ArgsIter = ExplicitArgsIter<'a, 'b>;
373
374 fn remaining_source(&self) -> Str<'a> {
375 "".into()
376 }
377}
378
379impl<'a, 'b> Iterator for ExplicitIter<'a, 'b> {
380 type Item = TreeItem<'a, ExplicitArgsIter<'a, 'b>>;
381
382 fn next(&mut self) -> Option<Self::Item> {
383 loop {
384 match self.tree_stack.pop()? {
385 TreeStackElem::FuncCall(func_call) => {
386 let mut iter = ExplicitArgsIter { args_stack: vec![] };
387 iter.push_args(func_call);
388 return Some(TreeItem::FuncCall {
389 func_name: func_call.func_name.clone(),
390 args: iter,
391 });
392 }
393 TreeStackElem::Comments(items) => {
394 if let Some((head, tail)) = items.split_first() {
395 self.tree_stack.push(TreeStackElem::Comments(tail));
396 return Some(TreeItem::Comment { value: head });
397 }
398 }
399 }
400 }
401 }
402}
403
404impl<'a, 'b> ArgsIter<'a> for ExplicitArgsIter<'a, 'b> {
405 type TreeIter = ExplicitIter<'a, 'b>;
406}
407
408impl<'a, 'b> Iterator for ExplicitArgsIter<'a, 'b> {
409 type Item = ArgsItem<'a, ExplicitIter<'a, 'b>>;
410
411 fn next(&mut self) -> Option<Self::Item> {
412 loop {
413 match self.args_stack.pop()? {
414 ArgsStackElem::Arg(arg) => {
415 return match arg.value.try_clone_value() {
416 Ok(v) => Some(ArgsItem::Regular {
417 key: arg.key.clone(),
418 value: v,
419 value_source: arg.value_source.clone(),
420 }),
421 Err(tree) => {
422 let mut iter = ExplicitIter { tree_stack: vec![] };
423 iter.push_tree(tree);
424 Some(ArgsItem::List {
425 key: arg.key.clone(),
426 square_open: "".into(),
427 tree: iter,
428 })
429 }
430 };
431 }
432 ArgsStackElem::Comments(items) => {
433 if let Some((head, tail)) = items.split_first() {
434 self.args_stack.push(ArgsStackElem::Comments(tail));
435 return Some(ArgsItem::Comment { value: head });
436 }
437 }
438 }
439 }
440 }
441}
442
443pub fn parse<'a>(source: &'a str, errs: super::ErrorAccumulator<'a>) -> impl TreeIter<'a> {
445 let lexer = lexer::Lexer::new(source, errs.clone());
446 parse_using_lexer(lexer, errs)
447}
448
449pub fn parse_using_lexer<'a>(
453 lexer: lexer::Lexer<'a>,
454 errs: super::ErrorAccumulator<'a>,
455) -> impl TreeIter<'a> {
456 ParseTreeIter {
457 next_tree: None,
458 c: ParseIterCommon {
459 comments: Default::default(),
460 next_token: None,
461 lexer,
462 errs,
463 },
464 }
465}
466
467struct ParseTreeIter<'a> {
468 next_tree: Option<(Str<'a>, lexer::Lexer<'a>)>,
469 c: ParseIterCommon<'a>,
470}
471
472struct ParseArgsIter<'a> {
473 next_arg: Option<ArgsItem<'a, ParseTreeIter<'a>>>,
474 c: ParseIterCommon<'a>,
475}
476
477struct ParseIterCommon<'a> {
478 comments: VecDeque<&'a str>,
479 next_token: Option<lexer::Token<'a>>,
480 lexer: lexer::Lexer<'a>,
481 errs: super::ErrorAccumulator<'a>,
482}
483
484impl<'a> ParseIterCommon<'a> {
485 fn refill(&mut self) {
486 if self.next_token.is_some() {
487 return;
488 }
489 for token in self.lexer.by_ref() {
490 match token.value {
491 lexer::TokenValue::Comment => {
492 self.comments.push_back(token.source.str());
493 }
494 lexer::TokenValue::SquareClose | lexer::TokenValue::RoundClose => {
495 self.errs.add(crate::Error::UnmatchedClosingBracket {
496 close: token.source,
497 });
498 }
499 _ => {
500 self.next_token = Some(token);
501 break;
502 }
503 }
504 }
505 }
506
507 fn parse_optional<F: Fn(&lexer::Token<'a>) -> bool>(&mut self, f: F) {
508 self.refill();
509 if let Some(token) = &self.next_token {
510 if f(token) {
511 self.next_token = None;
512 }
513 }
514 }
515
516 fn parse_required<T, F: FnMut(lexer::Token<'a>) -> Option<T>>(
517 &mut self,
518 mut f: F,
519 want: &'static str,
520 ) -> Option<T> {
521 loop {
522 self.refill();
523 let token = self.next_token.take()?;
524 enum Skipped {
525 Parens(Option<ClosingParen>),
526 Other,
527 }
528 let skipped = match token.value {
529 lexer::TokenValue::SquareOpen { closing }
530 | lexer::TokenValue::RoundOpen { closing } => Skipped::Parens(closing),
531 _ => Skipped::Other,
532 };
533 let token_source = token.source.clone();
534 if let Some(t) = f(token) {
535 return Some(t);
536 }
537 let skipped = match skipped {
538 Skipped::Parens(closing) => {
539 let inner = self.lexer.split_nested(closing);
540 let mut s = inner.remaining_source();
541 include_parens(&mut s);
542 s
543 }
544 Skipped::Other => token_source.clone(),
545 };
546 self.errs.add(Error::UnexpectedToken {
547 want,
548 got: token_source,
549 skipped,
550 });
551 }
552 }
553}
554
555fn include_parens(s: &mut Str) {
556 if let Some(i) = s.start.checked_sub(1) {
558 if (s.value.as_bytes()[i] as u32) == ('[' as u32)
559 || (s.value.as_bytes()[i] as u32) == ('(' as u32)
560 {
561 s.start = i;
562 }
563 }
564 if s.value[s.end..].starts_with(']') || s.value[s.end..].starts_with(')') {
566 s.end += 1;
567 }
568}
569
570impl<'a> TreeIter<'a> for ParseTreeIter<'a> {
571 type ArgsIter = ParseArgsIter<'a>;
572 fn remaining_source(&self) -> Str<'a> {
573 let mut s = self.c.lexer.remaining_source();
574 include_parens(&mut s);
575 s
576 }
577}
578
579impl<'a> Iterator for ParseTreeIter<'a> {
580 type Item = TreeItem<'a, ParseArgsIter<'a>>;
581
582 fn next(&mut self) -> Option<Self::Item> {
583 if let Some(comment) = self.c.comments.pop_front() {
584 return Some(TreeItem::Comment { value: comment });
585 }
586 if let Some((func_name, lexer)) = self.next_tree.take() {
587 return Some(TreeItem::FuncCall {
588 func_name,
589 args: ParseArgsIter {
590 next_arg: None,
591 c: ParseIterCommon {
592 comments: Default::default(),
593 next_token: None,
594 lexer,
595 errs: self.c.errs.clone(),
596 },
597 },
598 });
599 }
600
601 let func_name_or = self.c.parse_required(
603 |token| match token.value {
604 lexer::TokenValue::Keyword => Some(token.source),
605 _ => None,
606 },
607 "a function name",
608 );
609 let func_name = match func_name_or {
610 Some(func_name) => func_name,
611 None => {
612 if self.c.comments.is_empty() {
613 return None;
614 }
615 return self.next();
616 }
617 };
618 let closing_or = self.c.parse_required(
620 |token| match token.value {
621 lexer::TokenValue::RoundOpen { closing } => Some(closing),
622 _ => None,
623 },
624 "opening parenthesis",
625 );
626 let closing = match closing_or {
627 Some(closing) => closing,
628 None => {
629 self.c.errs.add(Error::MissingArgsForFunction {
630 function_name: func_name,
631 });
632 return self.next();
633 }
634 };
635 let inner = self.c.lexer.split_nested(closing);
636 self.next_tree = Some((func_name, inner));
637 self.next()
638 }
639}
640
641impl<'a> ArgsIter<'a> for ParseArgsIter<'a> {
642 type TreeIter = ParseTreeIter<'a>;
643}
644
645impl<'a> Iterator for ParseArgsIter<'a> {
646 type Item = ArgsItem<'a, ParseTreeIter<'a>>;
647
648 fn next(&mut self) -> Option<Self::Item> {
649 if let Some(comment) = self.c.comments.pop_front() {
650 return Some(ArgsItem::Comment { value: comment });
651 }
652 if let Some(next) = self.next_arg.take() {
653 return Some(next);
654 }
655
656 enum ArgStart<'a> {
657 Value(lexer::Token<'a>),
658 Keyword(Str<'a>),
659 }
660 let start = self.c.parse_required(
661 |token| {
662 use lexer::TokenValue;
663 match token.value {
664 TokenValue::String(_)
665 | TokenValue::Integer(_)
666 | TokenValue::Scaled(_)
667 | TokenValue::InfiniteGlue(_, _)
668 | TokenValue::SquareOpen { .. } => Some(ArgStart::Value(token)),
669 lexer::TokenValue::Keyword => Some(ArgStart::Keyword(token.source)),
670 _ => None,
671 }
672 },
673 "a function argument",
674 );
675 let Some(start) = start else {
676 if self.c.comments.is_empty() {
677 return None;
678 }
679 return self.next();
680 };
681 let (key, value) = match start {
682 ArgStart::Keyword(key) => {
683 self.c.parse_required(
684 |token| match token.value {
685 lexer::TokenValue::Equal => Some(()),
686 _ => None,
687 },
688 "an equals",
689 );
690 let value = self.c.parse_required(
691 |token| {
692 use lexer::TokenValue;
693 match token.value {
694 TokenValue::String(_)
695 | TokenValue::Integer(_)
696 | TokenValue::Scaled(_)
697 | TokenValue::InfiniteGlue(_, _)
698 | TokenValue::SquareOpen { .. } => Some(token),
699 _ => None,
700 }
701 },
702 "value of a keyword argument",
703 );
704 let Some(value) = value else {
705 self.c
706 .errs
707 .add(Error::IncompleteKeywordArg { keyword: key });
708 return self.next();
709 };
710 (Some(key), value)
711 }
712 ArgStart::Value(value) => (None, value),
713 };
714 let mut c = None;
715 let value_v = match value.value {
716 lexer::TokenValue::String(s) => Value::String(s),
717 lexer::TokenValue::Integer(n) => Value::Integer(n),
718 lexer::TokenValue::Scaled(n) => Value::Scaled(n),
719 lexer::TokenValue::InfiniteGlue(s, o) => Value::InfiniteGlue(s, o),
720 lexer::TokenValue::SquareOpen { closing } => {
721 c = closing;
722 Value::List(Default::default())
723 }
724 _ => unreachable!(),
725 };
726 self.next_arg = Some(match value_v {
727 Value::List(_) => {
728 let lexer = self.c.lexer.split_nested(c);
729 ArgsItem::List {
730 key,
731 square_open: value.source,
732 tree: ParseTreeIter {
733 next_tree: None,
734 c: ParseIterCommon {
735 comments: Default::default(),
736 next_token: None,
737 lexer,
738 errs: self.c.errs.clone(),
739 },
740 },
741 }
742 }
743 value_v => ArgsItem::Regular {
744 key,
745 value: value_v,
746 value_source: value.source,
747 },
748 });
749 self.c
751 .parse_optional(|token| matches!(token.value, lexer::TokenValue::Comma));
752 self.next()
753 }
754}
755
756#[derive(Debug, Clone)]
758pub struct Arg<'a> {
759 pub comments: Vec<&'a str>,
761 pub key: Option<Str<'a>>,
764 pub value: Value<'a>,
765 pub value_source: Str<'a>,
766}
767
768impl<'a> PartialEq for Arg<'a> {
769 fn eq(&self, other: &Self) -> bool {
770 let eq = self.comments == other.comments && self.value == other.value;
771 if self.value_source.is_empty() || other.value_source.is_empty() {
773 eq
774 } else {
775 eq && self.value_source == other.value_source
776 }
777 }
778}
779
780#[derive(Debug, PartialEq, Clone)]
782pub enum Value<'a> {
783 Integer(i32),
784 Scaled(common::Scaled),
785 InfiniteGlue(common::Scaled, common::GlueOrder),
786 String(Cow<'a, str>),
787 List(Tree<'a>),
788}
789
790impl<'a> Value<'a> {
791 pub fn try_clone_value(&self) -> Result<Self, &Tree<'a>> {
796 use Value::*;
797 let ok = match self {
798 Integer(i) => Integer(*i),
799 Scaled(scaled) => Scaled(*scaled),
800 InfiniteGlue(scaled, glue_order) => InfiniteGlue(*scaled, *glue_order),
801 String(cow) => String(cow.clone()),
804 List(tree) => return Err(tree),
805 };
806 Ok(ok)
807 }
808 pub fn description(&self) -> &'static str {
809 use Value::*;
810 match self {
811 Integer(_) => "an integer",
812 Scaled(_) => "a number",
813 InfiniteGlue(_, _) => "an infinite glue component",
814 String(_) => "a string",
815 List(_) => "a list",
816 }
817 }
818}
819
820impl<'a> std::fmt::Display for Value<'a> {
821 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
822 use Value::*;
823 match self {
824 Integer(i) => write!(f, "{i}"),
825 Scaled(scaled) => write!(f, "{scaled}"),
826 InfiniteGlue(scaled, glue_order) => {
827 write!(f, "{}{glue_order}", scaled.display_no_units())
828 }
829 String(str) => {
830 write!(f, r#"""#)?;
831 for c in str.chars() {
832 write!(f, "{}", c.escape_debug())?;
833 }
834 write!(f, r#"""#)
835 }
836 List(tree) => write!(f, "{tree}"),
837 }
838 }
839}
840
841#[derive(Debug, PartialEq, Clone)]
843pub struct FuncCall<'a> {
844 pub comments: Vec<&'a str>,
846 pub func_name: Str<'a>,
848 pub args: Vec<Arg<'a>>,
850 pub trailing_comments: Vec<&'a str>,
852}
853
854impl<'a> FuncCall<'a> {
855 pub fn iter<'b>(&'b self) -> impl TreeIter<'a> + 'b {
856 let mut iter = ExplicitIter { tree_stack: vec![] };
857 iter.push_func_call(self);
858 iter
859 }
860}
861
862impl<'a> std::fmt::Display for FuncCall<'a> {
863 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
864 pretty_print(f, self.iter())
865 }
866}
867
868#[cfg(test)]
869mod tests {
870 use crate::ErrorAccumulator;
871
872 use super::*;
873
874 fn run_parse_test(input: &str, want: Vec<FuncCall>) {
875 let want = Tree {
876 calls: want,
877 trailing_comments: vec![],
878 };
879 let errs: ErrorAccumulator = Default::default();
880 let got = Tree::build(parse(input, errs.clone()));
881 assert_eq!(got, want);
882 assert_eq!(Ok(()), errs.check());
883 }
884
885 fn run_convert_test(input: Vec<FuncCall>) {
886 let tree = Tree {
887 calls: input,
888 trailing_comments: vec![],
889 };
890 let got = Tree::build(tree.iter());
891 assert_eq!(got, tree);
892 }
893
894 macro_rules! cst_tests {
895 ( $( (
896 $name: ident,
897 $input: expr,
898 $want: expr,
899 ), )+ ) => {
900 $(
901 mod $name {
902 use super::*;
903 #[test]
904 fn parse_test() {
905 let input = $input;
906 let want = $want;
907 run_parse_test(&input, want);
908 }
909 #[test]
910 fn convert_test() {
911 let input = $want;
912 run_convert_test(input);
913 }
914 }
915 )+
916 };
917 }
918
919 cst_tests!(
920 (
921 basic_case,
922 "a(b=[c()])",
923 vec![FuncCall {
924 comments: vec![],
925 func_name: "a".into(),
926 args: vec![Arg {
927 comments: vec![],
928 key: Some("b".into()),
929 value: Value::List(Tree {
930 calls: vec![FuncCall {
931 comments: vec![],
932 func_name: "c".into(),
933 args: vec![],
934 trailing_comments: vec![],
935 }],
936 trailing_comments: vec![],
937 }),
938 value_source: "[c()]".into(),
939 },],
940 trailing_comments: vec![],
941 }],
942 ),
943 (
944 comma_after_list,
945 "a(b=[],)",
946 vec![FuncCall {
947 comments: vec![],
948 func_name: "a".into(),
949 args: vec![Arg {
950 comments: vec![],
951 key: Some("b".into()),
952 value: Value::List(Default::default()),
953 value_source: "[]".into(),
954 },],
955 trailing_comments: vec![],
956 }],
957 ),
958 (
959 comment_in_empty_list,
960 "a(b=[#X\n])",
961 vec![FuncCall {
962 comments: vec![],
963 func_name: "a".into(),
964 args: vec![Arg {
965 comments: vec![],
966 key: Some("b".into()),
967 value: Value::List(Tree {
968 calls: vec![],
969 trailing_comments: vec!["X"]
970 }),
971 value_source: "[#X\n]".into(),
972 },],
973 trailing_comments: vec![],
974 }],
975 ),
976 );
977
978 fn run_comments_test(
979 input: &str,
980 func_comments: Vec<&'static str>,
981 arg_1_comments: Vec<&'static str>,
982 arg_2_comments: Vec<&'static str>,
983 trailing_comments: Vec<&'static str>,
984 ) {
985 let want = vec![FuncCall {
986 comments: func_comments,
987 func_name: "f".into(),
988 args: vec![
989 Arg {
990 comments: arg_1_comments,
991 key: None,
992 value: Value::Integer(3),
993 value_source: "3".into(),
994 },
995 Arg {
996 comments: arg_2_comments,
997 key: Some("key".into()),
998 value: Value::Integer(4),
999 value_source: "4".into(),
1000 },
1001 ],
1002 trailing_comments,
1003 }];
1004 run_parse_test(input, want.clone());
1005 run_convert_test(want);
1006 }
1007
1008 macro_rules! comment_tests {
1009 ( $( (
1010 $name: ident,
1011 $input: expr,
1012 $(
1013 func_comments: $func_comments: expr,
1014 )?
1015 $(
1016 arg_1_comments: $arg_1_comments: expr,
1017 )?
1018 $(
1019 arg_2_comments: $arg_2_comments: expr,
1020 )?
1021 $(
1022 trailing_comments: $trailing_comments: expr,
1023 )?
1024 ), )+ ) => {
1025 $(
1026 #[test]
1027 #[allow(unused_assignments, unused_mut)]
1028 fn $name() {
1029 let input = $input;
1030 let mut func_comments = vec![];
1031 $(
1032 func_comments = $func_comments;
1033 )?
1034 let mut arg_1_comments = vec![];
1035 $(
1036 arg_1_comments = $arg_1_comments;
1037 )?
1038 let mut arg_2_comments = vec![];
1039 $(
1040 arg_2_comments = $arg_2_comments;
1041 )?
1042 let mut trailing_comments = vec![];
1043 $(
1044 trailing_comments = $trailing_comments;
1045 )?
1046 run_comments_test(&input, func_comments, arg_1_comments, arg_2_comments, trailing_comments);
1047 }
1048 )+
1049 };
1050 }
1051
1052 comment_tests!(
1053 (
1054 comment_0,
1055 "f(3,key=4,)",
1056 ),
1057 (
1058 comment_1,
1059 "#X\nf(3,key=4,)",
1060 func_comments: vec!["X"],
1061 ),
1062 (
1063 comment_2,
1064 "f#X\n(3,key=4,)",
1065 func_comments: vec!["X"],
1066 ),
1067 (
1068 comment_3,
1069 "f(#X\n3,key=4,)",
1070 arg_1_comments: vec!["X"],
1071 ),
1072 (
1073 comment_4,
1074 "f(3#X\n,key=4,)",
1075 arg_1_comments: vec!["X"],
1076 ),
1077 (
1078 comment_5,
1079 "f(3,#X\nkey=4,)",
1080 arg_2_comments: vec!["X"],
1081 ),
1082 (
1083 comment_6,
1084 "f(3,key#X\n=4,)",
1085 arg_2_comments: vec!["X"],
1086 ),
1087 (
1088 comment_7,
1089 "f(3,key=#X\n4,)",
1090 arg_2_comments: vec!["X"],
1091 ),
1092 (
1093 comment_8,
1094 "f(3,key=4#X\n,)",
1095 arg_2_comments: vec!["X"],
1096 ),
1097 (
1098 comment_9,
1099 "f(3,key=4,#X\n)",
1100 trailing_comments: vec!["X"],
1101 ),
1102 (
1103 comment_10,
1104 "f(3,key=4#X\n)",
1105 arg_2_comments: vec!["X"],
1106 ),
1107 );
1111}