1use crate::parser::common::{
6 bool_literal, compound_identifier, identifier, many_until_eof, map_err, numeric_literal,
7 string_literal, using_list, ws, BindParserError, CompoundIdentifier, Include, NomSpan,
8};
9use nom::branch::alt;
10use nom::bytes::complete::{tag, take_until};
11use nom::combinator::{map, opt, value};
12use nom::multi::separated_list1;
13use nom::sequence::{delimited, separated_pair, terminated};
14use nom::{IResult, Parser};
15
16#[derive(Debug, PartialEq)]
17pub struct Ast {
18 pub name: CompoundIdentifier,
19 pub using: Vec<Include>,
20 pub declarations: Vec<Declaration>,
21}
22
23#[derive(Clone, Debug, PartialEq)]
24pub struct Declaration {
25 pub identifier: CompoundIdentifier,
26 pub value_type: ValueType,
27 pub extends: bool,
28 pub values: Vec<Value>,
29}
30
31#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, serde::Deserialize, serde::Serialize)]
32pub enum ValueType {
33 Number,
34 Str,
35 Bool,
36 Enum,
37}
38
39#[derive(Clone, Debug, PartialEq)]
40pub enum Value {
41 Number(String, u64),
42 Str(String, String),
43 Bool(String, bool),
44 Enum(String),
45}
46
47impl TryFrom<&str> for Ast {
48 type Error = BindParserError;
49
50 fn try_from(input: &str) -> Result<Self, Self::Error> {
51 match library(NomSpan::new(input)) {
52 Ok((_, ast)) => Ok(ast),
53 Err(nom::Err::Error(e)) => Err(e),
54 Err(nom::Err::Failure(e)) => Err(e),
55 Err(nom::Err::Incomplete(_)) => {
56 unreachable!("Parser should never generate Incomplete errors")
57 }
58 }
59 }
60}
61
62impl Value {
63 pub fn identifier(&self) -> &str {
64 match self {
65 Value::Number(identifier, _)
66 | Value::Str(identifier, _)
67 | Value::Bool(identifier, _)
68 | Value::Enum(identifier) => &identifier,
69 }
70 }
71}
72
73fn keyword_extend(input: NomSpan) -> IResult<NomSpan, NomSpan, BindParserError> {
74 ws(tag("extend")).parse(input)
75}
76
77fn keyword_uint(input: NomSpan) -> IResult<NomSpan, ValueType, BindParserError> {
78 value(ValueType::Number, ws(map_err(tag("uint"), BindParserError::Type))).parse(input)
79}
80
81fn keyword_string(input: NomSpan) -> IResult<NomSpan, ValueType, BindParserError> {
82 value(ValueType::Str, ws(map_err(tag("string"), BindParserError::Type))).parse(input)
83}
84
85fn keyword_bool(input: NomSpan) -> IResult<NomSpan, ValueType, BindParserError> {
86 value(ValueType::Bool, ws(map_err(tag("bool"), BindParserError::Type))).parse(input)
87}
88
89fn keyword_enum(input: NomSpan) -> IResult<NomSpan, ValueType, BindParserError> {
90 value(ValueType::Enum, ws(map_err(tag("enum"), BindParserError::Type))).parse(input)
91}
92
93fn value_list<'a, O, F>(
94 mut f: F,
95) -> impl Parser<NomSpan<'a>, Output = Vec<O>, Error = BindParserError>
96where
97 F: Parser<NomSpan<'a>, Output = O, Error = BindParserError>,
98{
99 move |input: NomSpan<'a>| {
100 let separator = || ws(map_err(tag(","), BindParserError::ListSeparator));
101 let values = separated_list1(separator(), |s| f.parse(s));
102
103 let values = terminated(values, opt(separator()));
105
106 let (input, vals_input) =
109 map_err(terminated(take_until(";"), tag(";")), BindParserError::Semicolon)
110 .parse(input)?;
111
112 if vals_input.fragment().is_empty() {
113 return Ok((input, Vec::new()));
114 }
115
116 let list_start = map_err(tag("{"), BindParserError::ListStart);
117 let list_end = map_err(tag("}"), BindParserError::ListEnd);
118 let (_, result) = delimited(ws(list_start), ws(values), ws(list_end)).parse(vals_input)?;
119
120 Ok((input, result))
121 }
122}
123
124fn number_value_list(input: NomSpan) -> IResult<NomSpan, Vec<Value>, BindParserError> {
125 let token = map_err(tag("="), BindParserError::Assignment);
126 let value = separated_pair(ws(identifier), ws(token), ws(numeric_literal));
127 value_list(map(value, |(ident, val)| Value::Number(ident, val))).parse(input)
128}
129
130fn string_value_list(input: NomSpan) -> IResult<NomSpan, Vec<Value>, BindParserError> {
131 let token = map_err(tag("="), BindParserError::Assignment);
132 let value = separated_pair(ws(identifier), ws(token), ws(string_literal));
133 value_list(map(value, |(ident, val)| Value::Str(ident, val))).parse(input)
134}
135
136fn bool_value_list(input: NomSpan) -> IResult<NomSpan, Vec<Value>, BindParserError> {
137 let token = map_err(tag("="), BindParserError::Assignment);
138 let value = separated_pair(ws(identifier), ws(token), ws(bool_literal));
139 value_list(map(value, |(ident, val)| Value::Bool(ident, val))).parse(input)
140}
141
142fn enum_value_list(input: NomSpan) -> IResult<NomSpan, Vec<Value>, BindParserError> {
143 value_list(map(ws(identifier), Value::Enum)).parse(input)
144}
145
146fn declaration(input: NomSpan) -> IResult<NomSpan, Declaration, BindParserError> {
147 let (input, extends) = opt(keyword_extend).parse(input)?;
148
149 let (input, value_type) =
150 alt((keyword_uint, keyword_string, keyword_bool, keyword_enum)).parse(input)?;
151
152 let (input, identifier) = ws(compound_identifier).parse(input)?;
153
154 let value_parser = match value_type {
155 ValueType::Number => number_value_list,
156 ValueType::Str => string_value_list,
157 ValueType::Bool => bool_value_list,
158 ValueType::Enum => enum_value_list,
159 };
160
161 let (input, vals) = value_parser(input)?;
162
163 Ok((input, Declaration { identifier, value_type, extends: extends.is_some(), values: vals }))
164}
165
166fn library_name(input: NomSpan) -> IResult<NomSpan, CompoundIdentifier, BindParserError> {
167 let keyword = ws(map_err(tag("library"), BindParserError::LibraryKeyword));
168 let terminator = ws(map_err(tag(";"), BindParserError::Semicolon));
169 delimited(keyword, ws(compound_identifier), terminator).parse(input)
170}
171
172fn library(input: NomSpan) -> IResult<NomSpan, Ast, BindParserError> {
173 map(
174 (ws(library_name), ws(using_list), many_until_eof(ws(declaration))),
175 |(name, using, declarations)| Ast { name, using, declarations },
176 )
177 .parse(input)
178}
179
180#[cfg(test)]
181mod test {
182 use super::*;
183 use crate::make_identifier;
184 use crate::parser::common::test::check_result;
185
186 mod number_value_lists {
187 use super::*;
188
189 #[test]
190 fn single_value() {
191 check_result(
192 number_value_list(NomSpan::new("{abc = 123};")),
193 "",
194 vec![Value::Number("abc".to_string(), 123)],
195 );
196 }
197
198 #[test]
199 fn multiple_values() {
200 check_result(
202 number_value_list(NomSpan::new("{abc = 123, DEF = 456};")),
203 "",
204 vec![Value::Number("abc".to_string(), 123), Value::Number("DEF".to_string(), 456)],
205 );
206 check_result(
207 number_value_list(NomSpan::new("{abc = 123, DEF = 456, ghi = 0xabc};")),
208 "",
209 vec![
210 Value::Number("abc".to_string(), 123),
211 Value::Number("DEF".to_string(), 456),
212 Value::Number("ghi".to_string(), 0xabc),
213 ],
214 );
215 }
216
217 #[test]
218 fn whitespace() {
219 check_result(
221 number_value_list(NomSpan::new("{ abc=123,\n\tDEF\t = 0xdef\n};")),
222 "",
223 vec![
224 Value::Number("abc".to_string(), 123),
225 Value::Number("DEF".to_string(), 0xdef),
226 ],
227 );
228 }
229
230 #[test]
231 fn invalid_values() {
232 assert_eq!(
234 number_value_list(NomSpan::new("{abc = \"string\"};")),
235 Err(nom::Err::Error(BindParserError::NumericLiteral("\"string\"}".to_string())))
236 );
237 assert_eq!(
238 number_value_list(NomSpan::new("{abc = true};")),
239 Err(nom::Err::Error(BindParserError::NumericLiteral("true}".to_string())))
240 );
241 }
242
243 #[test]
244 fn trailing_comma() {
245 check_result(
247 number_value_list(NomSpan::new("{abc = 123,};")),
248 "",
249 vec![Value::Number("abc".to_string(), 123)],
250 );
251 }
252
253 #[test]
254 fn empty_list() {
255 assert_eq!(
257 number_value_list(NomSpan::new("{};")),
258 Err(nom::Err::Error(BindParserError::Identifier("}".to_string())))
259 );
260 }
261
262 #[test]
263 fn invalid_list() {
264 assert_eq!(
266 number_value_list(NomSpan::new("abc = 123};")),
267 Err(nom::Err::Error(BindParserError::ListStart("abc = 123}".to_string())))
268 );
269 assert_eq!(
270 number_value_list(NomSpan::new("{abc = 123;")),
271 Err(nom::Err::Error(BindParserError::ListEnd("".to_string())))
272 );
273
274 assert_eq!(
276 number_value_list(NomSpan::new("{abc 123};")),
277 Err(nom::Err::Error(BindParserError::Assignment("123}".to_string())))
278 );
279 }
280
281 #[test]
282 fn no_list() {
283 check_result(number_value_list(NomSpan::new(";")), "", vec![]);
285 }
286 }
287
288 mod string_value_lists {
289 use super::*;
290
291 #[test]
292 fn single_value() {
293 check_result(
294 string_value_list(NomSpan::new(r#"{abc = "xyz"};"#)),
295 "",
296 vec![Value::Str("abc".to_string(), "xyz".to_string())],
297 );
298 }
299
300 #[test]
301 fn multiple_values() {
302 check_result(
304 string_value_list(NomSpan::new(r#"{abc = "xyz", DEF = "UVW"};"#)),
305 "",
306 vec![
307 Value::Str("abc".to_string(), "xyz".to_string()),
308 Value::Str("DEF".to_string(), "UVW".to_string()),
309 ],
310 );
311 check_result(
312 string_value_list(NomSpan::new(r#"{abc = "xyz", DEF = "UVW", ghi = "rst"};"#)),
313 "",
314 vec![
315 Value::Str("abc".to_string(), "xyz".to_string()),
316 Value::Str("DEF".to_string(), "UVW".to_string()),
317 Value::Str("ghi".to_string(), "rst".to_string()),
318 ],
319 );
320 }
321
322 #[test]
323 fn whitespace() {
324 check_result(
326 string_value_list(NomSpan::new("{ abc=\"xyz\",\n\tDEF\t = \"UVW\"\n};")),
327 "",
328 vec![
329 Value::Str("abc".to_string(), "xyz".to_string()),
330 Value::Str("DEF".to_string(), "UVW".to_string()),
331 ],
332 );
333 }
334
335 #[test]
336 fn invalid_values() {
337 assert_eq!(
339 string_value_list(NomSpan::new("{abc = 123};")),
340 Err(nom::Err::Error(BindParserError::StringLiteral("123}".to_string())))
341 );
342 assert_eq!(
343 string_value_list(NomSpan::new("{abc = true};")),
344 Err(nom::Err::Error(BindParserError::StringLiteral("true}".to_string())))
345 );
346 }
347
348 #[test]
349 fn trailing_comma() {
350 check_result(
352 string_value_list(NomSpan::new(r#"{abc = "xyz",};"#)),
353 "",
354 vec![Value::Str("abc".to_string(), "xyz".to_string())],
355 );
356 }
357
358 #[test]
359 fn empty_list() {
360 assert_eq!(
362 string_value_list(NomSpan::new("{};")),
363 Err(nom::Err::Error(BindParserError::Identifier("}".to_string())))
364 );
365 }
366
367 #[test]
368 fn invalid_list() {
369 assert_eq!(
371 string_value_list(NomSpan::new(r#"abc = "xyz"};"#)),
372 Err(nom::Err::Error(BindParserError::ListStart(r#"abc = "xyz"}"#.to_string())))
373 );
374 assert_eq!(
375 string_value_list(NomSpan::new(r#"{abc = "xyz";"#)),
376 Err(nom::Err::Error(BindParserError::ListEnd("".to_string())))
377 );
378
379 assert_eq!(
381 number_value_list(NomSpan::new(r#"{abc "xyz"};"#)),
382 Err(nom::Err::Error(BindParserError::Assignment(r#""xyz"}"#.to_string())))
383 );
384 }
385
386 #[test]
387 fn no_list() {
388 check_result(string_value_list(NomSpan::new(";")), "", vec![]);
390 }
391 }
392
393 mod bool_value_lists {
394 use super::*;
395
396 #[test]
397 fn single_value() {
398 check_result(
400 bool_value_list(NomSpan::new("{abc = true};")),
401 "",
402 vec![Value::Bool("abc".to_string(), true)],
403 );
404 }
405
406 #[test]
407 fn multiple_values() {
408 check_result(
410 bool_value_list(NomSpan::new("{abc = true, DEF = false};")),
411 "",
412 vec![Value::Bool("abc".to_string(), true), Value::Bool("DEF".to_string(), false)],
413 );
414 check_result(
415 bool_value_list(NomSpan::new("{abc = true, DEF = false, ghi = false};")),
416 "",
417 vec![
418 Value::Bool("abc".to_string(), true),
419 Value::Bool("DEF".to_string(), false),
420 Value::Bool("ghi".to_string(), false),
421 ],
422 );
423 }
424
425 #[test]
426 fn whitespace() {
427 check_result(
429 bool_value_list(NomSpan::new("{ abc=true,\n\tDEF\t = false\n};")),
430 "",
431 vec![Value::Bool("abc".to_string(), true), Value::Bool("DEF".to_string(), false)],
432 );
433 }
434
435 #[test]
436 fn invalid_values() {
437 assert_eq!(
439 bool_value_list(NomSpan::new("{abc = 123};")),
440 Err(nom::Err::Error(BindParserError::BoolLiteral("123}".to_string())))
441 );
442 assert_eq!(
443 bool_value_list(NomSpan::new("{abc = \"string\"};")),
444 Err(nom::Err::Error(BindParserError::BoolLiteral("\"string\"}".to_string())))
445 );
446 }
447
448 #[test]
449 fn trailing_comma() {
450 check_result(
452 bool_value_list(NomSpan::new(r#"{abc = true,};"#)),
453 "",
454 vec![Value::Bool("abc".to_string(), true)],
455 );
456 }
457
458 #[test]
459 fn empty_list() {
460 assert_eq!(
462 bool_value_list(NomSpan::new("{};")),
463 Err(nom::Err::Error(BindParserError::Identifier("}".to_string())))
464 );
465 }
466
467 #[test]
468 fn invalid_list() {
469 assert_eq!(
471 bool_value_list(NomSpan::new("abc = true};")),
472 Err(nom::Err::Error(BindParserError::ListStart("abc = true}".to_string())))
473 );
474 assert_eq!(
475 bool_value_list(NomSpan::new("{abc = true;")),
476 Err(nom::Err::Error(BindParserError::ListEnd("".to_string())))
477 );
478
479 assert_eq!(
481 number_value_list(NomSpan::new("{abc false};")),
482 Err(nom::Err::Error(BindParserError::Assignment("false}".to_string())))
483 );
484 }
485
486 #[test]
487 fn no_list() {
488 check_result(bool_value_list(NomSpan::new(";")), "", vec![]);
490 }
491 }
492
493 mod enum_value_lists {
494 use super::*;
495
496 #[test]
497 fn single_value() {
498 check_result(
500 enum_value_list(NomSpan::new("{abc};")),
501 "",
502 vec![Value::Enum("abc".to_string())],
503 );
504 }
505
506 #[test]
507 fn multiple_values() {
508 check_result(
510 enum_value_list(NomSpan::new("{abc,def};")),
511 "",
512 vec![Value::Enum("abc".to_string()), Value::Enum("def".to_string())],
513 );
514 check_result(
515 enum_value_list(NomSpan::new("{abc,def,ghi};")),
516 "",
517 vec![
518 Value::Enum("abc".to_string()),
519 Value::Enum("def".to_string()),
520 Value::Enum("ghi".to_string()),
521 ],
522 );
523 }
524
525 #[test]
526 fn whitespace() {
527 check_result(
529 enum_value_list(NomSpan::new("{abc, def, \tghi,\n jkl};")),
530 "",
531 vec![
532 Value::Enum("abc".to_string()),
533 Value::Enum("def".to_string()),
534 Value::Enum("ghi".to_string()),
535 Value::Enum("jkl".to_string()),
536 ],
537 );
538 }
539
540 #[test]
541 fn trailing_comma() {
542 check_result(
544 enum_value_list(NomSpan::new("{abc,};")),
545 "",
546 vec![Value::Enum("abc".to_string())],
547 );
548 }
549
550 #[test]
551 fn no_list() {
552 check_result(enum_value_list(NomSpan::new(";")), "", vec![]);
554 }
555
556 #[test]
557 fn invalid_list() {
558 assert_eq!(
560 enum_value_list(NomSpan::new("{abc,}")),
561 Err(nom::Err::Error(BindParserError::Semicolon("{abc,}".to_string())))
562 );
563
564 assert_eq!(
566 enum_value_list(NomSpan::new("abc};")),
567 Err(nom::Err::Error(BindParserError::ListStart("abc}".to_string())))
568 );
569 assert_eq!(
570 enum_value_list(NomSpan::new("{abc;")),
571 Err(nom::Err::Error(BindParserError::ListEnd("".to_string())))
572 );
573 }
574
575 #[test]
576 fn empty_list() {
577 assert_eq!(
579 enum_value_list(NomSpan::new("{};")),
580 Err(nom::Err::Error(BindParserError::Identifier("}".to_string())))
581 );
582 }
583 }
584
585 mod declarations {
586 use super::*;
587
588 #[test]
589 fn no_value() {
590 check_result(
592 declaration(NomSpan::new("uint test;")),
593 "",
594 Declaration {
595 identifier: make_identifier!["test"],
596 value_type: ValueType::Number,
597 extends: false,
598 values: vec![],
599 },
600 );
601 }
602
603 #[test]
604 fn numbers() {
605 check_result(
607 declaration(NomSpan::new("uint test { x = 1 };")),
608 "",
609 Declaration {
610 identifier: make_identifier!["test"],
611 value_type: ValueType::Number,
612 extends: false,
613 values: vec![Value::Number("x".to_string(), 1)],
614 },
615 );
616 }
617
618 #[test]
619 fn strings() {
620 check_result(
622 declaration(NomSpan::new(r#"string test { x = "a" };"#)),
623 "",
624 Declaration {
625 identifier: make_identifier!["test"],
626 value_type: ValueType::Str,
627 extends: false,
628 values: vec![Value::Str("x".to_string(), "a".to_string())],
629 },
630 );
631 }
632
633 #[test]
634 fn bools() {
635 check_result(
637 declaration(NomSpan::new("bool test { x = false };")),
638 "",
639 Declaration {
640 identifier: make_identifier!["test"],
641 value_type: ValueType::Bool,
642 extends: false,
643 values: vec![Value::Bool("x".to_string(), false)],
644 },
645 );
646 }
647
648 #[test]
649 fn enums() {
650 check_result(
652 declaration(NomSpan::new("enum test { x };")),
653 "",
654 Declaration {
655 identifier: make_identifier!["test"],
656 value_type: ValueType::Enum,
657 extends: false,
658 values: vec![Value::Enum("x".to_string())],
659 },
660 );
661 }
662
663 #[test]
664 fn extend() {
665 check_result(
667 declaration(NomSpan::new("extend uint test { x = 1 };")),
668 "",
669 Declaration {
670 identifier: make_identifier!["test"],
671 value_type: ValueType::Number,
672 extends: true,
673 values: vec![Value::Number("x".to_string(), 1)],
674 },
675 );
676 }
677
678 #[test]
679 fn type_mismatch() {
680 assert_eq!(
682 declaration(NomSpan::new("uint test { x = false };")),
683 Err(nom::Err::Error(BindParserError::NumericLiteral("false }".to_string())))
684 );
685 }
686
687 #[test]
688 fn invalid() {
689 assert_eq!(
691 declaration(NomSpan::new("bool { x = false };")),
692 Err(nom::Err::Error(BindParserError::Identifier("{ x = false };".to_string())))
693 );
694 assert_eq!(
695 declaration(NomSpan::new("test { x = false };")),
696 Err(nom::Err::Error(BindParserError::Type("test { x = false };".to_string())))
697 );
698
699 assert_eq!(
701 declaration(NomSpan::new("bool test { x = false }")),
702 Err(nom::Err::Error(BindParserError::Semicolon(" { x = false }".to_string())))
703 );
704 }
705
706 #[test]
707 fn compound_identifier() {
708 check_result(
710 declaration(NomSpan::new("uint this.is.a.test { x = 1 };")),
711 "",
712 Declaration {
713 identifier: make_identifier!["this", "is", "a", "test"],
714 value_type: ValueType::Number,
715 extends: false,
716 values: vec![Value::Number("x".to_string(), 1)],
717 },
718 );
719 }
720
721 #[test]
722 fn empty() {
723 assert_eq!(
725 declaration(NomSpan::new("")),
726 Err(nom::Err::Error(BindParserError::Type("".to_string())))
727 );
728 }
729 }
730
731 mod library_names {
732 use super::*;
733
734 #[test]
735 fn single_name() {
736 check_result(library_name(NomSpan::new("library a;")), "", make_identifier!["a"]);
737 }
738
739 #[test]
740 fn compound_name() {
741 check_result(
742 library_name(NomSpan::new("library a.b;")),
743 "",
744 make_identifier!["a", "b"],
745 );
746 }
747
748 #[test]
749 fn whitespace() {
750 check_result(
751 library_name(NomSpan::new("library \n\t a\n\t ;")),
752 "",
753 make_identifier!["a"],
754 );
755 }
756
757 #[test]
758 fn invalid() {
759 assert_eq!(
761 library_name(NomSpan::new("library ;")),
762 Err(nom::Err::Error(BindParserError::Identifier(";".to_string())))
763 );
764
765 assert_eq!(
767 library_name(NomSpan::new("library a")),
768 Err(nom::Err::Error(BindParserError::Semicolon("".to_string())))
769 );
770 }
771
772 #[test]
773 fn empty() {
774 assert_eq!(
776 library_name(NomSpan::new("")),
777 Err(nom::Err::Error(BindParserError::LibraryKeyword("".to_string())))
778 );
779 }
780 }
781
782 mod libraries {
783 use super::*;
784
785 #[test]
786 fn empty() {
787 assert_eq!(
789 library(NomSpan::new("")),
790 Err(nom::Err::Error(BindParserError::LibraryKeyword("".to_string())))
791 );
792 }
793
794 #[test]
795 fn empty_library() {
796 check_result(
797 library(NomSpan::new("library a;")),
798 "",
799 Ast { name: make_identifier!["a"], using: vec![], declarations: vec![] },
800 );
801 }
802
803 #[test]
804 fn using_list() {
805 check_result(
806 library(NomSpan::new("library a; using c as d;")),
807 "",
808 Ast {
809 name: make_identifier!["a"],
810 using: vec![Include {
811 name: make_identifier!["c"],
812 alias: Some("d".to_string()),
813 }],
814 declarations: vec![],
815 },
816 );
817 }
818
819 #[test]
820 fn declarations() {
821 check_result(
822 library(NomSpan::new("library a; uint t { x = 1 };")),
823 "",
824 Ast {
825 name: make_identifier!["a"],
826 using: vec![],
827 declarations: vec![Declaration {
828 identifier: make_identifier!["t"],
829 value_type: ValueType::Number,
830 extends: false,
831 values: vec![(Value::Number("x".to_string(), 1))],
832 }],
833 },
834 );
835 }
836
837 #[test]
838 fn multiple_elements() {
839 check_result(
841 library(NomSpan::new("library a; using b.c as d; extend enum d.t { x };")),
842 "",
843 Ast {
844 name: make_identifier!["a"],
845 using: vec![Include {
846 name: make_identifier!["b", "c"],
847 alias: Some("d".to_string()),
848 }],
849 declarations: vec![Declaration {
850 identifier: make_identifier!["d", "t"],
851 value_type: ValueType::Enum,
852 extends: true,
853 values: vec![Value::Enum("x".to_string())],
854 }],
855 },
856 );
857
858 check_result(
860 library(NomSpan::new("library a; using b.c as d; extend enum d.t { x }; bool e;")),
861 "",
862 Ast {
863 name: make_identifier!["a"],
864 using: vec![Include {
865 name: make_identifier!["b", "c"],
866 alias: Some("d".to_string()),
867 }],
868 declarations: vec![
869 Declaration {
870 identifier: make_identifier!["d", "t"],
871 value_type: ValueType::Enum,
872 extends: true,
873 values: vec![Value::Enum("x".to_string())],
874 },
875 Declaration {
876 identifier: make_identifier!["e"],
877 value_type: ValueType::Bool,
878 extends: false,
879 values: vec![],
880 },
881 ],
882 },
883 );
884 }
885
886 #[test]
887 fn consumes_entire_input() {
888 assert_eq!(
890 library(NomSpan::new("library a; using b.c as d; invalid input")),
891 Err(nom::Err::Error(BindParserError::Type("invalid input".to_string())))
892 );
893 }
894
895 #[test]
896 fn whitespace() {
897 assert_eq!(
899 library(NomSpan::new(
900 "\n\t library a;\t using b.c as d;\n extend enum d.t { x }; \t bool e;\n "
901 ))
902 .unwrap()
903 .1,
904 library(NomSpan::new("library a; using b.c as d; extend enum d.t { x }; bool e;"))
905 .unwrap()
906 .1,
907 );
908 }
909 }
910}