OLD | NEW |
| (Empty) |
1 /// This package contains matches to write tests for parsers. | |
2 /// | |
3 /// Examples: | |
4 /// | |
5 /// var json = new JsonParser(); | |
6 /// | |
7 /// // verifies that the input gets parsed and all input is consumed | |
8 /// expect('{"a": 1}', accepts(new JsonParser())); | |
9 /// | |
10 /// // verifies that the input gets parsed to a dictionary and that all inpu
t is consumed | |
11 /// expect('{"a": 1}', parses(new JsonParser(), {'a': 1})); | |
12 | |
13 library petitparser.test_util; | |
14 | |
15 import 'package:matcher/matcher.dart'; | |
16 import 'package:petitparser/petitparser.dart' hide predicate; | |
17 | |
18 /// Returns a matcher that succeeds if the [parser] accepts the input. | |
19 Matcher accept(Parser parser) { | |
20 return parse(parser, predicate((value) => true, 'input')); | |
21 } | |
22 | |
23 /// Returns a matcher that succeeds if the [parser] succeeds and accepts the pro
vided [matcher]. | |
24 Matcher parse(Parser parser, matcher, [int position = -1]) { | |
25 return new _Parse(parser, wrapMatcher(matcher), position); | |
26 } | |
27 | |
28 class _Parse extends Matcher { | |
29 | |
30 final Parser parser; | |
31 final Matcher matcher; | |
32 final int position; | |
33 | |
34 _Parse(this.parser, this.matcher, this.position); | |
35 | |
36 @override | |
37 bool matches(item, Map matchState) { | |
38 Result result = parser.parse(item); | |
39 if (result.isFailure) { | |
40 addStateInfo(matchState, {'reason': 'failure', 'result': result}); | |
41 return false; | |
42 } | |
43 if (!matcher.matches(result.value, matchState)) { | |
44 addStateInfo(matchState, {'reason': 'matcher', 'result': result}); | |
45 return false; | |
46 } | |
47 if (position >= 0 && position != result.value) { | |
48 addStateInfo(matchState, {'reason': 'position', 'result': result}); | |
49 return false; | |
50 } | |
51 return true; | |
52 } | |
53 | |
54 @override | |
55 Description describe(Description description) { | |
56 return description.add('"$parser" accepts ').addDescriptionOf(matcher); | |
57 } | |
58 | |
59 @override | |
60 Description describeMismatch(item, Description description, Map matchState, bo
ol verbose) { | |
61 description.add('"$parser" produces "${matchState['result']}"'); | |
62 switch (matchState['reason']) { | |
63 case 'failure': | |
64 description.add(' which is not accepted'); | |
65 return description; | |
66 case 'matcher': | |
67 description.add(' which parse result '); | |
68 var subDescription = new StringDescription(); | |
69 matcher.describeMismatch(matchState['result'].value, subDescription, | |
70 matchState['state'], verbose); | |
71 if (subDescription.length > 0) { | |
72 description.add(subDescription.toString()); | |
73 } else { | |
74 description.add('doesn\'t match'); | |
75 matcher.describe(description); | |
76 } | |
77 return description; | |
78 case 'position': | |
79 description | |
80 .add(' that consumes input to ') | |
81 .add(matchState['result'].position.toString()) | |
82 .add(' instead of ') | |
83 .add(position.toString()); | |
84 return description; | |
85 } | |
86 throw new Exception('Internal matcher error'); | |
87 } | |
88 } | |
OLD | NEW |