leque はレキとかレクとか読むらしい。愛知県在住。最近はぶらぶらしてます。
あとは http://www.katch.ne.jp/~leque/software/ にも色々と
Gauche:LibraryWishList みたいなものがあったら、ネタに困ったときや、必要なライブラリの拡充に便利かもしれないとふと思った。→作ってみた
平日の夜ということだったのに盛況だった。メモとかはとっていなかったので簡単な感想を。
未完成。 lalr.scm
勉強がてら LALR(1) 構文解析器を書いてみました。
bigloo の LALR Parser と同じような構文で使えるつもり。 最初に LR(1) 構文解析表をつくってから LALR(1) 構文解析表をつくるので実用的な速度は出ません (PowerPC G4 800 MHz、メモリ 640 MB で、下記の四則演算の場合で 1 秒程度、 c-wrapper クラスのものになると 10 分弱)。
例:
(use util.lalr) (define *tokens* ; (2 + 3) * 4 / 2 - 1 * 7 => 3 '(lp (i . 2) op-plus (i . 3) rp op-mult (i . 4) op-div (i . 2) op-minus (i . 1) op-mult (i . 7)) ) (define lexer (let1 tokens *tokens* (lambda () (let1 v (or (null? tokens) (pop! tokens)) (if (pair? v) v (cons v v)))))) (define parser (lalr-grammar ((left op-mult op-div) (left op-plus op-minus) lp rp i) (expr ((lp expr rp) expr) ((op-plus expr) expr) ((op-minus expr) (- expr)) ((expr@a op-mult expr@b) (* a b)) ((expr@a op-div expr@b) (/ a b)) ((expr@a op-plus expr@b) (+ a b)) ((expr@a op-minus expr@b) (- a b)) ((i) i)))) (define (main args) (print (lr-parse parser lexer))) ; => 3
で動くはずなんだけれど、lr1-parser->lalr1-parser のなかで
*** ERROR: hash table doesn't have an entry for key #<set equal?(45)> Stack Trace: _______________________________________ 0 (ref lr1->lalr1-table state)
と言われる。debug-print を仕込んでみると
#?=(and (member state (hash-table-keys lr1->lalr1-table)) #t) #?- #t #?=(hash-table-exists? lr1->lalr1-table state) #?- #f
うーん…。
ときどき UTF-8 なテキストを編集しなくてはいけないことがあって nvi だといろいろ不便なので これを機に Emacs に乗り換えた(vim も候補にあがったけれど、vim script があまり好きになれそうにないのと、:set lisp しても ( や ) が S式単位でうごいてくれなかったので×)。
とりあえず viper-mode で :set lisp できるようにして (, ), {, }, [[, ]] の挙動をそれらしくした。
Scheme プログラムの編集は Gauche:EditingWithEmacs を参考に inferior-gacuhe-mode と koguro さんの gca を使わせていただくことにした。
ついでに EmacsLisp の練習にカーソル位置のシンボルを export する関数を書いてみた (gca に依存しています)。
(defun gca-export-current-sym () (interactive) (let ((word (gca-current-word))) (save-excursion (unless (re-search-backward "^\\s *(export\\Sw+" nil t) (error "No export clause found.")) (let ((bp (match-beginning 0))) (unless (re-search-forward "\\s)" nil t) (error "Unclosed export clause.")) (let ((ep (match-beginning 0))) (goto-char bp) (if (re-search-forward (concat "\\s " (regexp-quote word) "[ \t\n\f\v\)]") (1+ ep) t) (message "%s is already exported." word) (goto-char ep) (insert " " word) (lisp-indent-line) (message "Exported %s." word)))))))
c-wrapper を使って SS Tagger を Gauche から使えるようにしてみました(libsstagger.tar.gz)。 mecab と同じ方式で C++ で書かれた元プログラムを一旦 C で wrap してから c-wrapper を使っています。
これで Scheme 側から finalizer を追加できたら C で拡張ライブラリを書くのとほとんど遜色がなさそう。
使い方:
% tar xzf postagger-1.0.tar.gz % cd postagger-1.0 % tar xzf ../libsstagger.tar.gz % ./configure # 注: オリジナルの Makefile を上書きします % make % make install % cp sstagger.scm `gauche-config --sitelibdir`/lingua/en % gosh gosh> (use lingua.en.sstagger) #<undef> gosh> (define tagger (make-sstagger "/path/to/postagger-1.0/models")) tagger gosh> (sstagger-do-tagging tagger "He opened the window.") "He/PRP opened/VBD the/DT window/NN ./." gosh> (tagger "He opened the window.") "He/PRP opened/VBD the/DT window/NN ./." gosh> (sstagger-destroy tagger) #<undef> gosh> ^D
今日の一行 木の復元。先行順の場合だけ。
(use srfi-11) (use srfi-42) (use util.match) (define (enum from to step) (unfold (cut > <> to) values (cut + <> step) from (lambda _ '()))) (define make-tree (case-lambda ((val) (list val)) ((val left right) (list val left right)))) (define (list->tree/preorder xs) (match xs (() xs) ((val) (list (make-tree val))) (_ (let* ((x (car xs)) (ys (cdr xs)) (left&rights (map (lambda (i) (call-with-values (cut split-at ys i) cons)) (enum 1 (- (length ys) 1) 2)))) (append-map (lambda (left&right) (receive (left right) (car+cdr left&right) (list-ec (: l (list->tree/preorder left)) (: r (list->tree/preorder right)) (make-tree x l r)))) left&rights)))))
続 AA 折れ線グラフ
hanatani さんの解答を 見て map-accum の存在に気づいた。
(use srfi-1) (use srfi-11) (use util.match) (use gauche.collection) (define (main args) (graph (second args))) (define (graph spec) (let*-values (((xs _) (map-accum (lambda (ch y) (case ch ((#?C) (values (cons #?_ y) y)) ((#?R) (values (cons #?/ y) (+ y 1))) ((#?F) (values (cons #?? (- y 1)) (- y 1))))) 0 spec)) ((bottom top) (apply min&max (map cdr xs)))) (apply for-each (cut print <...>) (map (match-lambda ((c . pos) (map (lambda (i) (if (= i pos) c #?space)) (iota (+ (- top bottom) 1) top -1)))) xs))))
今日の一行(2006-03-14) AA 折れ線グラフ をやってみた。
(use srfi-1) (use util.match) (define (main args) (graph (second args))) (define (graph spec) (for-each print (let loop ((cs (string->list spec)) (top 0) (bottom 0) (y 0) (rs '())) (if (null? cs) (let1 height (+ (- top bottom) 1) (apply map string (map (match-lambda ((c . pos) (list-tabulate height (lambda (i) (if (= i (- height (- pos bottom) 1)) c #?space))))) (reverse! rs)))) (match (car cs) (#?C (loop (cdr cs) top bottom y (alist-cons #?_ y rs))) (#?R (let1 ny (+ y 1) (loop (cdr cs) (max top ny) bottom ny (alist-cons #?/ y rs)))) (#?F (let1 ny (- y 1) (loop (cdr cs) top (min ny bottom) ny (alist-cons #?? ny rs)))))))))