1use nom::{
7 IResult, Parser,
8 character::complete::{char, multispace0},
9 combinator::map,
10 multi::separated_list0,
11 sequence::preceded,
12};
13use std::{
14 fmt,
15 sync::Arc,
16};
17
18use crate::{
19 aim::{WriterLike, Writer},
20 literals::{parse_tag, parse_text},
21 values::Value,
22};
23
24#[derive(Debug, Clone, PartialEq)]
29pub struct Format {
30 instruction: Arc<str>,
31 template: Arc<str>,
32 examples: Arc<Vec<Arc<str>>>,
33}
34
35impl Format {
36 pub fn as_value(instruction: Arc<str>, template: Arc<str>, examples: Arc<Vec<Arc<str>>>) -> Value {
38 Value::Format(Format {
39 instruction: instruction,
40 template: template,
41 examples: examples,
42 })
43 }
44
45 pub fn instruction(&self) -> Arc<str> {
47 self.instruction.clone()
48 }
49
50 pub fn template(&self) -> Arc<str> {
52 self.template.clone()
53 }
54
55 pub fn examples(&self) -> Arc<Vec<Arc<str>>> {
57 self.examples.clone()
58 }
59
60 pub fn print(&self, writer: &mut Writer) {
62 writer.print(&self.instruction);
63 writer.write_str(" <");
64 writer.print(&self.template);
65 writer.write_str("> ");
66 for (index, text) in self.examples.iter().enumerate() {
67 if index > 0 {
68 writer.write_str(", ");
69 }
70 writer.print(text);
71 }
72 }
73
74 pub fn to_formula(&self) -> String {
76 let mut writer = Writer::formulizer();
77 self.print(&mut writer);
78 writer.finish()
79 }
80}
81
82impl WriterLike for Format {
83 fn write(&self, writer: &mut Writer) {
84 self.print(writer);
85 }
86}
87
88impl fmt::Display for Format {
89 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90 write!(f, "{}", self.to_stringized())
91 }
92}
93
94pub fn parse_format(input: &str) -> IResult<&str, Format> {
96 map(
97 (
98 multispace0,
99 parse_text,
100 multispace0,
101 parse_tag,
102 multispace0,
103 parse_string_array,
104 ),
105 |(_, instruction, _, template, _, examples)| {
106 Format {
107 instruction,
108 template,
109 examples: Arc::new(examples),
110 }
111 },
112 )
113 .parse(input)
114}
115
116pub fn parse_string_array(input: &str) -> IResult<&str, Vec<Arc<str>>> {
118 separated_list0(
119 preceded(multispace0, char(',')),
120 preceded(multispace0, parse_text),
121 )
122 .parse(input)
123}