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