history

青木日記 RSS

<前月 | 最新 | 次月>

2006-07-05

Racc: その場でパーサ生成

ここ三日くらいの寝不足により、こんなのが動くようになった。

require 'racc'
 
grammar = Racc::Grammar.define {
  g = self
 
  g.precedence_table {
    prechigh
    left '*', '/'
    left '+', '-'
    preclow
  }
 
  g.target      = rule(:exp) | rule() { 0 }
 
  g.exp         = rule(:exp, '+', :exp) {|x,_,y| x + y }\
                | rule(:exp, '-', :exp) {|x,_,y| x - y }\
                | rule(:exp, '*', :exp) {|x,_,y| x * y }\
                | rule(:exp, '/', :exp) {|x,_,y| x / y }\
                | rule('(', :exp, ')') {|_,n,_| n }\
                | rule('-', :NUMBER) {|_,n| -n }\
                | rule(:NUMBER)
}
Calculator = grammar.parser_class

この仕組み自体より、腐ったコードを書き直すほうに時間を取られてしまった。

(01:21)

Racc: その場でパーサ生成 (2)

どうせなら「n 回以上の繰り返し」とか「省略可能」とかも実装したいところだが、 インターフェイスをどーしたもんかなー。 現状の rule(:exp, '+', :exp) {....} てのもベストとは言い難いし。

(01:27)

てんさく

さて逃避活動はイーカゲンにして、るびまの添削記事を書かねばいかんわけです。

(03:20)


2006-07-06

racc/cparse.so: アホすぎるバグ発見

まさかとは思ったが、VALUE 作ってるのに全然マークしてないじゃん!! よくこれまで落ちなかったなー、これ……。 1.8.5 の前に見付かってよかったと考えるべきか、 それともすでに手遅れと考えるべきだろうか。

(22:18)


2006-07-08

skk.vim

http://www.vim.org/scripts/script.php?script_id=1589

vim で SKK が使えるプラグイン。 こんなものがあったのか! すっげえ便利だー! 即座に常用決定。

(01:55)


2006-07-11

オープンソースマガジン 8 月号 ハッカー養成塾「オープンソースマガジンの中心 (付近のページ) でバカと叫ぶ」

http://www.unixuser.jp/magazine/2006/200608.html

オープンソースマガジン 8 月号で記事を書かせてもらいました。 ハッカー養成塾という連載のうち一本で、 「オープンソースマガジンの中心 (付近のページ) でバカと叫ぶ」です。 いやー、もうね、なんかね、何書いてもいいと言われたので、 久しぶりにリミッターを外して書いてみました。 よかったら読んでやってください。

(06:09)

本日のツッコミ (全2件) [ツッコミを入れる]

hyuki [読みました。思いっきりメタに話を振ってましたねー(^_^)]

青木 [反応早っ。どうもありがとうございます。
ある人には「セカイ系ラノベぽい」と言われてちょっと納得しました。]


2006-07-13

Rubyist Magazine 15 号

http://jp.rubyist.net/magazine/?0015

Rubyist Magazine 15 号でた。

なかなか掲載できなかった Tropy の添削記事をようやく出せた。 今月も長い。最初はもっと長かった。

今月号は添削と YARV 以外読んでないので、おれもこれから読む。

(00:25)

本日のツッコミ (全2件) [ツッコミを入れる]

miwako [あのー、ちょっとよろしいでしょうか?
「引き伸ばしまくってた 」は、
「引き延ばしまくってた」ではないでしょうか。]

青木 [修正しました。ありがとうございます。]


2006-07-14

Core 2 Duo は 64 ビットモードが遅い

http://akiba.ascii24.com/akiba/column/latestparts/2006/07/14/663447-002.html

なにいいい! Core 2 Duo は 64 ビットモードのが遅いって、なんだそれは! いくら絶対速度で Opteron に負けてないっても、 クロックとプロセスルールの差だけで勝ってるんじゃねえのこれ? おれの使いかたじゃ SSE なんて使わねえし。 Opteron のクロックが上がったらまたすぐ負けたりしてな。萎えるー。

急激に Core 2 買う気が失せてきた。 やっぱりもうしばらくは AMD にしよう……。

(00:28)

本日のツッコミ (全2件) [ツッコミを入れる]

タナカコウイチロウ [田中という者です。
先日のHaskell読書会に出ていた者です。

参照透過性についての話題。

ライカン著「言語哲学」(けい草書房)で、クワインの用語法で
”指示的に透明(transparent)”(p.20)がありました。

また、飯田隆著「言語哲学大全III」(けい草書房)の索引には、
”指示的に透明な(referentially transparent)文脈”の項目が
ありました。(自分は理解していません)

しかし、クワインの用語と因果関係はアルのかと、自問したくなります。
それでは。]

青木 [あ、これはどうも。クワインかー。ちょっとぐぐってみたところ、
http://sources.redhat.com/ml/guile/1998-08/msg00401.html
というページがありました。このページによると、クワインは
"Principia Mathematica" から持ってきたとか、もしかしたら
フレーゲかもー、とか書いてありますね。プログラミング言語に
持ち込まれたときに意味が変化してるようです。]


2006-07-26

コミット渋滞

みんなで同時にコミットしてるもんだから ものすごい勢いで ChangeLog がコンフリクトしてるよ……。

(18:41)

今日のどうでもいい話

「十六茶」を「16茶」と書くと違和感たっぷり

(18:42)

バグつぶし (1) strscan

StringScanner.new("").scan(//) が nil になるよ問題。 これはだいたい問題なく終わる。

Ruby 1.8 でテストが失敗するよーと思っていたら、 鬼車と GNU regex の挙動の差が原因だった。 明示的なチェックを入れて修正完了。

(19:06)

バグつぶし (2) fileutils

ファイルシステムをまたぐ mv が元のファイルを消してなかった件。当然バグ。 なんか見たことあると思ってたら、妙に迂遠な経路を経て [ruby-dev:28223] で報告されていたやつだった。修正済。

mv をアトミックにしろと言われてもなあ。 てんぷファイル (添付じゃなくて tmp な) を作るのは好きじゃないんだよね俺。

(19:10)

バグつぶし (3) net/http

これは 2ch に流れてたやつと同じかなあ。

require 'net/http'
 
Net::HTTP.start('www3.nikkei.co.jp') {|h|
  res = h.post('/nkave/data/index.cfm', 'yyyy=1950&mm=1&dd=11')
  puts res.body
}

このコードでなぜか Content-Type が付かなくなるらしい。 なぜか確認されてるのは mswin32 だけ。 ヘッダの操作なんて文字列処理しかしてねーのに どうしてプラットフォーム依存になるのか、激しく謎だ。

VC++8 / Windows XP SP2 で何事もなく動いてしまった。

ああそうか、これは CVS HEAD だった。 1.8 じゃないとだめなんだなたぶん。 Ruby 1.8 で試すとあっさり再現した。

あ、わかった。req.content_type が nil にならないからだ。 HEAD は修正したけど 1.8 は直してなかったのか。 なんかこのへんは他にもバグバグしてるなあ。

ん? なんだ、じゃあ別に mswin32 限定でもなんでもないんじゃないか。 1.8.3 〜 1.8.4 ならどのプラットフォームでも同じように失敗する。

ちなみにデフォルトで Content-Type をセットするのは、 Content-Type がついてないと Tomcat が文句を言う、 と文句を言う人が多かったから。だったような気がする。

(22:01)


2006-07-28

iPod

iPod を買ってしまった。nano 2GB のやつ。

これで俺も人並のデジタルライフが送れるだろうか。

(14:46)

net/http での deflate 対応

net/http の deflate 対応パッチをもらった。 おおむねそのまま使えそうなので、 近いうちに修正を加えて 1.9 に取り込む予定。

(15:45)

Racc: Dynamic Parser Generation

レポートを書いてたはずなのにいつのまにか Racc をいじっている不思議。 今日は Parsec ちっくに many とか option を使えるようにしてみた。

どことなく C 風の文法 (アクションはまだ適当)

 grammar = Racc::Grammar.define {
   g = self
 
   precedence_table {
     higher
     right '['
     right '*@', '&@', :CAST
     right '+@', '-@', '!'
     left '*', '/'
     left '+', '-'
     left ">>", "<<"
     left '&'
     left '|'
     left "==", "!=", '>', '>=', '<', '<='
     left "&&"
     left "||"
     lower
   }
 
   g.program = many(:decl)
 
   g.decl = seq(:defvar)      {|field|  declare field }\
          | seq(:defun)       {|func|   declare func }\
          | seq(:defstruct)   {|struct| define_type struct }\
          | seq(:defunion)    {|union|  define_type union }
 
   g.defvar = seq(:storage, :type, :IDENT, option(:initval), ';') {
                  |storage,  type,  name,  val,               _|
                Field.new(storage, type, name, val)
              }
 
   g.initval = seq('=', :expr) {|_, expr| expr }
 
   g.defun = seq(
     :storage, :type, :IDENT, '(', :params, ')', '{', :scope, '}') {
     |storage,  type,  name,   _,   params,  _,   _,   body,   _|
               Function.new(storage, type, name, params, body)
             }
 
   g.params = separated_by(',', :slot)
 
   g.defstruct = seq(:STRUCT, :IDENT, '{', many(:memb), '}', ';') {
                     |_,       tag,    _,  membs,        _,   _|
                   StructType.new(tag, membs)
                 }
 
   g.defunion  = seq(:UNION, :IDENT, '{', many(:memb), '}', ';') {
                     |_,      tag,    _,  membs,        _,   _|
                   UnionType.new(tag, membs)
                 }
 
   g.memb = seq(:slot, ';') {|slot, _| slot }
 
   g.struct_decl = seq(:STRUCT, :IDENT, ';') {|_, tag, _|
                     StructType.new(tag, nil)
                   }
 
   g.union_decl = seq(:UNION, :IDENT, ';') {|_, tag, _|
                    UnionType.new(tag, nil)
                  }
 
   g.scope = seq(_ { push_scope }, many(:vardecl), :stmts) {|_, decls, stmts|
               pop_scope
               ScopeNode.new(decls, stmts)
             }
 
   g.storage = null() | seq(:STATIC) | seq(:EXTERN)
 
   g.slot = seq(:type, :IDENT) {|type, name| Slot.new(type, new) }
 
   g.type = seq(:VOID) {|_| @types.void }\
          | seq(:CHAR) {|_| @types.char }\
          | seq(:SHORT) {|_| @types.short }\
          | seq(:INT) {|_| @types.int }\
          | seq(:LONG) {|_| @types.long }\
          | seq(:LONG, :LONG) {|_,_| @types.longlong }\
          | seq(:type, '[',']') {|t,_,_| @types.array_of(t) }\
          | seq(:type, '*') {|t,_,_| @types.pointer_to(t) }\
          | seq(:STRUCT, :IDENT) {|_, tag| @types.struct(tag) }\
          | seq(:UNION, :IDENT) {|_, tag| @types.union(tag) }
 
   g.stmts = many(:stmt) {|stmts| stmts.compact }
 
   g.stmt = seq(';') { nil }\
          | seq(:expr, ';') {|node, _| node }\
          | seq(:IF, '(', :expr, ')', '{', :scope, '}', option(:else)){
               |_,   _,   cond,  _,   _,   then_body, _, else_node|
              n = IfNode.new(cond, then_body, else_node)
              n.location = cond.location
              n
            }\
          | seq(:WHILE, '(', :expr, ')', '{', :scope, '}') {
               |_,      _,   cond,  _,   _,   body,     _|
              n = WhileNode.new(cond, body)
              n.location = cond.location
              n
            }\
          | seq(:BREAK, ';') {|*| BreakNode.new(nil) }\
          | seq(:CONTINUE, ';') {|*| ContinueNode.new(nil) }\
          | seq(:RETURN, ';') {|*| ReturnNode.new(nil) }\
          | seq(:RETURN, :expr, ';') {|_, expr, _| ReturnNode.new(expr) }
 
   g.else = seq(:ELSE, '{', :stmts, '}') {|_, _, body, _| body }
 
   g.expr = seq(:primary)\
          | seq(:expr, '+',  :expr) {|*a| newnode(BinaryOpNode, *a) }\
          | seq(:expr, '-',  :expr) {|*a| newnode(BinaryOpNode, *a) }\
          | seq(:expr, '*',  :expr) {|*a| newnode(BinaryOpNode, *a) }\
          | seq(:expr, '/',  :expr) {|*a| newnode(BinaryOpNode, *a) }\
          | seq(:expr, '&',  :expr) {|*a| newnode(BinaryOpNode, *a) }\
          | seq(:expr, '|',  :expr) {|*a| newnode(BinaryOpNode, *a) }\
          | seq(:expr, '>>', :expr) {|*a| newnode(BinaryOpNode, *a) }\
          | seq(:expr, '<<', :expr) {|*a| newnode(BinaryOpNode, *a) }\
          | seq(:expr, '>',  :expr) {|*a| newnode(BinaryOpNode, *a) }\
          | seq(:expr, '>=', :expr) {|*a| newnode(BinaryOpNode, *a) }\
          | seq(:expr, '<',  :expr) {|*a| newnode(BinaryOpNode, *a) }\
          | seq(:expr, '<=', :expr) {|*a| newnode(BinaryOpNode, *a) }\
          | seq(:expr, '==', :expr) {|*a| newnode(BinaryOpNode, *a) }\
          | seq(:expr, '!=', :expr) {|*a| newnode(BinaryOpNode, *a) }\
          | seq(:expr, '&&', :expr) {|*a| newnode(BinaryOpNode, *a) }\
          | seq(:expr, '||', :expr) {|*a| newnode(BinaryOpNode, *a) }
 
   g.primary = seq(:DIGIT) {|num| newnode(LiteralNode, @types.int, num) }\
             | seq(:CHARACTER) {|ch| newnode(LiteralNode, @types.char, ch) }\
             | seq(:STRING) {|str|
                 newnode(LiteralNode,
                         @target.types(@types.char),
                         string_constant(str))
               }\
             | seq(:IDENT) {|sym| newnode(VarrefNode, @namespace, sym) }\
             | seq('+', :primary).prec('+@') {|op, expr|
                 newnode(UnaryOpNode, op, expr)
               }\
             | seq('-', :primary).prec('-@') {|op, expr|
                 newnode(UnaryOpNode, op, expr)
               }\
             | seq('!', :primary) {|op, expr|
                 newnode(UnaryOpNode, op, expr)
               }\
             | seq('*', :primary).prec('*@') {|op, expr|
                 newnode(UnaryOpNode, op, expr)
               }\
             | seq('&', :primary).prec('&@') {|op, expr|
                 newnode(UnaryOpNode, op, expr)
               }\
             | seq(:primary, '[', :expr, ']') {|expr, _, idx, _|
                 newnode(BinaryOpNode, '[]', expr, idx)
               }\
             | seq(:IDENT, '(', separated_by(',', :expr), ')') {
                  |name,   _,   args,                       _|
                 newnode(FuncallNode, name, args)
               }\
             | seq(:cast, :primary).prec(:CAST) {|type, node|
                 CastNode.new(type, node)
               }\
             | seq('(', :expr, ')') {|_, node, _| node }
 }

生成される文法

rule 1 program:
rule 2 program: program decl
rule 3 decl: defvar
rule 4 decl: defun
rule 5 decl: defstruct
rule 6 decl: defunion
rule 7 decl: struct_decl
rule 8 decl: union_decl
rule 9 defvar: storage type IDENT option@initval ";"
rule 10 option@initval:
rule 11 option@initval: initval
rule 12 initval: "=" expr
rule 13 defun: storage type IDENT "(" params ")" "{" scope "}"
rule 14 separated_by1@slot: slot
rule 15 separated_by1@slot: separated_by1@slot "," slot
rule 16 params:
rule 17 params: separated_by1@slot
rule 18 defstruct: STRUCT IDENT "{" many@memb "}" ";"
rule 19 many@memb:
rule 20 many@memb: many@memb memb
rule 21 defunion: UNION IDENT "{" many@memb "}" ";"
rule 22 memb: slot ";"
rule 23 struct_decl: STRUCT IDENT ";"
rule 24 union_decl: UNION IDENT ";"
rule 25 scope: @1 many@vardecl stmts
rule 26 @1:
rule 27 many@vardecl:
rule 28 many@vardecl: many@vardecl vardecl
rule 29 storage:
rule 30 storage: STATIC
rule 31 storage: EXTERN
rule 32 slot: type IDENT
rule 33 type: VOID
rule 34 type: CHAR
rule 35 type: SHORT
rule 36 type: INT
rule 37 type: LONG
rule 38 type: LONG LONG
rule 39 type: type "[" "]"
rule 40 type: type "*"
rule 41 type: STRUCT IDENT
rule 42 type: UNION IDENT
rule 43 stmts: many@stmt-1-base
rule 44 many@stmt-1-base:
rule 45 many@stmt-1-base: many@stmt-1-base stmt
rule 46 stmt: ";"
rule 47 stmt: expr ";"
rule 48 stmt: IF "(" expr ")" "{" scope "}" option@else
rule 49 stmt: WHILE "(" expr ")" "{" scope "}"
rule 50 stmt: BREAK ";"
rule 51 stmt: CONTINUE ";"
rule 52 stmt: RETURN ";"
rule 53 stmt: RETURN expr ";"
rule 54 option@else:
rule 55 option@else: else
rule 56 else: ELSE "{" stmts "}"
rule 57 expr: primary
rule 58 expr: expr "+" expr
rule 59 expr: expr "-" expr
rule 60 expr: expr "*" expr
rule 61 expr: expr "/" expr
rule 62 expr: expr "&" expr
rule 63 expr: expr "|" expr
rule 64 expr: expr ">>" expr
rule 65 expr: expr "<<" expr
rule 66 expr: expr ">" expr
rule 67 expr: expr ">=" expr
rule 68 expr: expr "<" expr
rule 69 expr: expr "<=" expr
rule 70 expr: expr "==" expr
rule 71 expr: expr "!=" expr
rule 72 expr: expr "&&" expr
rule 73 expr: expr "||" expr
rule 74 primary: DIGIT
rule 75 primary: CHARACTER
rule 76 primary: STRING
rule 77 primary: IDENT
rule 78 primary: "+" primary
rule 79 primary: "-" primary
rule 80 primary: "!" primary
rule 81 primary: "*" primary
rule 82 primary: "&" primary
rule 83 primary: primary "[" expr "]"
rule 84 primary: IDENT "(" option@separated_by1@expr ")"
rule 85 primary: cast primary
rule 86 primary: "(" expr ")"
rule 87 separated_by1@expr: expr
rule 88 separated_by1@expr: separated_by1@expr "," expr
rule 89 option@separated_by1@expr:
rule 90 option@separated_by1@expr: separated_by1@expr

(03:10)


<前月 | 最新 | 次月>
2002|04|05|06|07|08|09|10|11|12|
2003|01|02|03|04|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|