Help us understand the problem. What is going on with this article?

005 - Blocklyを使ったオリジナルVisual Programming Editorを作ってみる : C言語を出力するには

More than 3 years have passed since last update.

今回の目標

前回、JavaScriptのソースコードを出力するところまではできました。今回はJavaScriptでもPythonでもDartでもない、C言語を出力してみたいと思います。

CのGeneratorを作成する

いままでの作業でだいたいこの辺りを作成すれば動きそうな気配がしています。

  • /blockly/generators に出力したい言語に対応したgeneratorを実装
  • /blockly/generators/c/ に各ブロックに対応したgeneratorを実装

恐らくこれでいけるはず。まずは雑に必要なファイルを用意してみます。

  1. "/blockly/generators/c/"というディレクトリを作り、その中に"/blockly/generators/javascript/" 内のファイルをコピーします。

  2. "/blockly/generators/javascript.js" のコピーを作り、c.jsという名前にリネームします。

まずは1でコピーしたファイルを開き、"JavaScript"という文字列を"C"にリプレースします。例えば/blockly/generators/c/colour.jsであれば

'use strict';

goog.provide('Blockly.C.colour');

goog.require('Blockly.C');


Blockly.C['colour_picker'] = function(block) {
  // Colour picker.
  var code = '\'' + block.getFieldValue('COLOUR') + '\'';
  return [code, Blockly.C.ORDER_ATOMIC];
};

// 以下略

といった具合です。また、"/blockly/generators/c.js"においても同様の事を行います。
本当はこの生成処理をC言語の文法に合わせて書き直す必要がありますが、今はそのままにして先へ進みます。この自作ジェネレーターが実行されているか確かめるために最後の戻り値をいじってみます。(こんなことしなくてもブレーク貼って確かめればいいんですがね…)

// 自分がいじった時は199行目でした
Blockly.C.scrub_ = function(block, code) {
  var commentCode = '';
  // Only collect comments for blocks that aren't inline.
  if (!block.outputConnection || !block.outputConnection.targetConnection) {
    // Collect comment for this block.
    var comment = block.getCommentText();
    if (comment) {
      commentCode += Blockly.C.prefixLines(comment, '// ') + '\n';
    }
    // Collect comments for all value arguments.
    // Don't collect comments for nested statements.
    for (var x = 0; x < block.inputList.length; x++) {
      if (block.inputList[x].type == Blockly.INPUT_VALUE) {
        var childBlock = block.inputList[x].connection.targetBlock();
        if (childBlock) {
          var comment = Blockly.C.allNestedComments(childBlock);
          if (comment) {
            commentCode += Blockly.C.prefixLines(comment, '# ');
          }
        }
      }
    }
  }
  var nextBlock = block.nextConnection && block.nextConnection.targetBlock();
  var nextCode = Blockly.C.blockToCode(nextBlock);
  // ここに適当なコメントを入れてみる
  return '// Cジェネレーターから出力\n' + commentCode + code + nextCode;
};

ここまで来たらビルド…なんですが、このままだとビルドターゲットに今回追加されたファイルが含まれていません。なので、"/blockly/build.py"を編集します。155行目あたりにrunという関数があるので、そこに"c"を追加します。ここに登録されているファイルとディレクトリがビルド対象となるようです。

def run(self):
    self.gen_core()
    self.gen_blocks()
    self.gen_generator('javascript')
    self.gen_generator('python')
    self.gen_generator('dart')
    self.gen_generator('c')

さあ、ここまで来たらビルドしてみます。

python /blockly/build.py

正常に終了すれば"/blockly/c_compressed.js"というファイルができているはずです。これをindex.htmlで読み込んでCのソースコード(今はJavaScriptが出力されますが…)を出力してみましよう。

<script src="blockly/c_compressed.js"></script>

中略

<script>
    function ShowCodeRealTime(e)
    {
      //var code = Blockly.JavaScript.workspaceToCode(workspace);
      var code = Blockly.C.workspaceToCode(workspace);
      document.getElementById('outputArea').value = code;
    }
</script>

こんな感じです。今回は出力されたコードを'outputArea'というidを割り当てたTextAreaに表示させるようにしてみました。では、index.htmlをブラウザ開いてみましよう。これでTextAreaにCのジェネレーターから出力されたコードが表示されます。"// Cジェネレーターから出力"というコメントが出力されていれば成功です。

まとめ

ひとまずこれでジェネレータ開発の環境が整いました。あとは"/blockly/generators/c.js"を編集し、予約語の登録、演算子の優先順位をC言語向けに修正。"/blockly/generators/c/*.js"もC言語を出力するように修正することで"Blockly for C"が出来上がると思います。みなさんも標準で実装されていない言語を出力できるBlocklyを作ってみてください。現在、C言語用は社内向けに機能を絞って作成しております。

heyhachi
都内で働く人。 業種的には組み込み系寄りだが、ハードを叩くコードを書いたりすることはそんなにない。 基本的に業務はC言語で行うが、広く浅く色々とちょっかいを出す浮気症。 酒と写真が好き。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした