root/lang/scheme/gauche/bindings/mecab/trunk/mecab-lib.scm

Revision 131, 24.4 kB (checked in by naoya_t, 15 years ago)

=> http://cvs.sourceforge.jp/view/gauche/Gauche-mecab/

Line 
1;;;
2;;; mecab.stub - MeCab binding
3;;;
4;;;   Copyright (c) 2004 Kimura Fuyuki, All rights reserved.
5;;;
6;;;   Redistribution and use in source and binary forms, with or without
7;;;   modification, are permitted provided that the following conditions
8;;;   are met:
9;;;
10;;;   1. Redistributions of source code must retain the above copyright
11;;;      notice, this list of conditions and the following disclaimer.
12;;;
13;;;   2. Redistributions in binary form must reproduce the above copyright
14;;;      notice, this list of conditions and the following disclaimer in the
15;;;      documentation and/or other materials provided with the distribution.
16;;;
17;;;   3. Neither the name of the authors nor the names of its contributors
18;;;      may be used to endorse or promote products derived from this
19;;;      software without specific prior written permission.
20;;;
21;;;   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22;;;   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23;;;   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24;;;   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25;;;   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26;;;   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27;;;   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28;;;   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29;;;   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30;;;   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31;;;   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32;;;
33;;;  $Id: mecab-lib.scm,v 1.3 2009/03/25 09:42:14 naoya_t Exp $
34;;;
35
36(define-module text.mecab
37  (use srfi-1)
38  (use srfi-13)
39  (use gauche.charconv)
40  (export <mecab> <mecab-node> <mecab-dictionary-info>
41          mecab? mecab-node? mecab-dictionary-info?
42          mecab-do mecab-new mecab-new2
43          mecab-version mecab-strerror mecab-destroy mecab-destroyed?
44          mecab mecab-options
45
46          mecab-tagger ; message passing
47          <mecab-tagger> mecab-make-tagger ; class
48
49          mecab-get-partial mecab-set-partial
50          mecab-get-theta mecab-set-theta
51          mecab-get-lattice-level mecab-set-lattice-level
52          mecab-get-all-morphs mecab-set-all-morphs
53
54          mecab-sparse-tostr mecab-sparse-tostr2 ;; mecab-sparse-tostr3
55          mecab-sparse-tonode mecab-sparse-tonode2
56          mecab-nbest-sparse-tostr mecab-nbest-sparse-tostr2 ;; mecab-nbest-sparse-tostr3
57          mecab-nbest-init mecab-nbest-init2
58          mecab-nbest-next-tostr ;; mecab-nbest-next-tostr2
59          mecab-nbest-next-tonode
60          mecab-format-node
61          mecab-dictionary-info
62          mecab-dict-index mecab-dict-gen
63          mecab-cost-train mecab-system-eval mecab-test-gen
64
65          mecab-node-prev mecab-node-next mecab-node-enext mecab-node-bnext
66          mecab-node-surface mecab-node-feature
67          mecab-node-length mecab-node-rlength
68          mecab-node-id mecab-node-rc-attr mecab-node-lc-attr
69          mecab-node-posid mecab-node-char-type
70          mecab-node-stat mecab-node-best?
71          mecab-node-alpha mecab-node-beta mecab-node-prob
72          mecab-node-wcost mecab-node-cost
73
74          mecab-dictionary-info-filename mecab-dictionary-info-charset
75          mecab-dictionary-info-size mecab-dictionary-info-type
76          mecab-dictionary-info-lsize mecab-dictionary-info-rsize
77          mecab-dictionary-info-version mecab-dictionary-info-next
78          ))
79(select-module text.mecab)
80
81;; This should be configurable, since mecab can be compiled to use utf-8.
82(define-constant MECAB_ENCODING 'euc-jp)
83
84;; We need cv-send and cv-recv if MeCab is configured with --enable-utf8-only option.
85;(define (cv-send str)
86;  (ces-convert str (gauche-character-encoding) MECAB_ENCODING))
87;(define (cv-recv str)
88;  (and str (ces-convert str MECAB_ENCODING)))
89(define (cv-send str) str)
90(define (cv-recv str) str)
91
92(define (mecab-do args)
93  (unless (every string? args)
94    (error "mecab-do: list of strings required, but got:" args))
95  (%mecab-do (map cv-send args)))
96
97(define (mecab-new args)
98  (unless (every string? args)
99    (error "mecab-new: list of strings required, but got:" args))
100  (%mecab-new (map cv-send args) (mecab-parse-options args)))
101
102(define (mecab-new2 str)
103  (%mecab-new2 (cv-send str) (mecab-parse-options str)))
104
105(define (mecab-strerror m)
106; (cv-recv (%mecab-strerror m))) ;; m can be #f
107  (cv-recv (if m (%mecab-strerror m) (%mecab-strerror-with-null))))
108
109(define (mecab-sparse-tostr m str)
110  (cv-recv (%mecab-sparse-tostr m (cv-send str))))
111
112(define (mecab-sparse-tostr2 m str len)
113  (cv-recv (%mecab-sparse-tostr2 m (cv-send str) len)))
114
115(define (mecab-sparse-tonode m str)
116  (%mecab-sparse-tonode m (cv-send str)))
117
118(define (mecab-sparse-tonode2 m str len)
119  (%mecab-sparse-tonode2 m (cv-send str) len))
120
121(define (mecab-nbest-sparse-tostr m n str)
122  (cv-recv (%mecab-nbest-sparse-tostr m n (cv-send str))))
123
124(define (mecab-nbest-sparse-tostr2 m n str len)
125  (cv-recv (%mecab-nbest-sparse-tostr2 m n (cv-send str) len)))
126
127(define (mecab-nbest-init m str)
128  (%mecab-nbest-init m (cv-send str)))
129
130(define (mecab-nbest-init2 m str len)
131  (%mecab-nbest-init2 m (cv-send str) len))
132
133(define (mecab-nbest-next-tostr m)
134  (cv-recv (%mecab-nbest-next-tostr m)))
135
136(define (mecab-format-node m node)
137  (cv-recv (%mecab-format-node m node)))
138
139(define (mecab-dict-index args)
140  (unless (every string? args)
141    (error "mecab-dict-index: list of strings required, but got:" args))
142  (%mecab-dict-index (map cv-send args)))
143
144(define (mecab-dict-gen args)
145  (unless (every string? args)
146    (error "mecab-dict-gen: list of strings required, but got:" args))
147  (%mecab-dict-gen (map cv-send args)))
148
149(define (mecab-cost-train args)
150  (unless (every string? args)
151    (error "mecab-cost-train: list of strings required, but got:" args))
152  (%mecab-cost-train (map cv-send args)))
153
154(define (mecab-system-eval args)
155  (unless (every string? args)
156    (error "mecab-system-eval: list of strings required, but got:" args))
157  (%mecab-system-eval (map cv-send args)))
158
159(define (mecab-test-gen args)
160  (unless (every string? args)
161    (error "mecab-test-gen: list of strings required, but got:" args))
162  (%mecab-test-gen (map cv-send args)))
163
164;; mecab_node_t
165(define (mecab-node-surface n)
166  (cv-recv (%mecab-node-surface n)))
167
168(define (mecab-node-feature n)
169  (cv-recv (%mecab-node-feature n)))
170
171(define (mecab-node-stat n)
172  (vector-ref #(mecab-nor-node mecab-unk-node mecab-bos-node mecab-eos-node)
173              (%mecab-node-stat n)))
174
175;; mecab_dictionary_info_t
176(define (mecab-dictionary-info-type dinfo)
177  (vector-ref #(mecab-sys-dic mecab-usr-dic mecab-unk-dic)
178              (%mecab-dictionary-info-type dinfo)))
179
180;;
181(inline-stub
182 "#include <mecab.h>"
183
184 ;; mecab_t type holder.
185 "typedef struct ScmMeCabRec {
186   SCM_HEADER;
187   mecab_t *m; /* NULL if closed */
188   ScmObj   options;
189 } ScmMeCab;
190
191 typedef struct ScmMeCabNodeRec {
192   SCM_HEADER;
193   const mecab_node_t *node;
194 } ScmMeCabNode;
195
196 typedef struct ScmMeCabDictionaryInfoRec {
197   SCM_HEADER;
198   const mecab_dictionary_info_t *dic_info;
199 } ScmMeCabDictionaryInfo;"
200
201 (define-cclass <mecab> :private ScmMeCab* "Scm_MeCabClass"
202   ()
203   ())
204
205 (define-cclass <mecab-node> :private ScmMeCabNode* "Scm_MeCabNodeClass"
206   ()
207   ())
208
209 (define-cclass <mecab-dictionary-info> :private ScmMeCabDictionaryInfo* "Scm_MeCabDictionaryInfoClass"
210   ()
211   ())
212
213 ;; internal utility functions
214 (define-cfn mecab-cleanup (m::ScmMeCab*) ::void :static
215   (unless (== (-> m m) NULL)
216     (mecab-destroy (-> m m))
217     (set! (-> m m) NULL)))
218 
219 (define-cfn mecab-finalize (obj data::void*) ::void :static
220   (mecab-cleanup (SCM_MECAB obj)))
221
222 (define-cfn make-mecab (m::mecab_t* options::ScmObj) :static
223   (when (== m NULL) (mecab-strerror NULL))
224   (let* ([obj::ScmMeCab* (SCM_NEW ScmMeCab)])
225     (SCM_SET_CLASS obj (& Scm_MeCabClass))
226     (set! (-> obj m) m)
227     (set! (-> obj options) options)
228     (Scm_RegisterFinalizer (SCM_OBJ obj) mecab-finalize NULL)
229     (return (SCM_OBJ obj))))
230
231 (define-cfn make-mecab-node (n::"const mecab_node_t*") :static
232   ;; returns #f when n==NULL ... for convenience of mecab_nbest_next_*
233   (if (== n NULL) (return SCM_FALSE)
234       (let* ([obj::ScmMeCabNode* (SCM_NEW ScmMeCabNode)])
235         (SCM_SET_CLASS obj (& Scm_MeCabNodeClass))
236         (set! (-> obj node) n)
237         (return (SCM_OBJ obj)))))
238
239 (define-cfn make-mecab-dictionary-info (dic_info::"const mecab_dictionary_info_t*") :static
240   ;; returns #f when dic_info==NULL ... for convenience of mecab-dictionary-info-next
241   (if (== dic_info NULL) (return SCM_FALSE)
242       (let* ([obj::ScmMeCabDictionaryInfo* (SCM_NEW ScmMeCabDictionaryInfo)])
243         (SCM_SET_CLASS obj (& Scm_MeCabDictionaryInfoClass))
244         (set! (-> obj dic_info) dic_info)
245         (return (SCM_OBJ obj)))))
246
247 ;;
248 ;; MeCab API
249 ;;
250 ;;  NB: for the default configuration, MeCab API takes EUC-JP string.
251 ;;  The conversion is handled in the Scheme level.
252 (define-cproc %mecab-do (args::<list>) ::<int>
253   (let* ([argc::int (Scm_Length args)]
254          [argv::char** (Scm_ListToCStringArray args TRUE NULL)])
255     (result (mecab-do argc argv))))
256
257 (define-cproc %mecab-new (args::<list> options)
258   (let* ([argc::int (Scm_Length args)]
259          [argv::char** (Scm_ListToCStringArray args TRUE NULL)])
260     (result (make-mecab (mecab-new argc argv) options))))
261
262 (define-cproc %mecab-new2 (arg::<string> options)
263   (result (make-mecab (mecab-new2 (Scm_GetString arg)) options)))
264
265 (define-cproc mecab-version () ::<const-cstring> mecab-version)
266
267 (define-cproc mecab-destroy (m::<mecab>) ::<void>
268   (mecab-cleanup m))
269
270 (define-cproc mecab-destroyed? (m::<mecab>) ::<boolean>
271   (result (== (-> m m) NULL)))
272
273 (define-cproc mecab-options (m::<mecab>)
274   (result (-> m options)))
275
276 (define-cproc %mecab-strerror (m::<mecab>) ::<const-cstring>
277   (result (mecab-strerror (-> m m))))
278
279 (define-cproc %mecab-strerror-with-null () ::<const-cstring>
280   (result (mecab-strerror NULL)))
281
282 (define-cproc mecab-get-partial (m::<mecab>) ::<int>
283   (result (mecab-get-partial (-> m m))))
284
285 (define-cproc mecab-set-partial (m::<mecab> partial::<int>) ::<void>
286   (mecab-set-partial (-> m m) partial))
287
288 (define-cproc mecab-get-theta (m::<mecab>) ::<float>
289   (result (mecab-get-theta (-> m m))))
290
291 (define-cproc mecab-set-theta (m::<mecab> theta::<float>) ::<void>
292   (mecab-set-theta (-> m m) theta))
293
294 (define-cproc mecab-get-lattice-level (m::<mecab>) ::<int>
295   (result (mecab-get-lattice-level (-> m m))))
296
297 (define-cproc mecab-set-lattice-level (m::<mecab> level::<int>) ::<void>
298   (mecab-set-lattice-level (-> m m) level))
299
300 (define-cproc mecab-get-all-morphs (m::<mecab>) ::<int>
301   (result (mecab-get-all-morphs (-> m m))))
302
303 (define-cproc mecab-set-all-morphs (m::<mecab> all_morphs::<int>) ::<void>
304   (mecab-set-all-morphs (-> m m) all_morphs))
305
306 (define-cproc %mecab-sparse-tostr (m::<mecab> str::<const-cstring>)
307   ::<const-cstring>?
308   (result (mecab-sparse-tostr (-> m m) str)))
309
310 (define-cproc %mecab-sparse-tostr2 (m::<mecab> str::<const-cstring> len::<uint>)
311   ::<const-cstring>?
312   (result (mecab-sparse-tostr2 (-> m m) str len)))
313
314 (define-cproc %mecab-nbest-sparse-tostr (m::<mecab> n::<uint> str::<const-cstring>)
315   ::<const-cstring>?
316   (result (mecab-nbest-sparse-tostr (-> m m) n str)))
317
318 (define-cproc %mecab-nbest-sparse-tostr2 (m::<mecab> n::<uint> str::<const-cstring> len::<uint>)
319   ::<const-cstring>?
320   (result (mecab-nbest-sparse-tostr2 (-> m m) n str len)))
321
322 (define-cproc %mecab-nbest-init (m::<mecab> str::<const-cstring>) ::<int>
323   (result (mecab-nbest-init (-> m m) str)))
324
325 (define-cproc %mecab-nbest-init2 (m::<mecab> str::<const-cstring> len::<uint>) ::<int>
326   (result (mecab-nbest-init2 (-> m m) str len)))
327
328 (define-cproc %mecab-nbest-next-tostr (m::<mecab>) ;; returns null at the end
329;   (result (mecab-nbest-next-tostr (-> m m))))
330" const char *s = mecab_nbest_next_tostr(m->m);
331  return s ? SCM_MAKE_STR_COPYING(s) : SCM_FALSE;")
332
333 (define-cproc mecab-nbest-next-tonode (m::<mecab>) ;; returns null at the end
334   (result (make-mecab-node (mecab-nbest-next-tonode (-> m m)))))
335
336 (define-cproc %mecab-sparse-tonode (m::<mecab> str::<const-cstring>)
337   (result (make-mecab-node (mecab-sparse-tonode (-> m m) str))))
338
339 (define-cproc %mecab-sparse-tonode2 (m::<mecab> str::<const-cstring> siz::<uint>)
340   (result (make-mecab-node (mecab-sparse-tonode2 (-> m m) str siz))))
341
342 (define-cproc mecab-dictionary-info (m::<mecab>)
343   (result (make-mecab-dictionary-info (mecab-dictionary-info (-> m m)))))
344
345 (define-cproc %mecab-format-node (m::<mecab> n::<mecab-node>) ::<const-cstring>?
346   (result (mecab-format-node (-> m m) (-> n node))))
347
348 (define-cproc %mecab-dict-index (args::<list>) ::<int>
349   (let* ([argc::int (Scm_Length args)]
350          [argv::char** (Scm_ListToCStringArray args TRUE NULL)])
351     (result (mecab-dict-index argc argv))))
352
353 (define-cproc %mecab-dict-gen (args::<list>) ::<int>
354   (let* ([argc::int (Scm_Length args)]
355          [argv::char** (Scm_ListToCStringArray args TRUE NULL)])
356     (result (mecab-dict-gen argc argv))))
357
358 (define-cproc %mecab-cost-train (args::<list>) ::<int>
359   (let* ([argc::int (Scm_Length args)]
360          [argv::char** (Scm_ListToCStringArray args TRUE NULL)])
361     (result (mecab-cost-train argc argv))))
362
363 (define-cproc %mecab-system-eval (args::<list>) ::<int>
364   (let* ([argc::int (Scm_Length args)]
365          [argv::char** (Scm_ListToCStringArray args TRUE NULL)])
366     (result (mecab-system-eval argc argv))))
367
368 (define-cproc %mecab-test-gen (args::<list>) ::<int>
369   (let* ([argc::int (Scm_Length args)]
370          [argv::char** (Scm_ListToCStringArray args TRUE NULL)])
371     (result (mecab-test-gen argc argv))))
372
373;;
374;; mecab_node_t
375;;
376 (define-cproc mecab-node-prev (n::<mecab-node>)
377   (result (make-mecab-node (-> (-> n node) prev))))
378
379 (define-cproc mecab-node-next (n::<mecab-node>)
380   (result (make-mecab-node (-> (-> n node) next))))
381
382 (define-cproc mecab-node-enext (n::<mecab-node>)
383   (result (make-mecab-node (-> (-> n node) enext))))
384
385 (define-cproc mecab-node-bnext (n::<mecab-node>)
386   (result (make-mecab-node (-> (-> n node) bnext))))
387
388 (define-cproc %mecab-node-surface (n::<mecab-node>)
389   (result (Scm-MakeString (-> (-> n node) surface)
390                           (-> (-> n node) length) ;; size
391                           -1 ;; Gauche will count the 'length' of this substring
392                           SCM-STRING-COPYING)))
393
394 (define-cproc %mecab-node-feature (n::<mecab-node>)
395   ::<const-cstring> (result (-> (-> n node) feature)))
396
397 (define-cproc mecab-node-length (n::<mecab-node>)
398   ::<uint> (result (-> (-> n node) length)))
399
400 (define-cproc mecab-node-rlength (n::<mecab-node>)
401   ::<uint> (result (-> (-> n node) rlength)))
402
403 (define-cproc mecab-node-id (n::<mecab-node>)
404   ::<uint> (result (-> (-> n node) id)))
405
406 (define-cproc mecab-node-rc-attr (n::<mecab-node>)
407   ::<uint> (result (-> (-> n node) rcAttr)))
408
409 (define-cproc mecab-node-lc-attr (n::<mecab-node>)
410   ::<uint> (result (-> (-> n node) lcAttr)))
411
412 (define-cproc mecab-node-posid (n::<mecab-node>)
413   ::<uint> (result (-> (-> n node) posid)))
414
415 (define-cproc mecab-node-char-type (n::<mecab-node>)
416   ::<uint> (result (-> (-> n node) char-type)))
417
418 (define-cproc %mecab-node-stat (n::<mecab-node>)
419   ::<int> (result (-> (-> n node) stat)))
420
421 (define-cproc mecab-node-best? (n::<mecab-node>)
422   ::<boolean> (result (-> (-> n node) isbest)))
423
424 (define-cproc mecab-node-alpha (n::<mecab-node>)
425   ::<float> (result (-> (-> n node) alpha)))
426
427 (define-cproc mecab-node-beta (n::<mecab-node>)
428   ::<float> (result (-> (-> n node) beta)))
429
430 (define-cproc mecab-node-prob (n::<mecab-node>)
431   ::<float> (result (-> (-> n node) prob)))
432
433 (define-cproc mecab-node-wcost (n::<mecab-node>)
434   ::<int> (result (-> (-> n node) wcost)))
435
436 (define-cproc mecab-node-cost (n::<mecab-node>)
437   ::<int> (result (-> (-> n node) cost)))
438
439;;
440;; mecab_dictionary_info_t
441;;
442 (define-cproc mecab-dictionary-info-filename (dinfo::<mecab-dictionary-info>)
443   ::<const-cstring> (result (-> (-> dinfo dic_info) filename)))
444
445 (define-cproc mecab-dictionary-info-charset (dinfo::<mecab-dictionary-info>)
446   ::<const-cstring> (result (-> (-> dinfo dic_info) charset)))
447
448 (define-cproc mecab-dictionary-info-size (dinfo::<mecab-dictionary-info>)
449   ::<uint> (result (-> (-> dinfo dic_info) size)))
450
451 (define-cproc %mecab-dictionary-info-type (dinfo::<mecab-dictionary-info>)
452   ::<int> (result (-> (-> dinfo dic_info) type)))
453
454 (define-cproc mecab-dictionary-info-lsize (dinfo::<mecab-dictionary-info>)
455   ::<uint> (result (-> (-> dinfo dic_info) lsize)))
456
457 (define-cproc mecab-dictionary-info-rsize (dinfo::<mecab-dictionary-info>)
458   ::<uint> (result (-> (-> dinfo dic_info) rsize)))
459
460 (define-cproc mecab-dictionary-info-version (dinfo::<mecab-dictionary-info>)
461   ::<uint> (result (-> (-> dinfo dic_info) version)))
462
463 (define-cproc mecab-dictionary-info-next (dinfo::<mecab-dictionary-info>)
464   (result (make-mecab-dictionary-info (-> (-> dinfo dic_info) next))))
465
466 )
467
468(define-macro (mecab? obj) `(is-a? ,obj <mecab>))
469(define-macro (mecab-node? obj) `(is-a? ,obj <mecab-node>))
470(define-macro (mecab-dictionary-info? obj) `(is-a? ,obj <mecab-dictionary-info>))
471
472(define-method write-object ((m <mecab>) out)
473  (format out "#<mecab ~s>" (mecab-options m)))
474(define-method write-object ((m <mecab-node>) out)
475  (format out "#<mecab-node>"))
476(define-method write-object ((m <mecab-dictionary-info>) out)
477  (format out "#<mecab-dictionary-info>"))
478
479(define *mecab-options+*
480  '((r rcfile FILE)
481    (d dicdir DIR)
482    (u userdic FILE)
483    (l lattice-level INT)
484    (D dictionary-info)
485    (a all-morphs)
486    (O output-format-type TYPE)
487    (p partial)
488    (F node-format STR)
489    (U unk-format STR)
490    (B bos-format STR)
491    (E eos-format STR)
492    (x unk-feature STR)
493    (b input-buffer-size INT)
494    (P dump-config)
495    (M open-mutable-dictionary)
496    (C allocate-sentence)
497    (N nbest INT)
498    (t theta FLOAT)
499    (c cost-factor INT)
500    (o output FILE)
501    (v version)
502    (h help)))
503
504(define *mecab-options* (map cdr *mecab-options+*))
505
506(define (cast argtype obj)
507  (case argtype
508    [(STR DIR FILE) (x->string obj)]
509    [(INT FLOAT) obj]
510    [(TYPE) (string->symbol (x->string obj))]
511    [else obj]))
512
513(define (requires-arg? option)
514  (let1 opt (assoc option *mecab-options*)
515    (if opt (= 2 (length opt)) #f)))
516
517(define (argtype option)
518  (cadr (or (assoc option *mecab-options*) (list #f #f))))
519
520(define (long-option-name short-option-name)
521  (cadr (or (assoc short-option-name *mecab-options+*) (list #f #f))))
522
523(define (keyword-length keyword)
524  (string-length (keyword->string keyword)))
525
526(define (keyword->symbol keyword)
527  (string->symbol (keyword->string keyword)))
528
529(define (mecab-parse-options args)
530  ;; eg. ("-Ochasen" :l 1 "--theta" "0.75")
531  ;;     => (:output-format-type "chasen" :lattice-level 1 :theta "0.75")
532  (let1 args* (append-map
533               (lambda (arg)
534                 (cond [(string? arg)
535                        (if (string=? "" arg) '()
536                            (append-map
537                             (lambda (str)
538                               (let1 len (string-length str)
539                                 (if (<= 2 len)
540                                     (if (eq? #\- (string-ref str 0))
541                                         ;; --option, -X[arg]
542                                         (if (eq? #\- (string-ref str 1))
543                                             ;; --option
544                                             (list (string->symbol (substring str 2 len)))
545                                             ;; -X[arg]
546                                             (let1 option (long-option-name (string->symbol (substring str 1 2)))
547                                               (if (= len 2)
548                                                   ;; -X
549                                                   (list option)
550                                                   ;; -Xarg
551                                                   (list option (cast (argtype option) (substring str 2 len))))))
552                                         (list str))
553                                     (list str))))
554                             (string-split arg #[ =])))]
555                       [(keyword? arg)
556                        (if (= 1 (keyword-length arg))
557                            (list (long-option-name (keyword->symbol arg)))
558                            (list (keyword->symbol arg)))]
559                       [else
560                        (list arg)]))
561               (if (list? args) args (list args)))
562    ;; eg. (:output-format-type "chasen" :lattice-level 1 :theta "0.75")
563    ;;     => ((output-format-type chasen) (lattice-level 1) (theta 0.75))
564    (let loop ((rest args*) (options '()))
565      (if (null? rest)
566          (reverse! options)
567          (let1 option (car rest)
568            (if (symbol? option)
569                (if (requires-arg? option)
570                    (loop (cddr rest) (cons (list option (cast (argtype option) (cadr rest))) options))
571                    (loop (cdr rest) (cons (list option (if #f #f)) options)))
572                (loop (cdr rest) options)))))))
573
574(define (mecab . args) ;; inspired by leque's make-mecab
575  (let* ([options (mecab-parse-options args)]
576         [options-str (append-map (lambda (option+arg)
577                                    (let* ([option (car option+arg)]
578                                           [option-str (format "--~a" option)])
579                                      (if (requires-arg? option)
580                                          (list option-str (x->string (cadr option+arg)))
581                                          (list option-str) )))
582                                  options)])
583    (%mecab-new options-str options)))
584
585(define-reader-ctor 'mecab mecab)
586
587;; Tagger
588(define (mecab-tagger . args)
589  (let1 m (apply mecab args)
590    (define (parse-to-string str . args)
591      (let-optionals* args ((len #f))
592        (if len
593            (mecab-sparse-tostr2 m str len)
594            (mecab-sparse-tostr m str) )))
595
596    (define (parse-to-node str) (mecab-sparse-tonode m str))
597
598    ;; requires "-l 1" in option
599    (define (parse-nbest n str) (mecab-nbest-sparse-tostr m n str))
600
601    (define (parse-nbest-init str) (mecab-nbest-init m str))
602
603    (define (next) (mecab-nbest-next-tostr m))
604
605    (define (next-node) (mecab-nbest-next-tonode m))
606
607    (define (format-node node) (mecab-format-node m node))
608
609    (define (destroy) (mecab-destroy m))
610
611    (lambda (m)
612      (case m
613        [(parse parse-to-string) parse-to-string]
614        [(parse-to-node) parse-to-node]
615        [(parse-nbest) parse-nbest]
616        [(parse-nbest-init) parse-nbest-init]
617        [(next) next]
618        [(next-node) next-node]
619        [(format-node) format-node]
620        [(destroy) destroy]
621        ))))
622
623(define-class <mecab-tagger> () (m #f))
624
625(define (mecab-make-tagger paramstr)
626  (make <mecab-tagger> :mecab (mecab paramstr)))
627
628(define (tagger-mecab tagger) (slot-ref tagger 'm))
629
630(define-method parse ((tagger <mecab-tagger>) (str <string>))
631  (mecab-sparse-tostr (tagger-mecab tagger) str))
632
633(define-method parse ((tagger <mecab-tagger>) (str <string>) (len <integer>))
634  (mecab-sparse-tostr2 (tagger-mecab tagger) str len))
635
636(define-method parse-to-string ((tagger <mecab-tagger>) (str <string>))
637  (mecab-sparse-tostr (tagger-mecab tagger) str))
638
639(define-method parse-to-string ((tagger <mecab-tagger>) (str <string>) (len <integer>))
640  (mecab-sparse-tostr (tagger-mecab tagger) str len))
641
642(define-method parse-to-node ((tagger <mecab-tagger>) (str <string>))
643  (mecab-sparse-tonode (tagger-mecab tagger) str))
644
645(define-method parse-to-node ((tagger <mecab-tagger>) (str <string>) (len <integer>))
646  (mecab-sparse-tonode2 (tagger-mecab tagger) str len))
647
648(define-method parse-nbest ((tagger <mecab-tagger>) (n <integer>) (str <string>))
649  (mecab-nbest-sparse-tostr (tagger-mecab tagger) str))
650
651(define-method parse-nbest ((tagger <mecab-tagger>) (n <integer>) (str <string>) (len <integer>))
652  (mecab-nbest-sparse-tostr (tagger-mecab tagger) str len))
653
654(define-method parse-nbest-init ((tagger <mecab-tagger>) (str <string>))
655  (mecab-nbest-init (tagger-mecab tagger) str))
656
657(define-method parse-nbest-init ((tagger <mecab-tagger>) (str <string>) (len <integer>))
658  (mecab-nbest-init (tagger-mecab tagger) str len))
659
660(define-method next ((tagger <mecab-tagger>))
661  (mecab-nbest-next-tostr (tagger-mecab tagger)))
662
663(define-method next-node ((tagger <mecab-tagger>))
664  (mecab-nbest-next-tonode (tagger-mecab tagger)))
665
666(define-method format-node ((tagger <mecab-tagger>) (node <mecab-node>))
667  (mecab-format-node (tagger-mecab tagger) node))
668
669(provide "text/mecab")
670
671;; Local variables:
672;; mode: scheme
673;; end:
Note: See TracBrowser for help on using the browser.