Skip to content

Commit

Permalink
Don't get confused by back references referring to the register named…
Browse files Browse the repository at this point in the history
… "NIL".

This fixes issue edicl#12.  Back references referring to the register named
"NIL" were being associated with the register objects with NIL for
their NAME slot (indicating an unnamed register) instead of those that
actually have "NIL" for a name.

One corollary of this patch is that back references may now refer to
named registers using symbols in addition to strings.  This is only
consistent, since named registers may themselves be named from
symbols.  To put it another way: names are strings, but they may be
represented in the parse tree with symbols.
  • Loading branch information
nbtrap committed Jan 26, 2014
1 parent e6029ed commit b51cb5c
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 6 deletions.
18 changes: 12 additions & 6 deletions convert.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -594,10 +594,13 @@ when NAME is not NIL."
:name name)))

(defmethod convert-compound-parse-tree ((token (eql :named-register)) parse-tree &key)
"The case for \(:NAMED-REGISTER <regex>)."
"The case for \(:NAMED-REGISTER <name> <regex>)."
(declare #.*standard-optimize-settings*)
;; call the method above and use the :NAME keyword argument
(convert-compound-parse-tree :register parse-tree :name (copy-seq (second parse-tree))))
(let ((name (second parse-tree)))
(check-type name (or string symbol))
(convert-compound-parse-tree :register parse-tree
:name (copy-seq (string name)))))

(defmethod convert-compound-parse-tree ((token (eql :filter)) parse-tree &key)
"The case for \(:FILTER <function> &optional <length>)."
Expand All @@ -624,16 +627,18 @@ when NAME is not NIL."
"The case for \(:BACK-REFERENCE <number>|<name>)."
(declare #.*standard-optimize-settings*)
(declare (special flags accumulate-start-p reg-num reg-names max-back-ref))
(let* ((backref-name (and (stringp (second parse-tree))
(second parse-tree)))
;; allow symbols or strings for back reference names, as with named registers
(let* ((backref-name (typecase (second parse-tree)
((or string symbol) (string (second parse-tree)))
(otherwise nil)))
(referred-regs
(when backref-name
;; find which register corresponds to the given name
;; we have to deal with case where several registers share
;; the same name and collect their respective numbers
(loop for name in reg-names
for reg-index from 0
when (string= name backref-name)
when (equal name backref-name)
;; NOTE: REG-NAMES stores register names in reversed
;; order REG-NUM contains number of (any) registers
;; seen so far; 1- will be done later
Expand All @@ -642,7 +647,8 @@ when NAME is not NIL."
(backref-number (or (first referred-regs) (second parse-tree))))
(declare (type (or fixnum null) backref-number))
(when (or (not (typep backref-number 'fixnum))
(<= backref-number 0))
(<= backref-number 0)
(not (= (length parse-tree) 2)))
(signal-syntax-error "Illegal back-reference: ~S." parse-tree))
;; stop accumulating into STARTS-WITH and increase MAX-BACK-REF if
;; necessary
Expand Down
72 changes: 72 additions & 0 deletions test/simple
Original file line number Diff line number Diff line change
Expand Up @@ -364,3 +364,75 @@ characters if there's a match."
(regex-replace-all (create-scanner "\\p{even}") "abcd" "+")
(regex-replace-all (create-scanner "\\p{true}") "abcd" "+")))
'("+b+d" "a+c+" "++++")))

(handler-case
(progn
(scan '(:sequence
(:register "f")
(:register "o")
(:back-reference "NIL"))
"foo")
nil)
(error () t))

(scan '(:sequence
(:register "f")
(:named-register nil "o")
(:back-reference "NIL"))
"foo")

(scan '(:sequence
(:register "f")
(:named-register "NIL" "o")
(:back-reference nil))
"foo")

(handler-case
(progn
(scan '(:sequence
(:register "f")
(:named-register "nil" "o")
(:back-reference nil))
"foo")
nil)
(error () t))

(handler-case
(progn
(scan '(:sequence
(:register "f")
(:named-register "o" "o")
(:back-reference #\o))
"foo")
nil)
(error () t))

(handler-case
(progn
(scan '(:sequence
(:register "f")
(:named-register #\o "o")
(:back-reference "o"))
"foo")
nil)
(error () t))

(handler-case
(progn
(scan '(:sequence
(:register "f")
(:named-register "nil" "o")
(:back-reference))
"foo")
nil)
(error () t))

(handler-case
(progn
(scan '(:sequence
(:register "f")
(:named-register)
(:back-reference "nil"))
"foo")
nil)
(error () t))

0 comments on commit b51cb5c

Please sign in to comment.