Exemple #1
0
void sys_fncCall(TknKind kd) /* 組込関数呼出 */
{
  int fnc_typ = 0;
  char *form;

  token = chk_nextTkn(nextTkn(), '(');                            /* ( のはず */
  switch (kd) {
  case Exit: fnc_typ = EXIT_F; expression(); break;
  case Input: fnc_typ = INPUT_F; break;
  case Printf:
    if (token.kind != String)
      err_s("printfの第1引数が不正");                           /* 書式がない */
    gencode2(LDI, token.intVal);                        /* 文字列アドレス取得 */
    form = mem_adrs(token.intVal);                                    /* 書式 */
    token = nextTkn();
    if (token.kind != ',')
      fnc_typ = PRINTF1_F;                                   /* 引数1個タイプ */
    else {
      fnc_typ = PRINTF2_F;                                   /* 引数2個タイプ */
      token = nextTkn(); expression();                         /* 第2引数評価 */
      if (token.kind == ',')
        err_s("printfの引数は2個までです。");                   /* 引数が多い */
      if (!good_format(form))                         /* 安全のために書式確認 */
        err_s("printfの書式が不正");
    }
    break;
  }
  token = chk_nextTkn(token, ')');                                /* ) のはず */
  gencode2(LIB, fnc_typ);
}
Exemple #2
0
int compile(char *fname) /* コンパイル */
{
  initChTyp();                                                    /* 文字種表 */
  gencode2(CALL, -1);                         /* main関数呼出。番地-1は仮設定 */
  gencode1(STOP);                                           /* プログラム終了 */

  fileOpen(fname);
  token = nextTkn();
  while (token.kind != EofTkn) {
    switch (token.kind) {
    case Int: case Void:                                        /* 変数か関数 */
      set_type(); set_name();                             /* 型名と名前を格納 */
      if (token.kind == '(') fncDecl(); else varDecl();      /* 関数,変数宣言 */
      break;
    case Semicolon:
      token = nextTkn();                                      /* 何もせず次へ */
      break;
    default:
      err_ss("構文エラー", token.text);
      token = nextTkn();
    }
  }
  if (err_ct == 0) backPatch_callAdrs();            /* 関数呼出未定番地を後埋 */
  *INT_P(mem_adrs(0)) = mallocG(0);            /* 静的領域サイズを0番地に格納 */

  if (err_ct > 0) fprintf(stderr, "%d個のエラーが発生しました。\n", err_ct);
  return err_ct == 0;                                     /* エラーなしなら真 */
}
Exemple #3
0
void fncDecl(void) /* 関数宣言 */
{
  SymTbl *f1;

  localAdrs = START_LocalAdrs;                /* 局所領域割付けカウンタ初期化 */
  f1 = search_name(tmpTb.name);
  if (f1!=NULL && f1->nmKind!=fncId && f1->nmKind!=protId) {
    err_ss("識別子が重複している", f1->name); f1 = NULL;
  }

  fncPt = enter(tmpTb, fncId);                                /* 記号表に登録 */
  token = nextTkn();
  localTBL_open();                                      /* 局所用記号表を用意 */

  switch (token.kind) {                                           /* 引数処理 */
  case Void: token = nextTkn(); break;                         /* 引数 (void) */
  case ')':  break;                                            /* 引数なし () */
  default:                                                        /* 引数あり */
    for (;;) {
      set_type(); set_name(); enter(tmpTb, paraId);               /* 引数登録 */
      ++(fncPt->args);                                        /* 引数個数を+1 */
      if (token.kind != ',') break;                               /* 宣言終了 */
      token = nextTkn();                                          /* 次の引数 */
    }
  }
  token = chk_nextTkn(token, ')');                               /* ')'のはず */

  if (token.kind == ';') fncPt->nmKind = protId;          /* 関数プロトタイプ */
  set_adrs(fncPt);                          /* 関数入口番地と引数アドレス設定 */
  if (f1 != NULL) fncChk(f1, fncPt);                    /* 関数の正しさを確認 */

  switch (token.kind) {
  case ';': token = nextTkn(); break;                         /* プロトタイプ */
  case '{':
    if (IS_MAIN(fncPt)) set_main();                           /* main関数処理 */
    fncDecl_begin();                                          /* 関数入口処理 */
    block(1);                                                 /* 関数本体処理 */
    fncDecl_end();                                            /* 関数出口処理 */
    break;
  default:  err_s("関数の ; または { がない"); exit(1);
  }
  localTBL_close(fncPt);                                /* 局所用記号表を解消 */
  del_fncTable(f1, fncPt);                                /* 重複登録なら解消 */
  fncPt = NULL;                                               /* 関数処理終了 */
}
Exemple #4
0
/* tk.kind==kdなら次のトークンを返す。異なるときはそのままtkを返す */
Token chk_nextTkn(Token tk, TknKind kd) /* 確認付トークン取得 */
{
  char ss[100];
  if (tk.kind == kd) return nextTkn();
  else {
    sprintf(ss, "%s の前に %c がありません", tk.text, kd); err_s(ss);
    return tk;                                                    /* 不一致時 */
  }
}
Exemple #5
0
void expression(void) /* 式処理 */
{
  term(2);
  if (token.kind == '=') {
    to_leftVal();                                             /* 左辺値にする */
    token = nextTkn(); expression();
    gencode1(ASSV);                                     /* 代入する(式値設定) */
  }
}
Exemple #6
0
void block(int is_func) /* {}内の処理 */
{
  TknKind kd = Others;

  token = nextTkn();
  ++blkNest;
  if (is_func) {                              /* 関数ブロックなら変数宣言処理 */
    while (token.kind == Int) { set_type(); set_name(); varDecl(); }
  }

  while (token.kind != '}') {                                     /* 文を処理 */
    kd = token.kind; statement();
  }
  last_statement = kd;                    /* 関数末尾のreturn有無確認に用いる */

  --blkNest;
  token = nextTkn();
}
Exemple #7
0
void varDecl(void) /* 変数宣言 */
{
  for (;;) {
    set_aryLen();                                         /* 配列なら長さ設定 */
    enter(tmpTb, varId);                          /* 変数登録(アドレスも設定) */
    if (token.kind != ',') break;                                 /* 宣言終了 */
    token = nextTkn(); set_name();                              /* 次の変数名 */
  }
  token = chk_nextTkn(token, ';');                               /* ';'のはず */
}
Exemple #8
0
void set_name(void) /* 名前設定 */
{
  if (token.kind == Ident) {
    tmpTb.name = s_malloc(token.text);                            /* 名前設定 */
    token = nextTkn();
  } else {
    err_ss("記述が不適切", token.text);
    tmpTb.name = "tmp$name1";                       /* ありえない名前を仮設定 */
  }
}
Exemple #9
0
void fncCall(SymTbl *fp) /* 関数呼出 */
{
  int  argCt = 0;

  token = chk_nextTkn(nextTkn(), '(');                            /* ( のはず */
  if (token.kind != ')') {                                      /* 引数がある */
    for (;;) {
      expression();                                           /* 引数式の処理 */
      ++argCt;                                                    /* 引数個数 */
      if (token.kind != ',') break;                       /* , なら引数が続く */
      token = nextTkn();
    }
  }
  token = chk_nextTkn(token, ')');                                /* ) のはず */

  if (argCt != fp->args)                                  /* 引数個数チェック */
    err_ss("関数の引数個数が不一致", fp->name);
  gencode2(CALL, fp->adrs);                                       /* 関数呼出 */
}
Exemple #10
0
void set_type(void) /* 型設定 */
{
  tmpTb.aryLen = tmpTb.adrs = tmpTb.args = 0;               /* クリアしておく */
  tmpTb.level = blkNest;                                     /* 0:大域 1:局所 */
  switch (token.kind) {
  case Int:  tmpTb.dtTyp = INT_T;  break;
  case Void: tmpTb.dtTyp = VOID_T; break;
  default:   err_ss("型指定誤り", token.text);
             tmpTb.dtTyp = INT_T;                              /* Intとみなす */
  }
  token = nextTkn();
}
Exemple #11
0
void term(int n) /* 項関連処理。nは優先順位 */
{
  TknKind kd;

  if (n == 8) { factor(); return; }
  term(n+1);
  while (n == opOrder(token.kind)) {                /* 強さが同じ演算子が続く */
    kd = token.kind;
    token = nextTkn(); term(n+1);
    gencode_Binary(kd);                                         /* 二項演算子 */
  }
}
Exemple #12
0
void set_aryLen(void) /* 配列サイズ設定 */
{
  tmpTb.aryLen = 0;
  if (token.kind != '[') return;                                /* 配列でない */

  token = nextTkn();
  if (token.kind == ']') {                                        /* []である */
    err_s("添字指定がない");
    token = nextTkn(); tmpTb.aryLen = 1; return;         /* 1だったことにする */
  }
  get_const(NULL);                                            /* 定数判定準備 */
  expr_with_chk(0, ']');                                        /* 添字を取得 */
  if (get_const(&(tmpTb.aryLen))) {                             /* 定数式なら */
    if (tmpTb.aryLen <= 0) {
      tmpTb.aryLen = 1; err_s("不正な添字");             /* 1だったことにする */
    }
  } else {
    err_s("配列幅指定が整数定数式でない");
  }

  if (token.kind == '[') {
    err_ss("多次元配列は宣言できない", token.text);
  }
}
Exemple #13
0
void factor(void) /* 因子関連処理 */
{
  SymTbl *tp;
  TknKind kd = token.kind;

  switch (kd) {
  case Plus: case Minus: case Not: case Incre: case Decre:     /* + - ! ++ -- */
    token = nextTkn(); factor();
    if (kd==Incre || kd==Decre) to_leftVal();                 /* 左辺値にする */
    gencode_Unary(kd);                                        /* 単項命令生成 */
    break;
  case IntNum:                                                    /* 整数定数 */
    gencode2(LDI, token.intVal);
    token = nextTkn();
    break;
  case Lparen:                                                      /* ( 式 ) */
    expr_with_chk('(', ')');
    break;
  case Printf: case Input: case Exit:
    if (kd != Input)
      err_ss("void型関数が式の中で使われている", token.text);
    sys_fncCall(kd);                                          /* 組込関数呼出 */
    break;
  case Ident:                                                       /* 識別子 */
    tp = search(token.text);                                    /* 記号表位置 */
    switch (tp->nmKind) {
    case fncId: case protId:                                      /* 関数呼出 */
      if (tp->dtTyp == VOID_T)
        err_ss("void型関数が式の中で使われている", tp->name);
      fncCall(tp);                                                /* 関数呼出 */
      break;
    case varId: case paraId:                                          /* 変数 */
      if (tp->aryLen == 0) {                                      /* 単純変数 */
        gencode3(LOD, b_flg(tp), tp->adrs);
        token = nextTkn();
      } else {                                                        /* 配列 */
        token = nextTkn();
        if (token.kind == '[') {                                  /* []がある */
          gencode3(LDA, b_flg(tp), tp->adrs);               /* 配列名アドレス */
          expr_with_chk('[', ']');                              /* 添字を取得 */
          gencode2(LDI, INTSIZE);                              /* 1要素サイズ */
          gencode1(MUL);                                 /* 添字×1要素サイズ */
          gencode1(ADD);                          /* それを配列アドレスに加算 */
          gencode1(VAL);                                          /* 内容取出 */
        } else {                                                  /* []がない */
          err_s("添字指定がない");                              /* 処理は続行 */
        }
      }
      if (token.kind==Incre || token.kind==Decre) {                 /* 後置++ */
        to_leftVal();                           /* 左辺値(アドレス表現)にする */
        if (token.kind==Incre) {gencode1(INC); gencode2(LDI,1); gencode1(SUB);}
        else                   {gencode1(DEC); gencode2(LDI,1); gencode1(ADD);}
        token = nextTkn();
      }
      break;
    }
    break;
  default:
    err_ss("不正な記述", token.text);
  }
}
Exemple #14
0
/* この関数内のラベル処理(飛先処理)の明快さのために以下のマクロを使用する */
#define UPLABEL(pos)  pos=nextCodeCt()              /* 上ジャンプ用ラベル機能 */
#define JMP_UP(pos)   gencode2(JMP,pos)             /* JMPでUPLABELへ         */
#define JPT_UP(pos)   gencode2(JPT,pos)             /* JPTでUPLABELへ         */
#define JMP_DOWN(pos) pos=gencode2(JMP,0)           /* JMPでDWNLABELへ        */
#define JPF_DOWN(pos) pos=gencode2(JPF,0)           /* JPFでDWNLABELへ        */
#define DWNLABEL(pos) backPatch(pos,nextCodeCt())   /* 下ジャンプ用ラベル機能 */
void statement(void) /* 文の処理 */
{
  TknKind kd;
  SymTbl *tp;
  DtType ret_typ = fncPt->dtTyp;
  int i, val;
  int LB_TOP, LB_EXP2, LB_EXP3, LB_BODY, LB_ELSE, LB_END, LB_TBL;

  kd = token.kind;

  if (kd==While || kd==Do || kd==Switch) continue_break_begin(kd);
  switch (kd) {
  case Break:
    if (loopNest_ct == 0) err_s("不正なbreak");
    else {
      gencode2(JMP, NO_FIX_BREAK_ADRS);                     /* 該当末尾位置へ */
      loopNest[loopNest_ct].break_flg = TRUE;              /* breakありを記憶 */
    }
    token = chk_nextTkn(nextTkn(), ';');                          /* ; のはず */
    break;
  case Continue:
    gencode2(JMP, get_loopTop());                   /* ループ開始行へジャンプ */
    token = chk_nextTkn(nextTkn(), ';');                          /* ; のはず */
    break;
  case Case:
    token = nextTkn();
    get_const(NULL);                                          /* 定数判定準備 */
    expr_with_chk(0, ':');                                      /* [式]の処理 */
    if (!get_const(&val))      err_s("case式が定数式でない");
    else if (swchNest_ct == 0) err_s("対応するswitch文がない");
    else {
      for (i=swchNest[swchNest_ct].startCaseList; i<=caseList_ct; i++) {
        if (caseList[i].value == val) {
          err_s("case式の値が重複している"); break;
        }
      }
      incVar(&caseList_ct, CASE_SIZ, "case句が%d個を超えました。");
      caseList[caseList_ct].value = val;                        /* case値設定 */
      caseList[caseList_ct].adrs = nextCodeCt();              /* 対応番地設定 */
    }
    statement();                                                  /* 文の処理 */
    break;
  case Default:
    if (swchNest_ct == 0)
      err_s("対応するswitch文がない");
    else if (swchNest[swchNest_ct].def_adrs != -1)
      err_s("defaultが重複している");
    else
      swchNest[swchNest_ct].def_adrs = nextCodeCt();              /* 番地設定 */
    token = chk_nextTkn(nextTkn(), ':');                          /* : のはず */
    statement();                                                  /* 文の処理 */
    break;
  case For:
    /*[式1]*/
    token = chk_nextTkn(nextTkn(), '(');                          /* ( のはず */
    if (token.kind == ';')
      token = nextTkn();                                           /* 式1なし */
    else {
      expr_with_chk(0, ';');                                   /* [式1]の処理 */
      remove_val();                                               /* 式値不要 */
    }

    /*[式2]*/
    UPLABEL(LB_EXP2);                               /* ←┐                   */
    if (token.kind == ';') {                        /*   │式2なし            */
      gencode2(LDI, 1);                             /*   │真(1)にする        */
      token = nextTkn();                            /*   │                   */
    } else {                                        /*   │                   */
      expr_with_chk(0, ';');                        /*   │[式2]の処理        */
    }                                               /*   │                   */
    JPF_DOWN(LB_END);                               /* ─┼┐  false時        */
    JMP_DOWN(LB_BODY);                              /* ─┼┼┐true時         */
                                                    /*   │││               */
    /*[式3]*/                                       /*   │││               */
    continue_break_begin(kd);                       /*   │││               */
    UPLABEL(LB_EXP3);                               /* ←┼┼┼┐             */
    if (token.kind == ')')                          /*   ││││             */
      token = nextTkn();                            /*   ││││式3なし      */
    else {                                          /*   ││││             */
      expr_with_chk(0, ')');                        /*   ││││[式3]の処理  */
      remove_val();                                 /*   ││││式値不要     */
    }                                               /*   ││││             */
    JMP_UP(LB_EXP2);                                /* ─┘│││             */
                                                    /*     │││             */
    /*[本体]*/                                      /*     │││             */
    DWNLABEL(LB_BODY);                              /* ←─┼┘│             */
    statement();                                    /*     │  │[文]の処理   */
    JMP_UP(LB_EXP3);                                /* ──┼─┘繰り返し     */
                                                    /*     │                 */
    /*[末尾]*/                                      /*     │                 */
    DWNLABEL(LB_END);                               /* ←─┘終端             */
    break;
  case If:
    token = nextTkn();
    expr_with_chk('(', ')');                        /*       [式]の処理       */
    JPF_DOWN(LB_ELSE);                              /* ─┐  false時          */
    statement();                                    /*   │  [文1]の処理      */
    if (token.kind != Else) {                       /*   │                   */
      DWNLABEL(LB_ELSE);                            /* ←┘elseない時の終端   */
      break;                                        /*   │                   */
    }                                               /*   │elseある時         */
    JMP_DOWN(LB_END);                               /* ─┼┐                 */
    DWNLABEL(LB_ELSE);                              /* ←┘│                 */
    token = nextTkn();                              /*     │                 */
    statement();                                    /*     │[文2]の処理      */
    DWNLABEL(LB_END);                               /* ←─┘                 */
    break;
  case While:
    token = nextTkn();
    UPLABEL(LB_TOP);                                /* ←┐                   */
    expr_with_chk('(', ')');                        /*   │  [式]の処理       */
    JPF_DOWN(LB_END);                               /* ─┼┐false時          */
    statement();                                    /*   ││[文]の処理       */
    JMP_UP(LB_TOP);                                 /* ─┘│繰り返し         */
    DWNLABEL(LB_END);                               /* ←─┘                 */
    break;
  case Do:
    token = nextTkn();
    UPLABEL(LB_TOP);                                /* ←┐                   */
    statement();                                    /*   │[文]の処理         */
    if (token.kind == While) {                      /*   │                   */
      token = nextTkn();                            /*   │                   */
      expr_with_chk('(', ')');                      /*   │[式]の処理         */
      token = chk_nextTkn(token, ';');              /*   │; のはず           */
      JPT_UP(LB_TOP);                               /* ─┘true時             */
    } else {
      err_s("do終端のwhileがない");
    }
    break;
  case Switch:
    token = nextTkn();
    expr_with_chk('(', ')');                        /*      [式]の処理        */
    JMP_DOWN(LB_TBL);                               /* ─┐  テーブル処理へ   */
    swch_begin();                                   /*   │                   */
    statement();                                    /* case,default文の処理.  */
    JMP_DOWN(LB_END);                               /* ─┼┐末尾へ           */
    DWNLABEL(LB_TBL);                               /* ←┘│                 */
    swch_end();                                     /*     │テーブル処理     */
    DWNLABEL(LB_END);                               /* ←─┘                 */
    break;
  case Return:
    token = nextTkn();
    if (token.kind == ';') {                                      /* 戻値なし */
      if (ret_typ != VOID_T) err_s("return文に戻り値がない");
    } else {                                                      /* 戻値あり */
      expression();                                               /* 戻値作成 */
      if (ret_typ == VOID_T) err_s("void型関数に値を返すreturn文がある");
    }
    gencode2(JMP, NO_FIX_RET_ADRS);                         /* 関数出口処理へ */
    token = chk_nextTkn(token, ';');                              /* ; のはず */
    break;
  case Printf: case Exit:                                   /* void型組込関数 */
    sys_fncCall(kd);
    token = chk_nextTkn(token, ';');                  /* printf() + b; を防止 */
    break;
  case Input:                                             /* 非void型組込関数 */
    expr_with_chk(0, ';');                                    /* 通常の式解析 */
    remove_val();                                                 /* 式値不要 */
    break;
  case Incre: case Decre:                                      /* ++var --var */
    expr_with_chk(0, ';');
    remove_val();                                                 /* 式値不要 */
    break;
  case Ident:                                           /* 識別子(関数か変数) */
    tp = search(token.text);                                    /* 記号表位置 */
    if ((tp->nmKind==fncId || tp->nmKind==protId) && tp->dtTyp==VOID_T) {
      fncCall(tp);                                  /* void型関数はここで処理 */
      token = chk_nextTkn(token, ';');                            /* ; のはず */
    } else {
      expr_with_chk(0, ';');                                  /* 通常の式解析 */
      remove_val();                                               /* 式値不要 */
    }
    break;
  case Lbrace:                                                    /* 複合文{} */
    block(0);                                             /* 0:非関数ブロック */
    break;
  case Semicolon:                                 /* 空文,forの実行文等で出現 */
    token = nextTkn();
    break;
  case EofTkn:                             /* 最後の } を忘れた場合などに発生 */
    err_s("意図しない終了。'}'不足? "); exit(1);
  default:
    err_ss("不正な記述", token.text);
    token = nextTkn();
  }
  if (kd==For || kd==While || kd==Do || kd==Switch) continue_break_end();
}
Token nextLine_tkn() /* 다음 행을 읽고 다음 토큰을 반환한다 */
{
  nextLine();
  return nextTkn();
}
Token chk_nextTkn(const Token& tk, int kind2) /* 확인부 토큰 획득 */
{
  if (tk.kind != kind2) err_exit(err_msg(tk.text, kind_to_s(kind2)));
  return nextTkn();
}