author | Jan Vrany <jan.vrany@fit.cvut.cz> |
Thu, 21 May 2015 17:19:17 +0100 | |
changeset 469 | 8dc4eb06316e |
parent 427 | a7f5e6de19d2 |
permissions | -rw-r--r-- |
376
a2656b27cace
Added monticelloName to package definition to ease export to .mcz
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
375
diff
changeset
|
1 |
"{ Package: 'stx:goodies/petitparser/tests' }" |
0 | 2 |
|
427
a7f5e6de19d2
Merged JK's version from Monticello
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
385
diff
changeset
|
3 |
"{ NameSpace: Smalltalk }" |
a7f5e6de19d2
Merged JK's version from Monticello
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
385
diff
changeset
|
4 |
|
186 | 5 |
PPAbstractParserTest subclass:#PPComposedTest |
0 | 6 |
instanceVariableNames:'' |
7 |
classVariableNames:'' |
|
8 |
poolDictionaries:'' |
|
9 |
category:'PetitTests-Tests' |
|
10 |
! |
|
11 |
||
12 |
||
13 |
!PPComposedTest methodsFor:'accessing'! |
|
14 |
||
15 |
comment |
|
16 |
^ ($" asParser , $" asParser negate star , $" asParser) flatten |
|
17 |
! |
|
18 |
||
19 |
identifier |
|
20 |
^ (#letter asParser , #word asParser star) flatten |
|
21 |
! |
|
22 |
||
23 |
number |
|
24 |
^ ($- asParser optional , #digit asParser plus , ($. asParser , #digit asParser plus) optional) flatten |
|
25 |
! ! |
|
26 |
||
27 |
!PPComposedTest methodsFor:'testing'! |
|
28 |
||
29 |
testDoubledString |
|
186 | 30 |
| parser | |
31 |
parser := ($' asParser , (($' asParser , $' asParser) / $' asParser negate) star flatten , $' asParser) |
|
32 |
==> [ :nodes | nodes second copyReplaceAll: '''''' with: '''' ]. |
|
0 | 33 |
|
186 | 34 |
self assert: parser parse: '''''' to: ''. |
35 |
self assert: parser parse: '''a''' to: 'a'. |
|
36 |
self assert: parser parse: '''ab''' to: 'ab'. |
|
37 |
self assert: parser parse: '''a''''b''' to: 'a''b'. |
|
38 |
self assert: parser parse: '''a''''''''b''' to: 'a''''b' |
|
0 | 39 |
! |
40 |
||
41 |
testEvenNumber |
|
42 |
"Create a grammar that parses an even number of a's and b's." |
|
14 | 43 |
|
0 | 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 ]) |
|
377
6112a403a52d
Updated to latest version from Moose repository.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
51 |
ifFalse: [ PPFailure message: 'Even number of a and b expected' context: stream at: 0 ] ]. |
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. |
|
14 | 61 |
|
0 | 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 | |
|
186 | 77 |
start := PPDelegateParser new. |
0 | 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. |
|
186 | 83 |
start setParser: (if , cond , then , start , else , start) / (if , cond , then , start) / expr. |
0 | 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'" |
|
14 | 99 |
|
0 | 100 |
| parser | |
186 | 101 |
parser := PPDelegateParser new. |
102 |
parser setParser: ((parser , $x asParser , parser) / $1 asParser) memoized flatten. |
|
0 | 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" |
|
14 | 114 |
|
0 | 115 |
| number list parser | |
186 | 116 |
number := #digit asParser plus flatten trim |
117 |
==> [ :node | node asInteger ]. |
|
0 | 118 |
list := (number separatedBy: $, asParser token trim) |
427
a7f5e6de19d2
Merged JK's version from Monticello
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
385
diff
changeset
|
119 |
==> [ :node | node select: [ :each | each isKindOf: Integer ] ]. |
0 | 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. |
|
14 | 139 |
|
0 | 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 |
|
186 | 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 := PPDelegateParser new. |
|
159 |
inside := end not , (parser / any). |
|
160 |
parser setParser: 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' |
|
0 | 165 |
! |
166 |
||
167 |
testPalindrome |
|
168 |
"S0 ::= a S1 a | b S1 b | ... |
|
169 |
S1 ::= S0 | epsilon" |
|
14 | 170 |
|
0 | 171 |
| s0 s1 parser | |
186 | 172 |
s0 := PPDelegateParser new. |
173 |
s1 := PPDelegateParser new. |
|
174 |
s0 setParser: ($a asParser , s1 , $a asParser) |
|
0 | 175 |
/ ($b asParser , s1 , $b asParser) |
14 | 176 |
/ ($c asParser , s1 , $c asParser). |
186 | 177 |
s1 setParser: s0 / nil asParser. |
0 | 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'. |
|
14 | 183 |
|
0 | 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" |
|
14 | 200 |
|
0 | 201 |
| s0 s1 parser | |
186 | 202 |
s0 := PPDelegateParser new. |
203 |
s1 := PPDelegateParser new. |
|
204 |
s0 setParser: $a asParser , s1 , $b asParser. |
|
205 |
s1 setParser: s0 / nil asParser. |
|
0 | 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" |
|
14 | 226 |
|
0 | 227 |
| s0 s1 parser | |
186 | 228 |
s0 := PPDelegateParser new. |
0 | 229 |
s1 := $a asParser , $a asParser , s0. |
186 | 230 |
s0 setParser: s1 / nil asParser. |
0 | 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)+" |
|
14 | 246 |
|
0 | 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. |
|
14 | 259 |
|
0 | 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. |
|
14 | 288 |
|
0 | 289 |
self assert: parser fail: ''. |
290 |
self assert: parser fail: 'c' |
|
291 |
! |
|
292 |
||
293 |
testParseAnBnCn |
|
14 | 294 |
"PEGs for a non context- free language: |
295 |
||
0 | 296 |
a^n , b^n , c^n |
14 | 297 |
|
298 |
S <- &P1 P2 |
|
299 |
P1 <- AB 'c' |
|
0 | 300 |
AB <- 'a' AB 'b' / epsilon |
301 |
P2 <- 'a'* BC end |
|
302 |
BC <- 'b' BC 'c' / epsilon" |
|
14 | 303 |
|
0 | 304 |
| s p1 ab p2 bc | |
186 | 305 |
s := PPDelegateParser new. |
306 |
p1 := PPDelegateParser new. |
|
307 |
ab := PPDelegateParser new. |
|
308 |
p2 := PPDelegateParser new. |
|
309 |
bc := PPDelegateParser new. |
|
14 | 310 |
|
186 | 311 |
s setParser: (p1 and , p2 end) flatten. |
312 |
p1 setParser: ab , $c asParser. |
|
313 |
ab setParser: ($a asParser , ab , $b asParser) optional. |
|
314 |
p2 setParser: $a asParser star , bc. |
|
315 |
bc setParser: ($b asParser , bc , $c asParser) optional. |
|
14 | 316 |
|
0 | 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. |
|
14 | 377 |
|
0 | 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'. |
|
14 | 382 |
|
0 | 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 | |
|
186 | 391 |
number := #digit asParser plus flatten. |
0 | 392 |
spaces := #space asParser star. |
393 |
return := (spaces , $^ asParser token , spaces , number) |
|
186 | 394 |
==> [ :nodes | Array with: #return with: (nodes at: 4) ]. |
0 | 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'). |
|
14 | 400 |
|
0 | 401 |
self assert: return fail: '1'. |
402 |
self assert: return fail: '^' |
|
403 |
! ! |
|
404 |
||
405 |
!PPComposedTest class methodsFor:'documentation'! |
|
406 |
||
14 | 407 |
version |
186 | 408 |
^ '$Header: /cvs/stx/stx/goodies/petitparser/PPComposedTest.st,v 1.5 2014-03-04 14:34:10 cg Exp $' |
14 | 409 |
! |
410 |
||
411 |
version_CVS |
|
186 | 412 |
^ '$Header: /cvs/stx/stx/goodies/petitparser/PPComposedTest.st,v 1.5 2014-03-04 14:34:10 cg Exp $' |
14 | 413 |
! |
414 |
||
385
44a36ed4e484
Commited a Smalltalk parser (MC package PetitSmalltalk)
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
377
diff
changeset
|
415 |
version_HG |
44a36ed4e484
Commited a Smalltalk parser (MC package PetitSmalltalk)
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
377
diff
changeset
|
416 |
|
44a36ed4e484
Commited a Smalltalk parser (MC package PetitSmalltalk)
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
377
diff
changeset
|
417 |
^ '$Changeset: <not expanded> $' |
44a36ed4e484
Commited a Smalltalk parser (MC package PetitSmalltalk)
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
377
diff
changeset
|
418 |
! |
44a36ed4e484
Commited a Smalltalk parser (MC package PetitSmalltalk)
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
377
diff
changeset
|
419 |
|
0 | 420 |
version_SVN |
186 | 421 |
^ '$Id: PPComposedTest.st,v 1.5 2014-03-04 14:34:10 cg Exp $' |
0 | 422 |
! ! |
186 | 423 |