[プログラミング言語の作り方] 符号処理を実装

言語仕様
– 文字列
– 整数123, 実数123.4
– グローバル変数、変数の値の参照
– 代入演算子(=)
– print関数でカンマ区切りで複数の引数指定
– 複数文は、セミコロンで区切る
– // から行末まではコメント
– 足し算、引き算
– 掛け算、割り算
– 符号

### source.3

a = -2 * 3;
print("a = -2 * 3 = ", a);

b = -2 * -3;
print("b = -2 * -3 = ", b);

### parser.js
単項の符号に対応するため、flagを追加。右結合なので、リセットでcommaであること、単項であるため、左辺読まずに最後のreturnでfunccallを呼ぶ

function flag(){

    var op;
    while(op = accept(tokens,"+","-")){

        var right = comma();

        if(op == "+") return right;

        return {left:{left:"0", op:"-",right:"1"}, op:"*",right};
    }
    return funccall();
}

$ node interpretor.js
token =[
‘a’, ‘=’,
‘-‘, ‘2’,
‘*’, ‘3’,
‘;’, ‘print’,
‘(‘, ‘”a = -2 * 3 = “‘,
‘,’, ‘a’,
‘)’, ‘;’,
‘b’, ‘=’,
‘-‘, ‘2’,
‘*’, ‘-‘,
‘3’, ‘;’,
‘print’, ‘(‘,
‘”b = -2 * -3 = “‘, ‘,’,
‘b’, ‘)’,
‘;’
]
ast={
left: {
left: {
left: {
left: {
left: ‘a’,
op: ‘=’,
right: {
left: { left: ‘0’, op: ‘-‘, right: ‘1’ },
op: ‘*’,
right: { left: ‘2’, op: ‘*’, right: ‘3’ }
}
},
op: ‘;’,
right: {
left: ‘print’,
op: ‘()’,
right: { left: ‘”a = -2 * 3 = “‘, op: ‘,’, right: ‘a’ }
}
},
op: ‘;’,
right: {
left: ‘b’,
op: ‘=’,
right: {
left: { left: ‘0’, op: ‘-‘, right: ‘1’ },
op: ‘*’,
right: {
left: ‘2’,
op: ‘*’,
right: {
left: { left: ‘0’, op: ‘-‘, right: ‘1’ },
op: ‘*’,
right: ‘3’
}
}
}
}
},
op: ‘;’,
right: {
left: ‘print’,
op: ‘()’,
right: { left: ‘”b = -2 * -3 = “‘, op: ‘,’, right: ‘b’ }
}
},
op: ‘;’,
right: undefined
}
a = -2 * 3 = -6
b = -2 * -3 = 6

余白の有無関係なしに”-“をopとして解釈してしまうから、加算、引き算の後に、符号の処理をするのね
return {left:{left:”0″, op:”-“,right:”1″}, op:”*”,right};とすることで、-3がASTでは以下のように -1 * 3 と表される

right: {
left: { left: ‘0’, op: ‘-‘, right: ‘1’ },
op: ‘*’,
right: ‘3’
}