プログラミング言語の作り方

javascript/C言語/アセンブラを用い、 字句解析、構文解析、インタプリタ、コンパイラのプログラムをスクラッチから作りながら、 「プログラミング言語の作り方」を解説する。

関数呼び出し対応
javascript版プログラミング言語の作り方(インタプリタ開発)

print文専用の構文解析をやめ、汎用的な関数呼び出しの構文解析に対応する。

ページメニュー

関数呼び出しの構文解析funccallに対応する。 また、どれにも該当しない場合、そのままの値を返すvalue関数を作成。

parser.jsの実装

funccallもsemi関数と同じ構造にすることで汎用化する。 ただし、関数呼び出し特有のカッコの部分は異なる。

left側の呼び出しは、valueだが、 right側の呼び出しは、カッコの中なので、心機一転、semiから新しい構文解析を始める

$ cat parser.js
//---------------構文解析---------------//
module.exports = parser;
var {expect,accept,show,error}  = require("./utils.js");
var tokens;

//構文解析開始
function parser(t){
    tokens = t;
    var ast = semi();
    if(tokens.length>0){
        show("ast=",ast);
        show("処理後tokens =",tokens);
        error("tokensが余っているので、どこかおかしいので終了");
    }
    return ast;
}


//その他は値としてそのまま返す
function value(){
    if(tokens.length ==0) return;
    //そのまま返す
    return tokens.shift();
}

//関数呼び出し
function funccall(){
    //関数名を取得
    var left = value();

    //関数呼び出しのカッコ
    var op;
    while(op = accept(tokens,"(")){
        //ここはvalueではなく、semiであることに注意
        //カッコの中は心機一転、新しい構文解析を始める
        (@var right = semi();@)

        //閉じカッコであることを確認して取得
        (@op += expect(tokens,")");@)

        //新しいノードを作成し階層を深める
        left = {left,op,right};
    }
    return left;
}



//セミコロン=複数文
function semi(){
    //左辺を取得
    var left = funccall();

    //演算子が続く間は連続する
    var op;
    while(op = accept(tokens,";")){
        //右辺を取得
        var right = funccall();

        //新しいノードを作成し階層を深める
        left = {left,op,right};
    }
    return left;
}

インタプリタの実行

parserの処理を汎用的に変えたが、結果は同じだ。

$ ./interpretor.js
tokens =[
  'print',          '(',
  '"hello world"',  ')',
  ';',              'print',
  '(',              '"hello world2"',
  ')',              ';',
  'print',          '(',
  '"hello world3"', ')',
  ';'
]
ast={
  left: {
    left: {
      left: { left: 'print', op: '()', right: 'hello world' },
      op: ';',
      right: { left: 'print', op: '()', right: 'hello world2' }
    },
    op: ';',
    right: { left: 'print', op: '()', right: 'hello world3' }
  },
  op: ';',
  right: undefined
}
hello world
hello world2
hello world3

このページの目次へ戻るサイトの最上位へ戻る