challenge α置換

標準入力から与えられたソースコードの変数名
を置換するプログラムを作ってください。
最近はリファクタリングツールなどの普及でこ
のような需要は少ないかと思われますが、viな
ど貧弱なエディタを使っているときに困る
のが変数名の置換です。さすがに以下の例のよ
うなプログラムは例としてしか書きませんが、
置換しようとしている変数名と同じ綴りの他の
ものがプログラム中に出てくることはまれにあ
ります。そこで、与えられたソースコードに現
れる変数だけを指定された名前に置換してくだ
さい。
置換対象となるソースコードと使用言語は同じ
ものを使ってください。与えられるソースコー
ドは、完全なコンパイル単位、もしくはパース
して意味が通る範囲のものどちらであってもか
まいません。後者の場合、一番外側の変数だけ
置換できるようにしてください。
C言語での解答例をつけたかったのですが、と
ても難しかったためまだ作成できていません。
ご容赦ください。

例
$ cat a.c
/* a */
int foo()
{
        struct a {int a;} a;
#if FOO
        a.a = 1;
#endif
        { int a; }
	return 0;
}
$ alpha -DFOO=1 b a < a.c
/* a */
int foo()
{
        struct a {int a;} b;
#if FOO
        b.a = 1;
#endif
        { int a; }
	return 0;
}

Posted feedbacks - Ruby

変数v0を全てv1に置換した後に, 文字列とヒアドキュメント内のv1をv0に戻す処理をしています.

テストに使用したファイルを生成するコードも添付します.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def subst_var(file, v0, v1)
  hdocr = '[-]?[\"\'`]?([A-Z]+)'
  shared_reg = 's,;&|=+-*/[](){}'
  former, latter = %w[@$^ .].map{|reg|
    "#{shared_reg}#{reg}".each_char.inject(''){|a,b| "#{a}\\#{b}"}}
  gsub, rev_gsub = [:to_a, :reverse].map{|meth|
    proc{|s| s.gsub(*[v0, v1].__send__(meth))}}
  open(file, 'r'){|f| f.read}.
    gsub(/(?:^#{v0})?(?:[#{former}]#{v0})+[#{latter}]/, &gsub).
    gsub(/".*"/, &rev_gsub).
    gsub(/<<#{hdocr}(?:.|\s)+[^<]#{hdocr}/, &rev_gsub)
end
file = 'sample.rb'
puts subst_var(file, 'v0', 'v1')

open(file, 'w'){|f| f.write(<<EOF)}
v0+v0=v0
@v0 = 0
$v00, ^v0
"v0 v0 "
<<EOS
v0 v0
EOS
$v0, v0, v0
v0/v0*v0-v0+v0
EOF

Ripperを使ってみました。Ruby 1.9.0以上じゃないと動かないと思います。

AlphaConverter.newの第2引数以降で置換する変数を指定します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
require 'ripper'

class AlphaConverter<Ripper::Filter
  def initialize(src, *vars)
    super(src)
    @alpha_dict = {}
    vars.each do |o, n|
      @alpha_dict[o] = n
    end
  end

  def var_common(token, data)
    if @alpha_dict[token] then
      data << @alpha_dict[token]
    else
      data << token
    end
  end

  def on_default(event, token, data)
    data << token
  end

  # クラス変数
  def on_cvar(token, data)
    var_common(token, data)
  end

  # 大域変数
  def on_gvar(token, data)
    var_common(token, data)
  end

  # インスタンス変数
  def on_ivar(token, data)
    var_common(token, data)
  end 
 
  # ローカル変数
  def on_ident(token, data)
    var_common(token, data)
  end
end

print AlphaConverter.new(ARGF, ['event', 'ee'], ['@alpha_dict', '@ad']).parse('')

Index

Feed

Other

Link

Pathtraq

loading...