Skip to content

Instantly share code, notes, and snippets.

@kujirahand
Last active August 9, 2022 10:49
Show Gist options
  • Save kujirahand/d382d5cc929215e8901cee19cf50c37d to your computer and use it in GitHub Desktop.
Save kujirahand/d382d5cc929215e8901cee19cf50c37d to your computer and use it in GitHub Desktop.
セキュリティキャンプ2022 - プログラミング言語の開発 - 演習資料

演習リスト [N4,N12] プログラミング言語を自作しよう

  • 2022年8月9日(火)13:30~15:30
  • 2022年8月11日(木)13:30~15:30

演習の準備

  • Node.jsが動く環境を用意しておく
  • リポジトリがダウンロードできるよう、Gitをインストールしておく

第1部 いろいろなプログラミング言語

  • 【演習1】理想のプログラミング言語の企画書を書いてみよう (資料なし)

第2部 最速でプログラミング言語を作ってみよう

【演習2】RPN電卓を作ろう

製作のヒント

下記のヒントを見ないで作ることを推奨するが、見ても問題ない。

  • (1) 文字列を空白でトークンに区切る
  • (2) トークンを1つ読む
  • (3) 数値なら、スタックに積む
  • (4) 演算子なら、スタックから2つ値を取り出して計算してスタックに積む
  • (5) トークンが空でなければ(2)に戻る

【演習3】簡易スタック言語の開発

演習2で作ったRPN電卓を簡易スタック言語に改良しよう! 以下の命令を実装すること。

  • 変数の代入 --- (値) (変数名) set
  • 変数の取得 --- (変数名) get
  • 変数の取得(簡易記法) --- %(変数名)
  • 画面表示 --- (値) print

【演習4】altJS化してみよう

  • 演習3で作ったスタック言語を altJS にして、ブラウザで動くようにする
  • 生成したJavaScriptが見える形で出力しよう

第3部 なでしこを改良してみよう

【演習5】なでしこに電卓機能を追加しよう

なでしこのソースコードをダウンロード。

$ git clone --recursive https://github.com/kujirahand/nadesiko3.git
$ cd nadesiko3
$ npm install

TypeScriptのソースコードをJavaScriptに変換しつつ、WebPackでソースコードを1つにまとめる方法。

# コンパイル
$ npm run build:webpack

# ブラウザ上でなでしこを実行
$ npm start

例えば以下のプログラムが動くように、「RPN計算」命令を追加してみよう!

「30 50 * 5 +」をRPN計算して表示。

【演習5オマケ】作ったライブラリをパッケージマネージャーで世界中に公開

JavaScriptのパッケージマネージャーnpmでプロジェクトを作成。

# プロジェクトの作成
$ mkdir nadesiko3-fuga && cd nadesiko3-fuga
$ npm -f init 
$ npm install nadesiko3 --save-dev

# プロジェクトの公開
$ npm publish

【演習6】なでしこにインクリメント演算子を実装しよう

【手順1】字句解析器に手を加える

$ vim core/src/nako_lex_rule.mts 

上記に以下のコードを追加。

{ name: ‘incNum’, pattern: /\+\+/ },

【手順2】構文解析にルールを追加

$ vim core/src/nako_parser3.mts

メソッド ySentence に以下のコードを追加。 これは、構文木にincNumというコードを追加するもの。

if (this.accept(['word', 'incNum'])) {
    return {
        type:'incNum', 
        name: this.getVarNameRef(this.y[0]).value, 
        ... this.peekSourceMap()
    }
}

【手順3】コード生成を修正

$ vim core/src/nako_gen.mts 

メソッド _convGen ()のswitch文にコード生成処理を追加

case 'incNum': code += this.genVar(node.name as string, node) + '++;'; break;

最後にビルドしてインクリメント演算子が実装できたか確認してみよう。

$ npm run build:webpack
$ npm start

第4部 自作言語を自作してみよう

【演習7】peg 四則演算の定義

# PEGパーサのインストール
$ npm install -g pegjs

# プログラムを作る
$ touch sisoku.pegjs

# コンパイル
# pegjs sisoku.pegjs
start = add

add = left:mul "+" right:add { return left + right; }
    / left:mul "-" right:add { return left - right; }
    / mul

mul = left:val "*" right:mul { return left * right; }
    / left:val "/" right:mul { return left / right; }
    / left:val "%" right:mul { return left % right; }
    / val

val = _ "(" _ expr:add _ ")" _ { return expr }
     / _ nums:[0-9]+ _ { return parseInt(nums.join('')); }
 
_ "whitespace" = [\s\n ]*

【演習8】 peg 変数とPRINT文を実装

PEGで変数機能とPRINT構文を実装してみよう。

  • PRINT (式)
  • 変数 = 式
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment