void factor() /* 인자 */
{
  TknKind kd = code.kind;

  if (syntaxChk_mode) {                                          /* 구문 chk 시 */
    switch (kd) {
    case Not: case Minus: case Plus:
         code = nextCode(); factor(); stk.pop(); stk.push(1.0);
         break;
    case Lparen:
         expression('(', ')');
         break;
    case IntNum: case DblNum:
         stk.push(1.0); code = nextCode();
         break;
    case Gvar: case Lvar:
         (void)get_memAdrs(code); stk.push(1.0);
         break;
    case Toint: case Input:
         sysFncExec_syntax(kd);
         break;
    case Fcall:
         fncCall_syntax(code.symNbr);
         break;
    case EofLine:
         err_exit("식이 바르지 않습니다.");
    default:
         err_exit("식 오류:", kind_to_s(code));            /* a + = 등에서 발생 */
    }
    return;
  }

  switch (kd) {                                                     /* 실행시 */
  case Not: case Minus: case Plus:
       code = nextCode(); factor();                         /* 다음 값을 획득 */
       if (kd == Not) stk.push(!stk.pop());                      /* !처리한다 */
       if (kd == Minus) stk.push(-stk.pop());                    /* -처리한다 */
       break;                                /* 단항 +는 아무것도 하지 않는다 */
  case Lparen:
       expression('(', ')');
       break;
  case IntNum: case DblNum:
       stk.push(code.dblVal); code = nextCode();
       break;
  case Gvar: case Lvar:
       chk_dtTyp(code);                                 /* 값 설정을 마친 변수인가 */
       stk.push(Dmem.get(get_memAdrs(code)));
       break;
  case Toint: case Input:
       sysFncExec(kd);
       break;
  case Fcall:
       fncCall(code.symNbr);
       break;
  }
}
Beispiel #2
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);
  }
}
Beispiel #3
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();
}
void statement() /* 문 */
{
  CodeSet save;
  int top_line, end_line, varAdrs;
  double wkVal, endDt, stepDt;

  if (Pc>maxLine || exit_Flg) return;                     /* 프로그램 종료 */
  code = save = firstCode(Pc);
  top_line = Pc; end_line = code.jmpAdrs;          /* 제어 범위의 시작과 끝 */
  if (code.kind == If ) end_line = endline_of_If(Pc);     /* if문일 때의 끝 */

  switch (code.kind) {
  case If:
    // if
    if (get_expression(If, 0)) {                          /*   참(TRUE)이면    */
      ++Pc; block(); Pc = end_line + 1;                   /*   실행하고     */
      return;                                             /*   종료        */
    }
    Pc = save.jmpAdrs;                                    /*   다음으로         */
    // elif
    while (lookCode(Pc) == Elif) {
      save = firstCode(Pc); code = nextCode();
      if (get_expression()) {                             /*   참(TRUE)이면     */
        ++Pc; block(); Pc = end_line + 1;                 /*   실행하고    */
        return;                                           /*   종료         */
      }
      Pc = save.jmpAdrs;                                  /*   다음으로         */
    }
    // else
    if (lookCode(Pc) == Else) {                           /* else를       */
      ++Pc; block(); Pc = end_line + 1;                   /*   실행하고      */
      return;                                             /* 종료         */
    }
    // end
    ++Pc;
    break;
  case While:
    for (;;) {                                           /*                   */
      if (!get_expression(While, 0)) break;              /*   false 종료   */
      ++Pc; block();                                     /*        [실행]      */
      if (break_Flg || return_Flg || exit_Flg) {         /*                  */
        break_Flg = false; break;                        /*        중단        */
      }                                                  /*                   */
      Pc = top_line; code = firstCode(Pc);               /*   맨 앞으로        */
    }                                                    /*                   */
    Pc = end_line + 1;                                   /*                   */
    break;
  case For:										/* for 제어변수, 초깃값, 최종값, 증분식 */
    save = nextCode();
    varAdrs = get_memAdrs(save);                    /* 제이변수 주소 구하기  */

    expression('=', 0);                                             /* 초깃값   */
    set_dtTyp(save, DBL_T);                                         /* 형 확정  */
    Dmem.set(varAdrs, stk.pop());                             /*   초깃값을 설정  */

    endDt = get_expression(To, 0);                            /* 최종값을 보존   */
                                                              /* 증분값을 보존   */
    if (code.kind == Step) stepDt = get_expression(Step, 0); else stepDt = 1.0;
    for (;; Pc=top_line) {                               /*                   */
      if (stepDt >= 0) {                                 /*   증가 루프         */
        if (Dmem.get(varAdrs) > endDt) break;            /* 거짓이면 종료        */
      } else {                                           /*   감소 루프         */
        if (Dmem.get(varAdrs) < endDt) break;            /* 거짓이면 종료        */
      }                                                  /*                   */
      ++Pc; block();                                     /*   [ 실행 ]         */
      if (break_Flg || return_Flg || exit_Flg) {         /*                   */
        break_Flg = false; break;                        /*    중단            */
      }                                                  /*                   */
      Dmem.add(varAdrs, stepDt);                         /* 값 갱신             */
    }                                                    /*                   */
    Pc = end_line + 1;                                   /*                    */
    break;
  case Fcall:                                           /* 대입이 없는 함수 호출 */
    fncCall(code.symNbr);
    (void)stk.pop();                                            /* 반환 값 불필요 */
    ++Pc;
    break;
  case Func:                                            /* 함수 정의는 건너뀜 */
    Pc = end_line + 1;
    break;
  case Print: case Println:
    sysFncExec(code.kind);
    ++Pc;
    break;
  case Gvar: case Lvar:                                             /* 대입문 */
    varAdrs = get_memAdrs(code);
    expression('=', 0);
    set_dtTyp(save, DBL_T);                                 /* 대입할 때 형 확정*/
    Dmem.set(varAdrs, stk.pop());
    ++Pc;
    break;
  case Return:
    wkVal = returnValue;
    code = nextCode();
    if (code.kind!='?' && code.kind!=EofLine)   /* '식'이 있으면 반환 값을 계산 */
      wkVal = get_expression();
    post_if_set(return_Flg);                                /* ?가 있으면 처리 */
    if (return_Flg) returnValue = wkVal;
    if (!return_Flg) ++Pc;
    break;
  case Break:
    code = nextCode(); post_if_set(break_Flg);              /* ? 가 있으면 처리 */
    if (!break_Flg) ++Pc;
    break;
  case Exit:
    code = nextCode(); exit_Flg = true;
    break;
  case Option: case Var: case EofLine:                        /* 실행 시는 무시 */
    ++Pc;
    break;
  default:
    err_exit("잘못된 기술입니다: ", kind_to_s(code.kind));
  }
}