どう書く?org : α置換

original page : http://ja.doukaku.org/171/

標準入力から与えられたソースコードの変数名
を置換するプログラムを作ってください。
最近はリファクタリングツールなどの普及でこ
のような需要は少ないかと思われますが、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;
}

#7124

original page : http://ja.doukaku.org/comment/7124/

substitute()を使って、Rのparserにお任せします。

お題の「一番外側の変数」というのは、「スコープ内の変数」という解釈でいいのでしょうか。例えば以下のようなコードでは、xの最終的な値は10になるので、スコープをさしているのであれば「一番外側」にこだわる必要はないと判断しました。

例では、変数"x"を"aaaa"に変更しています。リストの項目名である"x"や文字列中の"x"、別の変数名の一部に含まれる"x"など、置換するべきでないものは残されているようです。:

> alpha.replace("x", "aaaa")

(入力)
x <- 1
y <- list(x=10)
z <- "w x y z"
xyz <- 1
zzz <- {
x <- 10
}
x

(出力)
{
aaaa <- 1
y <- list(x = 10)
z <- "w x y z"
xyz <- 1
zzz <- {
aaaa <- 10
}
aaaa
}

alpha.replace <- function(from, to){
   script <- c("substitute({",readLines(),"}, list(",from,"=quote(",to,")))")
   eval(parse(text=script))
}