/**************************************/ /* filename:bbi_tkn.cpp トークン処理 */ /**************************************/ #include "bbi.h" #include "bbi_prot.h" struct KeyWord { const char *keyName; TknKind keyKind; }; KeyWord KeyWdTbl[] = { {"func" , Func}, {"var", Var}, {"if", If}, {"elif", Elif}, {"else", Else}, {"for", For}, {"to", To}, {"step", Step}, {"while", While}, {"end", End}, {"break", Break}, {"return", Return}, {"print", Print}, {"println", Println}, {"option", Option}, {"input", Input}, {"toint", Toint}, {"exit", Exit}, {"(", Lparen}, {")", Rparen}, {"[", Lbracket}, {"]", Rbracket}, {"+", Plus}, {"-", Minus}, {"*", Multi}, {"/", Divi}, {"==", Equal }, {"!=", NotEq }, {"<", Less}, {"<=", LessEq}, {">", Great}, {">=",GreatEq }, {"&&", And}, {"||", Or}, {"!", Not}, {"%", Mod}, {"?", Ifsub }, {"=", Assign }, {"\\", IntDivi }, {",", Comma}, {"\"", DblQ }, {"@dummy", END_KeyList}, }; int srcLineno; TknKind ctyp[256]; char *token_p; bool endOfFile_F; char buf[LIN_SIZ+5]; ifstream fin; #define MAX_LINE 2000 void initChTyp() { int i; for (i =0; i<256; i++){ctyp[i]= Others; } for(i='0'; i<='9'; i++){ ctyp[i]= Digit; } for(i='A'; i<='Z'; i++){ ctyp[i]= Letter; } for (i='a'; i<='z'; i++){ ctyp[i]= Letter; } ctyp['_']=Letter; ctyp['$'] = Doll; ctyp['(']= Lparen; ctyp[')']= Rparen; ctyp['[']=Lbracket; ctyp[']']= Rbracket; ctyp['<']=Less; ctyp['>']= Great; ctyp['+']= Plus; ctyp['-']=Minus; ctyp['*']= Multi; ctyp['/']= Divi; ctyp['!']= Not, ctyp['%']=Mod; ctyp['?']= Ifsub; ctyp['=']= Assign; ctyp['\\']= IntDivi; ctyp[',']= Comma; ctyp['\"']= DblQ; } void fileOpen(char *fname) { srcLineno = 0; endOfFile_F = false; fin.open(fname); if (!fin) { cout << fname << "をオープンにできません\n"; exit(1);} } void nextLine() { string s; if (endOfFile_F) return; fin.getline(buf, LIN_SIZ+5); if (fin.eof()){ fin.clear(); fin.close(); endOfFile_F = true; return; } if (strlen(buf) > LIN_SIZ) err_exit("プログラムは1行", LIN_SIZ, "文字以内で記述してください。"); if (++srcLineno > MAX_LINE) err_exit("プログラムが", MAX_LINE, "を超えました。"); token_p = buf; } Token nextLine_tkn() { nextLine(); return nextTkn(); } #define CH (*token_p) #define C2 (*(token_p+1)) #define NEXT_CH() ++token_p 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())); 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); } bool is_ope2(char c1, char c2) { char s[] = " "; if (c1 == '\0' || c2=='\0') return false; s[1] = c1; s[2]= c2; return strstr(" ++ -- <= >= != && || ", s) != NULL; } TknKind get_kind(const string& s) { for (int i=0; KeyWdTbl[i].keyKind != END_KeyList; i++){ if (s == KeyWdTbl[i].keyName) return KeyWdTbl[i].keyKind; } if (ctyp[S[0]]==Letter || ctyp[s[0]]==Doll) return Ident; if (ctyp[s[0]]== Digit) return DblNum; return Others; } Token chk_nextTkn(const Token& tk, int kind2) { if (tk.kind != kind2) err_exit(err_msg(tk.text, kind_to_s(kind2))); return nextTkn(); } void set_token_p(char *p) { token_p = p; } string kind_to_s(int kd) { for (int i=0; ; i++){ if(KeyWdTbl[i].keyKind == END_KeyList) break; if(KeyWdTbl[i].keyKind == kd) return KeyWdTbl[i].keyName; } return ""; } string kind_to_s(const CodeSet& cd) { switch (cd.kind){ case Lvar: case Gvar: case Fcall: return tableP(cd)->name; case IntNum: case DblNum: return dbl_to_s(cd.dblVal); case String : return string("\"") + cd.text + "\""; case EofLine: return ""; } return kind_to_s(cd.kind); } int get_lineNo() { extern int Pc; return (Pc == -1) ? srcLineno : Pc; }