1 module pegged.examples.parameterized;
2 
3 import pegged.grammar;
4 
5 /**
6  * Example of parameterized rules. Pick and chose the ones you need.
7  */
8 enum parameterizedExamples = `
9 Parameterized:
10 
11 # Standard list: skip spaces, drop the separator
12 # Minimum one Elem
13 List(Elem, Sep) < Elem (:Sep Elem)*
14 
15 # A list accepting 0 element as a valid input
16 List0(Elem, Sep) < List(Elem, Sep)?
17 
18 # Standard comma-separated list
19 CommaList(Elem) < List(Elem, ',')
20 
21 # Standard space-separated list
22 SpaceList(Elem) < List(Elem, ' ')
23 
24 # Standard array rule: [1, 2, ... ].
25 Array(Elem) < :'[' List0(Elem, ',') :']'
26 
27 
28 # Apply Pattern until End
29 Until(Pattern, End) <- (!End Pattern)* :End
30 
31 # Everything but the End marker. Concatenates the entire match
32 But(End) <~ Until(., End)
33 
34 # Input delimited by a begin and a close marker
35 Delimited(Begin, Close) <- :Begin But(Close)
36 
37 # Standard double-quoted string
38 String <- Delimited(doublequote, doublequote)
39 
40 # Line (everything to the end of the line)
41 Line <- Delimited(eps, endOfLine)
42 
43 # Line comment
44 LineComment <- Delimited(:"//", endOfLine)
45 `;
46 
47 mixin(grammar(parameterizedExamples));
48 
49 unittest
50 {
51     mixin(grammar("
52     ParamTest1:
53         A <- Parameterized.List(identifier, ',')
54     "));
55 
56     assert(ParamTest1("abc, def, ghi").successful);
57     assert(ParamTest1("abc, def, ghi").matches == ["abc", "def", "ghi"]);
58     assert(ParamTest1("abc, def, ").successful);
59     assert(ParamTest1("abc, def, ").matches == ["abc", "def"]);
60     assert(ParamTest1("abc,      def, ghi").successful);
61     assert(ParamTest1("abc,      def, ghi").matches == ["abc", "def", "ghi"]);
62     assert(ParamTest1("abc,").successful);
63     assert(ParamTest1("a").successful);
64     // stops before the end:
65     assert(ParamTest1("abc,, def, ghi").successful);
66     assert(ParamTest1("abc,, def, ghi").matches == ["abc"]);
67     // not lists:
68     assert(!ParamTest1("").successful);
69     assert(!ParamTest1(",abc, def, ghi").successful);
70 
71     mixin(grammar("
72     ParamTest2:
73         A <- Parameterized.List(identifier, ' ')
74     "));
75 
76     assert(ParamTest2("abc def ghi").successful);
77     assert(ParamTest2("abc def ").successful);
78     assert(ParamTest2("abc      def ghi").successful);
79     assert(ParamTest2("abc ").successful);
80     assert(ParamTest2("a").successful);
81     // not lists:
82     assert(!ParamTest2("").successful);
83     assert(!ParamTest2("  ").successful);
84 
85     mixin(grammar("
86     ParamTest3:
87         A <- Parameterized.Array( ~[0-9]+ )
88     "));
89 
90     assert(ParamTest3("[1]").successful);
91     assert(ParamTest3("[]").successful);
92     assert(ParamTest3("[1, 2, 3]").successful);
93     assert(ParamTest3("[1, 2, 3]").matches == ["1", "2", "3"]);
94     assert(ParamTest3("[123,456,789]").successful);
95     assert(ParamTest3("[123,456,789]").matches == ["123", "456", "789"]);
96     // not arrays:
97     assert(!ParamTest3("[1,2,]").successful, "Trailing comma.");
98     assert(!ParamTest3("[1,,2,3]").successful, "Two commas in a row.");
99     assert(!ParamTest3("[1,2,3").successful, "Missing closing ']'.");
100     assert(!ParamTest3("1,2,3]").successful, "Missing opening '['.");
101     assert(!ParamTest3("[,]").successful, "No numbers in array.");
102 
103     mixin(grammar("
104     ParamTest4:
105         A <- Parameterized.String
106     "));
107 
108     assert(ParamTest4(`"abc"`).matches == [`"abc"`]);
109     assert(ParamTest4(`""`).matches == [`""`]);
110 
111     mixin(grammar("
112     ParamTest5:
113         A <- Parameterized.LineComment
114     "));
115 
116     ParseTree p5 = ParamTest5("// This is a comment!
117     This is not a comment.
118     End.");
119     assert(p5.successful);
120     assert(p5.matches == [" This is a comment!"]);
121 }