コンパイラ作成(106) バグ修正

バグ

エラー処理周りのチェックをしていてバグを見つけたよ。

// 配列
int main()
{
    double a[10], *p = a;
    a[0) = 42;
    a[1] = 55;
    printf("*p = %f\n", *p);
}

配列の閉じ括弧が間違ってる場合。エラーにならずにコンパイル通っちゃってたよ。

read_el
  # 式の最後までのトークンを読み込む
  #   返り値
  #     el   : expression's token list
  #     kind : 処理しなかったトークン(セミコロンもしくは閉じ括弧)
  #     str  : 処理しなかったトークン(セミコロンもしくは閉じ括弧)
  def read_el(fkind,fstr,skind,sstr)
    el = []
    if fkind == TK::ID && sstr == "(" then
      # 関数呼出の処理
      sel = []
      sel << Token.new(fkind,fstr)
      sel << Token.new(skind,"()")
      skind, sstr = @lex.gettoken
      loop do
        if skind == TK::SYMBOL && sstr == ")" then break end
        fkind, fstr = skind, sstr
        skind, sstr = @lex.gettoken
        pel, skind, sstr = read_modify_el fkind, fstr, skind, sstr
        sel << pel
        if skind == TK::SYMBOL && sstr == "," then
          skind, sstr = @lex.gettoken
        elsif skind != TK::SYMBOL || sstr != ")" then
          perror
        end
      end
      el << sel
      if skind != TK::SYMBOL || sstr != ")" then perror end
      skind, sstr = @lex.gettoken
    elsif fstr == "(" then
      # 括弧の処理
      fkind, fstr = skind, sstr
      skind, sstr = @lex.gettoken
      sel, skind, sstr = read_el fkind, fstr, skind, sstr
      el << sel
      skind, sstr = @lex.gettoken
    elsif sstr == "[" then
      # 配列の処理
      el << Token.new(fkind,fstr)
      el << Token.new(skind,"[]")
      fkind, fstr = @lex.gettoken
      skind, sstr = @lex.gettoken
      sel, skind, sstr = read_el fkind, fstr, skind, sstr
      if sel.size > 1 then
        el << sel
      else
        el << sel[0]
      end
      if skind != TK::SYMBOL || sstr != "]" then perror "expected ']'" end
      skind, sstr = @lex.gettoken
    else
      el << Token.new(fkind,fstr)
    end
    loop do
      if skind == TK::EOF then break end
      if sstr == ";" then break end
      if sstr == ")" then break end
      if sstr == "]" then break end
      if sstr == "," then break end
      if sstr == "}" then break end
      fkind, fstr = skind, sstr
      skind, sstr = @lex.gettoken
      if fkind == TK::ID && sstr == "(" then
        # 関数呼出の処理
        sel = []
        sel << Token.new(fkind,fstr)
        sel << Token.new(skind,"()")
        skind, sstr = @lex.gettoken
        loop do
          if skind == TK::SYMBOL && sstr == ")" then break end
          fkind, fstr = skind, sstr
          skind, sstr = @lex.gettoken
          pel, skind, sstr = read_el fkind, fstr, skind, sstr
          sel << pel
          if skind == TK::SYMBOL && sstr == "," then
            skind, sstr = @lex.gettoken
          elsif skind != TK::SYMBOL || sstr != ")" then
            perror
          end
        end
        el << sel
        if skind != TK::SYMBOL || sstr != ")" then perror end
        skind, sstr = @lex.gettoken
      elsif fstr == "(" then
        # 括弧の処理
        fkind, fstr = skind, sstr
        skind, sstr = @lex.gettoken
        sel, skind, sstr = read_el fkind, fstr, skind, sstr
        el << sel
        skind, sstr = @lex.gettoken
      elsif sstr == "[" then
        # 配列の処理
        el << Token.new(fkind,fstr)
        el << Token.new(skind,"[]")
        fkind, fstr = @lex.gettoken
        skind, sstr = @lex.gettoken
        sel, skind, sstr = read_el fkind, fstr, skind, sstr
        if sel.size > 1 then
          el << sel
        else
          el << sel[0]
        end
        if skind != TK::SYMBOL || sstr != "]" then perror "expected ']'" end
        skind, sstr = @lex.gettoken
      else
        el << Token.new(fkind,fstr)
      end
    end
    return el, skind, sstr
  end

チェックが抜けてたよ。

動作テスト
~/myc$ myc err50.myc
err50.myc:5:8 error: expected ']'
~/myc$

ちゃんとエラーになったよ。次回なにやろうかな。うーん駄目だ。もう頭が働かなくなってる。明日起きてから考えよう。