1use pest_derive::Parser;
23
24#[derive(Parser)]
26#[grammar = "program.pest"]
27pub struct FslParser {}
28
29#[cfg(test)]
30mod tests {
31 use crate::parser::fsl_parser::{FslParser, Rule};
32 use crate::sample_program::sample_program;
33 use anyhow::Result;
34 use hamcrest::{equal_to, is, HamcrestMatcher};
35 use parameterized::parameterized;
36 use pest::Parser;
37
38 #[parameterized(
39 program = {
40 &sample_program("me.fsl"),
41 &sample_program("plusfoo-plusbar.fsl")
42 }
43 )
44 ]
45 fn parses_program(program: &str) -> Result<()> {
46 let parsed = FslParser::parse(Rule::program, program)
47 .expect("Failed to parse FSL syntax")
48 .next()
49 .expect("Failed to get pair");
50 let pairs = parsed.into_inner().as_str();
51 let mut trimmed = program.to_string();
52 trimmed.pop().expect("Failed to remove last character");
53 assert_that!(String::from(pairs), is(equal_to(trimmed)));
54 Ok(())
55 }
56
57 #[test]
58 fn parses_me() -> Result<()> {
59 let parse = FslParser::parse(Rule::me, "me: @jeff")
60 .expect("Failed to parse FSL syntax");
61 assert_that!(parse.as_str(), is(equal_to("me: @jeff")));
62 Ok(())
63 }
64
65 #[parameterized(input = {"@jeff", "@x"})]
66 fn parses_login(input: &str) -> Result<()> {
67 let parsed = FslParser::parse(Rule::login, input)
68 .expect("Failed to parse login");
69 assert_that!(parsed.as_str(), is(equal_to(input)));
70 Ok(())
71 }
72
73 #[should_panic(expected = "Failed to parse login")]
74 #[parameterized(
75 input = {
76 "@_f",
77 "abc",
78 "@",
79 "testing@",
80 "@."
81 }
82 )]
83 fn panics_on_invalid_login(input: &str) {
84 FslParser::parse(Rule::login, input).expect("Failed to parse login");
85 }
86
87 #[test]
88 fn parses_command() -> Result<()> {
89 let parsed = FslParser::parse(Rule::command, "+repo me/foo > foo")
90 .expect("Failed to parse FSL syntax");
91 assert_that!(parsed.as_str(), is(equal_to("+repo me/foo > foo")));
92 Ok(())
93 }
94
95 #[test]
96 fn parses_object() -> Result<()> {
97 let parsed = FslParser::parse(Rule::object, "repo me/foo > foo")
98 .expect("Failed to parse FSL syntax");
99 assert_that!(parsed.as_str(), is(equal_to("repo me/foo > foo")));
100 Ok(())
101 }
102
103 #[test]
104 fn parses_object_without_attributes() -> Result<()> {
105 let parsed = FslParser::parse(Rule::object, "repo > foo")
106 .expect("Failed to parse FSL syntax");
107 assert_that!(parsed.as_str(), is(equal_to("repo > foo")));
108 Ok(())
109 }
110
111 #[test]
112 fn parses_new() -> Result<()> {
113 let parsed = FslParser::parse(Rule::new, "> x")
114 .expect("Failed to parse FSL syntax");
115 assert_that!(parsed.as_str(), is(equal_to("> x")));
116 Ok(())
117 }
118
119 #[parameterized(input = {"x", "xy", "foo", "test"})]
120 fn parses_ref(input: &str) -> Result<()> {
121 let parsed = FslParser::parse(Rule::reference, input)
122 .expect("Failed to parse FSL syntax");
123 assert_that!(parsed.as_str(), is(equal_to(input)));
124 Ok(())
125 }
126
127 #[test]
128 fn parses_application() -> Result<()> {
129 let parsed = FslParser::parse(Rule::application, "-> x")
130 .expect("Failed to parse application syntax");
131 assert_that!(parsed.as_str(), is(equal_to("-> x")));
132 Ok(())
133 }
134
135 #[test]
136 fn parses_object_with_application() -> Result<()> {
137 let parsed = FslParser::parse(Rule::object, "issue testing -> x")
138 .expect("Failed to parse object syntax");
139 assert_that!(parsed.as_str(), is(equal_to("issue testing -> x")));
140 Ok(())
141 }
142
143 #[should_panic(expected = "Failed to parse reference")]
144 #[parameterized(
145 input = {
146 "_",
147 "_test",
148 "@",
149 "!",
150 "!bar",
151 ".",
152 "/t",
153 "X",
154 "XYZ"
155 }
156 )]
157 fn panics_on_invalid_ref(input: &str) {
158 FslParser::parse(Rule::reference, input)
159 .expect("Failed to parse reference");
160 }
161
162 #[parameterized(
163 input = {
164 "# test",
165 "# UPPER CASE",
166 "# extra space",
167 "# with extra words",
168 "# with dot in the end.",
169 "# test, and another test.",
170 "#sticky works too.",
171 "# it works THIS way TOO.",
172 "# parses with tag inside #",
173 "# parses with text after tag # this way",
174 "# `special` 'characters' ```test```"
175 }
176 )]
177 fn parses_comment(input: &str) -> Result<()> {
178 let parsed = FslParser::parse(Rule::comment, input)
179 .expect("failed to parse comment");
180 assert_that!(parsed.as_str(), is(equal_to(input)));
181 Ok(())
182 }
183
184 #[test]
185 fn parses_program_with_comments() -> Result<()> {
186 let program = &sample_program("with-comments.fsl");
187 let pairs = FslParser::parse(Rule::program, program)
188 .expect("failed to parse program with comments");
189 assert_that!(pairs.as_str().len(), is(equal_to(143)));
190 Ok(())
191 }
192
193 #[test]
194 fn parses_program_with_license() -> Result<()> {
195 let program = &sample_program("with-license.fsl");
196 let pairs = FslParser::parse(Rule::program, program)
197 .expect("failed to parse program with license");
198 assert_that!(pairs.as_str().len(), is(equal_to(211)));
199 Ok(())
200 }
201}