[javascript]spreadsheet4 デバッグ

再帰しまくりなパーサ・コンピネータのデバッグは、ぐるぐると動き回るパーサがEBNFのどの辺を処理しようとしているのかはテキスト(target)と読取り位置(position)で把握できるけど、スタックコールにはsequenceやmapぐらいしか見えないから、非終端記号(EBNFの左辺の識別子(名前))レベルでパーサのネストの進行状態をイメージするのは難しい。

強固な防壁魔法の呪文を観て分析し解除するのに似ている。

平たく言えば、スタックコールのsequenceやmapの組み合わせを観て、虫を刈り取るイメージができるかどうかにかかっている。

大体、groupやoptionの配下にもchoiceやsequenceがダラダラと入り込むのでイメージするのは容易ではないから、サクサクと進む訳も無く、瞑想に頼るしかない。

そろそろ、そんな状況もかったるいので、

非終端記号はParser.map()(パラメータのsequence処理が成功したらコールバックを呼ぶパーサ)をよく使うのでmapのパラメータに非終端記号名を追加し、解析時にスタックし、mapのパース処理後に処理結果と非終端記号のネスト具合をログに書き出す様にセル手入力直後のパースにログを入れてみた。

async closeEntry(fSave = true) {
・・・
_exprParser.map.DEBUG = true;
const parseResult = _exprParser.parse(text);
_exprParser.map.DEBUG = false;
・・・
}
["expr_cell","logical_expr","add_sub_expr","mul_div_expr","number"]: x
["expr_cell","logical_expr","add_sub_expr","mul_div_expr","boolean"]: x
["expr_cell","logical_expr","add_sub_expr","mul_div_expr","function_def","symbol"]: ["B","1"]
["expr_cell","logical_expr","add_sub_expr","mul_div_expr","function_def"]: x
["expr_cell","logical_expr","add_sub_expr","mul_div_expr","a1_range","a1"]: ["B","1"]
["expr_cell","logical_expr","add_sub_expr","mul_div_expr","a1_range"]: x
["expr_cell","logical_expr","add_sub_expr","mul_div_expr","a1"]: ["B","1"]
["expr_cell","logical_expr","add_sub_expr","mul_div_expr"]: [{"type":"a1","address":[{"row":1,"col":2}]},[]]
["expr_cell","logical_expr","add_sub_expr"]: [{"type":"a1","address":[{"row":1,"col":2}]},[]]
["expr_cell","logical_expr"]: [{"type":"a1","address":[{"row":1,"col":2}]},null]
["expr_cell"]: ["=",{"type":"a1","address":[{"row":1,"col":2}]}]

順に見ていくと、

  • number、booleanと失敗し
  • function_def.symbolで B1 を判定したものの、
    • 多分、「(…)」が無いので、function_defを諦め、
  • a1_range.a1でB1を再度判定したものの、
    • 多分、「:」が無いのでa1_range諦め、
  • a1で渋々納得し、
  • パーサのネストを駆け戻り、
  • mul_div_expr、add_sub_expr、logical_expr、expr_cellを経て、
  • [“=”,{“type”:”a1″,”address”:[{“row”:1,”col”:2}]}]を得ている。

と大雑把に動きが見えるようになった。

しかし、多分、「xx」が無い、部分はまだ推測するしかないのでtokenやregexpパーサにも解析ログを付けたら、エラーチェック実装時に「「xx」が来ると予想されたxxx文字目に「yy」がありました。」とか出せそうな気がしたけど、

["expr_cell","o: '=","logical_expr","add_sub_expr","mul_div_expr","number","x: '[-]?([0-9]+)([.][0-9]*)?'"]: x
["expr_cell","o: '=","logical_expr","add_sub_expr","mul_div_expr","boolean","x: 'true'","x: 'false'"]: x
["expr_cell","o: '=","logical_expr","add_sub_expr","mul_div_expr","function_def","symbol","o: 'B1"]: ["B","1"]
["expr_cell","o: '=","logical_expr","add_sub_expr","mul_div_expr","function_def","x: '('"]: x
["expr_cell","o: '=","logical_expr","add_sub_expr","mul_div_expr","a1_range","a1","o: 'B1"]: ["B","1"]
["expr_cell","o: '=","logical_expr","add_sub_expr","mul_div_expr","a1_range","x: ':'"]: x
["expr_cell","o: '=","logical_expr","add_sub_expr","mul_div_expr","a1","o: 'B1"]: ["B","1"]
["expr_cell","o: '=","logical_expr","add_sub_expr","mul_div_expr","x: '*', '/'"]: [{"type":"a1","address":[{"row":1,"col":2}]},[]]
["expr_cell","o: '=","logical_expr","add_sub_expr","x: '+', '-', '&'"]: [{"type":"a1","address":[{"row":1,"col":2}]},[]]
["expr_cell","o: '=","logical_expr","x: '=', '>', '<', '>=', '<=', '<>'"]: [{"type":"a1","address":[{"row":1,"col":2}]},null]
["expr_cell","o: '="]: ["=",{"type":"a1","address":[{"row":1,"col":2}]}]

「x:’(’」 は良い感じだけど、非終端識別子の終わりにx:がいっぱい付いているのは・・・

あった方が良い様な、最後のxだけで良い様な、微妙な感じ。

先は長いなぁ~




コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA