Ruby・Raccを使用した
言語処理系の日本語プログラミング化
    長野県松本工業高等学校
       桐井 祐樹
自己紹介
• 工業高校3年生�電子工業科 所属
 – 部活動でロボットとか作っていました


• セキュリティ&プログラミングキャンプ2010
� プログラミングコース 言語組 卒業生

• サイボウズ・ラボ ユース�第一期サブメンバー
卒業課題研究
• 電子工業科3年の行う授業
• 言語処理系の構造と動作について学ぶ
 – Ruby & Racc で作られたインタプリタ言語「Intp」�
 –               Ruby を256倍使うための本�無道編
 ��������������������� 青木 峰郎�著
冬の開発合宿でやったこと
• Intp の拡張と改造
 – 演算子の追加
   剰余算(%), 比較( >, <, >=, <=)
   否定(!=)

 – 英字以外で記述されたプログラムの実行
   • 日本語プログラミング言語化
Intp�
•   Ruby に似た構文規則
•   変数の型はなし
•   パーサジェネレータに Racc を使用
•   組み込みの関数は Ruby のメソッドを使用
     message = "hello"
     puts( concat( message, ", world! " )) �#=> hello, world

     a = 10
     b = 20
     if a <= b then
       print( "if ok!" + "n" )   ������������ �#=> if ok!
     end
Racc
• Ruby 向けパーサジェネレータ�( Ruby yacc )
• 文字の並びをコンピュータが理解できるよう
 変換する (パース parse)
• 文法ファイル�*.y を読み込み *.rb を生成
 – 規則部 (文法規則を記述)
 – ユーザーコード部
   (ファイルからの読み込み・スキャナ部を記述)
演算子の追加
• Racc 文法ファイルに規則を追加
- parser.y
 expr : expr '+' expr
�����      | expr '-' expr
��������������������・
��������������������・�������(省略)
��������������������・
     ���� | expr '%' expr
     ���� {
        ������result = FuncallNode.new( @fname,
�����������������������������val[0].lineno,�'%', [val[0],val[2]] )
       ����}
• Ruby の演算子
 – 実際にはメソッド呼び出し ( 再定義可能 )
  | �^ �& �<=> �== �=== �=~ �> �>= �< �<= �<< � >>
  + �-� *� /� %� **� ~� +@� -@ �[]� []=� `
                  Ruby 1.9.2 リファレンスマニュアル - 演算子式

     例 ) 5�%�2�の場合
     �������$ irb
     �������irb(main):001:0> 5 % 2
     �������=> 1
     �������irb(main):002:0> 5.%( 2 )
     �������=> 1
     �������irb(main):003:0> 5.send( '%', 2 )
     �������=> 1
• send で % メソッドを指定して実行
-�parser.y
����result = FuncallNode.new( @fname,�
                          val[0].lineno, '%', [val[0],�val[2]] )
�������������������������������������������������������������5����������2

-�node.rb
����recv = arg.shift
����recv.send @funcname, *arg
  �����5���� ������������%�� ������� 2
日本語による記述への対応
• 英字以外でプログラミングできないか?
 – 記号
 – 絵文字
 – 漢字・ひらがな・カタカナ


• 日本語でプログラミング・・・?
 – 命令の置き換え & 並べ方 で実現できるかも
• 命令を一つずつ日本語表現に置き換える
message = “hello!”       message に「こんにちは!」 を代入
puts message             message を表示

a = 10                   a に 10 を代入
b = 20                   b に 20 を代入
if a > b then            もし a が b より大きい なら
   puts “a は b よりも大きい”     「a は b よりも大きい」 と表示
else                     それ以外なら
   puts “a は b よりも小さい”     「a は b よりも小さい」 と表示
end                      終了

true                     真
false                    偽
• スキャナ部に正規表現を追加
  #代入
   when /A代入(する?)|入れる/
     @q.push [ :DAINYU, [lineno, $&.intern] ]

  #条件分岐(if)
   when /Aもし(も)?/
     @q.push [ :IF, [lineno, $&.intern] ]
   when /Aなら(ば)?/
     @q.push [ :THEN, [lineno, $&.intern] ]
   when /Aそうでないなら(ば)?|それ以外なら(ば)?/
     @q.push [ :ELSE, [lineno, $&.intern] ]

 – 日本語表現1つ1つに記号を割り当て

  マッチした場合、記号と値をキューに push する
• 文法ファイルに日本語用の規則を追加
       例)�変数への代入
       Racc 文法ファイルの規則部                         �������実際の記述例
assign : IDENT '=' expr
   ��� {                                             �����message = “hello!”
        ����result = AssignNode.new( @fname,
            ���       val[0][0], val[0][1], val[2] )
     ���}
     ���| IDENT NI expr WO DAINYU
    � �{                                             �����message に 「こんにちは!」を 代入
        ����result = AssignNode.new( @fname,
                  �� val[0][0], val[0][1], val[2] )
     ��}
     ���| expr WO IDENT NI DAINYU
     ��{                                             �����「こんにちは!」を message に 代入
        ����result = AssignNode.new( @fname,
                 � val[2][0], val[2][1], val[0] )
     ��}
課題研究発表会
• 全校生徒に発表しました!
研究を通して
• 言語処理系の構造と動作について
 – 以前より理解を深めることができた
 � 実装のためのスキル向上をしなければ・・・
• 日本語化に関して
 – 記号増加による規則の衝突の発生
   (17 shift/reduce conflicts)
 – コンピュータを操作する手段としての「言語」
   普段のプログラミングとは違う感覚
   ( UI ・ 情報可視化の分野へどう繋げられるか )
ご清聴ありがとうございました

ラボユース 最終成果報告会

  • 1.
  • 2.
    自己紹介 • 工業高校3年生�電子工業科 所属 – 部活動でロボットとか作っていました • セキュリティ&プログラミングキャンプ2010 � プログラミングコース 言語組 卒業生 • サイボウズ・ラボ ユース�第一期サブメンバー
  • 3.
    卒業課題研究 • 電子工業科3年の行う授業 • 言語処理系の構造と動作について学ぶ – Ruby & Racc で作られたインタプリタ言語「Intp」� – Ruby を256倍使うための本�無道編 ��������������������� 青木 峰郎�著
  • 4.
    冬の開発合宿でやったこと • Intp の拡張と改造 – 演算子の追加 剰余算(%), 比較( >, <, >=, <=) 否定(!=) – 英字以外で記述されたプログラムの実行 • 日本語プログラミング言語化
  • 5.
    Intp� • Ruby に似た構文規則 • 変数の型はなし • パーサジェネレータに Racc を使用 • 組み込みの関数は Ruby のメソッドを使用 message = "hello" puts( concat( message, ", world! " )) �#=> hello, world a = 10 b = 20 if a <= b then print( "if ok!" + "n" ) ������������ �#=> if ok! end
  • 6.
    Racc • Ruby 向けパーサジェネレータ�(Ruby yacc ) • 文字の並びをコンピュータが理解できるよう 変換する (パース parse) • 文法ファイル�*.y を読み込み *.rb を生成 – 規則部 (文法規則を記述) – ユーザーコード部 (ファイルからの読み込み・スキャナ部を記述)
  • 7.
    演算子の追加 • Racc 文法ファイルに規則を追加 -parser.y expr : expr '+' expr ����� | expr '-' expr ��������������������・ ��������������������・�������(省略) ��������������������・ ���� | expr '%' expr ���� { ������result = FuncallNode.new( @fname, �����������������������������val[0].lineno,�'%', [val[0],val[2]] ) ����}
  • 8.
    • Ruby の演算子 – 実際にはメソッド呼び出し ( 再定義可能 ) | �^ �& �<=> �== �=== �=~ �> �>= �< �<= �<< � >> + �-� *� /� %� **� ~� +@� -@ �[]� []=� ` Ruby 1.9.2 リファレンスマニュアル - 演算子式 例 ) 5�%�2�の場合 �������$ irb �������irb(main):001:0> 5 % 2 �������=> 1 �������irb(main):002:0> 5.%( 2 ) �������=> 1 �������irb(main):003:0> 5.send( '%', 2 ) �������=> 1
  • 9.
    • send で% メソッドを指定して実行 -�parser.y ����result = FuncallNode.new( @fname,� val[0].lineno, '%', [val[0],�val[2]] ) �������������������������������������������������������������5����������2 -�node.rb ����recv = arg.shift ����recv.send @funcname, *arg �����5���� ������������%�� ������� 2
  • 10.
    日本語による記述への対応 • 英字以外でプログラミングできないか? –記号 – 絵文字 – 漢字・ひらがな・カタカナ • 日本語でプログラミング・・・? – 命令の置き換え & 並べ方 で実現できるかも
  • 11.
    • 命令を一つずつ日本語表現に置き換える message =“hello!” message に「こんにちは!」 を代入 puts message message を表示 a = 10 a に 10 を代入 b = 20 b に 20 を代入 if a > b then もし a が b より大きい なら puts “a は b よりも大きい” 「a は b よりも大きい」 と表示 else それ以外なら puts “a は b よりも小さい” 「a は b よりも小さい」 と表示 end 終了 true 真 false 偽
  • 12.
    • スキャナ部に正規表現を追加 #代入 when /A代入(する?)|入れる/ @q.push [ :DAINYU, [lineno, $&.intern] ] #条件分岐(if) when /Aもし(も)?/ @q.push [ :IF, [lineno, $&.intern] ] when /Aなら(ば)?/ @q.push [ :THEN, [lineno, $&.intern] ] when /Aそうでないなら(ば)?|それ以外なら(ば)?/ @q.push [ :ELSE, [lineno, $&.intern] ] – 日本語表現1つ1つに記号を割り当て マッチした場合、記号と値をキューに push する
  • 13.
    • 文法ファイルに日本語用の規則を追加 例)�変数への代入 Racc 文法ファイルの規則部 �������実際の記述例 assign : IDENT '=' expr ��� { �����message = “hello!” ����result = AssignNode.new( @fname, ��� val[0][0], val[0][1], val[2] ) ���} ���| IDENT NI expr WO DAINYU � �{ �����message に 「こんにちは!」を 代入 ����result = AssignNode.new( @fname, �� val[0][0], val[0][1], val[2] ) ��} ���| expr WO IDENT NI DAINYU ��{ �����「こんにちは!」を message に 代入 ����result = AssignNode.new( @fname, � val[2][0], val[2][1], val[0] ) ��}
  • 14.
  • 15.
    研究を通して • 言語処理系の構造と動作について –以前より理解を深めることができた � 実装のためのスキル向上をしなければ・・・ • 日本語化に関して – 記号増加による規則の衝突の発生 (17 shift/reduce conflicts) – コンピュータを操作する手段としての「言語」 普段のプログラミングとは違う感覚 ( UI ・ 情報可視化の分野へどう繋げられるか )
  • 16.