ちょっぱやで、新しいプログラミング言語を作る
概要
正確性を捨てて、ちょっぱやで言語を作る話。
改行で区切って、何の文かを正規表現で判定&キャプチャするだけ。
キャプチャした文字列をまた更に判定にかけて……と再帰させておしまい。ちょっぱや!
本題
ソースコードを改行で区切って文字列の配列にします。
各行に正規表現を使って、if 文になのか、for 文になのか、関数呼び出しなのか、などを判定します。
判定するついでにキャプチャもしておきます。
code: js
result = /if(.*)then(.*)end/.exec('if true then alert("true") end')
// 頭の要素はいらないので捨てる
result.shift()
// 余白を取り除く
result = result.map(i => i.trim())
// 条件式などが取れる
console.log(result) // => "true", "alert(\"true\")"
// まだ処理は続く ...
上記の例は if 文を解析する parseIf 関数の一部分です。
こういった関数を構文ごとに作っていきます。
それぞれの構文を解析する関数を束ねた parse 関数を作ります。
code:js
function parse(line){
let result;
// if 文の解析
result = parseIf(line);
if(result) return result;
// for 文の解析
result = parseFor(line);
if(result) return result;
// リテラルの解析
result = parseLiteral(line);
if(result) return result;
// ...
throw new Error("構文エラー : どの文にも一致しませんでした。");
}
そして parseIf 関数の続きに戻ります。
code: js
// 正規表現を使って、条件式などを取得できていました。
console.log(result) // => "true", "alert(\"true\")"
// 条件式を parse 関数で解析して、実際のデータを入手します。
let value = parse(result0)
// 実際のデータで条件分岐し、
if(value){
// 残りを解析&実行します。
return parse(result1)
}
といった感じで再帰していくことで解析&実行していきます。
最終的にはリテラル解析や、変数の呼び出し解析などが呼ばれ、データが取得され、それを使って条件を判定することになります。
できないこと
if 文などの途中に改行を入れること
改行で区切りを入れて判定してるので、判定できなくなる
制御文を入れ子すること
if 文の中に if 文を書けない
正規表現のキャプチャだと限界
文字列の中に else などがあっても無視できない
その他、色々……
まとめ
これで "ちょっぱや" で言語を作ることができると思います。どんどん軽率に言語を作っていきましょう!
ちなみに本気でプログラミング言語を作る場合は、今回の方法はあんまり参考にならないと思います。色々方法はありますが代表的には、字句解析して、構文解析して、AST 作って……など工程が違うのでご注意ください。
余談:にほんごプログラミング
そもそも今回紹介した方法は「ゆる言語学ラジオ」を聞き、格助詞に感動してプログラミング言語を作ってる途中で編み出したものです。ガチで実用的な言語を作るというより、とにかく格助詞を活用したくて作ったので「できないこと」が多いです。
おしまい!