と言ってもブログの引っ越しです。いっかいWordpressを触ってみたかったので自鯖に立てて、しばらく運用してみたのですが満足したので、はてなに移ります。
http://d.hatena.ne.jp/gabuchan/
id:gabuchan が取れたのが、すごく嬉しいので、はてな大好きになりました。
と言ってもブログの引っ越しです。いっかいWordpressを触ってみたかったので自鯖に立てて、しばらく運用してみたのですが満足したので、はてなに移ります。
http://d.hatena.ne.jp/gabuchan/
id:gabuchan が取れたのが、すごく嬉しいので、はてな大好きになりました。
「コンパイラを作ろう」第3回にして初エントリーを書くとか、相当ブログばなれが進んでいるなぁと反省。
どうでもいいけど、Wordpressのビジュアルモードが激しくウザいので、はてダに乗り換えたいと考え中。
ってことで、知らない人のためにも書くと先月から、CSNAGOYAの「コンパイラを作ろう」という勉強会に参加しています。冨沢高明さんの「コンパイラ入門」という最高の参考書をもとに全員が好きな言語でコンパイラを作るという勉強会です。参考書がPascalのコンパイラを作るため僕らもPascalの構文を解析することになりました。
好きな言語でコンパイラを作る。ということで、かなり悩んだあげくSICPを読むためにSchemeを覚えたいなぁと思い、GaucheでPascalのコンパイラを作ることに。この組み合わせが何とも言えません。
ちなみに、どこまで勉強会が進んでいるかというと
さて、前置きが長くなりましたが今日までの宿題になっていた、字句解析部分の実装を晒すことになっているんですが、Gauche を合計1週間も勉強していない人間が作ったソースコードだと思って読んでください。(言い訳)
main も、用意していないので lexer 関数に string を渡すと、それをTokenに分解して print する所までしか出来ていません。(print は本質的には必要ないんですがデバッグ用です。)
(use srfi-1)
(define-class ()
((def :init-keyword :def :init-value “”)
(str :init-keyword :str :init-value “”)
(type :init-keyword :type :init-value “”)))
(define (make-token def str type)
(make :def def :str str :type type))
(define reserved
(hash-table ’string=?
‘(”MODULE” . 0)
‘(”BEGIN” .0)
‘(”END” .0)
‘(”VAR” .0)
‘(”INTEGER” .0)
‘(”STRING” .0)
‘(”IF” .0)
‘(”THEN” .0)
‘(”ELSE” .0)
‘(”WHILE” .0)
‘(”DO” .0)))
(define symbols
(hash-table ’string=?
‘(”+” . “PLUS”)
‘(”-” . “MINUS”)
‘(”*” . “MULT”)
‘(”/” . “DIV”)
‘(”=” . “EQ”)
‘(”< " . "LT")
'("<=" . "LE")
'(">” . “GT”)
‘(”>=” . “GE”)
‘(”<>” . “NE”)
‘(”:=” . “ASSIGN”)
‘(”;” . “COLON”)
‘(”:” . “SEMICOLON”)
‘(”,” . “COMMA”)
‘(”(” . “OPEN”)
‘(”)” . “CLOSE”)
‘(”.” . “PIRIOD”)))
(define (add lis e)
(append lis (list e)))
(define (print-token-list lis)
(map (lambda (e) (print #`”DEF[,(ref e ‘def)]ttSTR[,(ref e ’str)]”)) lis))
(define (lexer str)
(print-token-list (scanner (string->list str) ‘())))
;; (d (scanner (string->list str) ‘())))
(define (scanner char-list token-list)
(if (null? char-list)
token-list
(let ((c (car char-list))
(cs (cdr char-list)))
(cond [(char-whitespace? c) (scanner cs token-list)]
[(char-alphabetic? c)
(pred-scanner cs
token-list
(list c)
(lambda (char) (or (char-alphabetic? char) (char-numeric? char)))
(lambda (char-list)
(let* ((str (list->string char-list))
(def (if (hash-table-exists? reserved str)
str
“IDENT”)))
(make-token def str “”))))]
[(char-numeric? c)
(pred-scanner cs
token-list
(list c)
(lambda (char) (char-numeric? char))
(lambda (char-list)
(make-token “NUMBER” (list->string char-list) “”)))]
[(char-numeric? c) (scan-of-pred cs (list c) token-list char-numeric?)]
[(or (equal? c #=)
(equal? c #+)
(equal? c #-)
(equal? c #*)
(equal? c #/)
(equal? c #;)
(equal? c #,)
(equal? c #()
(equal? c #))
(equal? c #.))
(let ((str (make-string 1 c)))
(scanner cs (add token-list (make-token (hash-table-get symbols str) str “”))))]
[(or (equal? c #< )
(equal? c #>)
(equal? c #:))
(let ((pred (cond [(equal? c #< )
(lambda (e) (or (equal? e #=)
(equal? e #>)))]
[(equal? c #>)
(lambda (e) (equal? e #=))]
[(equal? c #:)
(lambda (e) (equal? e #=))])))
(pred-scanner cs
token-list
(list c)
pred
(lambda (char-list)
(let ((str (list->string char-list)))
(make-token (hash-table-get symbols str) str “”)))))]
[(equal? c #\”)
(let ((index (list-index (lambda (c) (equal? c #\”)) cs)))
(scanner (drop cs (+ 1 index)) (add token-list (make-token “STR” (take cs index) “”))))]
))))
(define (pred-scanner char-list token-list buffered-char-list pred maker)
(if (null? char-list)
(scanner char-list (add token-list (maker buffered-char-list)))
(let ((c (car char-list))
(cs (cdr char-list)))
(cond [(pred c) (pred-scanner cs token-list (add buffered-char-list c) pred maker)]
[else (scanner (cons c cs) (add token-list (maker buffered-char-list)))]))))
こんなソースコード生んで本当にすみません。
でも、綺麗にしたいんです><コメントお願いします><
Recent Comments