clucumber 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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)