サークルで作ってるプログラムで,サーバーとの通信をS式でやっているので,それで使う用。
ありがちなので探せば絶対ありそうだけど練習も兼ねて。
(a b)
というStringをちまちま置換して
["a", "b"]
というStringにして、evalを使ってArrayに変換した。
最初はスタックに入れたり出したりしながらやっていたのだけど、最終的にはこのような形に落ち着いた。
eval使えたのでよかったことにする。
#!/usr/bin/ruby # S-Expression methods # add to_sexp method. class String def to_sexp # split the string with (,), . array = self.chomp.split(/([()])| /).delete_if{|c| c.size == 0} raise "The expression doesn't close." if array[-1] != ')' array.parse_sexp end def cut_each_end self[1..-2] end end class Array # this method returns s-expression string. def to_s_sexp str="" str += '(' self.each do |s| str += ( s.class == Array ? s.to_s_sexp : s.to_s ) str += ' ' end str += ')' str end # parse s-expression and convert to array. def parse_sexp q = [] q << '[' self.each do |l| case l when '(' q << '[' when ')' q << '],' else q << '"' + l + '",' end end q << ']' return eval( q.join ) end end # main if __FILE__ == $0 s=[] s << '(a b)' s << '(a)(b)' s << '(a(b(c)))' s.each do |l| puts l # convert s-exp-string to array p l.to_sexp # convert array to string puts l.to_sexp.to_s_sexp.cut_each_end puts end end
これを実行すると
(a b) [["a", "b"]] (a b ) (a)(b) [["a"], ["b"]] (a ) (b ) (a(b(c))) [["a", ["b", ["c"]]]] (a (b (c ) ) )
が出る。
上から順に,入力のString,パースしたArray,パースしたArrayをStringに戻したもの。
たしかに正しく動いている(気がする)。