淫夢語でプログラミング
こんにちは。プルさわです。
最近私の周りに淫夢好きなよく分からない人が目に着くようになりました。たまげたなあ。
私は正直淫夢のことは良くわからないのですが、最近ハマってる変なプログラミング言語シリーズと絡めてなんかしてみようということで、今回新しいプログラミング言語を作ってみました。
ということで、できたのがIceTea(アイスティー)という言語です。
Rubyで作りました。
命令とか使い方とか
とは言っても内容はBrainf_ckに毛が生えた程度のものなので、とりあえず知らない人は↓の記事でも読んでいただけると良いかと思います。
以下のように使ってください。
命令文字列 | 機能 |
---|---|
n回だよ、n回あくしろよ | ポインタの指す値をn増やす |
n回だよ、n回お手だよ | ポインタの指す値をn減らす |
なんか足んねえよなぁもうn回鳴いてみろ | ポインタをn進める |
この野郎もうn回鳴いてみろ | ポインタをn戻す |
こ↑こ↓ | ポインタの指す値をUTF-8のコードとみなして出力する |
(小学生並みの感想) | 1文字入力を読み込んで、ポインタの指す値に設定します |
ハイ、よーいスタート | ポインタの指す値が0以外なら何もせず、0ならループを終了して次へ進む。 |
2人は幸せなキスをして終了 | ループの終了を意味します。この位置まで来ると、対応するループの先頭へ戻ります |
Hello, World!
サンプルプログラムです。
以下のプログラムを実行すると「Hello, World!」が出力されます。
9回だよ、9回あくしろよ ハイ、よーいスタート なんか足んねえよなぁもう1回鳴いてみろ 8回だよ、8回あくしろよ なんか足んねえよなぁもう1回鳴いてみろ 11回だよ、11回あくしろよ なんか足んねえよなぁもう1回鳴いてみろ 5回だよ、5回あくしろよ この野郎もう3回鳴いてみろ 1回だよ、1回お手だよ 2人は幸せなキスをして終了 なんか足んねえよなぁもう1回鳴いてみろ こ↑こ↓ なんか足んねえよなぁもう1回鳴いてみろ 2回だよ、2回あくしろよ こ↑こ↓ 7回だよ、7回あくしろよ こ↑こ↓ こ↑こ↓ 3回だよ、3回あくしろよ こ↑こ↓ なんか足んねえよなぁもう1回鳴いてみろ 1回だよ、1回お手だよ こ↑こ↓ 12回だよ、12回お手だよ こ↑こ↓ この野郎もう1回鳴いてみろ 8回だよ、8回あくしろよ こ↑こ↓ 8回だよ、8回お手だよ こ↑こ↓ 3回だよ、3回あくしろよ こ↑こ↓ 6回だよ、6回お手だよ こ↑こ↓ 8回だよ、8回お手だよ こ↑こ↓ なんか足んねえよなぁもう1回鳴いてみろ 1回だよ、1回あくしろよ こ↑こ↓
その他実装とかの細かい話
参考資料(偉大な先人達)
以下の本はBrainf_ckの実装で大変お世話になりました。
それから、Rubyで言語実装系を作る際にとても勉強になります。
Rubyで作る奇妙なプログラミング言語 ?ヘンな言語のつくりかた?
- 作者: 原悠
- 出版社/メーカー: マイナビ
- 発売日: 2014/01/16
- メディア: Kindle版
- この商品を含むブログを見る
以下のサイトはBrainf_ckを元に変な言語を作った人たちです。
masarakki/nyaruko_lang · GitHub
ソースコード
class Icetea # エラークラスを継承する class ProgramError < StandardError; end ORDERS = [ /\d+回だよ、\d+回あくしろよ/, /\d+回だよ、\d+回お手だよ/, /なんか足んねえよなぁもう\d+回鳴いてみろ/, /この野郎もう\d+回鳴いてみろ/, /こ↑こ↓/, /\(小学生並みの感想\)/, /ハイ、よーいスタート/, /2人は幸せなキスをして終了/ ] def initialize(src) # トークンを入れる配列 @tokens = src.scan(Regexp.union(ORDERS)) @jumps = analyze_jumps(@tokens) end # 実行 def run # テープを表した配列 tape = Array.new() # 何番目の命令を実行しているか pc = 0 # ポインタが現在どこを指しているか cur = 0 while pc < @tokens.size case @tokens[pc] when /(\d+)回だよ、\d+回あくしろよ/ tape[cur] = tape[cur].to_i + $1.to_i when /(\d+)回だよ、\d+回お手だよ/ tape[cur] = tape[cur].to_i - $1.to_i when /なんか足んねえよなぁもう(\d+)回鳴いてみろ/ cur += $1.to_i when /この野郎もう(\d+)回鳴いてみろ/ cur -= $1.to_i raise ProgramError, "You can't move lefft from start point" if cur < 0 when /ハイ、よーいスタート/ pc = @jumps[pc] if tape[cur].to_i == 0 when /2人は幸せなキスをして終了/ pc = @jumps[pc] if tape[cur].to_i != 0 when /こ↑こ↓/ n = tape[cur].to_i print n.chr when /\(小学生並みの感想\)/ tape[cur] = $stdin.getc.ord end pc += 1 end end private # ジャンプ命令を解析する def analyze_jumps(tokens) jumps = {} starts =[] startword = "ハイ、よーいスタート" endword = "2人は幸せなキスをして終了" tokens.each_with_index do |e, i| if e == startword starts << i elsif e == endword raise ProgramError, "total number of #{startword} is more than #{endword}" if starts.empty? from = starts.pop to = i jumps[from] = to jumps[to] = from end end raise ProgramError, "total number of #{endword} is more than #{startword}" unless starts.empty? return jumps end end begin Icetea.new(ARGF.read).run rescue Icetea::ProgramError => e puts e.message end
エンジョイ!プログラミングライフ!