$30 off During Our Annual Pro Sale. View Details »

ユーザが構文を自由に変更できるプログラミング言語

 ユーザが構文を自由に変更できるプログラミング言語

第5期サイボウズ・ラボユース成果報告会
言語処理系ゼミ

Akama Hitoshi

March 30, 2016
Tweet

More Decks by Akama Hitoshi

Other Decks in Programming

Transcript

  1. ユーザが構文を自由に変更できる
    プログラミング言語
    第5期サイボウズラボ・ユース成果報告会
    言語処理系ゼミ
    2016/03/30
    東京工業大学 理学部 情報科学科
    赤間 仁志

    View Slide

  2. 目的
    ● 構文を自由に変更できるプログラミング言語を作れないか?
    ● ユーザが新しい構文を導入するメリット:
    ○ 簡潔な見た目
    ○ 少ない記述量で望んだ処理を行う
    ● 書いてる途中にどんどん構文が変わっていく言語
    ○ 面白そう
    ○ 個人的な興味
    2

    View Slide

  3. 構文を変更できるとうれしい例 in C
    ● 固定回数のループ文
    ● forループ特有の条件部分を書かなくてよい
    for (int i = 0; i < 10; i++) {
    printf(“Hello, %d\n”, i);
    }
    times(i, 10) {
    printf(“Hello, %d\n”, i);
    }
    Before After
    3
    #define times(i, n) \
    for (int i; i < (n); i++)

    View Slide

  4. 構文を変更できる言語の要件
    1. 処理系を変更することで構文を変更するのはダメ
    ○ ユーザの手によって構文が変更できること
    2. 構文を追加することも,削除することもできること
    ○ 不要になった構文もユーザの手で削除できる
    3. 構文を定義する構文も作成できること
    ○ 構文の定義方法もユーザが作成可能
    4
    画像素材:http://www.irasutoya.com/

    View Slide

  5. プログラミング言語Garbanzo(仮) ver. 2
    ● 動的型つけ
    ● インタプリタ方式
    ○ いくつかの命令を搭載
    ● 組み込みの構文は最小限
    ○ ほぼ構文木をそのまま
    ○ どんどん構文を拡張可能
    5
    {“@”: “print”,
    {“@”: “append”,
    “left”: “Hello”,
    “right”: ”World”
    }
    }
    画像素材:http://www.irasutoya.com/

    View Slide

  6. 一般的なインタプリタ
    構文解析器 評価器
    AST
    ソース
    コード
    結果
    “(3 + 4) * 6”
    *
    3 4
    6
    +
    42
    6

    View Slide

  7. Garbanzoでの構文解析
    ● 実行にともない,構文解析ルールを書き換える
    ○ 文を1つずつ読み込んで実行
    ● 構文解析器そのものがGarbanzoのプログラム
    ○ Garbanzoの評価器の上で動作
    ● 構文解析ルールはファーストクラスの値
    ○ プログラム内で操作できる
    7
    プログラム
    構文を変更する
    宣言・命令
    新しい構文で
    記述したプログラム
    7

    View Slide

  8. 実行の流れ
    構文解析器
    評価器
    AST
    ソース
    コード
    結果
    構文解析
    実行
    ルールの
    追加・削除
    8

    View Slide

  9. 構文の定義
    ● 組込の構文は,構文木をそのまま書くので,なんでもできる
    ● けど長ったらしい
    9
    {"@": "set",
    "object":
    {"@": "get",
    "object":
    {"@": "get",
    "object":
    {"@": "get",
    "object":
    {"@": "get",
    "object":
    {"@": "getenv"
    },
    "key": "/"
    },
    "key": "parser"
    },
    "key": "sentence"
    },
    "key": "children"
    },
    "key": "newline",
    "value":
    {"@": "quote",
    "value":
    {"@": "scope",
    "body":
    {"0":
    {"@": "terminal",
    "string": "\n"
    }
    }
    }
    }
    }

    View Slide

  10. 自動生成
    ● 構文の定義をバージョン1のコードで自動生成
    ○ 共通のランタイム
    ● バージョン1(自作言語)でバージョン2(自作言語)の開発
    ○ デバッガなし
    ○ リファレンスなし
    ○ 質問する相手なし
    ● 生成された構文をGarbanzoの初期構文とする
    ○ 標準ライブラリ的な構文
    10

    View Slide

  11. 自動生成
    ● 構文の定義をバージョン1のコードで自動生成
    ○ 共通のランタイム
    ● バージョン1(自作言語)でバージョン2(自作言語)の開発
    ○ デバッガなし
    ○ リファレンスなし
    ○ 質問する相手なし
    ● 生成された構文をGarbanzoの初期構文とする
    ○ 標準ライブラリ的な構文
    11
    ヤバい

    View Slide

  12. 初期構文を用いる例
    fib = fun(n)
    if n < 2
    n;
    else
    ../fib(n - 1) + ../fib(n - 2);
    end
    end;
    /print(fib(7));
    12
    ここで利用している構文:
    ● 数値リテラル
    ● 代入
    ● 匿名関数
    ● if〜else文
    ● 加算・減算
    ● 関数呼び出し
    ● etc.

    View Slide

  13. 構文の拡張例(カッコ)
    paren = block
    %/tokenize(/terminal("("));
    inner = %/parser/expression;
    %/tokenize(/terminal(")"));
    inner;
    end;
    /parser/expression/children/paren = paren;
    13
    ここで利用している構文:
    ● block ~ end
    ● 代入
    ● 関数呼び出し
    ● etc.

    View Slide

  14. 構文を拡張する構文
    ● 構文の拡張はまだ煩雑
    ● 構文を拡張する構文を作成
    ● Schemeのマクロのような,パターンマッチ式での構文
    ● 構文ルールの優先度(prec)も指定
    let:prec pattern1 pattern2 … patternN := template;
    ● 初期構文を用いて約60行で実装
    14

    View Slide

  15. 構文を拡張する構文の使用例
    ● 優先順位をまとめるためのカッコ
    let:0 “(“ inner:1000 “)” := inner;
    例: (4 + 5)
    ● 添え字つきのアクセス
    let:15 store:14 “[“ key:1000 “]” := /get(store, key);
    例: hoge[“key”]
    15

    View Slide

  16. 課題
    ● 構文解析ルールの曖昧さへの対処
    ○ ルールが合成可能な構文解析の方式が必要
    ● Rubyでプロトタイプを実装したため,極めて低速
    ○ のちのち他の言語で処理系を書き直す
    ● 構文解析エラーのわかりやすさの向上
    16
    画像素材:http://www.irasutoya.com/

    View Slide

  17. ラボユースでの活動
    ● プログラミング言語処理系の開発
    ○ プロトタイプ作成による試行錯誤
    ● 情報処理学会 第57回プログラミング・シンポジウムに参加
    ○ 論文を執筆
    ○ 勉強になる
    17

    View Slide

  18. まとめ
    ● 構文を拡張可能なプログラミング言語Garbanzo(仮)を紹介
    ● 構文解析ルールをユーザが動的に追加することで構文を変更
    ● 構文を定義する構文も作成可能
    ○ 構文の拡張をくり返すことができる
    ● プログラミング・シンポジウムで発表
    ○ 開発以外でもラボユースの活動を行う
    ※適当につけた名前なので,カッコいい名前を募集中です
    GitHub: https://github.com/akamah/garbanzo
    18

    View Slide

  19. 補足のスライド
    19

    View Slide

  20. データ型
    ● 文字列,数値,真偽値
    ● 関数
    ● データストア
    ○ 順序をもったハッシュテーブル
    ○ 構文木の構成などに利用
    20

    View Slide

  21. 細かな実行の流れ
    1. 特別な構文解析ルール sentence に従って入力から読み取る
    2. その結果を評価器に入力(eval)する
    ○ この時,読み込んだプログラムが構文解析ルールを変更することがある
    3. 入力が空になるまで1から2をくり返す
    21

    View Slide

  22. 構文解析の実際
    ● 構文解析ルール = Garbanzoのプログラム片
    ● evalされると,構文解析を実行する
    ● 構文解析専用の命令を評価器に搭載
    ○ terminal: 指定された文字列を読み取る
    ○ choice: 与えられた構文解析ルールを順に試す
    ○ etc.
    22

    View Slide

  23. 構文解析器の変更
    ● いくつかの構文解析ルール(= Garbanzoのプログラム)が既に存在
    ● これら既に存在したルールの構文木を直接変更
    23

    View Slide

  24. Ver. 1による自動生成の例
    integer = '/parser/integer = '{
    digit = [@: "quote", value: [@: "oneof", string: "0123456789"]]
    a = [@: "sub", left: [@: "tocode", string: %digit], right: [@: "tocode", string: "0"]]
    rest = [@: "many", parser: digit]
    ten = [@: "sub", left: [@: "tocode", string: "K"], right: [@: "tocode", string: "A"]]
    "generate";
    /foreach([store: rest, func: ^{
    n = [@: "sub", left: [@: "tocode", string: value], right: [@: "tocode", string: "0"]]
    ../a = ../a * ../ten + n
    }]);
    a;
    }
    24

    View Slide