clucumber 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. data/LICENSE +1 -1
  2. data/README.md +4 -9
  3. data/lib/clucumber/clucumber-bootstrap.lisp +32 -0
  4. data/lib/clucumber/vendor/cl-interpol/alias.lisp +55 -0
  5. data/lib/clucumber/vendor/cl-interpol/cl-interpol.asd +56 -0
  6. data/lib/clucumber/vendor/cl-interpol/load.lisp +53 -0
  7. data/lib/clucumber/vendor/cl-interpol/packages.lisp +40 -0
  8. data/lib/clucumber/vendor/cl-interpol/read.lisp +716 -0
  9. data/lib/clucumber/vendor/cl-interpol/specials.lisp +113 -0
  10. data/lib/clucumber/vendor/cl-interpol/test/packages.lisp +34 -0
  11. data/lib/clucumber/vendor/cl-interpol/test/tests.lisp +128 -0
  12. data/lib/clucumber/vendor/cl-interpol/test.lisp +177 -0
  13. data/lib/clucumber/vendor/cl-interpol/test2.lisp +6254 -0
  14. data/lib/clucumber/vendor/cl-interpol/unicode.lisp +13912 -0
  15. data/lib/clucumber/vendor/cl-interpol/util.lisp +122 -0
  16. data/lib/clucumber/vendor/cl-ppcre/api.lisp +1262 -0
  17. data/lib/clucumber/vendor/cl-ppcre/charmap.lisp +152 -0
  18. data/lib/clucumber/vendor/cl-ppcre/charset.lisp +242 -0
  19. data/lib/clucumber/vendor/cl-ppcre/chartest.lisp +98 -0
  20. data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-test.asd +34 -0
  21. data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-unicode/packages.lisp +38 -0
  22. data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-unicode/resolver.lisp +61 -0
  23. data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-unicode.asd +58 -0
  24. data/lib/clucumber/vendor/cl-ppcre/cl-ppcre.asd +79 -0
  25. data/lib/clucumber/vendor/cl-ppcre/closures.lisp +471 -0
  26. data/lib/clucumber/vendor/cl-ppcre/convert.lisp +875 -0
  27. data/lib/clucumber/vendor/cl-ppcre/errors.lisp +84 -0
  28. data/lib/clucumber/vendor/cl-ppcre/lexer.lisp +737 -0
  29. data/lib/clucumber/vendor/cl-ppcre/lispworks-defsystem.lisp +57 -0
  30. data/lib/clucumber/vendor/cl-ppcre/load.lisp +67 -0
  31. data/lib/clucumber/vendor/cl-ppcre/optimize.lisp +578 -0
  32. data/lib/clucumber/vendor/cl-ppcre/packages.lisp +68 -0
  33. data/lib/clucumber/vendor/cl-ppcre/parser.lisp +319 -0
  34. data/lib/clucumber/vendor/cl-ppcre/ppcre-tests.lisp +269 -0
  35. data/lib/clucumber/vendor/cl-ppcre/regex-class-util.lisp +555 -0
  36. data/lib/clucumber/vendor/cl-ppcre/regex-class.lisp +259 -0
  37. data/lib/clucumber/vendor/cl-ppcre/repetition-closures.lisp +833 -0
  38. data/lib/clucumber/vendor/cl-ppcre/scanner.lisp +506 -0
  39. data/lib/clucumber/vendor/cl-ppcre/specials.lisp +172 -0
  40. data/lib/clucumber/vendor/cl-ppcre/test/packages.lisp +37 -0
  41. data/lib/clucumber/vendor/cl-ppcre/test/perl-tests.lisp +150 -0
  42. data/lib/clucumber/vendor/cl-ppcre/test/tests.lisp +159 -0
  43. data/lib/clucumber/vendor/cl-ppcre/test/unicode-tests.lisp +80 -0
  44. data/lib/clucumber/vendor/cl-ppcre/util.lisp +201 -0
  45. data/lib/clucumber/vendor/cl-unicode/alias.lisp +135 -0
  46. data/lib/clucumber/vendor/cl-unicode/api.lisp +412 -0
  47. data/lib/clucumber/vendor/cl-unicode/build/char-info.lisp +133 -0
  48. data/lib/clucumber/vendor/cl-unicode/build/dump.lisp +239 -0
  49. data/lib/clucumber/vendor/cl-unicode/build/read.lisp +280 -0
  50. data/lib/clucumber/vendor/cl-unicode/build/util.lisp +182 -0
  51. data/lib/clucumber/vendor/cl-unicode/cl-unicode.asd +90 -0
  52. data/lib/clucumber/vendor/cl-unicode/conditions.lisp +54 -0
  53. data/lib/clucumber/vendor/cl-unicode/derived.lisp +120 -0
  54. data/lib/clucumber/vendor/cl-unicode/hash-tables.lisp +20 -0
  55. data/lib/clucumber/vendor/cl-unicode/lists.lisp +10 -0
  56. data/lib/clucumber/vendor/cl-unicode/methods.lisp +15 -0
  57. data/lib/clucumber/vendor/cl-unicode/packages.lisp +76 -0
  58. data/lib/clucumber/vendor/cl-unicode/specials.lisp +135 -0
  59. data/lib/clucumber/vendor/cl-unicode/test/packages.lisp +34 -0
  60. data/lib/clucumber/vendor/cl-unicode/test/tests.lisp +150 -0
  61. data/lib/clucumber/vendor/cl-unicode/test-functions.lisp +94 -0
  62. data/lib/clucumber/vendor/cl-unicode/util.lisp +274 -0
  63. data/lib/clucumber/vendor/lift/compare/fiveam-tests.lisp +14 -0
  64. data/lib/clucumber/vendor/lift/compare/lift-tests.lisp +13 -0
  65. data/lib/clucumber/vendor/lift/compare/rt-tests.lisp +16 -0
  66. data/lib/clucumber/vendor/lift/compare/xlunit-tests.lisp +15 -0
  67. data/lib/clucumber/vendor/lift/dev/changes.lisp +61 -0
  68. data/lib/clucumber/vendor/lift/dev/config.lisp +354 -0
  69. data/lib/clucumber/vendor/lift/dev/copy-file.lisp +117 -0
  70. data/lib/clucumber/vendor/lift/dev/introspection.lisp +232 -0
  71. data/lib/clucumber/vendor/lift/dev/lift-interface.lisp +56 -0
  72. data/lib/clucumber/vendor/lift/dev/lift-notes.lisp +202 -0
  73. data/lib/clucumber/vendor/lift/dev/lift-randomized.lisp +45 -0
  74. data/lib/clucumber/vendor/lift/dev/lift.lisp +2383 -0
  75. data/lib/clucumber/vendor/lift/dev/macros.lisp +229 -0
  76. data/lib/clucumber/vendor/lift/dev/measuring.lisp +156 -0
  77. data/lib/clucumber/vendor/lift/dev/packages.lisp +161 -0
  78. data/lib/clucumber/vendor/lift/dev/port.lisp +151 -0
  79. data/lib/clucumber/vendor/lift/dev/prototypes.lisp +282 -0
  80. data/lib/clucumber/vendor/lift/dev/random-testing.lisp +124 -0
  81. data/lib/clucumber/vendor/lift/dev/report-locations.lisp +13 -0
  82. data/lib/clucumber/vendor/lift/dev/reports.lisp +916 -0
  83. data/lib/clucumber/vendor/lift/dev/utilities.lisp +242 -0
  84. data/lib/clucumber/vendor/lift/docs/package.lisp +6 -0
  85. data/lib/clucumber/vendor/lift/docs/setup.lisp +17 -0
  86. data/lib/clucumber/vendor/lift/examples/basic-examples.lisp +289 -0
  87. data/lib/clucumber/vendor/lift/examples/random-testing.lisp +32 -0
  88. data/lib/clucumber/vendor/lift/lift-documentation.asd +28 -0
  89. data/lib/clucumber/vendor/lift/lift-test.asd +35 -0
  90. data/lib/clucumber/vendor/lift/lift.asd +77 -0
  91. data/lib/clucumber/vendor/lift/test/equality-tests.lisp +40 -0
  92. data/lib/clucumber/vendor/lift/test/finding-tests.lisp +32 -0
  93. data/lib/clucumber/vendor/lift/test/lift-test.lisp +783 -0
  94. data/lib/clucumber/vendor/lift/test/order-of-operations.lisp +54 -0
  95. data/lib/clucumber/vendor/lift/test/packages.lisp +17 -0
  96. data/lib/clucumber/vendor/lift/test/test-config-files.lisp +20 -0
  97. data/lib/clucumber/vendor/lift/test/test-dynamic-variables.lisp +57 -0
  98. data/lib/clucumber/vendor/lift/test/test-maximum-problems.lisp +74 -0
  99. data/lib/clucumber/vendor/lift/test/test-prototypes.lisp +278 -0
  100. data/lib/clucumber/vendor/lift/test/test-timeout.lisp +37 -0
  101. data/lib/clucumber/vendor/lift/test/tests-in-progress.lisp +62 -0
  102. data/lib/clucumber/vendor/lift/test/testsuite-expects.lisp +60 -0
  103. data/lib/clucumber/vendor/lift/timeout/package.lisp +13 -0
  104. data/lib/clucumber/vendor/lift/timeout/with-timeout.lisp +123 -0
  105. data/lib/clucumber/vendor/lift/website/stuff/Temp.lisp +34 -0
  106. data/lib/clucumber/vendor/st-json/st-json.asd +3 -0
  107. data/lib/clucumber/vendor/st-json/st-json.lisp +310 -0
  108. data/lib/clucumber/vendor/trivial-backtrace/dev/backtrace.lisp +127 -0
  109. data/lib/clucumber/vendor/trivial-backtrace/dev/fallback.lisp +10 -0
  110. data/lib/clucumber/vendor/trivial-backtrace/dev/map-backtrace.lisp +103 -0
  111. data/lib/clucumber/vendor/trivial-backtrace/dev/mucking.lisp +75 -0
  112. data/lib/clucumber/vendor/trivial-backtrace/dev/packages.lisp +13 -0
  113. data/lib/clucumber/vendor/trivial-backtrace/dev/utilities.lisp +104 -0
  114. data/lib/clucumber/vendor/trivial-backtrace/test/packages.lisp +5 -0
  115. data/lib/clucumber/vendor/trivial-backtrace/test/test-setup.lisp +4 -0
  116. data/lib/clucumber/vendor/trivial-backtrace/test/tests.lisp +16 -0
  117. data/lib/clucumber/vendor/trivial-backtrace/trivial-backtrace-test.asd +22 -0
  118. data/lib/clucumber/vendor/trivial-backtrace/trivial-backtrace.asd +35 -0
  119. data/lib/clucumber/vendor/usocket/backend/allegro.lisp +199 -0
  120. data/lib/clucumber/vendor/usocket/backend/armedbear.lisp +491 -0
  121. data/lib/clucumber/vendor/usocket/backend/clisp.lisp +260 -0
  122. data/lib/clucumber/vendor/usocket/backend/cmucl.lisp +266 -0
  123. data/lib/clucumber/vendor/usocket/backend/lispworks.lisp +741 -0
  124. data/lib/clucumber/vendor/usocket/backend/mcl.lisp +369 -0
  125. data/lib/clucumber/vendor/usocket/backend/openmcl.lisp +206 -0
  126. data/lib/clucumber/vendor/usocket/backend/sbcl.lisp +424 -0
  127. data/lib/clucumber/vendor/usocket/backend/scl.lisp +261 -0
  128. data/lib/clucumber/vendor/usocket/condition.lisp +227 -0
  129. data/lib/clucumber/vendor/usocket/package.lisp +82 -0
  130. data/lib/clucumber/vendor/usocket/server.lisp +45 -0
  131. data/lib/clucumber/vendor/usocket/test/package.lisp +13 -0
  132. data/lib/clucumber/vendor/usocket/test/test-usocket.lisp +166 -0
  133. data/lib/clucumber/vendor/usocket/usocket-test.asd +26 -0
  134. data/lib/clucumber/vendor/usocket/usocket.asd +37 -0
  135. data/lib/clucumber/vendor/usocket/usocket.lisp +542 -0
  136. data/lib/clucumber/vendor/usocket/vendor/kqueue.lisp +1 -0
  137. data/lib/clucumber/vendor/usocket/vendor/split-sequence.lisp +245 -0
  138. data/lib/clucumber.rb +29 -7
  139. metadata +151 -5
@@ -0,0 +1,555 @@
1
+ ;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-PPCRE; Base: 10 -*-
2
+ ;;; $Header: /usr/local/cvsrep/cl-ppcre/regex-class-util.lisp,v 1.9 2009/09/17 19:17:31 edi Exp $
3
+
4
+ ;;; This file contains some utility methods for REGEX objects.
5
+
6
+ ;;; Copyright (c) 2002-2009, Dr. Edmund Weitz. All rights reserved.
7
+
8
+ ;;; Redistribution and use in source and binary forms, with or without
9
+ ;;; modification, are permitted provided that the following conditions
10
+ ;;; are met:
11
+
12
+ ;;; * Redistributions of source code must retain the above copyright
13
+ ;;; notice, this list of conditions and the following disclaimer.
14
+
15
+ ;;; * Redistributions in binary form must reproduce the above
16
+ ;;; copyright notice, this list of conditions and the following
17
+ ;;; disclaimer in the documentation and/or other materials
18
+ ;;; provided with the distribution.
19
+
20
+ ;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED
21
+ ;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22
+ ;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
+ ;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
24
+ ;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ ;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
26
+ ;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
+ ;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28
+ ;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29
+ ;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30
+ ;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+
32
+ (in-package :cl-ppcre)
33
+
34
+ ;;; The following four methods allow a VOID object to behave like a
35
+ ;;; zero-length STR object (only readers needed)
36
+
37
+ (defmethod len ((void void))
38
+ (declare #.*standard-optimize-settings*)
39
+ 0)
40
+
41
+ (defmethod str ((void void))
42
+ (declare #.*standard-optimize-settings*)
43
+ "")
44
+
45
+ (defmethod skip ((void void))
46
+ (declare #.*standard-optimize-settings*)
47
+ nil)
48
+
49
+ (defmethod start-of-end-string-p ((void void))
50
+ (declare #.*standard-optimize-settings*)
51
+ nil)
52
+
53
+ (defgeneric case-mode (regex old-case-mode)
54
+ (declare #.*standard-optimize-settings*)
55
+ (:documentation "Utility function used by the optimizer (see GATHER-STRINGS).
56
+ Returns a keyword denoting the case-(in)sensitivity of a STR or its
57
+ second argument if the STR has length 0. Returns NIL for REGEX objects
58
+ which are not of type STR."))
59
+
60
+ (defmethod case-mode ((str str) old-case-mode)
61
+ (declare #.*standard-optimize-settings*)
62
+ (cond ((zerop (len str))
63
+ old-case-mode)
64
+ ((case-insensitive-p str)
65
+ :case-insensitive)
66
+ (t
67
+ :case-sensitive)))
68
+
69
+ (defmethod case-mode ((regex regex) old-case-mode)
70
+ (declare #.*standard-optimize-settings*)
71
+ (declare (ignore old-case-mode))
72
+ nil)
73
+
74
+ (defgeneric copy-regex (regex)
75
+ (declare #.*standard-optimize-settings*)
76
+ (:documentation "Implements a deep copy of a REGEX object."))
77
+
78
+ (defmethod copy-regex ((anchor anchor))
79
+ (declare #.*standard-optimize-settings*)
80
+ (make-instance 'anchor
81
+ :startp (startp anchor)
82
+ :multi-line-p (multi-line-p anchor)
83
+ :no-newline-p (no-newline-p anchor)))
84
+
85
+ (defmethod copy-regex ((everything everything))
86
+ (declare #.*standard-optimize-settings*)
87
+ (make-instance 'everything
88
+ :single-line-p (single-line-p everything)))
89
+
90
+ (defmethod copy-regex ((word-boundary word-boundary))
91
+ (declare #.*standard-optimize-settings*)
92
+ (make-instance 'word-boundary
93
+ :negatedp (negatedp word-boundary)))
94
+
95
+ (defmethod copy-regex ((void void))
96
+ (declare #.*standard-optimize-settings*)
97
+ (make-instance 'void))
98
+
99
+ (defmethod copy-regex ((lookahead lookahead))
100
+ (declare #.*standard-optimize-settings*)
101
+ (make-instance 'lookahead
102
+ :regex (copy-regex (regex lookahead))
103
+ :positivep (positivep lookahead)))
104
+
105
+ (defmethod copy-regex ((seq seq))
106
+ (declare #.*standard-optimize-settings*)
107
+ (make-instance 'seq
108
+ :elements (mapcar #'copy-regex (elements seq))))
109
+
110
+ (defmethod copy-regex ((alternation alternation))
111
+ (declare #.*standard-optimize-settings*)
112
+ (make-instance 'alternation
113
+ :choices (mapcar #'copy-regex (choices alternation))))
114
+
115
+ (defmethod copy-regex ((branch branch))
116
+ (declare #.*standard-optimize-settings*)
117
+ (with-slots (test)
118
+ branch
119
+ (make-instance 'branch
120
+ :test (if (typep test 'regex)
121
+ (copy-regex test)
122
+ test)
123
+ :then-regex (copy-regex (then-regex branch))
124
+ :else-regex (copy-regex (else-regex branch)))))
125
+
126
+ (defmethod copy-regex ((lookbehind lookbehind))
127
+ (declare #.*standard-optimize-settings*)
128
+ (make-instance 'lookbehind
129
+ :regex (copy-regex (regex lookbehind))
130
+ :positivep (positivep lookbehind)
131
+ :len (len lookbehind)))
132
+
133
+ (defmethod copy-regex ((repetition repetition))
134
+ (declare #.*standard-optimize-settings*)
135
+ (make-instance 'repetition
136
+ :regex (copy-regex (regex repetition))
137
+ :greedyp (greedyp repetition)
138
+ :minimum (minimum repetition)
139
+ :maximum (maximum repetition)
140
+ :min-len (min-len repetition)
141
+ :len (len repetition)
142
+ :contains-register-p (contains-register-p repetition)))
143
+
144
+ (defmethod copy-regex ((register register))
145
+ (declare #.*standard-optimize-settings*)
146
+ (make-instance 'register
147
+ :regex (copy-regex (regex register))
148
+ :num (num register)
149
+ :name (name register)))
150
+
151
+ (defmethod copy-regex ((standalone standalone))
152
+ (declare #.*standard-optimize-settings*)
153
+ (make-instance 'standalone
154
+ :regex (copy-regex (regex standalone))))
155
+
156
+ (defmethod copy-regex ((back-reference back-reference))
157
+ (declare #.*standard-optimize-settings*)
158
+ (make-instance 'back-reference
159
+ :num (num back-reference)
160
+ :case-insensitive-p (case-insensitive-p back-reference)))
161
+
162
+ (defmethod copy-regex ((char-class char-class))
163
+ (declare #.*standard-optimize-settings*)
164
+ (make-instance 'char-class
165
+ :test-function (test-function char-class)))
166
+
167
+ (defmethod copy-regex ((str str))
168
+ (declare #.*standard-optimize-settings*)
169
+ (make-instance 'str
170
+ :str (str str)
171
+ :case-insensitive-p (case-insensitive-p str)))
172
+
173
+ (defmethod copy-regex ((filter filter))
174
+ (declare #.*standard-optimize-settings*)
175
+ (make-instance 'filter
176
+ :fn (fn filter)
177
+ :len (len filter)))
178
+
179
+ ;;; Note that COPY-REGEX and REMOVE-REGISTERS could have easily been
180
+ ;;; wrapped into one function. Maybe in the next release...
181
+
182
+ ;;; Further note that this function is used by CONVERT to factor out
183
+ ;;; complicated repetitions, i.e. cases like
184
+ ;;; (a)* -> (?:a*(a))?
185
+ ;;; This won't work for, say,
186
+ ;;; ((a)|(b))* -> (?:(?:a|b)*((a)|(b)))?
187
+ ;;; and therefore we stop REGISTER removal once we see an ALTERNATION.
188
+
189
+ (defgeneric remove-registers (regex)
190
+ (declare #.*standard-optimize-settings*)
191
+ (:documentation "Returns a deep copy of a REGEX (see COPY-REGEX) and
192
+ optionally removes embedded REGISTER objects if possible and if the
193
+ special variable REMOVE-REGISTERS-P is true."))
194
+
195
+ (defmethod remove-registers ((register register))
196
+ (declare #.*standard-optimize-settings*)
197
+ (declare (special remove-registers-p reg-seen))
198
+ (cond (remove-registers-p
199
+ (remove-registers (regex register)))
200
+ (t
201
+ ;; mark REG-SEEN as true so enclosing REPETITION objects
202
+ ;; (see method below) know if they contain a register or not
203
+ (setq reg-seen t)
204
+ (copy-regex register))))
205
+
206
+ (defmethod remove-registers ((repetition repetition))
207
+ (declare #.*standard-optimize-settings*)
208
+ (let* (reg-seen
209
+ (inner-regex (remove-registers (regex repetition))))
210
+ ;; REMOVE-REGISTERS will set REG-SEEN (see method above) if
211
+ ;; (REGEX REPETITION) contains a REGISTER
212
+ (declare (special reg-seen))
213
+ (make-instance 'repetition
214
+ :regex inner-regex
215
+ :greedyp (greedyp repetition)
216
+ :minimum (minimum repetition)
217
+ :maximum (maximum repetition)
218
+ :min-len (min-len repetition)
219
+ :len (len repetition)
220
+ :contains-register-p reg-seen)))
221
+
222
+ (defmethod remove-registers ((standalone standalone))
223
+ (declare #.*standard-optimize-settings*)
224
+ (make-instance 'standalone
225
+ :regex (remove-registers (regex standalone))))
226
+
227
+ (defmethod remove-registers ((lookahead lookahead))
228
+ (declare #.*standard-optimize-settings*)
229
+ (make-instance 'lookahead
230
+ :regex (remove-registers (regex lookahead))
231
+ :positivep (positivep lookahead)))
232
+
233
+ (defmethod remove-registers ((lookbehind lookbehind))
234
+ (declare #.*standard-optimize-settings*)
235
+ (make-instance 'lookbehind
236
+ :regex (remove-registers (regex lookbehind))
237
+ :positivep (positivep lookbehind)
238
+ :len (len lookbehind)))
239
+
240
+ (defmethod remove-registers ((branch branch))
241
+ (declare #.*standard-optimize-settings*)
242
+ (with-slots (test)
243
+ branch
244
+ (make-instance 'branch
245
+ :test (if (typep test 'regex)
246
+ (remove-registers test)
247
+ test)
248
+ :then-regex (remove-registers (then-regex branch))
249
+ :else-regex (remove-registers (else-regex branch)))))
250
+
251
+ (defmethod remove-registers ((alternation alternation))
252
+ (declare #.*standard-optimize-settings*)
253
+ (declare (special remove-registers-p))
254
+ ;; an ALTERNATION, so we can't remove REGISTER objects further down
255
+ (setq remove-registers-p nil)
256
+ (copy-regex alternation))
257
+
258
+ (defmethod remove-registers ((regex regex))
259
+ (declare #.*standard-optimize-settings*)
260
+ (copy-regex regex))
261
+
262
+ (defmethod remove-registers ((seq seq))
263
+ (declare #.*standard-optimize-settings*)
264
+ (make-instance 'seq
265
+ :elements (mapcar #'remove-registers (elements seq))))
266
+
267
+ (defgeneric everythingp (regex)
268
+ (declare #.*standard-optimize-settings*)
269
+ (:documentation "Returns an EVERYTHING object if REGEX is equivalent
270
+ to this object, otherwise NIL. So, \"(.){1}\" would return true
271
+ \(i.e. the object corresponding to \".\", for example."))
272
+
273
+ (defmethod everythingp ((seq seq))
274
+ (declare #.*standard-optimize-settings*)
275
+ ;; we might have degenerate cases like (:SEQUENCE :VOID ...)
276
+ ;; due to the parsing process
277
+ (let ((cleaned-elements (remove-if #'(lambda (element)
278
+ (typep element 'void))
279
+ (elements seq))))
280
+ (and (= 1 (length cleaned-elements))
281
+ (everythingp (first cleaned-elements)))))
282
+
283
+ (defmethod everythingp ((alternation alternation))
284
+ (declare #.*standard-optimize-settings*)
285
+ (with-slots (choices)
286
+ alternation
287
+ (and (= 1 (length choices))
288
+ ;; this is unlikely to happen for human-generated regexes,
289
+ ;; but machine-generated ones might look like this
290
+ (everythingp (first choices)))))
291
+
292
+ (defmethod everythingp ((repetition repetition))
293
+ (declare #.*standard-optimize-settings*)
294
+ (with-slots (maximum minimum regex)
295
+ repetition
296
+ (and maximum
297
+ (= 1 minimum maximum)
298
+ ;; treat "<regex>{1,1}" like "<regex>"
299
+ (everythingp regex))))
300
+
301
+ (defmethod everythingp ((register register))
302
+ (declare #.*standard-optimize-settings*)
303
+ (everythingp (regex register)))
304
+
305
+ (defmethod everythingp ((standalone standalone))
306
+ (declare #.*standard-optimize-settings*)
307
+ (everythingp (regex standalone)))
308
+
309
+ (defmethod everythingp ((everything everything))
310
+ (declare #.*standard-optimize-settings*)
311
+ everything)
312
+
313
+ (defmethod everythingp ((regex regex))
314
+ (declare #.*standard-optimize-settings*)
315
+ ;; the general case for ANCHOR, BACK-REFERENCE, BRANCH, CHAR-CLASS,
316
+ ;; LOOKAHEAD, LOOKBEHIND, STR, VOID, FILTER, and WORD-BOUNDARY
317
+ nil)
318
+
319
+ (defgeneric regex-length (regex)
320
+ (declare #.*standard-optimize-settings*)
321
+ (:documentation "Return the length of REGEX if it is fixed, NIL otherwise."))
322
+
323
+ (defmethod regex-length ((seq seq))
324
+ (declare #.*standard-optimize-settings*)
325
+ ;; simply add all inner lengths unless one of them is NIL
326
+ (loop for sub-regex in (elements seq)
327
+ for len = (regex-length sub-regex)
328
+ if (not len) do (return nil)
329
+ sum len))
330
+
331
+ (defmethod regex-length ((alternation alternation))
332
+ (declare #.*standard-optimize-settings*)
333
+ ;; only return a true value if all inner lengths are non-NIL and
334
+ ;; mutually equal
335
+ (loop for sub-regex in (choices alternation)
336
+ for old-len = nil then len
337
+ for len = (regex-length sub-regex)
338
+ if (or (not len)
339
+ (and old-len (/= len old-len))) do (return nil)
340
+ finally (return len)))
341
+
342
+ (defmethod regex-length ((branch branch))
343
+ (declare #.*standard-optimize-settings*)
344
+ ;; only return a true value if both alternations have a length and
345
+ ;; if they're equal
346
+ (let ((then-length (regex-length (then-regex branch))))
347
+ (and then-length
348
+ (eql then-length (regex-length (else-regex branch)))
349
+ then-length)))
350
+
351
+ (defmethod regex-length ((repetition repetition))
352
+ (declare #.*standard-optimize-settings*)
353
+ ;; we can only compute the length of a REPETITION object if the
354
+ ;; number of repetitions is fixed; note that we don't call
355
+ ;; REGEX-LENGTH for the inner regex, we assume that the LEN slot is
356
+ ;; always set correctly
357
+ (with-slots (len minimum maximum)
358
+ repetition
359
+ (if (and len
360
+ (eql minimum maximum))
361
+ (* minimum len)
362
+ nil)))
363
+
364
+ (defmethod regex-length ((register register))
365
+ (declare #.*standard-optimize-settings*)
366
+ (regex-length (regex register)))
367
+
368
+ (defmethod regex-length ((standalone standalone))
369
+ (declare #.*standard-optimize-settings*)
370
+ (regex-length (regex standalone)))
371
+
372
+ (defmethod regex-length ((back-reference back-reference))
373
+ (declare #.*standard-optimize-settings*)
374
+ ;; with enough effort we could possibly do better here, but
375
+ ;; currently we just give up and return NIL
376
+ nil)
377
+
378
+ (defmethod regex-length ((char-class char-class))
379
+ (declare #.*standard-optimize-settings*)
380
+ 1)
381
+
382
+ (defmethod regex-length ((everything everything))
383
+ (declare #.*standard-optimize-settings*)
384
+ 1)
385
+
386
+ (defmethod regex-length ((str str))
387
+ (declare #.*standard-optimize-settings*)
388
+ (len str))
389
+
390
+ (defmethod regex-length ((filter filter))
391
+ (declare #.*standard-optimize-settings*)
392
+ (len filter))
393
+
394
+ (defmethod regex-length ((regex regex))
395
+ (declare #.*standard-optimize-settings*)
396
+ ;; the general case for ANCHOR, LOOKAHEAD, LOOKBEHIND, VOID, and
397
+ ;; WORD-BOUNDARY (which all have zero-length)
398
+ 0)
399
+
400
+ (defgeneric regex-min-length (regex)
401
+ (declare #.*standard-optimize-settings*)
402
+ (:documentation "Returns the minimal length of REGEX."))
403
+
404
+ (defmethod regex-min-length ((seq seq))
405
+ (declare #.*standard-optimize-settings*)
406
+ ;; simply add all inner minimal lengths
407
+ (loop for sub-regex in (elements seq)
408
+ for len = (regex-min-length sub-regex)
409
+ sum len))
410
+
411
+ (defmethod regex-min-length ((alternation alternation))
412
+ (declare #.*standard-optimize-settings*)
413
+ ;; minimal length of an alternation is the minimal length of the
414
+ ;; "shortest" element
415
+ (loop for sub-regex in (choices alternation)
416
+ for len = (regex-min-length sub-regex)
417
+ minimize len))
418
+
419
+ (defmethod regex-min-length ((branch branch))
420
+ (declare #.*standard-optimize-settings*)
421
+ ;; minimal length of both alternations
422
+ (min (regex-min-length (then-regex branch))
423
+ (regex-min-length (else-regex branch))))
424
+
425
+ (defmethod regex-min-length ((repetition repetition))
426
+ (declare #.*standard-optimize-settings*)
427
+ ;; obviously the product of the inner minimal length and the minimal
428
+ ;; number of repetitions
429
+ (* (minimum repetition) (min-len repetition)))
430
+
431
+ (defmethod regex-min-length ((register register))
432
+ (declare #.*standard-optimize-settings*)
433
+ (regex-min-length (regex register)))
434
+
435
+ (defmethod regex-min-length ((standalone standalone))
436
+ (declare #.*standard-optimize-settings*)
437
+ (regex-min-length (regex standalone)))
438
+
439
+ (defmethod regex-min-length ((char-class char-class))
440
+ (declare #.*standard-optimize-settings*)
441
+ 1)
442
+
443
+ (defmethod regex-min-length ((everything everything))
444
+ (declare #.*standard-optimize-settings*)
445
+ 1)
446
+
447
+ (defmethod regex-min-length ((str str))
448
+ (declare #.*standard-optimize-settings*)
449
+ (len str))
450
+
451
+ (defmethod regex-min-length ((filter filter))
452
+ (declare #.*standard-optimize-settings*)
453
+ (or (len filter)
454
+ 0))
455
+
456
+ (defmethod regex-min-length ((regex regex))
457
+ (declare #.*standard-optimize-settings*)
458
+ ;; the general case for ANCHOR, BACK-REFERENCE, LOOKAHEAD,
459
+ ;; LOOKBEHIND, VOID, and WORD-BOUNDARY
460
+ 0)
461
+
462
+ (defgeneric compute-offsets (regex start-pos)
463
+ (declare #.*standard-optimize-settings*)
464
+ (:documentation "Returns the offset the following regex would have
465
+ relative to START-POS or NIL if we can't compute it. Sets the OFFSET
466
+ slot of REGEX to START-POS if REGEX is a STR. May also affect OFFSET
467
+ slots of STR objects further down the tree."))
468
+
469
+ ;; note that we're actually only interested in the offset of
470
+ ;; "top-level" STR objects (see ADVANCE-FN in the SCAN function) so we
471
+ ;; can stop at variable-length alternations and don't need to descend
472
+ ;; into repetitions
473
+
474
+ (defmethod compute-offsets ((seq seq) start-pos)
475
+ (declare #.*standard-optimize-settings*)
476
+ (loop for element in (elements seq)
477
+ ;; advance offset argument for next call while looping through
478
+ ;; the elements
479
+ for pos = start-pos then curr-offset
480
+ for curr-offset = (compute-offsets element pos)
481
+ while curr-offset
482
+ finally (return curr-offset)))
483
+
484
+ (defmethod compute-offsets ((alternation alternation) start-pos)
485
+ (declare #.*standard-optimize-settings*)
486
+ (loop for choice in (choices alternation)
487
+ for old-offset = nil then curr-offset
488
+ for curr-offset = (compute-offsets choice start-pos)
489
+ ;; we stop immediately if two alternations don't result in the
490
+ ;; same offset
491
+ if (or (not curr-offset)
492
+ (and old-offset (/= curr-offset old-offset)))
493
+ do (return nil)
494
+ finally (return curr-offset)))
495
+
496
+ (defmethod compute-offsets ((branch branch) start-pos)
497
+ (declare #.*standard-optimize-settings*)
498
+ ;; only return offset if both alternations have equal value
499
+ (let ((then-offset (compute-offsets (then-regex branch) start-pos)))
500
+ (and then-offset
501
+ (eql then-offset (compute-offsets (else-regex branch) start-pos))
502
+ then-offset)))
503
+
504
+ (defmethod compute-offsets ((repetition repetition) start-pos)
505
+ (declare #.*standard-optimize-settings*)
506
+ ;; no need to descend into the inner regex
507
+ (with-slots (len minimum maximum)
508
+ repetition
509
+ (if (and len
510
+ (eq minimum maximum))
511
+ ;; fixed number of repetitions, so we know how to proceed
512
+ (+ start-pos (* minimum len))
513
+ ;; otherwise return NIL
514
+ nil)))
515
+
516
+ (defmethod compute-offsets ((register register) start-pos)
517
+ (declare #.*standard-optimize-settings*)
518
+ (compute-offsets (regex register) start-pos))
519
+
520
+ (defmethod compute-offsets ((standalone standalone) start-pos)
521
+ (declare #.*standard-optimize-settings*)
522
+ (compute-offsets (regex standalone) start-pos))
523
+
524
+ (defmethod compute-offsets ((char-class char-class) start-pos)
525
+ (declare #.*standard-optimize-settings*)
526
+ (1+ start-pos))
527
+
528
+ (defmethod compute-offsets ((everything everything) start-pos)
529
+ (declare #.*standard-optimize-settings*)
530
+ (1+ start-pos))
531
+
532
+ (defmethod compute-offsets ((str str) start-pos)
533
+ (declare #.*standard-optimize-settings*)
534
+ (setf (offset str) start-pos)
535
+ (+ start-pos (len str)))
536
+
537
+ (defmethod compute-offsets ((back-reference back-reference) start-pos)
538
+ (declare #.*standard-optimize-settings*)
539
+ ;; with enough effort we could possibly do better here, but
540
+ ;; currently we just give up and return NIL
541
+ (declare (ignore start-pos))
542
+ nil)
543
+
544
+ (defmethod compute-offsets ((filter filter) start-pos)
545
+ (declare #.*standard-optimize-settings*)
546
+ (let ((len (len filter)))
547
+ (if len
548
+ (+ start-pos len)
549
+ nil)))
550
+
551
+ (defmethod compute-offsets ((regex regex) start-pos)
552
+ (declare #.*standard-optimize-settings*)
553
+ ;; the general case for ANCHOR, LOOKAHEAD, LOOKBEHIND, VOID, and
554
+ ;; WORD-BOUNDARY (which all have zero-length)
555
+ start-pos)