• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright 2016 Google Inc.
3   *
4   * Use of this source code is governed by a BSD-style license that can be
5   * found in the LICENSE file.
6   */
7  
8  #include "Test.h"
9  
10  #if defined(SK_XML)
11  #include "SkPEG.h"
12  #include "SkTo.h"
13  
14  using namespace skpeg;
15  
16  namespace {
17  
18  struct Alpha {
19      using V = char;
20      using MatchT = MatchResult<V>;
21  
Match__anon549d07750111::Alpha22      static MatchT Match(const char* in) {
23          static constexpr unsigned kAlphaRange = 'z' - 'a';
24          return static_cast<unsigned>(*in - 'a') <= kAlphaRange
25              || static_cast<unsigned>(*in - 'A') <= kAlphaRange
26              ? MatchT(in + 1, *in)
27              : nullptr;
28      }
29  };
30  
31  struct Digit {
32      using V = uint8_t;
33      using MatchT = MatchResult<V>;
34  
Match__anon549d07750111::Digit35      static MatchT Match(const char* in) {
36          static constexpr unsigned kDigitRange = '9' - '0';
37          return static_cast<unsigned>(*in - '0') <= kDigitRange
38              ? MatchT(in + 1, SkTo<uint8_t>(*in - '0'))
39              : nullptr;
40      }
41  };
42  
test_EOS(skiatest::Reporter * r)43  void test_EOS(skiatest::Reporter* r) {
44      static const struct {
45          const char* fInput;
46          bool        fMatch;
47      } gTests[] = {
48          { ""   , true  },
49          { " "  , false },
50          { "\0" , true  },
51          { "foo", false },
52      };
53  
54      for (size_t i = 0; i < SK_ARRAY_COUNT(gTests); ++i) {
55          const auto match = EOS::Match(gTests[i].fInput);
56          REPORTER_ASSERT(r, match == gTests[i].fMatch);
57          REPORTER_ASSERT(r, match.fNext == (match ? gTests[i].fInput : nullptr));
58      }
59  }
60  
test_LIT(skiatest::Reporter * r)61  void test_LIT(skiatest::Reporter* r) {
62      static const struct {
63          const char* fInput;
64          bool        fMatch;
65      } gTests[] = {
66          { ""  , false },
67          { " " , false },
68          { "x" , false },
69          { "X" , true  },
70          { "xX", false },
71          { "Xx", true  },
72      };
73  
74      for (size_t i = 0; i < SK_ARRAY_COUNT(gTests); ++i) {
75          const auto match = LIT<'X'>::Match(gTests[i].fInput);
76          REPORTER_ASSERT(r, match == gTests[i].fMatch);
77          REPORTER_ASSERT(r, match.fNext == (match ? gTests[i].fInput + 1 : nullptr));
78      }
79  
80      REPORTER_ASSERT(r, !(LIT<'F', 'o', 'o'>::Match("")));
81      REPORTER_ASSERT(r, !(LIT<'F', 'o', 'o'>::Match("Fo")));
82      REPORTER_ASSERT(r, !(LIT<'F', 'o', 'o'>::Match("FoO")));
83      REPORTER_ASSERT(r,  (LIT<'F', 'o', 'o'>::Match("Foo")));
84      REPORTER_ASSERT(r,  (LIT<'F', 'o', 'o'>::Match("Foobar")));
85  }
86  
test_Alpha(skiatest::Reporter * r)87  void test_Alpha(skiatest::Reporter* r) {
88      static const struct {
89          const char* fInput;
90          bool        fMatch;
91          char        fMatchValue;
92      } gTests[] = {
93          { ""  , false,  0  },
94          { "\r", false,  0  },
95          { "\n", false,  0  },
96          { "\t", false,  0  },
97          { "0" , false,  0  },
98          { "9" , false,  0  },
99          { "a" , true , 'a' },
100          { "a" , true , 'a' },
101          { "z" , true , 'z' },
102          { "A" , true , 'A' },
103          { "Z" , true , 'Z' },
104          { "az", true , 'a' },
105          { "a0", true , 'a' },
106          { "0a", false,  0  },
107      };
108  
109      for (size_t i = 0; i < SK_ARRAY_COUNT(gTests); ++i) {
110          const auto match = Alpha::Match(gTests[i].fInput);
111          REPORTER_ASSERT(r, match == gTests[i].fMatch);
112          REPORTER_ASSERT(r, match.fNext == (match ? gTests[i].fInput + 1 : nullptr));
113          if (match) {
114              REPORTER_ASSERT(r, *match == gTests[i].fMatchValue);
115          }
116      }
117  }
118  
test_Digit(skiatest::Reporter * r)119  void test_Digit(skiatest::Reporter* r) {
120      static const struct {
121          const char* fInput;
122          bool        fMatch;
123          uint8_t     fMatchValue;
124      } gTests[] = {
125          { ""   , false, 0 },
126          { "/"  , false, 0 },
127          { ":"  , false, 0 },
128          { "x"  , false, 0 },
129          { "x0" , false, 0 },
130          { "0"  , true , 0 },
131          { "1x" , true , 1 },
132          { "9 a", true , 9 },
133      };
134  
135      for (size_t i = 0; i < SK_ARRAY_COUNT(gTests); ++i) {
136          const auto match = Digit::Match(gTests[i].fInput);
137          REPORTER_ASSERT(r, match == gTests[i].fMatch);
138          REPORTER_ASSERT(r, match.fNext == (match ? gTests[i].fInput + 1 : nullptr));
139          if (match) {
140              REPORTER_ASSERT(r, *match == gTests[i].fMatchValue);
141          }
142      }
143  }
144  
test_Opt(skiatest::Reporter * r)145  void test_Opt(skiatest::Reporter* r) {
146      static const struct {
147          const char* fInput;
148          bool        fMatch;
149      } gTests[] = {
150          { ""       , false },
151          { "fo"     , false },
152          { " foo"   , false },
153          { "foo"    , true },
154          { "foobar" , true },
155      };
156  
157      for (size_t i = 0; i < SK_ARRAY_COUNT(gTests); ++i) {
158          const auto m = Opt<LIT<'f', 'o', 'o'>>::Match(gTests[i].fInput);
159          REPORTER_ASSERT(r, m);
160          REPORTER_ASSERT(r, m->fValue.isValid() == gTests[i].fMatch);
161      }
162  }
163  
test_Seq(skiatest::Reporter * r)164  void test_Seq(skiatest::Reporter* r) {
165      REPORTER_ASSERT(r,  (Seq<LIT<'X'>, EOS>::Match("X")));
166      REPORTER_ASSERT(r, !(Seq<LIT<'X'>, EOS>::Match("x")));
167      REPORTER_ASSERT(r, !(Seq<LIT<'X'>, EOS>::Match("xX")));
168      REPORTER_ASSERT(r, !(Seq<LIT<'X'>, EOS>::Match("XX")));
169      REPORTER_ASSERT(r,  (Seq<LIT<'X'>, Seq<LIT<'X'>, EOS>>::Match("XX")));
170      REPORTER_ASSERT(r,  (Seq<LIT<'X'>, Seq<LIT<'X'>, EOS>>::Match("XX")));
171  
172      REPORTER_ASSERT(r, !(Seq<LIT<'F', 'o', 'o'>, EOS>::Match("FooBar")));
173      REPORTER_ASSERT(r,  (Seq<LIT<'F', 'o', 'o'>, EOS>::Match("Foo")));
174  
175      {
176          const auto m = Seq<LIT<'x'>, Digit>::Match("x5");
177          REPORTER_ASSERT(r, m);
178          REPORTER_ASSERT(r, m->get<1>() == 5);
179      }
180      {
181          const auto m = Seq<Digit, Digit>::Match("42");
182          REPORTER_ASSERT(r, m);
183          REPORTER_ASSERT(r, m->get<0>() == 4);
184          REPORTER_ASSERT(r, m->get<1>() == 2);
185      }
186  }
187  
test_Choice(skiatest::Reporter * r)188  void test_Choice(skiatest::Reporter* r) {
189      REPORTER_ASSERT(r, !(Choice<Digit,Alpha>::Match("")));
190      REPORTER_ASSERT(r, !(Choice<Digit,Alpha>::Match("\t")));
191      REPORTER_ASSERT(r, !(Choice<Digit,Alpha>::Match(" ")));
192      REPORTER_ASSERT(r,  (Choice<Digit,Alpha>::Match("a")));
193      REPORTER_ASSERT(r,  (Choice<Digit,Alpha>::Match("3")));
194      REPORTER_ASSERT(r,  (Choice<Digit,Alpha>::Match("a ")));
195      REPORTER_ASSERT(r,  (Choice<Digit,Alpha>::Match("3 ")));
196      REPORTER_ASSERT(r, !(Choice<Digit,Alpha>::Match(" a ")));
197      REPORTER_ASSERT(r, !(Choice<Digit,Alpha>::Match(" 3 ")));
198  
199      {
200          const auto m = Choice<Alpha, Digit>::Match("x");
201          REPORTER_ASSERT(r,  m);
202          REPORTER_ASSERT(r,  m->v1.isValid());
203          REPORTER_ASSERT(r, !m->v2.isValid());
204          REPORTER_ASSERT(r, *m->v1.get() == 'x');
205      }
206  
207      {
208          const auto m = Choice<Alpha, Digit>::Match("7");
209          REPORTER_ASSERT(r,  m);
210          REPORTER_ASSERT(r, !m->v1.isValid());
211          REPORTER_ASSERT(r,  m->v2.isValid());
212          REPORTER_ASSERT(r, *m->v2.get() == 7);
213      }
214  }
215  
test_AnySome(skiatest::Reporter * r)216  void test_AnySome(skiatest::Reporter* r) {
217      static const struct {
218          const char* fInput;
219          int         fCount;
220      } gTests[] = {
221          { ""      , 0 },
222          { "fo"    , 0 },
223          { "Foo"   , 0 },
224          { "foo"   , 1 },
225          { "foofoo", 2 },
226      };
227  
228      for (size_t i = 0; i < SK_ARRAY_COUNT(gTests); ++i) {
229          const auto matchAny = Any<LIT<'f', 'o', 'o'>>::Match(gTests[i].fInput);
230          REPORTER_ASSERT(r, matchAny);
231          REPORTER_ASSERT(r, matchAny->fValues.count() == gTests[i].fCount);
232  
233          const auto matchSome = Some<LIT<'f', 'o', 'o'>>::Match(gTests[i].fInput);
234          REPORTER_ASSERT(r,  matchSome == (gTests[i].fCount > 0));
235          REPORTER_ASSERT(r, !matchSome ||
236                              matchSome->get<1>().fValues.count() == gTests[i].fCount - 1);
237      }
238  
239      {
240          const auto m = Any<Digit>::Match("0123456789foo");
241          REPORTER_ASSERT(r, m);
242          REPORTER_ASSERT(r, m->fValues.count() == 10);
243          for (int i = 0; i < m->fValues.count(); ++i) {
244              REPORTER_ASSERT(r, m->fValues[i] == i);
245          }
246      }
247  }
248  
test_Complex(skiatest::Reporter * r)249  void test_Complex(skiatest::Reporter* r) {
250      // [0-9]+(,[0-9]+)?$
251      using P0 =
252          Seq<
253            Some<Digit>,
254            Opt<Seq<
255              LIT<','>,
256              Some<Digit>>>,
257            EOS>;
258  
259      REPORTER_ASSERT(r, !P0::Match(""));
260      REPORTER_ASSERT(r, !P0::Match(","));
261      REPORTER_ASSERT(r, !P0::Match("1,"));
262      REPORTER_ASSERT(r, !P0::Match(",1"));
263      REPORTER_ASSERT(r,  P0::Match("1"));
264      REPORTER_ASSERT(r,  P0::Match("1,2"));
265      REPORTER_ASSERT(r, !P0::Match("1,2 "));
266      REPORTER_ASSERT(r,  P0::Match("123,456"));
267  
268      // [ ]*[Ff]oo([Bb]ar)+[Bb]az[ ]*$
269      using P1 =
270          Seq<
271            Any<LIT<' '>>,
272            Choice<LIT<'F'>, LIT<'f'>>,
273            LIT<'o', 'o'>,
274            Some<Seq<
275              Choice<LIT<'B'>, LIT<'b'>>,
276              LIT<'a', 'r'>>>,
277            Choice<LIT<'B'>, LIT<'b'>>,
278            LIT<'a', 'z'>,
279            Any<LIT<' '>>,
280            EOS>;
281  
282      REPORTER_ASSERT(r, !P1::Match(""));
283      REPORTER_ASSERT(r, !P1::Match("FooBar"));
284      REPORTER_ASSERT(r, !P1::Match("FooBaz"));
285      REPORTER_ASSERT(r,  P1::Match("FooBarBaz"));
286      REPORTER_ASSERT(r,  P1::Match("foobarbaz"));
287      REPORTER_ASSERT(r,  P1::Match("  FooBarbaz     "));
288      REPORTER_ASSERT(r,  P1::Match(" FooBarbarbarBaz "));
289  }
290  
291  } // anonymous ns
292  
DEF_TEST(SkPEG,r)293  DEF_TEST(SkPEG, r) {
294      test_EOS(r);
295      test_LIT(r);
296      test_Alpha(r);
297      test_Digit(r);
298      test_Opt(r);
299      test_Seq(r);
300      test_Choice(r);
301      test_AnySome(r);
302      test_Complex(r);
303  }
304  
305  #endif // SK_XML
306