|
1 "{ Package: 'squeak:petitparser' }" |
|
2 |
|
3 PPAbstractParseTest subclass:#PPComposedTest |
|
4 instanceVariableNames:'' |
|
5 classVariableNames:'' |
|
6 poolDictionaries:'' |
|
7 category:'PetitTests-Tests' |
|
8 ! |
|
9 |
|
10 |
|
11 !PPComposedTest methodsFor:'accessing'! |
|
12 |
|
13 comment |
|
14 ^ ($" asParser , $" asParser negate star , $" asParser) flatten |
|
15 ! |
|
16 |
|
17 identifier |
|
18 ^ (#letter asParser , #word asParser star) flatten |
|
19 ! |
|
20 |
|
21 number |
|
22 ^ ($- asParser optional , #digit asParser plus , ($. asParser , #digit asParser plus) optional) flatten |
|
23 ! ! |
|
24 |
|
25 !PPComposedTest methodsFor:'testing'! |
|
26 |
|
27 testDoubledString |
|
28 | parser | |
|
29 parser := ($' asParser , (($' asParser , $' asParser) / $' asParser negate) star flatten , $' asParser) |
|
30 ==> [ :nodes | nodes second copyReplaceAll: '''''' with: '''' ]. |
|
31 |
|
32 self assert: parser parse: '''''' to: ''. |
|
33 self assert: parser parse: '''a''' to: 'a'. |
|
34 self assert: parser parse: '''ab''' to: 'ab'. |
|
35 self assert: parser parse: '''a''''b''' to: 'a''b'. |
|
36 self assert: parser parse: '''a''''''''b''' to: 'a''''b' |
|
37 |
|
38 "Modified: / 18-12-2010 / 18:00:16 / Jan Kurs <kurs.jan@post.cz>" |
|
39 ! |
|
40 |
|
41 testEvenNumber |
|
42 "Create a grammar that parses an even number of a's and b's." |
|
43 |
|
44 | a as b bs s | |
|
45 a := $a asParser ==> [ :char | as := as + 1 ]. |
|
46 b := $b asParser ==> [ :char | bs := bs + 1 ]. |
|
47 s := (a / b) star >=> [ :stream :cc | |
|
48 as := bs := 0. |
|
49 cc value. |
|
50 (as even and: [ bs even ]) |
|
51 ifFalse: [ PPFailure message: 'Even number of a and b expected' at: 0 ] ]. |
|
52 |
|
53 self assert: s fail: 'a' end: 1. |
|
54 self assert: s fail: 'b' end: 1. |
|
55 self assert: s fail: 'ab' end: 2. |
|
56 self assert: s fail: 'ba' end: 2. |
|
57 self assert: s fail: 'aaa' end: 3. |
|
58 self assert: s fail: 'bbb' end: 3. |
|
59 self assert: s fail: 'aab' end: 3. |
|
60 self assert: s fail: 'abb' end: 3. |
|
61 |
|
62 self assert: s parse: ''. |
|
63 self assert: s parse: 'aa'. |
|
64 self assert: s parse: 'bb'. |
|
65 self assert: s parse: 'aaaa'. |
|
66 self assert: s parse: 'aabb'. |
|
67 self assert: s parse: 'abab'. |
|
68 self assert: s parse: 'baba'. |
|
69 self assert: s parse: 'bbaa'. |
|
70 self assert: s parse: 'bbbb' |
|
71 ! |
|
72 |
|
73 testIfThenElse |
|
74 "S ::= if C then S else S | if C then S | X" |
|
75 |
|
76 | start if then else cond expr parser | |
|
77 start := PPUnresolvedParser new. |
|
78 if := 'if' asParser token trim. |
|
79 then := 'then' asParser token trim. |
|
80 else := 'else' asParser token trim. |
|
81 cond := 'C' asParser token trim. |
|
82 expr := 'X' asParser token trim. |
|
83 start def: (if , cond , then , start , else , start) / (if , cond , then , start) / expr. |
|
84 parser := start end. |
|
85 self assert: parser parse: 'X'. |
|
86 self assert: parser parse: 'if C then X'. |
|
87 self assert: parser parse: 'if C then X else X'. |
|
88 self assert: parser parse: 'if C then if C then X'. |
|
89 self assert: parser parse: 'if C then if C then X else if C then X'. |
|
90 self assert: parser parse: 'if C then if C then X else X else if C then X'. |
|
91 self assert: parser parse: 'if C then if C then X else X else if C then X else X'. |
|
92 self assert: parser fail: 'if C'. |
|
93 self assert: parser fail: 'if C else X'. |
|
94 self assert: parser fail: 'if C then if C' |
|
95 ! |
|
96 |
|
97 testLeftRecursion |
|
98 "S ::= S 'x' S / '1'" |
|
99 |
|
100 | parser | |
|
101 parser := PPUnresolvedParser new. |
|
102 parser def: ((parser , $x asParser , parser) / $1 asParser) memoized flatten. |
|
103 |
|
104 self assert: parser parse: '1' to: '1'. |
|
105 self assert: parser parse: '1x1' to: '1x1'. |
|
106 self assert: parser parse: '1x1x1' to: '1x1x1'. |
|
107 self assert: parser parse: '1x1x1x1' to: '1x1x1x1'. |
|
108 self assert: parser parse: '1x1x1x1x1' to: '1x1x1x1x1'. |
|
109 self assert: parser parse: '1x1x1x1x1x1' to: '1x1x1x1x1x1' |
|
110 ! |
|
111 |
|
112 testListOfIntegers |
|
113 "S ::= S , number | number" |
|
114 |
|
115 | number list parser | |
|
116 number := #digit asParser plus token trim |
|
117 ==> [ :node | node value asInteger ]. |
|
118 list := (number separatedBy: $, asParser token trim) |
|
119 ==> [ :node | node select: [ :each | each isInteger ] ]. |
|
120 parser := list end. |
|
121 |
|
122 self assert: parser parse: '1' to: (1 to: 1) asArray. |
|
123 self assert: parser parse: '1,2' to: (1 to: 2) asArray. |
|
124 self assert: parser parse: '1,2,3' to: (1 to: 3) asArray. |
|
125 self assert: parser parse: '1,2,3,4' to: (1 to: 4) asArray. |
|
126 self assert: parser parse: '1,2,3,4,5' to: (1 to: 5) asArray. |
|
127 |
|
128 self assert: parser parse: '1' to: (1 to: 1) asArray. |
|
129 self assert: parser parse: '1, 2' to: (1 to: 2) asArray. |
|
130 self assert: parser parse: '1, 2, 3' to: (1 to: 3) asArray. |
|
131 self assert: parser parse: '1, 2, 3, 4' to: (1 to: 4) asArray. |
|
132 self assert: parser parse: '1, 2, 3, 4, 5' to: (1 to: 5) asArray. |
|
133 |
|
134 self assert: parser parse: '1' to: (1 to: 1) asArray. |
|
135 self assert: parser parse: '1 ,2' to: (1 to: 2) asArray. |
|
136 self assert: parser parse: '1 ,2 ,3' to: (1 to: 3) asArray. |
|
137 self assert: parser parse: '1 ,2 ,3 ,4' to: (1 to: 4) asArray. |
|
138 self assert: parser parse: '1 ,2 ,3 ,4 ,5' to: (1 to: 5) asArray. |
|
139 |
|
140 self assert: parser fail: ''. |
|
141 self assert: parser fail: ','. |
|
142 self assert: parser fail: '1,'. |
|
143 self assert: parser fail: '1,,2' |
|
144 ! |
|
145 |
|
146 testNestedComments |
|
147 "C ::= B I* E" |
|
148 "I ::= !!E (C | T)" |
|
149 "B ::= /*" |
|
150 "E ::= */" |
|
151 "T ::= ." |
|
152 |
|
153 | begin end any inside parser | |
|
154 begin := '/*' asParser. |
|
155 end := '*/' asParser. |
|
156 any := #any asParser. |
|
157 |
|
158 parser := PPUnresolvedParser new. |
|
159 inside := end not , (parser / any). |
|
160 parser def: begin , inside star , end. |
|
161 |
|
162 self assert: parser parse: '/*ab*/cd' end: 6. |
|
163 self assert: parser parse: '/*a/*b*/c*/'. |
|
164 self assert: parser fail: '/*a/*b*/c' |
|
165 ! |
|
166 |
|
167 testPalindrome |
|
168 "S0 ::= a S1 a | b S1 b | ... |
|
169 S1 ::= S0 | epsilon" |
|
170 |
|
171 | s0 s1 parser | |
|
172 s0 := PPUnresolvedParser new. |
|
173 s1 := PPUnresolvedParser new. |
|
174 s0 def: ($a asParser , s1 , $a asParser) |
|
175 / ($b asParser , s1 , $b asParser) |
|
176 / ($c asParser , s1 , $c asParser). |
|
177 s1 def: s0 / nil asParser. |
|
178 parser := s0 flatten end. |
|
179 |
|
180 self assert: parser parse: 'aa' to: 'aa'. |
|
181 self assert: parser parse: 'bb' to: 'bb'. |
|
182 self assert: parser parse: 'cc' to: 'cc'. |
|
183 |
|
184 self assert: parser parse: 'abba' to: 'abba'. |
|
185 self assert: parser parse: 'baab' to: 'baab'. |
|
186 |
|
187 self assert: parser parse: 'abccba' to: 'abccba'. |
|
188 self assert: parser parse: 'abaaba' to: 'abaaba'. |
|
189 self assert: parser parse: 'cbaabc' to: 'cbaabc'. |
|
190 |
|
191 self assert: parser fail: 'a'. |
|
192 self assert: parser fail: 'ab'. |
|
193 self assert: parser fail: 'aab'. |
|
194 self assert: parser fail: 'abccbb' |
|
195 ! |
|
196 |
|
197 testParseAaaBbb |
|
198 "S0 ::= a S1 b |
|
199 S1 ::= S0 | epsilon" |
|
200 |
|
201 | s0 s1 parser | |
|
202 s0 := PPUnresolvedParser new. |
|
203 s1 := PPUnresolvedParser new. |
|
204 s0 def: $a asParser , s1 , $b asParser. |
|
205 s1 def: s0 / nil asParser. |
|
206 parser := s0 flatten. |
|
207 |
|
208 self assert: parser parse: 'ab' to: 'ab'. |
|
209 self assert: parser parse: 'aabb' to: 'aabb'. |
|
210 self assert: parser parse: 'aaabbb' to: 'aaabbb'. |
|
211 self assert: parser parse: 'aaaabbbb' to: 'aaaabbbb'. |
|
212 |
|
213 self assert: parser parse: 'abb' to: 'ab' end: 2. |
|
214 self assert: parser parse: 'aabbb' to: 'aabb' end: 4. |
|
215 self assert: parser parse: 'aaabbbb' to: 'aaabbb' end: 6. |
|
216 self assert: parser parse: 'aaaabbbbb' to: 'aaaabbbb' end: 8. |
|
217 |
|
218 self assert: parser fail: 'a'. |
|
219 self assert: parser fail: 'b'. |
|
220 self assert: parser fail: 'aab'. |
|
221 self assert: parser fail: 'aaabb' |
|
222 ! |
|
223 |
|
224 testParseAaaaaa |
|
225 "S ::= a a S | epsilon" |
|
226 |
|
227 | s0 s1 parser | |
|
228 s0 := PPUnresolvedParser new. |
|
229 s1 := $a asParser , $a asParser , s0. |
|
230 s0 def: s1 / nil asParser. |
|
231 parser := s0 flatten. |
|
232 |
|
233 self assert: parser parse: '' to: ''. |
|
234 self assert: parser parse: 'aa' to: 'aa'. |
|
235 self assert: parser parse: 'aaaa' to: 'aaaa'. |
|
236 self assert: parser parse: 'aaaaaa' to: 'aaaaaa'. |
|
237 |
|
238 self assert: parser parse: 'a' to: '' end: 0. |
|
239 self assert: parser parse: 'aaa' to: 'aa' end: 2. |
|
240 self assert: parser parse: 'aaaaa' to: 'aaaa' end: 4. |
|
241 self assert: parser parse: 'aaaaaaa' to: 'aaaaaa' end: 6 |
|
242 ! |
|
243 |
|
244 testParseAbAbAb |
|
245 "S ::= (A B)+" |
|
246 |
|
247 | parser | |
|
248 parser := ($a asParser , $b asParser) plus flatten. |
|
249 |
|
250 self assert: parser parse: 'ab' to: 'ab'. |
|
251 self assert: parser parse: 'abab' to: 'abab'. |
|
252 self assert: parser parse: 'ababab' to: 'ababab'. |
|
253 self assert: parser parse: 'abababab' to: 'abababab'. |
|
254 |
|
255 self assert: parser parse: 'abb' to: 'ab' end: 2. |
|
256 self assert: parser parse: 'ababa' to: 'abab' end: 4. |
|
257 self assert: parser parse: 'abababb' to: 'ababab' end: 6. |
|
258 self assert: parser parse: 'ababababa' to: 'abababab' end: 8. |
|
259 |
|
260 self assert: parser fail: ''. |
|
261 self assert: parser fail: 'a'. |
|
262 self assert: parser fail: 'bab' |
|
263 ! |
|
264 |
|
265 testParseAbabbb |
|
266 "S ::= (A | B)+" |
|
267 |
|
268 | parser | |
|
269 parser := ($a asParser / $b asParser) plus flatten. |
|
270 |
|
271 self assert: parser parse: 'a' to: 'a'. |
|
272 self assert: parser parse: 'b' to: 'b'. |
|
273 self assert: parser parse: 'ab' to: 'ab'. |
|
274 self assert: parser parse: 'ba' to: 'ba'. |
|
275 self assert: parser parse: 'aaa' to: 'aaa'. |
|
276 self assert: parser parse: 'aab' to: 'aab'. |
|
277 self assert: parser parse: 'aba' to: 'aba'. |
|
278 self assert: parser parse: 'baa' to: 'baa'. |
|
279 self assert: parser parse: 'abb' to: 'abb'. |
|
280 self assert: parser parse: 'bab' to: 'bab'. |
|
281 self assert: parser parse: 'bba' to: 'bba'. |
|
282 self assert: parser parse: 'bbb' to: 'bbb'. |
|
283 |
|
284 self assert: parser parse: 'ac' to: 'a' end: 1. |
|
285 self assert: parser parse: 'bc' to: 'b' end: 1. |
|
286 self assert: parser parse: 'abc' to: 'ab' end: 2. |
|
287 self assert: parser parse: 'bac' to: 'ba' end: 2. |
|
288 |
|
289 self assert: parser fail: ''. |
|
290 self assert: parser fail: 'c' |
|
291 ! |
|
292 |
|
293 testParseAnBnCn |
|
294 "PEGs for a non context- free language: |
|
295 |
|
296 a^n , b^n , c^n |
|
297 |
|
298 S <- &P1 P2 |
|
299 P1 <- AB 'c' |
|
300 AB <- 'a' AB 'b' / epsilon |
|
301 P2 <- 'a'* BC end |
|
302 BC <- 'b' BC 'c' / epsilon" |
|
303 |
|
304 | s p1 ab p2 bc | |
|
305 s := PPUnresolvedParser new. |
|
306 p1 := PPUnresolvedParser new. |
|
307 ab := PPUnresolvedParser new. |
|
308 p2 := PPUnresolvedParser new. |
|
309 bc := PPUnresolvedParser new. |
|
310 |
|
311 s def: (p1 and , p2 end) flatten. |
|
312 p1 def: ab , $c asParser. |
|
313 ab def: ($a asParser , ab , $b asParser) optional. |
|
314 p2 def: $a asParser star , bc. |
|
315 bc def: ($b asParser , bc , $c asParser) optional. |
|
316 |
|
317 self assert: s parse: 'abc' to: 'abc'. |
|
318 self assert: s parse: 'aabbcc' to: 'aabbcc'. |
|
319 self assert: s parse: 'aaabbbccc' to: 'aaabbbccc'. |
|
320 |
|
321 self assert: s fail: 'bc'. |
|
322 self assert: s fail: 'ac'. |
|
323 self assert: s fail: 'ab'. |
|
324 self assert: s fail: 'abbcc'. |
|
325 self assert: s fail: 'aabcc'. |
|
326 self assert: s fail: 'aabbc' |
|
327 ! ! |
|
328 |
|
329 !PPComposedTest methodsFor:'testing-examples'! |
|
330 |
|
331 testComment |
|
332 self assert: self comment parse: '""' to: '""'. |
|
333 self assert: self comment parse: '"a"' to: '"a"'. |
|
334 self assert: self comment parse: '"ab"' to: '"ab"'. |
|
335 self assert: self comment parse: '"abc"' to: '"abc"'. |
|
336 |
|
337 self assert: self comment parse: '""a' to: '""' end: 2. |
|
338 self assert: self comment parse: '"a"a' to: '"a"' end: 3. |
|
339 self assert: self comment parse: '"ab"a' to: '"ab"' end: 4. |
|
340 self assert: self comment parse: '"abc"a' to: '"abc"' end: 5. |
|
341 |
|
342 self assert: self comment fail: '"'. |
|
343 self assert: self comment fail: '"a'. |
|
344 self assert: self comment fail: '"aa'. |
|
345 self assert: self comment fail: 'a"'. |
|
346 self assert: self comment fail: 'aa"' |
|
347 ! |
|
348 |
|
349 testIdentifier |
|
350 self assert: self identifier parse: 'a' to: 'a'. |
|
351 self assert: self identifier parse: 'a1' to: 'a1'. |
|
352 self assert: self identifier parse: 'a12' to: 'a12'. |
|
353 self assert: self identifier parse: 'ab' to: 'ab'. |
|
354 self assert: self identifier parse: 'a1b' to: 'a1b'. |
|
355 |
|
356 self assert: self identifier parse: 'a_' to: 'a' end: 1. |
|
357 self assert: self identifier parse: 'a1-' to: 'a1' end: 2. |
|
358 self assert: self identifier parse: 'a12+' to: 'a12' end: 3. |
|
359 self assert: self identifier parse: 'ab^' to: 'ab' end: 2. |
|
360 self assert: self identifier parse: 'a1b*' to: 'a1b' end: 3. |
|
361 |
|
362 self assert: self identifier fail: ''. |
|
363 self assert: self identifier fail: '1'. |
|
364 self assert: self identifier fail: '1a' |
|
365 ! |
|
366 |
|
367 testNumber |
|
368 self assert: self number parse: '1' to: '1'. |
|
369 self assert: self number parse: '12' to: '12'. |
|
370 self assert: self number parse: '12.3' to: '12.3'. |
|
371 self assert: self number parse: '12.34' to: '12.34'. |
|
372 |
|
373 self assert: self number parse: '1..' to: '1' end: 1. |
|
374 self assert: self number parse: '12-' to: '12' end: 2. |
|
375 self assert: self number parse: '12.3.' to: '12.3' end: 4. |
|
376 self assert: self number parse: '12.34.' to: '12.34' end: 5. |
|
377 |
|
378 self assert: self number parse: '-1' to: '-1'. |
|
379 self assert: self number parse: '-12' to: '-12'. |
|
380 self assert: self number parse: '-12.3' to: '-12.3'. |
|
381 self assert: self number parse: '-12.34' to: '-12.34'. |
|
382 |
|
383 self assert: self number fail: ''. |
|
384 self assert: self number fail: '-'. |
|
385 self assert: self number fail: '.'. |
|
386 self assert: self number fail: '.1' |
|
387 ! |
|
388 |
|
389 testReturn |
|
390 | number spaces return | |
|
391 number := #digit asParser plus token. |
|
392 spaces := #space asParser star. |
|
393 return := (spaces , $^ asParser token , spaces , number) |
|
394 ==> [ :nodes | Array with: #return with: (nodes at: 4) value ]. |
|
395 |
|
396 self assert: return parse: '^1' to: #(return '1'). |
|
397 self assert: return parse: '^12' to: #(return '12'). |
|
398 self assert: return parse: '^ 123' to: #(return '123'). |
|
399 self assert: return parse: '^ 1234' to: #(return '1234'). |
|
400 |
|
401 self assert: return fail: '1'. |
|
402 self assert: return fail: '^' |
|
403 ! ! |
|
404 |
|
405 !PPComposedTest class methodsFor:'documentation'! |
|
406 |
|
407 version_SVN |
|
408 ^ '$Id: PPComposedTest.st,v 1.1 2011-08-18 18:56:17 cg Exp $' |
|
409 ! ! |