[cl-unification-cvs] CVS cl-unification/lib-dependent
mantoniotti
mantoniotti at common-lisp.net
Wed Apr 15 10:24:28 UTC 2009
Update of /project/cl-unification/cvsroot/cl-unification/lib-dependent
In directory cl-net:/tmp/cvs-serv30009/lib-dependent
Added Files:
cl-ppcre-template.lisp
Log Message:
Modified Files:
test/unification-tests.lisp
Added Files:
lib-dependent/cl-ppcre-template.lisp
The cl-ppcre-template reuses E. Weitz's wonderful CL-PPCRE library
to provide a seamless (YMMV) reuse of regular expressions within
CL-UNIFICATION.
--- /project/cl-unification/cvsroot/cl-unification/lib-dependent/cl-ppcre-template.lisp 2009/04/15 10:24:28 NONE
+++ /project/cl-unification/cvsroot/cl-unification/lib-dependent/cl-ppcre-template.lisp 2009/04/15 10:24:28 1.1
;;;; -*- Mode: Lisp -*-
;;;; cl-ppcre-template.lisp --
;;;; REGEXP template dependent on CL-PPCRE.
(in-package "CL.EXT.DACF.UNIFICATION") ; DACF = Data And Control Flow.
(require "CL-PPCRE")
;;;; REGEXP Templates.
;;;; Another extension of the type specifier language.
;;;; A template can also be
;;;;
;;;; <template> ::= #| templates from template-hierarchy.lisp |#
;;;; | <regexp template>
;;;;
;;;; Hairier REGEXP template spec syntax:
;;;;
;;;; (regexp|regular-expression) <REGEXP> &optional <unification vars> &rest <keys>
;;;;
;;;; where
;;;;
;;;; <REGEXP> ::= <a CL-PPCRE regexp string or tree>
;;;; <unification vars> ::= '(' <variable>* ')'
;;;; <keys> ::= <CL-PPCRE (constant) keys to be passed to CL-PPCRE:CREATE-SCANNER>
(defclass regular-expression-template (string-template)
((scanner :reader scanner)
(regexp :reader regular-expression)
(vars :reader variables
:reader registers
:type list)
)
(:documentation "The Regular Expression Template.
A template for matching strings using regular expressions.
The actual matching is done thankes to the CL-PPCRE library.")
)
(defgeneric regular-expression-template-p (x)
(:method ((x regular-expression-template)) t)
(:method ((x t)) nil))
(defmethod make-template ((kind (eql 'regexp)) (spec cons))
(make-instance 'regular-expression-template :spec spec))
(defmethod make-template ((kind (eql 'regular-expression)) (spec cons))
(make-template 'regexp spec))
(defmethod initialize-instance :after ((re-t regular-expression-template) &key)
(destructuring-bind (re-kwd regexp &optional vars &rest keys)
(template-spec re-t)
(declare (ignore re-kwd))
(multiple-value-bind (scanner reg-names)
(let ((cl-ppcre:*allow-named-registers* t))
(apply #'cl-ppcre:create-scanner regexp keys))
(declare (ignorable reg-names))
(setf (slot-value re-t 'scanner)
scanner
(slot-value re-t 'regexp)
regexp
(slot-value re-t 'vars)
vars ; Maybe will merge with REG-NAMES...
)
)))
#|
(defmethod initialize-instance :after ((re-t regular-expression-template) &key)
;; FIX: handling of CL-PPCRE:CREATE-SCANNER keywords. This can be
;; done by using the "harier" syntax of SPEC (see above).
(destructuring-bind (re-kwd regexp &optional vars &rest keys)
(template-spec re-t)
(declare (ignore re-kwd)
(ignorable regexp vars keys))
(multiple-value-bind (scanner reg-names)
(let ((cl-ppcre:*allow-named-registers* t))
(cl-ppcre:create-scanner (second (template-spec re-t))))
(declare (ignorable reg-names))
(setf (slot-value re-t 'scanner)
scanner
(slot-value re-t 'regexp)
(second (template-spec re-t)) ; For the time being just stored and
; used for debugging.
)
)))
|#
;;;;---------------------------------------------------------------------------
;;;; Implementation.
;;; Unification.
(defmethod unify ((ret1 regular-expression-template)
(ret2 regular-expression-template)
&optional (env (make-empty-environment))
&key &allow-other-keys)
(if (eq ret1 ret2)
env
;; I could UNIFY the result of the CL-PPCRE:PARSE-STRINGs.
(error 'unification-failure
:format-control "Do not know how unify the two ~
regular-expression templates: ~S and ~S."
:format-arguments (list ret1 ret2))))
(defmethod unify ((re-t regular-expression-template) (s string)
&optional (env (make-empty-environment))
&key
(start 0)
end
&allow-other-keys)
(declare (type (integer 0 #.most-positive-fixnum) start)
(type (or null (integer 0 #.most-positive-fixnum)) end))
(let ((end (or end (length s))))
(declare (type (integer 0 #.most-positive-fixnum) end))
(multiple-value-bind (m-start m-end r-starts r-ends)
(cl-ppcre:scan (scanner re-t) s :start start :end end)
;; Maybe SCAN-TO-STRINGS would be simpler to use...
(declare (type (integer 0 #.most-positive-fixnum) m-start m-end)
(type (vector (integer 0 #.most-positive-fixnum)) r-starts r-ends))
(unless (and (= start m-start) (= m-end end))
(error 'unification-failure
:format-control "String ~S cannot be matched against ~
regular expression ~S."
:format-arguments (list s
(regular-expression re-t))))
(let ((vars (variables re-t)))
(if (null vars)
env
(loop for r-start across r-starts
for r-end across r-ends
for r-string of-type string = (subseq s r-start r-end)
for v in vars
for result-env = (var-unify v r-string env)
then (var-unify v r-string result-env)
finally (return result-env))))
)))
(defmethod unify ((s string) (re-t regular-expression-template)
&optional (env (make-empty-environment))
&key (start 0) end &allow-other-keys)
(unify re-t s env :start start :end end))
;;;; end of file -- cl-ppcre-template.lisp --
More information about the Cl-unification-cvs
mailing list