コンパイラ作成(88) 式のエラーチェック
今回の目標
double型関連にちょっと疲れたんで別の事やるよ。壊れてる式をチェックしてエラーに。
// 壊れてる式 int main() { 1 + ; }
// 壊れてる式 int main() { + ; }
// 壊れてる式 int main() { / ; }
// 壊れてる式 int main() { int i; i++; }
ちょっとづつ違う4パターン。最後のはC言語としては正しいんだけど、mycはまだインクリメント演算子をサポートしてないんでエラー。
modify_el_unaryop
# elの変形(単行演算子の処理) # [-, 2, +, 3] # =>[[-, 2], + 3] # [-, 2, +, -, 3] # =>[[-, 2], + [-, 3]] def modify_el_unaryop(el, opl) mel = [] prev = nil loop do if el.size == 0 then break end x = el.shift if ((prev == nil) || (!prev.kind_of?(Array) && (prev.kind == TK::SYMBOL))) \ && !x.kind_of?(Array) && x.kind == TK::SYMBOL then if opl.include? x.str then tel = [] tel << x if el == [] then perror "broken expression" end x = el.shift if x.kind_of?(Array) then x = modify_el_unaryop x, opl elsif opl.include? x.str then sel = [] loop do sel << x if !opl.include? x.str then break end if el.size == 0 then break end x = el.shift end x = modify_el_unaryop sel, opl if x.size == 1 && x[0].kind_of?(Array) then x = x[0] end end tel << x mel << tel prev = tel else perror "broken expression" end else if x.kind_of?(Array) then x = modify_el_unaryop x, opl end mel << x prev = x end end return mel end
codegen_el
# 式のコード生成 def codegen_el(el) type = "int" if !el[0].kind_of?(Array) && el[0].kind == TK::SYMBOL type = codegen_unaryop el[0], [el[1]] elsif (el.size > 1) && el[1].str == "=" then type = codegen_assign el else type = codegen_elf el.shift loop do if el == [] then break end op = el.shift operand = el.shift if operand == nil then perror "broken expression" end type = codegen_els op, operand, type end end return type end
動作テスト
4つ纏めて行くよ。
~/myc$ myc err38.myc err38.myc:4:8 error: broken expression ~/myc$ myc err39.myc err39.myc:4:7 error: broken expression ~/myc$ myc err40.myc err40.myc:4:7 error: broken expression ~/myc$ myc err41.myc err41.myc:5:8 error: broken expression ~/myc$
みんなエラーになったよ。今回はこの4件をチェックしたけど、まだまだ漏れてるのあるだろうなあ。代入演算子、アドレス演算子、参照演算子がらみのチェックは不十分だよなあ。次回もエラーチェックかな。