Token nextTkn() /* 다음 토큰 */ { TknKind kd; string txt = ""; if (endOfFile_F) return Token(EofProg); /* 파일 종료 */ while (isspace(CH)) NEXT_CH(); /* 공백 스킵 */ if (CH == '\0') return Token(EofLine); /* 행끝 */ switch (ctyp[CH]) { case Doll: case Letter: txt += CH; NEXT_CH(); while (ctyp[CH]==Letter || ctyp[CH]==Digit) { txt += CH; NEXT_CH(); } break; case Digit: /* 수치상수 */ kd = IntNum; while (ctyp[CH] == Digit) { txt += CH; NEXT_CH(); } if (CH == '.') { kd = DblNum; txt += CH; NEXT_CH(); } while (ctyp[CH] == Digit) { txt += CH; NEXT_CH(); } return Token(kd, txt, atof(txt.c_str())); /* IntNum도 double형으로 저장 */ case DblQ: /* 문자열 상수 */ NEXT_CH(); while (CH!='\0' && CH!='"') { txt += CH; NEXT_CH(); } if (CH == '"') NEXT_CH(); else err_exit("문자열 리터럴이 닫혀있지 않다. "); return Token(String, txt); default: if (CH=='/' && C2=='/') return Token(EofLine); /* 주석 */ if (is_ope2(CH, C2)) { txt += CH; txt += C2; NEXT_CH(); NEXT_CH(); } else { txt += CH; NEXT_CH(); } } kd = get_kind(txt); /* 종류별 설정 */ if (kd == Others) err_exit("잘못된 토큰입니다: ", txt); return Token(kd, txt); }
Token nextTkn(void) /* 次のトークン */ { Token tkn = {NulKind, "", 0}; int errF = FALSE, num, ct, n; char *p = tkn.text, *p_end31 = p+ID_SIZ; char lite[100+1], *lite_end = lite+100; static int ch = ' '; /* 前回文字を保持するためstatic */ while (isspace(ch)) { ch = nextCh(); } /* 空白読み捨て */ if (ch == EOF) { tkn.kind = EofTkn; return tkn; } /* EOF */ switch (ctyp[ch]) { case Letter: for ( ; ctyp[ch]==Letter || ctyp[ch]==Digit; ch = nextCh()) { if (p < p_end31) *p++ = ch; /* 識別子は最大31文字まで有効 */ } *p = '\0'; break; case Digit: /* 数値定数 */ for (num=0; ctyp[ch]==Digit; ch = nextCh()) { num = num*10 + (ch-'0'); } tkn.kind = IntNum; tkn.intVal = num; /* 値格納 */ sprintf(tkn.text, "%d", num); /* エラー表示用 */ break; case SngQ: /* 文字定数 */ for (ct=0,ch=nextCh(); ch!=EOF && ch!='\n' && ch!='\''; ch=nextCh()) { if (ch == '\\') { if ((ch=nextCh()) == 'n') ch = '\n'; } /* \nの処理 */ if (++ct == 1) tkn.intVal = ch; /* 文字定数値格納 */ } if (ct != 1) errF = TRUE; if (ch == '\'') ch = nextCh(); else errF = TRUE; if (errF) err_s("不正な文字定数"); tkn.kind = IntNum; /* 以降は整数定数として扱う */ sprintf(tkn.text, "'%c'", tkn.intVal); /* エラー表示用 */ break; case DblQ: /* 文字列定数 */ p = lite; ch = nextCh(); while (ch!=EOF && ch!='\n' && ch!='"') { if (errF) { ch = nextCh(); continue; } if ((n=is_kanji(ch)) > 0) { while (n--) { if (p < lite_end) P_SET(); else errF = TRUE; } continue; } if (ch == '\\') { if ((ch=nextCh()) == 'n') ch = '\n'; } /* \nの処理 */ if (p < lite_end) P_SET(); else errF = TRUE; } *p = '\0'; if (errF) err_s("文字列リテラルが長すぎる"); if (ch == '"') ch = nextCh(); else err_s("文字列リテラルが閉じていない"); tkn.kind = String; tkn.intVal = mallocS(lite); /* 文字列をメモリに確保し番地を格納 */ tkn.text[0] = '\"'; /*以下エラー表示用に文字列確保*/ strncat(tkn.text+1, lite, 29); if (strlen(tkn.text) <= 29) strcat(tkn.text, "\""); break; default: /* 記号 */ if (ch<0 || 127<ch) err_s("不正な文字が使われている"); if ((n=is_kanji(ch)) > 0) { while (n--) P_SET(); } else P_SET(); if (is_ope2(*(p-1), ch)) P_SET(); /* == など */ *p = '\0'; } if (tkn.kind == NulKind) tkn = set_kind(tkn); /* 種別設定 */ if (tkn.kind == Others) err_ss("不正なトークン", tkn.text); return tkn; }