ここ三日くらいの寝不足により、こんなのが動くようになった。
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)
どうせなら「n 回以上の繰り返し」とか「省略可能」とかも実装したいところだが、 インターフェイスをどーしたもんかなー。 現状の rule(:exp, '+', :exp) {....} てのもベストとは言い難いし。
(01:27)
まさかとは思ったが、VALUE 作ってるのに全然マークしてないじゃん!! よくこれまで落ちなかったなー、これ……。 1.8.5 の前に見付かってよかったと考えるべきか、 それともすでに手遅れと考えるべきだろうか。
(22:18)
http://www.vim.org/scripts/script.php?script_id=1589
vim で SKK が使えるプラグイン。 こんなものがあったのか! すっげえ便利だー! 即座に常用決定。
(01:55)
http://www.unixuser.jp/magazine/2006/200608.html
オープンソースマガジン 8 月号で記事を書かせてもらいました。 ハッカー養成塾という連載のうち一本で、 「オープンソースマガジンの中心 (付近のページ) でバカと叫ぶ」です。 いやー、もうね、なんかね、何書いてもいいと言われたので、 久しぶりにリミッターを外して書いてみました。 よかったら読んでやってください。
(06:09)
http://jp.rubyist.net/magazine/?0015
Rubyist Magazine 15 号でた。
なかなか掲載できなかった Tropy の添削記事をようやく出せた。 今月も長い。最初はもっと長かった。
今月号は添削と YARV 以外読んでないので、おれもこれから読む。
(00:25)
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)
■
タナカコウイチロウ [田中という者です。
先日のHaskell読書会に出ていた者です。
参照透過性についての話題。
ライカン著「言語哲学」(けい草書房)で、クワインの用語法で
”指示的に透明(transparent)”(p.20)がありました。
また、飯田隆著「言語哲学大全III」(けい草書房)の索引には、
”指示的に透明な(referentially transparent)文脈”の項目が
ありました。(自分は理解していません)
しかし、クワインの用語と因果関係はアルのかと、自問したくなります。
それでは。]
■
青木 [あ、これはどうも。クワインかー。ちょっとぐぐってみたところ、
http://sources.redhat.com/ml/guile/1998-08/msg00401.html
というページがありました。このページによると、クワインは
"Principia Mathematica" から持ってきたとか、もしかしたら
フレーゲかもー、とか書いてありますね。プログラミング言語に
持ち込まれたときに意味が変化してるようです。]
StringScanner.new("").scan(//) が nil になるよ問題。 これはだいたい問題なく終わる。
Ruby 1.8 でテストが失敗するよーと思っていたら、 鬼車と GNU regex の挙動の差が原因だった。 明示的なチェックを入れて修正完了。
(19:06)
ファイルシステムをまたぐ mv が元のファイルを消してなかった件。当然バグ。 なんか見たことあると思ってたら、妙に迂遠な経路を経て [ruby-dev:28223] で報告されていたやつだった。修正済。
mv をアトミックにしろと言われてもなあ。 てんぷファイル (添付じゃなくて tmp な) を作るのは好きじゃないんだよね俺。
(19:10)
これは 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)
net/http の deflate 対応パッチをもらった。 おおむねそのまま使えそうなので、 近いうちに修正を加えて 1.9 に取り込む予定。
(15:45)
レポートを書いてたはずなのにいつのまにか 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)
■ hyuki [読みました。思いっきりメタに話を振ってましたねー(^_^)]
■ 青木 [反応早っ。どうもありがとうございます。
ある人には「セカイ系ラノベぽい」と言われてちょっと納得しました。]