[voikko] Common Lisp ja libvoikko

Teemu Likonen tlikonen at iki.fi
Mon Jul 4 09:23:56 EEST 2011


Teemu Likonen kirjoitti 3.7.2011 klo 23.07:

> Tein makron ja funktion, joilla oikolukua voi helposti kokeilla.

En aikonut tänne pahemmin Common Lispiä spämmätä, mutta kun aiemmassa
oli paha virhe, lähetän nyt paremman version vielä arkistoitavaksi. Tämä
osaa virheetkin. Esimerkki:


    VOIKKO> (with-voikko-handle (h)
              (print (voikko-spell h "toimii"))
              (print (voikko-spell h "tomii"))
              (print (voikko-spell h "toimi")))

    "toimii"
    NIL
    "toimi"


Virhetilanne:


    VOIKKO> (handler-case (with-voikko-handle (h :language "siansaksa")
                            "Tänne ei päästä lainkaan")
              (voikko-init-error (condition)
                (format t "~A" condition)))

    Specified dictionary variant was not found


;;; Koodi alkaa


(defpackage :voikko
  (:use :common-lisp :cffi)
  (:export :voikko-init :voikko-terminate :with-voikko-handle
           :voikko-spell :voikko-error :voikko-init-error
           :voikko-spell-checker-error :voikko-internal-error
           :voikko-charset-conversion-failed))

(in-package :voikko)

(load-foreign-library '(:default "libvoikko"))

(define-condition voikko-error (error)
  ((error-string :initarg :string :reader voikko-error-string))
  (:report (lambda (condition stream)
             (format stream "~A" (voikko-error-string condition)))))

(define-condition voikko-init-error (voikko-error) nil)
(define-condition voikko-internal-error (voikko-error) nil)
(define-condition voikko-charset-conversion-failed (voikko-error) nil)

(defun voikko-init (&key (language "fi_FI"))
  (with-foreign-objects ((error :pointer))
    (let ((handle (foreign-funcall "voikkoInit"
                                   :pointer error
                                   :string language
                                   :pointer (null-pointer)
                                   :pointer)))
      (if (and (pointerp handle)
               (not (null-pointer-p handle))
               (null-pointer-p (mem-aref error :pointer)))
          handle
          (error 'voikko-init-error
                 :string (foreign-string-to-lisp
                          (mem-aref error :pointer)))))))

(defun voikko-terminate (handle)
  (foreign-funcall "voikkoTerminate" :pointer handle :void)
  t)

(defmacro with-voikko-handle ((var &key (language "fi_FI")) &body body)
  (let ((handle (gensym "HANDLE")))
    `(let* ((,handle (voikko-init :language ,language))
            (,var ,handle))
       (declare (ignorable ,var))
       (unwind-protect (progn , at body)
         (voikko-terminate ,handle)))))

(defun voikko-spell (handle string)
  (let ((value (foreign-funcall "voikkoSpellCstr"
                                :pointer handle
                                :string string
                                :int)))
    (ecase value
      (0 nil)
      (1 string)
      (2 (error 'voikko-internal-error :string "Internal error"))
      (3 (error 'voikko-charset-conversion-failed
                :string "Charset conversion failed")))))



More information about the voikko mailing list