From: kjana@... (YANAGAWA Kazuhisa) Date: 1999-02-03T22:47:36+09:00 Subject: [ruby-list:11893] Re: [racc] help me In message <199902030923.SAA10248.keiju@bc.mbn.or.jp> keiju@rational.com (=?ISO-2022-JP?B?GyRCQFBETTc9PHkbKEI=?= ) writes: > >> でも, 私の実力ではrubyの字句を完全に識別できるような複雑な正規表現は > >> 書けないし(^^;;; > > > >結構簡単に書けると思いますけど.文字列とコメントにだけ気をつけてやれば > >良いわけで. こんなん書きましたけど,here document を考えたら突然どうにもならん程難 しいような気がしてきました.parser と協調しないと無理そう. > ># というりくつで適当に書いたのが前に出した scanner generator.ちなみに > ># あの後ちょっといじりました.誰か興味あります? > > こっちには興味ありますので, uploadしてもらえるとありがたいです. # メーリングリストサーバにメールを出すのは upload ととらえられなくもな # いが結局それがクライアントたる参加者のもとに配られることを考えると, # などというばか話はおいといて (^^; [ruby-list:11458] で出したものをほんのちょっと書き換えただけです.だけ なのに diff -u でも 80 行近くになるのはどうも.... まるのままつけても 134 行とかなのに. * GOTO ですぐに実行中のアクションから抜けていたのをやめました. * RETURN のデフォルトモードを現在のモードにしました. (前のは :default にしてた) * の前に書いたコードは本当に「書いたまま」生成される Scanner に取り込まれるようになりました. (前のは initialize の中にコピーしてた) * これにともない `init' というメソッドを定義しておくとこれが initialize から呼び出されるようにしました. テンプレートをいれちゃうより継承させた方がいいのかな.... # まだ名前が無い.まあいちおう `rlex.rb' という名前で使ってたりはする # んですが.サンプルは実際に使っているものです.何に使っているのかはお # いとくとして. -- 柳川和久 @ 東大阪市 . 大阪府 February 3, 1999 The more haste, the less speed. #!/usr/local/bin/ruby if ARGV[0] inf = File.open(ARGV[0]) ARGV.shift else inf = $stdin end if ARGV[0] out = File.open(ARGV[0], "w") ARGV.shift else out = $stdout end out.puts </ # mode declarations next if /^\s*$/ # until first mode declaration, any string is copied literally. out.puts " #{$_.chomp!}" end if $1 out.puts out.puts " def #{$1}" out.puts " case @__line__" end mode = [] while inf.gets case $_.chomp! when /(?:^\s*$)|(?:^#.*)/ # ignore when /^<([_a-zA-Z]\w*)>/ # mode declarations mode << $1 out.puts " else" out.puts " c = @__line__[0]" out.puts " @__line__ = @__line__[1..-1]" out.puts " return_with_val c" out.puts " end" out.puts " end" out.puts out.puts " def #{$1}" out.puts " case @__line__" when /^\s+.*/ # actions # action strings are copied literally. out.puts " #{$_}" else # patterns out.puts " when /\\A(#{$_})/" out.puts " @__line__ = $'" out.puts " matched = $1" end end out.puts " else" out.puts " c = @__line__[0]" out.puts " @__line__ = @__line__[1..-1]" out.puts " return_with_val c" out.puts " end" out.puts " end" out.puts < [_a-zA-Z]\w* RETURN [:ident, matched, @lineno] \[\]|:|;|\. RETURN [matched, matched, @lineno] \n @lineno += 1 \s+ # silently ignored " @str = "\"" GOTO :in_string . RETURN [matched, matched, @lineno] \\[a-zA-Z"] @str << "#{matched}" " @str << "\"" RETURN [:string, @str, @lineno], :default \n @lineno += 1 @str << "\n" [^"\\] @str << matched