Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

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

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

Avatar for Akama Hitoshi

Akama Hitoshi

March 30, 2016
Tweet

More Decks by Akama Hitoshi

Other Decks in Programming

Transcript

  1. 構文を変更できるとうれしい例 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++)
  2. プログラミング言語Garbanzo(仮) ver. 2 • 動的型つけ • インタプリタ方式 ◦ いくつかの命令を搭載 •

    組み込みの構文は最小限 ◦ ほぼ構文木をそのまま ◦ どんどん構文を拡張可能 5 {“@”: “print”, {“@”: “append”, “left”: “Hello”, “right”: ”World” } } 画像素材:http://www.irasutoya.com/
  3. Garbanzoでの構文解析 • 実行にともない,構文解析ルールを書き換える ◦ 文を1つずつ読み込んで実行 • 構文解析器そのものがGarbanzoのプログラム ◦ Garbanzoの評価器の上で動作 •

    構文解析ルールはファーストクラスの値 ◦ プログラム内で操作できる 7 プログラム 構文を変更する 宣言・命令 新しい構文で 記述したプログラム 7
  4. 構文の定義 • 組込の構文は,構文木をそのまま書くので,なんでもできる • けど長ったらしい 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" } } } } }
  5. 自動生成 • 構文の定義をバージョン1のコードで自動生成 ◦ 共通のランタイム • バージョン1(自作言語)でバージョン2(自作言語)の開発 ◦ デバッガなし ◦

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

    リファレンスなし ◦ 質問する相手なし • 生成された構文をGarbanzoの初期構文とする ◦ 標準ライブラリ的な構文 11 ヤバい
  7. 初期構文を用いる例 fib = fun(n) if n < 2 n; else

    ../fib(n - 1) + ../fib(n - 2); end end; /print(fib(7)); 12 ここで利用している構文: • 数値リテラル • 代入 • 匿名関数 • if〜else文 • 加算・減算 • 関数呼び出し • etc.
  8. 構文の拡張例(カッコ) paren = block %/tokenize(/terminal("(")); inner = %/parser/expression; %/tokenize(/terminal(")")); inner;

    end; /parser/expression/children/paren = paren; 13 ここで利用している構文: • block ~ end • 代入 • 関数呼び出し • etc.
  9. 構文を拡張する構文の使用例 • 優先順位をまとめるためのカッコ let:0 “(“ inner:1000 “)” := inner; 例:

    (4 + 5) • 添え字つきのアクセス let:15 store:14 “[“ key:1000 “]” := /get(store, key); 例: hoge[“key”] 15
  10. まとめ • 構文を拡張可能なプログラミング言語Garbanzo(仮)を紹介 • 構文解析ルールをユーザが動的に追加することで構文を変更 • 構文を定義する構文も作成可能 ◦ 構文の拡張をくり返すことができる •

    プログラミング・シンポジウムで発表 ◦ 開発以外でもラボユースの活動を行う ※適当につけた名前なので,カッコいい名前を募集中です GitHub: https://github.com/akamah/garbanzo 18
  11. 構文解析の実際 • 構文解析ルール = Garbanzoのプログラム片 • evalされると,構文解析を実行する • 構文解析専用の命令を評価器に搭載 ◦

    terminal: 指定された文字列を読み取る ◦ choice: 与えられた構文解析ルールを順に試す ◦ etc. 22
  12. 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