/** * Funkce strConCat udela konkatenaci retezcu s1 a s2 do s3. * @param s1 1.retezec * @param s2 2.retezec * @param s3 vyslednej retezec */ void strConCat(string *s1, string *s2, string *s3) { for(int i = 0; i < s1->length; i++) strAddChar(s3,s1->str[i]); for(int i = 0; i < s2->length; i++) strAddChar(s3,s2->str[i]); }
// Fuknce na generovánà nových proměnných void GenNewVariable(string *item) { strClear(item); strAddChar(item, '#'); int i; i = cnt; while(i != 0) { strAddChar(item, (char)(i % 10 + '0')); i = i / 10; } cnt++; }
int strConcate(string *s1, string *s2) // Funkce pøidá øetìzec s2 do øetìzce s1 { int delka1, delka2, newLength, index; // Promìnné pro pøidání delka1 = s1->length; // Zjistím délku prvního delka2 = s2->length; // Zjistím délku druhého newLength = delka1 + delka2; // Nová délka if(newLength >= s1->allocSize) // Pokud alokovaná pamì» nebude staèit { // Realokuji pamì» øetìzce if((s1->str = (char*)realloc(s1->str, newLength + 1)) == NULL) return STR_ERROR; // Pøi neúspì¹né realokaci vracím chybu s1->allocSize = newLength; // Pøenastavím alokovanou pamì» } // Zkopíruji po znacích druhý øetìzec do prvního øetìzce for(index = 0; index < delka2; index++) { if(strAddChar(s1, s2->str[index]) == STR_ERROR) // Pøidám znak na konec øetìzce s1 a kontrola return STR_ERROR; // Vracím chybu pøidání znaku } s1->length = newLength; // Zmìním délku v prvním øetìzci return STR_SUCCESS; // Úspì¹né pøidání øetìzce s2 do s1 }
/** * Funkce readStrToNUMB nacita z stdin retezec velkosti numb. * @param var string. */ void readStrToNUMB(string *var, int numb) { int c; for(int i = 0; i < numb; i++) { c = getchar(); strAddChar(var,(char)c); } }
/** * Funkce na vysekavani podretezce. * @param s1 prohledavany retezec. * @param s2 vyseknuty retezec. * @param beg Zacatek vysekavani. * @param end Konec vysekavani. */ void strSub(string *s1, string *s2,int beg,int end) { // Pocatecni testovani na hranicne body. if(beg > s1->length && end > s1->length) return; if(beg < 0 && end < 0 && beg < -s1->length && end < -s1->length) return; if(beg == 0 && end == 0) return; else if(beg < 0 && beg == end) { strAddChar(s2,s1->str[s1->length+beg]); return; } else if(beg == end || (beg > 0 && end > 0 && beg == s1->length) ) { strAddChar(s2,s1->str[beg-1]); return; } // Pokrocile podminky if(beg < 0) beg = beg + s1->length + 1; if(end < 0) end = end + s1->length + 1; // Vyber nejmensi prvek na zacatek int beg1 = 0; int end1 = 0; if(beg < end) { beg1 = beg; end1 = end; } else { beg1 = end; end1 = beg; } // Projdi cyklem a pridej znaky do retezce for(int i = beg1; i <= end1; i++) { if(!(i -1 < 0 || i -1 > s1->length)) strAddChar(s2,s1->str[i-1]); } }
void generateVariable(string *var) // generuje jedinecne nazvy identifikatoru // nazev se sklada ze znaku $ nasledovanym cislem // postupne se tu generuji prirozena cisla a do nazvu promenne se ukladaji // v reverzovanem poradi - na funkcnost to nema vliv, ale je jednodussi implementace { int i; strClear(var); strAddChar(var, '$'); i = counterVar; while (i != 0) { strAddChar(var, (char)(i % 10 + '0')); i = i / 10; } counterVar ++; }
/** * Funkce strAddText prida retezec do existujiciho stringu. * @param s1 string * @param text retezec * @return uspesnost funkce. */ int strAddText(string *s1, char *text) { int i = 0; while(text[i] != '\0') { if(strAddChar(s1,text[i]) == STR_ERROR) return STR_ERROR; i++; } return STR_SUCCESS; }
/** * Funkce strSearchParam vyhleda parametr v retezci oddeleny ';'. * @param func prohledavany retezec. * @param ref odkaz na retezec kam pridam parametr * @param param ktory parameter v poradi. */ void strSearchParam(string *func, string *ref,int param) { int countParam = 0; for(int i = 0; i < func->length; i++) { if(func->str[i] == ';') countParam++; if(countParam == param) { if(func->str[i] != ';') strAddChar(ref,func->str[i]); } } }
/** * Funkce strInitText inicializuje string a prida retezec do stringu. * @param s string * @param text retezec * @return Uspesnost funkce */ int strInitText(string *s, char *text) { if ((s->str = (char*) malloc(STR_LEN_INC)) == NULL) return STR_ERROR; s->str[0] = '\0'; s->length = 0; s->allocSize = STR_LEN_INC; int i = 0; while(text[i] != '\0') { if(strAddChar(s,text[i]) == STR_ERROR) return STR_ERROR; i++; } return STR_SUCCESS; }
int strCopyChar(string *s1, char retezec[]) // Funkce zkopíruje øetìzec do øetìzce s1 { int delka, x; // Promìnné pro kopírování strClear(s1); // Vyprázdnìní prvního øetìzce delka = strlen(retezec); // Zjistím délku øetìzce for(x = 0; x < delka; x++) // Procházím øetìzec po znacích { if(strAddChar(s1, retezec[x]) == STR_ERROR) // Pøidávám znak na konec øetìzce s1 return STR_ERROR; } return STR_SUCCESS; // Úspì¹né zkopírování øetìzce do øetìzce s1 }
int concateStrings(string *s1, string *s2, string *s3) // Funkce zkopíruje øetìzec s1 do s3 a pøidá za nìj øetìzec s2 { int delka, index; // Promìnné pro pøidávání if(strCopyString(s3,s1) == STR_ERROR) // Zkopíruji s1 do s3 a kontrola return STR_ERROR; delka = strGetLength(s2); // Ulo¾ím si délku druhého for(index = 0; index < delka; index++) // Kopíruji do s3 znaky z s2 { if(strAddChar(s3, s2->str[index]) == STR_ERROR) // Pøidám znak na konec øetìzce a kontrola return STR_ERROR; } return STR_SUCCESS; // Úspì¹né slouèení øetìzcù s1 a s2 do øetìzce s3 }
/* * @depractated * @bug this whole function is one big bug, do not use */ int unescapeStr(string* s) { string ret; //string help; //strInit(&help); strInit(&ret); int i = 0; while (s->str[i++]!='\0') { if (s->str[i] == '\\') { i++; } else { if (strAddChar(&ret, s->str[i])) { strFree(s); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } } return 1; }
string copy(string *str, int i, int j) //Funkce vrací podřetězec z řetězce str od i o délce j. { string strback; //Pomocná proměnná typu string. int p; //Řídící proměnná for cyklu. if (i < 1) //Pokud je i menší než 1, přiřadíme mu hodnotu 1, aby jsme nepřistupovali mimo string. { i=1; } if ((i+j-1) > str->length) //Pokud je j větší než délka řetězce, upravíme jej, aby jsme nekopírovali prvky za rozsahem stringu. { j=str->length-i+1; } strInit(&strback); //Inicializace stringu. for (p = 0; p < j; p++) //For cyklus o j opakováních. { strAddChar(&strback,str->str[i+p-1]); //Jednotlivé znaky přidáváme do strback. } return strback; //Vracíme string. }
/** * Funkce readStrToEOF nacita z stdin retezec po EOF. * @param var string. */ void readStrToEOF(string *var) { int c; while((c = getchar()) != -1)// EOF strAddChar(var,c); }
void gettoken() { strClear(&(T.s)); int x; char c; char h; int state=0; c=fgetc(f); if(c==EOF) { T.type=T_EOF; return; } while(1) { switch(state) { case 0: { if(c == '{') { if((x=jumpcomment()) == 1) { T.type=T_ERRORTOKEN; return; } c=fgetc(f); break; } else { if(isspace(c) != 0) { c=fgetc(f); break; } else { if(isalpha(c) != 0 || c=='_') { state=3; //T_ID if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } c=fgetc(f); break; } else{ if(isdigit(c) != 0) { state=4; //->T_INT/T_REAL if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } c=fgetc(f); break; } else{ if(c==EOF) { T.type=T_EOF; //T_EOF return; } else{ switch(c) //bude prepinat medzi dalsimi moznostami stale v pociatocnom stave { case '\'': { state=11;//->T_STRING c=fgetc(f); break; } case '(': { T.type=T_LB;//T_LB return; break; } case ')' : { T.type=T_RB;//T_RB return; break; } case ':' : { state=14;//T_COLON/T_ASSIGN c=fgetc(f); break; } case '*' : { T.type=T_MUL;//T_MUL return; break; } case '+' : { T.type=T_ADD;//T_ADD return; break; } case '-' : { T.type=T_SUB;//T_SUB return; break; } case '/' : { T.type=T_DIV;//T_DIV return; break; } case '<' : { state=12;//T_LESS/T_LESS_EQ if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } c=fgetc(f); break; } case '>' : { state=13;//T_MORE/T_MORE_EQ if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } c=fgetc(f); break; } case '=' : { T.type=T_EQUAL;//T_EQUAL return; break; } case '.' : { T.type=T_DOT;//T_DOT return; break; } case ',' : { T.type=T_COMMA;//T_COMMA return; break; } case ';' : { T.type=T_SEMICOLON;//T_SEMICOLON return; break; } default : //neplatny token { T.type=T_ERRORTOKEN; return; } } //switch c } // vylezie z else } } } } break; } case 3 : { if(isalpha(c) != 0 || isdigit(c) !=0 || c=='_') { if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } c=fgetc(f); } else { ungetc(c,f); if(iskeyword(strGetStr(&(T.s)))==1){ T.type=T_KEYWORD; } else if (iskeyword(strGetStr(&(T.s)))==3){ T.type=T_DATATYPE; } else{ if(iskeyword(strGetStr(&(T.s)))==2) T.type=T_KONST; else{ T.type=T_ID; } } return; } break; } case 4 : { if(c == '.') { state=5; h=c; c=fgetc(f); } else{ if(c=='e' ||c=='E') { if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } state=7; c=fgetc(f); break; } else{ if(isdigit(c)!=0) { if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } c=fgetc(f); } else{ ungetc(c,f); T.type=T_INT; return; } } } break; } case 5 : { if(isdigit(c)!=0) { if(strAddChar(&(T.s),h)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } state=6; c=fgetc(f); } else{ ungetc(c,f); ungetc(h,f); T.type=T_INT; return; } break; } case 6 : { if(isdigit(c)!=0) { if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } c=fgetc(f); } else{ if(c=='e' || c=='E') { if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } state=7; c=fgetc(f); break; } else { ungetc(c,f); T.type=T_REAL; return; } } break; } case 7 : { if(isdigit(c)!=0) { if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } state=9; c=fgetc(f); break; } else{ if(c=='+' || c=='-') { if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } state=8; c=fgetc(f); break; } else{ T.type=T_ERRORTOKEN; return; } } break; } case 8 : { if(isdigit(c)!=0) { if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } state=9; c=fgetc(f); break; } else { T.type=T_ERRORTOKEN; return; } break; } case 9 : { if(isdigit(c)!=0) { if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } state=9; c=fgetc(f); break; } else { T.type=T_REAL; ungetc(c,f); return; } break; } case 11 : { if ( c == '\'') { c=fgetc(f); if ( c == '\''){ if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } c=fgetc(f); break;} if ( c == '#'){ if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } c=fgetc(f); if(isdigit(c)!=0) { if(c == '0'){ while (c == '0') { c=fgetc(f); } if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } } } else { T.type = T_ERRORTOKEN; return; break; } c=fgetc(f); if(isdigit(c)!=0) { if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } } else { T.type = T_ERRORTOKEN; return; break; } c=fgetc(f); if(isdigit(c)!=0) { if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } } else { ungetc(c,f); } c=fgetc(f); if ( c != '\'') { T.type = T_ERRORTOKEN; return; } c=fgetc(f); break; } else { ungetc(c,f); T.type = T_STRING; return; } } else { while (c != '\'') { if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } c=fgetc(f); if(c==EOF) { T.type=T_ERRORTOKEN; return; } } state = 11; break; } } case 12: { if(c=='=') { if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } T.type=T_LESS_EQ; return; } else if (c=='>') { if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } T.type=T_NOT_EQ; return; } else { ungetc(c,f); T.type=T_LESS; return; } break; } case 13: { if(c=='=') { if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } T.type=T_MORE_EQ; return; } else { ungetc(c,f); T.type=T_MORE; return; } break; } case 14: //:= { if(c=='=') { if(strAddChar(&(T.s),c)== STR_ERROR) { T.type=T_ERRORSYSTEM; return; } T.type=T_ASSIGN; return; } else { ungetc(c,f); T.type=T_COLON; return; } break; } } } }
int get_token(FILE *F, double *num, string *stri, int *error ) { int pom; int cha=0; int err_char=0; int next_state=ST_START; char c; char *chyba; char min; *num=0; c=fgetc(F); while (c != EOF) { switch(next_state) { case ST_START: if (c == '\n') { line++; next_state=ST_START; } if (isspace(c)) { break; //Tohle jsem přidával !!!!!!!! } else if (c == ';') { return TP_SEM; } else if (c == '/') { return TP_MOD; } else if (c == '.') { return TP_DOT; } else if (c == '(') { return TP_LBRA; } else if (c == '+') { return TP_PLUS; } else if (c == '-') { return TP_MINUS; } else if (c == ')') { return TP_RBRA; } else if (c == '*') { return TP_MUL; } else if (isdigit(c)) { next_state=ST_NUMBER; strAddChar(stri,c); } else if (isalpha(c)) { pom=0; next_state=ST_IDENT_KEY; strAddChar(stri,c); } else if (c == '{') { next_state=ST_KOMENT; } else if (c == 39) { next_state=ST_STRING; } else if (c == ':') { next_state=ST_COLONS; strAddChar(stri,c); } else if (c == '<') { next_state=ST_LESS; } else if (c == '>') { next_state=ST_MORE; } else if (c == ',') { return TP_COMMA; } else { *error=1; //nastala chyba. } break; case ST_KOMENT: if (c == '}') { next_state=ST_START; } break; case ST_IDENT_KEY: if ((!(isdigit(c))) && (!(isalpha(c)) && (c != '_'))) { ungetc(c,F); return TP_IDENT; } else { strAddChar(stri,c); } for (pom=0;pom<20;pom++) { if ((strCmpConstStr(stri,KeyWord[pom]))==0) { c=fgetc(F); if ((!(isdigit(c))) && (!(isalpha(c)))) { ungetc(c,F); return pom+51; } else { ungetc(c,F); } } } break; case ST_NUMBER: if(!(isdigit(c))) { if(c == '.') { next_state=ST_REAL; strAddChar(stri,c); } else if ((c == 'E') || (c == 'e')) { next_state=ST_REAL_EXP; strAddChar(stri,c); } else if ((c == '+') || (c == '-')) { if (c == '-') { min='-'; } c=fgetc(F); if ((c == 'E') || (c == 'e')) { next_state=ST_REAL_EXP; strAddChar(stri,c); if (min == '-') { strAddChar(stri,'-'); } } else { *error=1; next_state=ST_START; } } else if ((isspace(c)) || (c == ';') || (c == '\n')) { *num = strtod(strGetStr(stri),&chyba); return TP_INT; } else { *error=1; next_state=ST_START; } } else { strAddChar(stri,c); } break; case ST_LESS: if (c == '>') { return TP_NEQU; } else if (c == '=') { return TP_LESSEQ; } else { ungetc(c,F); return TP_LESS; } break; case ST_MORE: if (c == '=') { return TP_MOREEQ; } else { ungetc(c,F); return TP_MORE; } break; case ST_COLONS: if (c == '=') { return TP_SGNMNT; } else { ungetc(c,F); return TP_COL; } break; case ST_CHAR: if (c == 39) { if (err_char == 0) { strAddChar(stri,cha); } err_char=0; next_state=ST_STRING; break; } if ((!(isdigit(c)) && (c != 39)) || (err_char==1)) { printf("chyba\n"); } else { cha=cha*10+(c-48); if ((cha <1) && (cha >255)) { printf("chyba\n"); err_char=1; } } break; case ST_STRING: if (c == 39) { c=fgetc(F); if (c == '#') { next_state=ST_CHAR; break; } else { ungetc(c,F); return TP_STRING; } } else { strAddChar(stri,c); } break; case ST_REAL: if(!(isdigit(c))) { if ((c == 'E') || (c == 'e')) { next_state=ST_REAL_EXP; strAddChar(stri,c); } else if ((c == '+') || (c == '-')) { if (c == '-') { min='-'; } c=fgetc(F); if ((c == 'E') || (c == 'e')) { next_state=ST_REAL_EXP; strAddChar(stri,c); if (min == '-') { strAddChar(stri,'-'); } } else { *error=1; next_state=ST_START; } } else if ((isspace(c)) || (c == ';') || (c == '\n')) { *num = strtod(strGetStr(stri),&chyba); return TP_REAL; } else { *error=1; next_state=ST_START; } } else { strAddChar(stri,c); } break; case ST_REAL_EXP: if(!(isdigit(c))) { if ((isspace(c)) || (c == ';') || (c == '\n')) { *num = strtod(strGetStr(stri),&chyba); return TP_REAL_EXP; } else { *error=1; next_state=ST_START; } } else { strAddChar(stri,c); } break; } c=fgetc(F); } return TP_EOF; }
int getNextToken(string *attr) { int c, state = 0; string pomEsc; strClear(attr); strClear(&pomEsc); while (1) { c = getc(source); switch (state) { case 0: // pocatecni stav { if (isspace(c)) state = 0; // ignorovani bilych mist else if (c == '{') state = 1; // komentar else if (isalpha(c)) { strAddChar(attr, c); state = 2; // zacatek identifikatoru nebo klic. slova } else if (isdigit(c)) { strAddChar(attr, c); state = 3; // cislo int ci double } else if (c == ':') { state = 4; // samostatna dvojtecka nebo operator prirazeni } else if (c == '<') state = 5; // mensi, mensi nebo rovno else if (c == '>') state = 6; // vetsi, vetsi nebo rovno else if (c == '\'') state = 8; // zacatek retezce else if (c == '+') return PLUS; else if (c == '-') return MINUS; else if (c == '*') return KRAT; else if (c == '/') return DELENO; else if (c == '=') return ROVNO; else if (c == ';') return STREDNIK; else if (c == ',') return CARKA; else if (c == '.') return TECKA; else if (c == '(') return LEVAZAVORKA; else if (c == ')') return PRAVAZAVORKA; else if (c == EOF) return KONECSOUBORU; else return LEXIKALNICHYBA; break; } case 1: // komentar { if (c == '}') state = 0; else if (c == EOF) return LEXIKALNICHYBA; break; } case 2: // alfanumericky znak (id nebo klic. slovo) { if (isalnum(c) || c == '_') strAddChar(attr, c); else { ungetc(c, source); return is_keyword(attr, c == '('); } break; } case 3: // libovolne cislo { if (isdigit(c)) strAddChar(attr, c); else if (c == '.') { strAddChar(attr, c); state = 7; } else { ungetc(c, source); return KONST_INTEGER; } break; } case 4: // prirazeni { if (c == '=') return PRIRAZENI; else { ungetc(c, source); return DVOJTECKA; } } case 5: // mensi, mensi nebo rovno, nerovno { if (c == '=') return MENSIROVNO; else if (c == '>') return NEROVNO; else { ungetc(c, source); return MENSI; } } case 6: // vetsi, vetsi nebo rovno { if (c == '=') return VETSIROVNO; else { ungetc(c, source); return VETSI; } } case 7: // zakladni realne cislo { if (isdigit(c)) strAddChar(attr, c); else return KONST_REAL; break; } case 8: // retezec { if (c == '\'') state = 9; else if (c == EOF || c == '\n') return LEXIKALNICHYBA; else strAddChar(attr, c); break; } case 9: // apostrof v retezci, escape sekvence nebo konec retezce { if (c == '\'') { strAddChar(attr, c); state = 8; // apostrof v retezci } else if (c == '#') state = 10; // escape sekvence else return KONST_STRING; // konec retezce break; } case 10: // escape sekvence { if (isdigit(c)) strAddChar(&pomEsc, c); else if (c == '\'') { if (strlen(pomEsc.str) == 0) return LEXIKALNICHYBA; // Zadne cislo escape sekvence int escape = atoi(pomEsc.str); if (esc < 1 || esc > 255) return LEXIKALNICHYBA; // Escape sekvence neni znak strAddChar(attr, escape); strClear(&pomEsc); state = 8; // pokracovani retezce } else return LEXIKALNICHYBA; break; } } } }
int getToken(tToken *Token, FILE* source) { //prvne zkontroluji frontu tokenu if (TQueue != NULL) {//nema cenu si neco na frontu zkouset kdyz je NULL TQDequeue(Token); if (Token != NULL) {//token byl ve fronte return 1; } } //alokace pameti pro cteny token tToken tok = (tToken)malloc(sizeof(struct stToken)); *Token = tok; /* @var c int actual character*/ int c = -1; /* @var prevRest int poslední načtený znak (Zbytek posledního průchodu) */ static int pom = -1; /* @var string s Uklada aktualne cteny string pokud je treba, pri kazdem * konci teto funkce musi byt volano strFree. */ string s; //strInit vraci 1 při chybe if (strInit(&s)) { FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } //string kam se ukladaji sekvence pro escape sekvence string escape; //nastavime vychozi stav int state = START; while (1) { if (pom > 0) {//pozustatek z minuleho cteni c = pom; pom = -1;//-1 je jedina hodnota kterou by nemela pomocna promenna nabyt pokud v ni opravdu je pozustatek //pokud je v ni opravdu EOF tak pomoci getc() ho stejne dostanu znovu } else { c = getc(source); character++; if (c == '\n') {//pokud ctu dalsi radek tak vynuluji citadlo znaku a inkrementuji citadlo radku line++; character = 0; } } switch (state) { case START: //pocatecni bile znaky nic nezmeni if (isspace(c)) { state = START; } //zacatek identifikatoru else if (isalpha(c) || c == '_') { state = IDENTIFICATOR; if (strAddChar(&s, c)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } //ulozi prvni nulu v cisle else if (c == '0') { state = FLOAT_OR_INT; if (strAddChar(&s, c)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } //platna cislice na zacatku retezce znamena celou cast cisla else if (c >= '1' && c <= '9') { state = INT_PART; if (strAddChar(&s, c)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } //strednik ulozi token strednik else if (c == ';') { tok->typ = SEMICOLON; strFree(&s); return 1; } //zacatek escape sekvenci rozsireni BASE else if (c == '\\') { state = ESCAPE; } //string zacina uvozovkami else if (c == '\"') { state = STRING; } //lomeno muze byt operatro nebo zacatek komentare else if (c == '/') { state = DIVISION_COMMENT; } //unarni minus, odcitani nebo dekremenrace else if (c == '-') { //jsem schopny rozlisit jen dekrementaci a minus //unarni minus ani rozdil mezi postfix/prefix neurcim state = DECREMENT_OPERATOR; } //scitani nebo inkrementace else if (c == '+') { state = INCREMENT_OPERATOR; } //nasobeni znamena jedine nasobeni else if (c == '*') { tok->typ = MULTIPLY; strFree(&s); return 1; } //toto mohou byt opertary se dvema znaky i jednim else if (c == '!' || c == '<' || c == '>' || c == '=') { state = TWO_CHAR_OPER; if (strAddChar(&s, c)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } //zaovrky ihned ulozime jako token else if (c == ')') { tok->typ = PARENTHESIS_CLOSING; strFree(&s); return 1; } else if (c == '(') { tok->typ = PARENTHESIS_OPENING; strFree(&s); return 1; } else if (c == '}') { tok->typ = BRACES_CLOSING; strFree(&s); return 1; } else if (c == '{') { tok->typ = BRACES_OPENING; strFree(&s); return 1; } //logicky or else if (c == '|') { state = LOGICAL_OR; } //logicky and else if (c == '&') { state = LOGICAL_AND; } //carka (comma) operator ulozime do tokenu else if (c == ',') { tok->typ = COMMA; strFree(&s); return 1; } //konec souboru cas vyhlasit chyby pokud nastaly jinak ulozit do tokenu EOF else if (c==EOF) { tok->typ = END_OF_FILE; strFree(&s); if (errorFlag) { freeTokenMem(&tok); return 42; } return 1; } else {//pokud na zacatku tokenu prislo cokoli jineho tak scanner nevi co se deje errorFlag = 1; Warning("%sLine - %d:%d\t- Unknown symbol.\n", ERR_MESSAGES[ERR_LEX], line, character); strFree(&s); freeTokenMem(&tok); return 42; } break; case INT_PART: //cteni cele casti cisla //cislice ukladam if (c >= '0' && c <= '9') { state = INT_PART; if (strAddChar(&s, c)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } //zacatek exponentu else if (c == 'e' || c == 'E') { state = EXPONENT_CHECK; if (strAddChar(&s, c)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } //zacatek desetine casti else if (c == '.') { //vlozen testovaci stav pro podminku ze za des. teckou musi byt cislice state = FLOAT_CHECK; if (strAddChar(&s, c)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } //uloz cele cislo else { int val; if (!strToInt(&s, &val)) { freeTokenMem(&tok); strFree(&s); FatalError(99, "%s-%d: Chyba pri nacteni celeho cisla.", ERR_MESSAGES[ERR_ALLOC], line); return 42; } pom = c; tok->typ = TYPE_INTEGER; tok->value.intVal = val; strFree(&s); return 1; } break; case FLOAT_OR_INT: //prvni nula byla ulozena pocatecnim stavu ted je necham byt if (c == '0') { state = FLOAT_OR_INT; } else if (c >= '1' && c<='9') {//pokud nasleduje cislice ctu cele cislo state = INT_PART; if (strAddChar(&s, c)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } else if (c == '.') { //zacatek desetine casti state = FLOAT_CHECK; if (strAddChar(&s, c)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } else if (c == 'e' || c == 'E') { //zacatek exponentu state = EXPONENT_CHECK; if (strAddChar(&s, c)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } else { //konec celeho cisla int val; if (!strToInt(&s, &val)) { errorFlag = 1; Warning("%sLine - %d:%d\t- Nepodarilo se nacist ciselny literal.\n",ERR_MESSAGES[ERR_LEX], line, character); strFree(&s); freeTokenMem(&tok); return 42; } tok->typ = TYPE_INTEGER; tok->value.intVal = val; strFree(&s); pom = c; return 1; } break; case FLOAT_CHECK: //tento stav slouzi ke kontrole neprazdnosti desetine casti if (c >= '0' && c <= '9') { state = FLOAT_PART; if (strAddChar(&s, c)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } //pokud za teckou neni cislice je to chyba else { pom = c; errorFlag = 1; Warning("%sLine - %d:%d\t- Nepodarilo se nacist ciselny literal. Desetina cast nesmi byt prazdna.\n", ERR_MESSAGES[ERR_LEX], line, character); strFree(&s); freeTokenMem(&tok); return 42; } break; case FLOAT_PART: if (c >= '0' && c <= '9') { //ulozi cislo a pokracuje ve cteni state = FLOAT_PART; if (strAddChar(&s, c)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } else if (c == 'e' || c == 'E') { //zacatek exponentu state = EXPONENT_CHECK; if (strAddChar(&s, c)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } else { //konec desetineho cisla, ulozme jej double val; if (!strToDouble(&s, &val)) { errorFlag = 1; Warning("%sLine - %d:%d\t- Nepodarilo se nacist ciselny literal.\n",ERR_MESSAGES[ERR_LEX], line, character); strFree(&s); freeTokenMem(&tok); return 42; } tok->typ = TYPE_DOUBLE; tok->value.doubleVal = val; strFree(&s); pom = c; return 1; } break; case EXPONENT_CHECK: if (c >= '0' && c <= '9') { //prislo cislo, ulozi jej a pokracuje j*z ve cteni exponentu state = EXPONENT; if (strAddChar(&s, c)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } else if (c == '+' || c == '-') { //znamenko na zacatku exponentu state = EXPONENT_PLUS_MINUS_CHECK; if (strAddChar(&s, c)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } //nemuzeme napsat exponent a neudat ho else{ errorFlag = 1; Warning("%sLine - %d:%d\t- Exponent musi obsahovat validni cislici.\n",ERR_MESSAGES[ERR_LEX], line, character); pom = c; strFree(&s); freeTokenMem(&tok); return 42; } break; case EXPONENT_PLUS_MINUS_CHECK: if (c >= '0' && c <= '9') { //spravne bylo za znamenkem exponentu cislo //pokracuji ve cteni expoenntu state = EXPONENT; if (strAddChar(&s, c)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } else { //nemuzem napsat znamenko exponentu a neudat jeho hodnotu errorFlag = 1; Warning("%sLine - %d:%d\t- Exponent musi obsahovat validni cislici.\n",ERR_MESSAGES[ERR_LEX], line, character); pom = c; strFree(&s); freeTokenMem(&tok); return 42; } break; case EXPONENT: if (c >= '0' && c <= '9') { //cte cisla dokud prichazi state = EXPONENT; if (strAddChar(&s, c)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } else { //prislo cokoli jineho nez cislo double val = 42; if (!strToDouble(&s, &val)) { errorFlag = 1; Warning("%sLine - %d:%d\t- Nepodarilo se nacist ciselny literal.\n",ERR_MESSAGES[ERR_LEX], line, character); strFree(&s); freeTokenMem(&tok); return 42; } tok->typ = TYPE_DOUBLE; tok->value.doubleVal = val; pom = c;//dalsi znak patri dalsimu tokenu strFree(&s); return 1; } break; case ESCAPE: //escape sekvence celociselne konstanty switch (c) { //binarni escape sekvence case 'b': case 'B': state = BINARY_NUMBER; break; //oktalova escape sekvence case '0': state = OCTAL_NUMBER; break; //hexadecimalni escape sekvence case 'x': case 'X': state = HEX_DEC_NUMBER; break; //cokoli jineho je chybou default: errorFlag = 1; Warning("%sLine - %d:%d\t- Ocekavan symbol pro ciselnou soustavu.\n",ERR_MESSAGES[ERR_LEX], line, character); strFree(&s); freeTokenMem(&tok); return 42; break; } break; case BINARY_NUMBER: //escape sekvence obsahujici binarni cislo if (c == '0' || c == '1') { //zahazuji nevyznamne nuly if (!(c == '0' && strGetLength(&s) == 0)) { if (strAddChar(&s, c)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } } else { pom = c; int val = 0; if (!strBinToInt(&s, &val)) { strFree(&s); freeTokenMem(&tok); return 42; } tok->typ = TYPE_INTEGER; tok->value.intVal = val; strFree(&s); return 1; } break; case OCTAL_NUMBER: //escape sekvence obsahujici oktalove cislo if (c >= '0' && c <= '7') { //zahazuji nevyznamne nuly if (!(c == '0' && strGetLength(&s) == 0)) { if (strAddChar(&s, c)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } } else { pom = c; int val = 0; if (!strOctToInt(&s, &val)) { strFree(&s); freeTokenMem(&tok); return 42; } tok->typ = TYPE_INTEGER; tok->value.intVal = val; strFree(&s); return 1; } break; case HEX_DEC_NUMBER: //escape sekvence obsahujici hexadecimalni cislo if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) { //zahazuji nevyznamne nuly if (!(c == '0' && strGetLength(&s)==0)) { if (strAddChar(&s, c)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } } else { pom = c; int val = 0; if (!strHexToInt(&s, &val)) { strFree(&s); freeTokenMem(&tok); return 42; } tok->typ = TYPE_INTEGER; tok->value.intVal = val; strFree(&s); return 1; } break; case LOGICAL_AND: //logicky and //v IFJ2015 neexistuje binarni and proto jediny prijatelny znak //v tuto chvili je & if (c == '&') { tok->typ = LOG_AND_OPER; strFree(&s); return 1; } else { pom = c; errorFlag = 1; Warning("%sLine - %d:%d\t- Binarni and neni podporovan v IFJ2015.\n",ERR_MESSAGES[ERR_LEX], line, character-1); strFree(&s); freeTokenMem(&tok); return 42; } break; case LOGICAL_OR: //logicky or //v IFJ2015 neexistuje binarni or proto jediny prijatelny znak //v tuto chvili je | if (c == '|') { tok->typ = LOG_OR_OPER; strFree(&s); return 1; } else { /*Abych se zotavil po teto chybe a docetl soubor*/ errorFlag = 1; Warning("%sLine - %d:%d\t- Binarni or neni podporovan v IFJ2015.\n",ERR_MESSAGES[ERR_LEX], line, character - 1); pom = c; strFree(&s); freeTokenMem(&tok); return 42; } break; case STRING: if (c == EOF) { errorFlag = 1; Warning("%sLine - %d:%d\t- Necekany konec souboru.\n",ERR_MESSAGES[ERR_LEX], line, character); strFree(&s); freeTokenMem(&tok); return 42; } else if (c == '\\') { state = STRING_ESCAPE; } else if (c == '"') {//konec retezce uloz ho tok->typ = TYPE_STRING; if (strInit(&tok->value.stringVal)) { //return stringval } if (strCopyString(&tok->value.stringVal, &s)) { //return error; } strFree(&s); return 1; } else if (c < 1 || c>255) {//nejaky znak mimo ASCII chyba } else {//uloz si znak if (strAddChar(&s, c)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } break; case STRING_ESCAPE: //escape sekvence ve stringu switch (c) { //binarni escape sekvence case 'b': case 'B': if (strInit(&escape)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } state = STRING_BINARY_NUMBER; break; //oktalova escape sekvence case '0': if (strInit(&escape)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } state = STRING_OCTAL_NUMBER; break; case 'x': case 'X': //hexadecimalni escape sekvence if (strInit(&escape)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } state = STRING_HEX_DEC_NUMBER; break; case '\\': //escape sekvence backslash if (strAddChar(&s, '\\')) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } state = STRING; break; case 'n': //escape sekvence noveho radku if (strAddChar(&s, '\n')) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } state = STRING; break; case 't': //escape sekvence tabulatoru if (strAddChar(&s, '\t')) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } state = STRING; break; case '\"': //escape sekvence uvozovek if (strAddChar(&s, '\"')) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } state = STRING; break; default: //cokoliv jineho je chybnym zapsani escape sekvence errorFlag = 1; Warning("%sLine - %d:%d\t- Ocekavana escape sekvence\n", ERR_MESSAGES[ERR_LEX], line, character); strFree(&s); freeTokenMem(&tok); return 42; break; } break; case STRING_BINARY_NUMBER: if ((c == '0' || c == '1')) {//ctu validni vstup if (strGetLength(&escape) < 8) {//jeste nemam 8 cislic tak ctu dal if (strAddChar(&escape, c)) { freeTokenMem(&tok); strFree(&escape); strFree(&s); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } else {//mam 8 cislic pom = c; int val; if (strBinToInt(&escape, &val) && val >= 1 && val <= 255) { if (strAddChar(&s, (char)val)) {//precteny znak pridam do stringu freeTokenMem(&tok); strFree(&escape); strFree(&s); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } else {//nepodarilo se prevest escape na string errorFlag = 1; Warning("%sLine - %d:%d\t- Retezec \"%s\" neni platnou escape sekvenci.\n", ERR_MESSAGES[ERR_LEX], line, character, escape.str); } strFree(&escape); state = STRING; } } else { if (strGetLength(&escape) < 8) { errorFlag = 1; Warning("%sLine - %d:%d\t- Retezec \"%s\" neni platnou escape sekvenci.\n", ERR_MESSAGES[ERR_LEX], line, character, escape.str); } if (strGetLength(&escape) == 8) { int val; if (strBinToInt(&escape, &val) && val >= 1 && val <= 255) { if (strAddChar(&s, (char)val)) { freeTokenMem(&tok); strFree(&escape); strFree(&s); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } else { errorFlag = 1; Warning("%sLine - %d:%d\t- Retezec \"%s\" neni platnou escape sekvenci.\n", ERR_MESSAGES[ERR_LEX], line, character, escape.str); } } pom = c; strFree(&escape); state = STRING; } break; case STRING_OCTAL_NUMBER: if ((c >= '0' && c <= '7')) {//ctu validni vstup if (strGetLength(&escape) < 3) { if (strAddChar(&escape, c)) { freeTokenMem(&tok); strFree(&escape); strFree(&s); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } else { pom = c; int val; if (strOctToInt(&escape, &val) && val >= 1 && val <= 255) { if (strAddChar(&s, (char)val)) { freeTokenMem(&tok); strFree(&escape); strFree(&s); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } else { errorFlag = 1; Warning("%sLine - %d:%d\t- Retezec \"%s\" neni platnou escape sekvenci.\n", ERR_MESSAGES[ERR_LEX], line, character, escape.str); } strFree(&escape); state = STRING; } } else { if (strGetLength(&escape) < 3) { errorFlag = 1; Warning("%sLine - %d:%d\t- Retezec \"%s\" neni platnou escape sekvenci.\n", ERR_MESSAGES[ERR_LEX], line, character, escape.str); } if (strGetLength(&escape) == 3) { int val; if (strOctToInt(&escape, &val) && val >= 1 && val <= 255) { if (strAddChar(&s, (char)val)) { freeTokenMem(&tok); strFree(&escape); strFree(&s); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } else { errorFlag = 1; Warning("%sLine - %d:%d\t- Retezec \"%s\" neni platnou escape sekvenci.\n", ERR_MESSAGES[ERR_LEX], line, character, escape.str); } } pom = c; strFree(&escape); state = STRING; } break; case STRING_HEX_DEC_NUMBER: if ((c >= '0' && c <= '9')||(c >= 'a' && c <= 'f')|| (c >= 'A' && c <= 'F')) {//ctu validni vstup if (strGetLength(&escape) < 2) { if (strAddChar(&escape, c)) { freeTokenMem(&tok); strFree(&escape); strFree(&s); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } else { int val; pom = c; if (strHexToInt(&escape, &val) && val >= 1 && val <= 255) { if (strAddChar(&s, (char)val)) { freeTokenMem(&tok); strFree(&escape); strFree(&s); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } else { errorFlag = 1; Warning("%sLine - %d:%d\t- Retezec \"%s\" neni platnou escape sekvenci.\n", ERR_MESSAGES[ERR_LEX], line, character, escape.str); } strFree(&escape); state = STRING; } } else { if (strGetLength(&escape) < 2) { errorFlag = 1; Warning("%sLine - %d:%d\t- Retezec \"%s\" neni platnou escape sekvenci.\n", ERR_MESSAGES[ERR_LEX], line, character, escape.str); } if (strGetLength(&escape) == 2) { int val; if (strHexToInt(&escape, &val) && val >= 1 && val <= 255) { if (strAddChar(&s, (char)val)) { freeTokenMem(&tok); strFree(&escape); strFree(&s); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } else { errorFlag = 1; Warning("%sLine - %d:%d\t- Retezec \"%s\" neni platnou escape sekvenci.\n", ERR_MESSAGES[ERR_LEX], line, character, escape.str); } } pom = c; strFree(&escape); state = STRING; } break; case IDENTIFICATOR: //ctu cislice, pismena nebo podtrzitka if (isalnum(c) || c == '_') { if (strAddChar(&s, c)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } //konec identifikatoru else { pom = c; int isIdent = isKeyWord(&s); tok->typ = isIdent; if (isIdent == TYPE_IDENTIFICATOR) { if (strInit(&(tok->value.stringVal))) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } if (strCopyString(&(tok->value.stringVal), &s)) { strFree(&s); freeTokenMem(&tok); FatalError(99, ERR_MESSAGES[ERR_ALLOC]); } } if (isIdent == KEYW_FALSE) { tok->typ = TYPE_BOOL; tok->value.boolVal = false; } if (isIdent == KEYW_TRUE) { tok->typ = TYPE_BOOL; tok->value.boolVal = true; } strFree(&s); return 1; } break; case DIVISION_COMMENT: if (c == '*') { state = BLOCK_COMMENT; } else if (c == '/') { state = LINE_COMMENT; } else {//jednoznakovy operator deleni tok->typ = DIVISION; pom = c; strFree(&s); return 1; } break; case LINE_COMMENT: if (c == '\n') {//konec radkoveho komentare hledame dalsi lexem state = START; } else if (c == EOF) {//nemusi byt lf pred koncem souboru pom = c; state = START; } else {//komentar pokracuje //reflection nepodporujeme takže komentáře zahodíme } break; case BLOCK_COMMENT: if (c == EOF) { Warning("%sLine - %d:%d\t- Necekany konec souboru.\n", ERR_MESSAGES[ERR_LEX], line, character); strFree(&s); freeTokenMem(&tok); return 42; } /*else if (c=='/') { state = NESTED_BLOCK_COMMENT_CHECK; }*/ else if (c=='*') { state = END_BLOCK_COMMENT; } break; case END_BLOCK_COMMENT: if (c == '*') { //zůstaneme tady komentář může končit x hvězdičkama } else if (c == EOF) { Warning("%sLine - %d:%d\t- Necekany konec souboru.\n", ERR_MESSAGES[ERR_LEX], line, character); strFree(&s); freeTokenMem(&tok); return 42; } else if (c == '/') {//konec blokového komentáře jdeme hledat další lexém state = START; } else { state = BLOCK_COMMENT; } break; //dvouznakove operatry case TWO_CHAR_OPER: //jako druhy znak muze jen rovna se //dle prvniho znaku rozhodneme co ulozime if (c == '=') { switch (s.str[0]) { case '!': tok->typ = NOT_EQUAL_OPER; break; case '<': tok->typ = LESS_EQUAL; break; case '>': tok->typ = GREATER_EQUAL; break; case '=': tok->typ = EQUAL; break; default: break; } } //pokud prislo cokoli jineho tak dle prvniho znaku rozhodneme co ulozime else { pom = c; switch (s.str[0]) { case '!': tok->typ = LOG_NOT_OPER; break; case '<': tok->typ = LESS; break; case '>': tok->typ = GREATER; break; case '=': tok->typ = SET_OPER; break; default: break; } } strFree(&s); return 1; break; case DECREMENT_OPERATOR: //druhe minus v rade znamena dekrementaci if (c == '-') { tok->typ = DECREMENTATION; strFree(&s); return 1; } //cokoli jineho znamena pouze minus else { pom = c; tok->typ = MINUS; strFree(&s); return 1; } break; case INCREMENT_OPERATOR: //druhe plus v rade je inkrementace if (c == '+') { tok->typ = INCREMENTATION; strFree(&s); return 1; } //pouze scitani else { pom = c; tok->typ = PLUS; strFree(&s); return 1; } break; default: break; } } }
int get_token() { typedef enum { INIT, OPERATOR, SLASH, STRING, STRING_BACKSLASH, STRING_HEXA, STRING_BINARY, STRING_OCTA, NUMBER, FLOAT, FLOAT_EXP, ID, ID_KEYWORD, LINE_COMMENT, BLOCK_COMMENT, BLOCK_COMMENT_END, BASE_EXT, BINARY, OCTA, HEXA } Tstate; Tstate state = INIT; int c; int j = 0; int ret_val = 0; int escape_seq = 0; //char *check; strClear(buffer); token.type = TT_ERR; while ((c = fgetc(in))) { if (c == '\n') { row++; col = 0; } else col++; if (c == EOF) { token.type = TT_EOF; return EOF; } #ifdef SCANNER_DEBUG fprintf(stderr, "%s (%s)", fsm_states[state], strGetStr(buffer)); if (strFirst(buffer) == '\0') fprintf(stderr, "\n"); else fprintf(stderr, " -> "); #endif // DEBUG switch(state) { case INIT: if (c == '/') // comment or operator { state = SLASH; strAddChar(buffer, c); } else if (is_operator(c)) { state = OPERATOR; strAddChar(buffer, c); } else if (c == '"') // string literal { state = STRING; } else if (c == '\\') // x, b, 0 literals supported - BASE { state = BASE_EXT; } else if (isdigit(c)) // number -> integer or double literal { state = NUMBER; strAddChar(buffer, c); } else if (c == '_') // id { state = ID; strAddChar(buffer, c); } else if (isalpha(c)) // alphabetic char -> id or keyword { state = ID_KEYWORD; strAddChar(buffer, c); } else if ((ret_val = is_delimiter(c))) { token.type = TYPE_DELIMITER + ret_val - 1; #ifdef SCANNER_DEBUG fprintf(stderr, "%s\n", token_name[token.type]); #endif return OK; } else if (!isspace(c)) // non valid character { lex_error("Unknown character: '%c'.\n", c); } break; case BASE_EXT: if (c == 'b') { state = BINARY; } else if (c == '0') { state = OCTA; } else if (c == 'x') { state = HEXA; } else lex_error("Unknown character in literal '\\%c'.\n", c); break; case HEXA: if (isxdigit(c)) { if (j < 8) // 8 hexadecimal digits are max int value { literal[j] = c; j++; } else lex_error("Hexadecimal literal too long -> int overflow!\n"); } else { ungetc(c, in); token.type = TT_VALUE_INT; literal[j] = '\0'; token.value_int = (int) strtol(literal, NULL, 16); // cannot fail if (token.value_int < 0) lex_warning("Hexadecimal literal '\\x%s' overflow to negative number %d\n", literal, token.value_int); return OK; } break; case OCTA: if (c >= '0' && c <= '7') { if (j < 12) // max int = \0 7777 7777 7777 { literal[j] = c; j++; } else lex_error("Octal literal too long -> int overflow!\n"); } else { ungetc(c, in); token.type = TT_VALUE_INT; literal[j] = '\0'; token.value_int = (int) strtol(literal, NULL, 8); if (token.value_int < 0) lex_warning("Octal literal '\\0%s' overflow to negative number %d\n", literal, token.value_int); return OK; } break; case BINARY: if ((c == '0' || c == '1')) { if (j < 32) { literal[j] = c; j++; } else lex_error("Binary literal too long -> int overflow!\n"); } else { ungetc(c, in); token.type = TT_VALUE_INT; literal[j] = '\0'; token.value_int = (int) strtol(literal, NULL, 2); if (token.value_int < 0) lex_warning("Binary literal '\\b%s' overflow to negative number %d\n", literal, token.value_int); return OK; } break; case ID_KEYWORD: if (isalpha(c)) // add another char into buffer { strAddChar(buffer, c); } else if (c == '_' || isdigit(c)) // id - these chars are not in any keyword { state = ID; strAddChar(buffer, c); } else // end of id or keyword { ungetc(c, in); // return last read char to buffer ret_val = is_keyword(strGetStr(buffer)); if (ret_val) { token.type = TYPE_KEYWORD + ret_val - 1; // magic #ifdef SCANNER_DEBUG fprintf(stderr, "%s\n", token_name[token.type]); #endif return OK; } else { token.type = TT_ID; token.p_string = strGetStr(buffer); #ifdef SCANNER_DEBUG fprintf(stderr, "%s\n", token_name[token.type]); #endif return OK; } } break; case ID: if (isalnum(c) || c == '_') { strAddChar(buffer, c); } else { ungetc(c, in); token.type = TT_ID; token.p_string = strGetStr(buffer); #ifdef SCANNER_DEBUG fprintf(stderr, "%s\n", token_name[token.type]); #endif return OK; } break; case SLASH: if (c == '/') { state = LINE_COMMENT; } else if (c == '*') { state = BLOCK_COMMENT; } else // it was division { ungetc(c, in); token.type = TT_DIVIDE; #ifdef SCANNER_DEBUG fprintf(stderr, "%s\n", token_name[token.type]); #endif return OK; } break; case OPERATOR: // not precisely "normal" fsm, but easily extensible (just add operator to operators[] and Ttoken_type) if (is_operator(c)) // c is one of valid chars, that can be in operator { strAddChar(buffer, c); ret_val = determine_operator(strGetStr(buffer)); // check if we still have valid operator in buffer if (!ret_val) // if it's not valid operator { ungetc(c, in); // return last char, it was not part of operator strDelChar(buffer); // delete wrong char from buffer ret_val = determine_operator(strGetStr(buffer)); // determine which operator we have token.type = TYPE_OPERATOR + ret_val - 1; // return token #ifdef SCANNER_DEBUG fprintf(stderr, "%s\n", token_name[token.type]); #endif return OK; } // continue with loading chars if it's valid } else // another char is not operator -> end { ungetc(c, in); ret_val = determine_operator(strGetStr(buffer)); if (ret_val) { token.type = TYPE_OPERATOR + ret_val - 1; #ifdef SCANNER_DEBUG fprintf(stderr, "%s\n", token_name[token.type]); #endif return OK; } else // shouldn't occur, just to be sure.. { lex_error("Unknown operator: '%s'.\n", strGetStr(buffer)); } } break; case LINE_COMMENT: if (c == '\n') // end of line comment { state = INIT; strClear(buffer); } break; case BLOCK_COMMENT: if (c == '*') // possible end of comment state = BLOCK_COMMENT_END; break; case BLOCK_COMMENT_END: if (c == '/') // comment ended { state = INIT; strClear(buffer); } else // false alarm - comment continues state = BLOCK_COMMENT; break; case NUMBER: if (isdigit(c)) { strAddChar(buffer, c); } else if (c == '.') { strAddChar(buffer, c); state = FLOAT; } else if (tolower(c) == 'e') { strAddChar(buffer, c); state = FLOAT_EXP; } else { ungetc(c, in); token.type = TT_VALUE_INT; token.value_int = (int) strtol(strGetStr(buffer), NULL, 10); #ifdef SCANNER_DEBUG fprintf(stderr, "%s\n", token_name[token.type]); #endif return OK; } break; case FLOAT: // aspoň jedna číslice! if (isdigit(c)) { strAddChar(buffer, c); } else if (tolower(c) == 'e') { strAddChar(buffer, c); state = FLOAT_EXP; } else { ungetc(c, in); token.type = TT_VALUE_DOUBLE; token.value_double = strtod(strGetStr(buffer), NULL); //&check); #ifdef SCANNER_DEBUG fprintf(stderr, "%s\n", token_name[token.type]); #endif return OK; } break; case FLOAT_EXP: if (isdigit(c)) { strAddChar(buffer, c); } else if (tolower(strLast(buffer)) == 'e' && (c == '+' || c == '-')) // optional +/- after e/E { strAddChar(buffer, c); } else { ungetc(c, in); token.type = TT_VALUE_DOUBLE; token.value_double = strtod(strGetStr(buffer), NULL); //&check); #ifdef SCANNER_DEBUG fprintf(stderr, "%s\n", token_name[token.type]); #endif return OK; } break; case STRING: if (c == '"') // end of string literal { token.type = TT_VALUE_STRING; token.p_string = strGetStr(buffer); #ifdef SCANNER_DEBUG fprintf(stderr, "%s\n", token_name[token.type]); #endif return OK; } else if (c == '\\') // string literal continues on another line or character constant state = STRING_BACKSLASH; else if (c != '\n') { strAddChar(buffer, c); } else { lex_error("String literal not closed.\n"); } break; case STRING_BACKSLASH: state = STRING; if (c == '\\') { strAddChar(buffer, '\\'); } else if (c == 'n') { strAddChar(buffer, '\n'); } else if (c == 't') { strAddChar(buffer, '\t'); } else if (c == '"') { strAddChar(buffer, '"'); } else if (c == 'x') { state = STRING_HEXA; } else if (c == 'b') { state = STRING_BINARY; } else if (c == '0') { state = STRING_OCTA; } else if (c == '\n') { // do nothing, string continues on next line - TODO: zdokumentovat upravu } else { lex_error("Escape sequence '\\%c' unknown.\n", c); } break; case STRING_HEXA: if (j < 2 && isxdigit(c)) // 2 is max hexadecimal escape length { literal[j] = c; j++; } else if (j == 0) // no valid hexadecimal digit after \x -> error { lex_error("'\\x%c' is not valid hexadecimal escape sequence.\n", c); } else // end of hexadecimal escape { literal[j] = '\0'; escape_seq = strtol(literal, NULL, 16); // will always be successful if (escape_seq == 0) { lex_error("\\x00 is not allowed hexadecimal escape sequence.\n"); } strAddChar(buffer, escape_seq); ungetc(c, in); // return currently read char j = 0; state = STRING; } break; case STRING_BINARY: if (j < 8 && (c == '0' || c == '1')) // 8 is max binary escape length { literal[j] = c; j++; } else if (j == 0) // no valid binary digit after \b -> error { lex_error("'\\b%c' is not valid binary escape sequence.\n", c); } else // end of binary escape { literal[j] = '\0'; escape_seq = strtol(literal, NULL, 2); // will always be successful if (escape_seq == 0) { lex_error("\\b00000000 is not allowed binary escape sequence.\n"); } strAddChar(buffer, escape_seq); ungetc(c, in); // return currently read char j = 0; state = STRING; } break; case STRING_OCTA: if (j < 3 && c >= '0' && c <= '7') // 3 is max octal escape length { literal[j] = c; j++; } else if (j == 0) // no valid octal digit after \0 -> error { lex_error("'\\0%c' is not valid octal escape sequence.\n", c); } else // end of octal escape { literal[j] = '\0'; escape_seq = strtol(literal, NULL, 8); // will always be successful if (escape_seq == 0) { lex_error("\\000 is not allowed octal escape sequence.\n"); } else if (escape_seq > 255) { lex_error("Octal escape '\\0%s' bigger than 255.\n", literal); } strAddChar(buffer, escape_seq); ungetc(c, in); // return currently read char j = 0; state = STRING; } break; default: lex_error("Scanner panic!!!\n"); break; } // end_switch } // end_while return 0; }
int getNextToken(string *attr) { int esc = 0; int state = 0; //při hledání každého nového tokenu bude počáteční stav 0 int c; strClear(attr);//vyčítím řetězec pro nové použití while(1) { c = getc(source); if (c == EOF && state != 0) lErr(); switch (state) { /***** DEFAULT STATE *****/ case 0: if (isspace(c)) state = 0; else if (c == '<') state = 1; else if (c == '>') state = 2; else if (c == '!') state = 3; else if (c == '=') state = 4; else if (isdigit(c)) { strAddChar(attr, c); state = 5; } else if (isalpha(c) || c == '_') { strAddChar(attr, c); state = 11; } else if (c == '"') { state = 15; } else if (c == '/') state = 20; else { switch(c) { case ';': return STREDNIK; break; case '+': return PLUS; break; case '-': return MINUS; break; case '*': return NASOBENI; break; case ',': return CARKA; break; case '(': return L_ZAVORKA; break; case ')': return P_ZAVORKA; break; case '{': return LS_ZAVORKA; break; case '}': return PS_ZAVORKA; break; case EOF: return FILEEND; break; default: lErr(); break; } } break; /***** LESS OR LESS_OR_EQUALS *****/ case 1: if (c == '=') return MENE_NEBO_ROVNO; // token -> [<=, ] else if (c == '<') return ZAPIS; // token -> [<<, ] else { ungetc(c, source); return MENE; // token -> [<, ] } break; /***** MORE OR MORE_OR_EQUALS *****/ case 2: if (c == '=') return VICE_NEBO_ROVNO; // token -> [>=, ] else if (c == '>') return CTENI; // token -> [>>, ] else { ungetc(c, source); return VICE; // token -> [>, ] } break; /***** NOT EQUALS *****/ case 3: if (c == '=') return NEROVNOST; // token -> [!=, ] else lErr(); break; /***** EQUALS *****/ case 4: if (c == '=') return ROVNA_SE; // token -> [==, ] else { ungetc(c, source); return PRIRAZENI; } break; /***** INT OR DOUBLE *****/ case 5: if (isdigit(c)) strAddChar(attr, c); else if (c == '.') { strAddChar(attr, c); state = 6; } else if (c == 'e' || c == 'E') { strAddChar(attr, c); state = 8; } else { ungetc(c, source); return INT_V; } // token -> [INT_V, N] break; case 6: if (isdigit(c)) { strAddChar(attr, c); state = 7; } else lErr(); break; case 7: if (isdigit(c)) strAddChar(attr, c); else if (c == 'e' || c == 'E') { strAddChar(attr, c); state = 8; } else { ungetc(c, source); return DOUBLE_V; // token -> [DOUBLE_V, D.D] } break; case 8: if (isdigit(c)) { strAddChar(attr, c); state = 10; } else if (c == '+' || c == '-') { strAddChar(attr, c); state = 9; } else lErr(); break; case 9: if (isdigit(c)) { strAddChar(attr, c); state = 10; } else lErr(); break; case 10: if (isdigit(c)) strAddChar(attr, c); else { ungetc(c, source); return DOUBLE_V; } break; /***** ID OR KEYWORD *****/ case 11: if (isalnum(c) || c == '_') strAddChar(attr, c); else { ungetc(c, source); if (!strCmpConstStr(attr, "auto")) return AUTO; else if (!strCmpConstStr(attr, "cin")) return CIN; else if (!strCmpConstStr(attr, "cout")) return COUT; else if (!strCmpConstStr(attr, "double")) return DOUBLE; else if (!strCmpConstStr(attr, "else")) return ELSE; else if (!strCmpConstStr(attr, "for")) return FOR; else if (!strCmpConstStr(attr, "if")) return IF; else if (!strCmpConstStr(attr, "int")) return INT; else if (!strCmpConstStr(attr, "return")) return RETURN; else if (!strCmpConstStr(attr, "string")) return STRING; else return ID; } break; /***** STRING *****/ case 15: if (c == '\\') { state = 16; } else if (c == '"') { return STRING_V; } else strAddChar(attr, c); break; case 16: if (c == '\\') { strAddChar(attr, '\\'); state = 15; } else if (c == 't') { strAddChar(attr, '\t'); state = 15; } else if (c == 'n') { strAddChar(attr, '\n'); state = 15; } else if (c == '"') { strAddChar(attr, '"'); state = 15; } else if (c == 'x') { state = 17; } else { lErr(); } break; case 17: if (isxdigit(c)) { if (c >= 'a' && c <= 'f') { esc = (c - 'a' + 10) * 16; } else if (c >= 'A' && c <= 'F') { esc = (c - 'A' + 10) * 16; } else { esc = (c - '0') * 16; } state = 18; } else lErr(); break; case 18: if (isxdigit(c)) { if (c == '0' && esc == 0) lErr(); if (c >= 'a' && c <= 'f') { esc = esc + (c - 'a' + 10); } else if (c >= 'A' && c <= 'F') { esc = esc + (c - 'A' + 10); } else { esc = esc + (c - '0'); } strAddChar(attr, esc); state = 15; } else lErr(); break; /***** COMMENT *****/ case 20: if (c == '*') state = 21; else if (c == '/') state = 23; else { ungetc(c, source); return DELENI; } break; case 21: if (c == '*') state = 22; break; case 22: if (c == '/') state = 0; else state = 21; break; case 23: if (c == '\n') state = 0; break; } } }
int getNextToken(string *attr){ char c; int stav = STATE_START; strClear(attr); while(1){ c = getc(sourceFile); switch(stav){ case STATE_START: if(isspace(c)){ stav = STATE_START; } else if(isalpha(c) || c == '_'){ // znaky: a-zA-Z nebo _ strAddChar(attr, c); stav = STATE_ALPHANUM; } else if(isdigit(c)){ // cisla strAddChar(attr, c); stav = STATE_DIGIT; } else if(c == 34) { // " //printf("%c", c); // strAddChar(attr, c); stav = STATE_STRING; } else { switch(c){ case '+': return TOK_ADDITION; break; case '-': return TOK_SUBTRACTION; break; case '*': return TOK_MULTIPLICATION; break; case '/': stav = STATE_SLASH; break; case '<': stav = STATE_LESS_THAN; break; case '>': stav = STATE_GREATER_THAN; break; case '=': stav = STATE_EQUALS; break; case '!': stav = STATE_INEQUALITY; break; case ';': return TOK_SEMICOLON; break; case '(': return TOK_LEFT_BRACKET; break; case ')': return TOK_RIGHT_BRACKET; break; case '.': return TOK_DOT; break; case ',': return TOK_COMMA; break; case EOF : return TOK_END_OF_FILE; break; case '{' : return TOK_LEFT_BRACE; break; case '}' : return TOK_RIGHT_BRACE; break; default: printf("defualt %c", c); break; } } break; case STATE_INEQUALITY: if(c == '='){ return TOK_INEQUALITY; } else { ungetc (c,sourceFile); return LEX_ERROR; } break; case STATE_STRING: if(c == '"'){ // strAddChar(attr, c); return TOK_STR; } else if(c == 92){ // ASCII 92 je zpetne lomitko // strAddChar(attr, c); stav = STATE_ESCAPE_SEQUENCE; } else if (c == EOF){ ungetc(c, sourceFile); return LEX_ERROR; } else if(c != 34 && c > 31){ strAddChar(attr, c); } else { ungetc(c, sourceFile); return LEX_ERROR; } break; case STATE_ESCAPE_SEQUENCE: if(c == 'n'){ strAddChar(attr, '\n'); stav = STATE_STRING; } else if (c == 92){ strAddChar(attr, '\\'); stav = STATE_STRING; } else if (c == 't'){ strAddChar(attr, '\t'); stav = STATE_STRING; } else if (c == '"'){ // strAddChar(attr, c); stav = STATE_STRING; } else if (c == 'x'){ strAddChar(attr, 92); strAddChar(attr, c); stav = STATE_HEXA_CHAR; } else { ungetc(c, sourceFile); return LEX_ERROR; } break; case STATE_HEXA_CHAR: if((c >= 48 && c <= 57) || (c >= 65 && c <= 70) || (c >= 97 && c <= 102)){ strAddChar(attr, c); stav = STATE_HEXA_CHAR_SECOND; } else { ungetc(c, sourceFile); return LEX_ERROR; } break; case STATE_HEXA_CHAR_SECOND: if((c >= 48 && c <= 57) || (c >= 65 && c <= 70) || (c >= 97 && c <= 102)){ strAddChar(attr, c); stav = STATE_STRING; } else { ungetc(c, sourceFile); return LEX_ERROR; } break; case STATE_DIGIT: if(isdigit(c)){ // prislo dalsi cislo strAddChar(attr, c); } else if(c == '.'){ strAddChar(attr, c); stav = STATE_FLOATING_POINT; } else if(c == 'E' || c == 'e'){ strAddChar(attr, c); stav = STATE_EXPONENT; } else { ungetc (c,sourceFile); return TOK_DECIMAL_NUMBER; } break; case STATE_FLOATING_POINT: if(isdigit(c)){ strAddChar(attr, c); } else if(c == 'E' || c == 'e'){ strAddChar(attr, c); stav = STATE_EXPONENT; } else { ungetc (c,sourceFile); return TOK_FLOATING_POINT_NUMBER; } break; case STATE_EXPONENT:// if(isdigit(c) != 0) { strAddChar(attr, c); stav = STATE_MORE_IN_EXPONENT; } else if(c == '+' || c == '-') { strAddChar(attr, c); stav = STATE_MORE_IN_EXPONENT; } else { ungetc(c, sourceFile); return LEX_ERROR; } break; case STATE_MORE_IN_EXPONENT: if(isdigit(c) != 0) { strAddChar(attr, c); stav = STATE_MORE_IN_EXPONENT2; } else { ungetc(c, sourceFile); return LEX_ERROR; } break; case STATE_MORE_IN_EXPONENT2: if(isdigit(c) != 0) { strAddChar(attr, c); } else if(c == ' ' || c == ';' || c == ')' || c == '+' || c == '-' || c == '/' || c == '*'){ ungetc(c, sourceFile); return TOK_FLOATING_POINT_NUMBER; } else{ ungetc(c, sourceFile); return LEX_ERROR; } break; case STATE_EQUALS: if(c == '='){ return TOK_COMPARISON; } else { ungetc (c,sourceFile); return TOK_EQUALS; break; } break; case STATE_ALPHANUM: if(!(isalnum(c) || c == '_')){ // kdyz neni toto: a-zA-Z0-9 nebo _ //printf("STATE_ALPHANUM: %s", attr->str); ungetc(c, sourceFile); if(0 == strCmpConstStr(attr, "int")){ return TOK_INT; } else if(0 == strCmpConstStr(attr, "double")){ return TOK_DOUBLE; } else if(0 == strCmpConstStr(attr, "else")){ return TOK_ELSE; } else if(0 == strCmpConstStr(attr, "if")){ return TOK_IF; } else if(0 == strCmpConstStr(attr, "return")){ return TOK_RETURN; } else if(0 == strCmpConstStr(attr, "string")){ return TOK_STRING; } else if(0 == strCmpConstStr(attr, "auto")){ return TOK_AUTO; } else if(0 == strCmpConstStr(attr, "cin")){ return TOK_CIN; } else if(0 == strCmpConstStr(attr, "for")){ return TOK_FOR; } else if(0 == strCmpConstStr(attr, "cout")){ return TOK_COUT; } else { return TOK_ID; } } else { strAddChar(attr, c); } break; case STATE_GREATER_THAN: switch(c){ case '=': return TOK_GREATER_THAN_OR_EQUAL; break; case '>': return TOK_DOUBLE_ARROW_RIGHT; break; default: ungetc (c,sourceFile); return TOK_GREATER_THAN; break; } break; case STATE_LESS_THAN: switch(c){ case '=': return TOK_LESS_THAN_OR_EQUAL; break; case '<': return TOK_DOUBLE_ARROW_LEFT; break; default: ungetc (c,sourceFile); return TOK_LESS_THAN; break; } break; case STATE_SLASH: switch(c){ case '/': stav = STATE_LINE_COMMENT; break; case '*': stav = STATE_BLOCK_COMMENT; break; default: ungetc (c,sourceFile); return TOK_DIVISION; break; } case STATE_LINE_COMMENT: if(c == '\n'){ stav = STATE_START; } break; case STATE_BLOCK_COMMENT: if(c == '*'){ stav = STATE_BLOCK_COMMENT_STAR; } break; case STATE_BLOCK_COMMENT_STAR: if(c == '/'){ stav = STATE_START; } break; default: break; } } return LEX_ERROR; }
/** * Funkce readStrToNl nacita z stdin retezec po konec radku. * @param var string. */ void readStrToNl(string *var) { int c; while((c = getchar()) != '\n') strAddChar(var,(char)c); }
int LokTableInsert(tGlobSymbolTable *T, string *nazev, int typ,Tridic *ridic){/*vlození noveho uzlu do lok table*/ sLokTableItem *novy; sLokTableItem *pomloka; int koren=0; if ((novy = (sLokTableItem*) malloc(sizeof(sLokTableItem)))==NULL) error(T,OTHER_RUNN_ERR,ridic);/*alokace mista na novy lokalni prvek*/ ridic->aktiv=novy;/*nastaveni aktivity na novy prvek*/ novy->data.def=1;/*plneni prvku*/ strInit(&(novy->data.nazev)); novy->data.typ=typ; novy->lptr=NULL; novy->rptr=NULL; if ( ridic->pomlog || ridic->deklaration){/*pokud se jedna o hlavicku fce*/ ridic->pocet_argumentu++; novy->data.def=1;/*argument je inicialyzovany*/ novy->poradi_argumentu=ridic->pocet_argumentu;/*poradí argumentu*/ }else { novy->data.def=0;/*lokalni promenna neni inicializovana*/ novy->poradi_argumentu=0;/*nejedna se o argument funkce*/ } if (nazev!=NULL){/*pokud se nejedna o navratovy typ*/ strCopyString((&novy->data.nazev), nazev);/*naplnim nazev*/ }else { strCopyString((&novy->data.nazev), &(ridic->nazev_func));/*jinak ziskam nazev z globalni tabulky z aktualniho prvku*/ novy->data.def=3; } sGlobTableItem *pomgl; koren=0; pomgl = T->first;/*nastavime koren stromu*/ koren= tableSearchGlob(ridic,&pomgl,&(novy->data.nazev));/*prohledame glob tabulku kvuli shodnym nazvum fci*/ if (koren==0 && nazev!=NULL){/*pokud byl prvek nalezen a lok promenna neni navratovy typ*/ if (pomgl->data.typ==FUNCTION_HEADER){/*pokud byla nalezena glob uzel ktery je funkce*/ ItemFreeAktu(NULL, novy);/*uvolni pridavany prvek*/ error(T,TAB_ERR,ridic);/*chyba v ramci tabulky*/ } } if (ridic->deklaration>0){/*pokud jsme v hlavicce funkce*/ sLokTableItem *poml; sGlobTableItem *pomgl; pomgl = ridic->aktivG;/*jako pomocný glob uzel nastavime aktivni glob uzel*/ poml=pomgl->link;/*jako pomocnou lok. tabulku nastavime odkaz z aktivniho glob uzlu*/ koren=0; koren=tableSearchLok(ridic,&poml,&(novy->data.nazev)); if (koren){ ItemFreeAktu(NULL, novy);/*uvolnime pridávany prvek*/ error(T,TAB_ERR,ridic);/*chyba v ramci tabulky*/ } ridic->deklaration++;/*kontrola poctu argumentu*/ if (ridic->deklaration==strGetLength(&(pomgl->arg))+1) {ridic->deklaration=0;}/*pocet prvku deklrovane a definovane funkce je jiny*/ if (poml->data.typ==typ){/*pokud sedi typ argumentu deklarovane a definovane funkce*/ if (poml->poradi_argumentu==novy->poradi_argumentu){/*pokud je na stejnem miste*/ if (nazev!=NULL){/*pokud se nejedna o navratovy parametr*/ if ((strCmpString(&(poml->data.nazev), nazev)==0)) {/*pokud sedi nazvy*/ ItemFreeAktu(NULL, novy);/*uvolnime vkladany argument*/ return 1;/*agrumnet je totozny*/ }else { ItemFreeAktu(NULL, novy);/*uvolnime vkladany argument*/ error(T,TAB_ERR,ridic);/*error v ramci tabulky*/ } }else{/*pokud se jedna o navratovy parametr*/ if (ridic->deklaration==strGetLength(&(ridic->aktivG->arg))) {/*pokud neni stejny pocet argumentu*/ ItemFreeAktu(NULL, novy);/*uvolnime vkladany argument*/ error(T,TAB_ERR,ridic);/*error v ramci tabulky*/ } ridic->aktivG=pomgl;/*uvolnime vkládaný argument*/ ItemFreeAktu(NULL,novy);/*error v ramci tabulky*/ return 1;/*agrumnet je totozny*/ } }else {/*nejedna se o stejny typ*/ ItemFreeAktu(NULL, novy);/*uvolníme vkladany argument*/ error(T,TAB_ERR,ridic);/*error v ramci tabulky*/ } } } else{/*pokud pridavame lokalni promennou*/ if (ridic->aktivG->link==NULL){/*pokud je strom prazdny*/ ridic->aktivG->link=novy;/*pridame jako koren*/ }else{ pomloka=ridic->aktivG->link; koren=0; koren=tableSearchLok(ridic,&pomloka,&(novy->data.nazev)); if (koren==0){/*pokud j*z prvek se stejnym klicem existuje*/ ItemFreeAktu(NULL, novy);/*uvolnime vkladany argument*/ error(T,TAB_ERR,ridic);/*error v ramci tabulky*/ } if (koren==1){/*pridame do leveho podstromu*/ pomloka->lptr=novy; }else if (koren==2) {pomloka->rptr=novy;}/*pridáme do praveho podstromu*/ } if ( (ridic->pomlog ) || (nazev==NULL) ){/*pokud jsme v hlavicce funkce*/ switch(typ){/*pridame typ argumnetu do glob tabulky*/ case TP_INT: if (strAddChar(&(ridic->aktivG->arg),'i')); break; case TP_REAL: if (strAddChar(&(ridic->aktivG->arg),'r')); break; case TP_STRING: if (strAddChar(&(ridic->aktivG->arg),'s')); break; case BOOLEAN: if (strAddChar(&(ridic->aktivG->arg),'b')); break; } } if (nazev==NULL) {/*pokud uz byl predan i navratovy typ*/ ridic->pocet_argumentu=0; /*nasleduji lok promenne*/ ridic->pomlog=0;/*nejsme j*z v hlavicce funkce*/ } return 1; } return 0; }
int getNextToken(string *attr) { int state = 0; int c; // vymazeme obsah atributu a v pripade identifikatoru // budeme postupne do nej vkladat jeho nazev strClear(attr); while (1) { // nacteni dalsiho znaku c = getc(source); switch (state) { case 0: // zakladni stav automatu if (isspace(c)) // bila mista - ignorovat state = 0; else if (c == '<') // komentar state = 1; else if (isalpha(c)) // identifikator nebo klicove slovo { strAddChar(attr, c); state = 2; } else if (c == '+') // operator ++ state = 3; else if (c == '-') // operator -- state = 4; else if (c == '{') return LEFT_VINCULUM; else if (c == '}') return RIGHT_VINCULUM; else if (c == ';') return SEMICOLON; else if (c == EOF) return END_OF_FILE; else return LEX_ERROR; break; case 1: // komentar if (c == '>') state = 0; else // komentar pokracuje libovolnymi znaky, zustan ve stavu 1, // ale kontroluj, zda neprijde EOF (neukonceny komentar) if (c == EOF) return LEX_ERROR; break; case 2: // identifikator nebo klicove slovo if (isalnum(c)) // identifikator pokracuje strAddChar(attr, c); else // konec identifikatoru { ungetc(c, source); // POZOR! Je potreba vratit posledni nacteny znak // kontrola, zda se nejedna o klicove slovo if (strCmpConstStr(attr, "setzero") == 0) return SETZERO; else if (strCmpConstStr(attr, "read") == 0) return READ; else if (strCmpConstStr(attr, "write") == 0) return WRITE; else if (strCmpConstStr(attr, "while") == 0) return WHILE; else // jednalo se skutecne o identifikator return ID; } break; case 3: // pokracovani operatoru ++ if (c == '+') return INC; else return LEX_ERROR; break; case 4: // pokracovani operatoru -- if (c == '-') return DEC; else return LEX_ERROR; break; } } }
void cString(string1 *s1, string1 *p) { int lenp = strlen(p->data); char ascii = 0; int len = 0; int index = 1; p->length = strlen(p->data); if ((p->data[0] != '\'') && (p->data[lenp-1] != '\'')) { error(4); } else { while (index < lenp-1) { if (p->data[index] != '\'') { strAddChar(s1, p->data[index]); index++; len++; } else { index++; if (p->data[index] == '\'') { strAddChar(s1, p->data[index]); len++; index++; } else if (p->data[index] == '\0') { error(4); } else if (p->data[index] != '#') { error(4); } else { int isnum = -1; index++; while (p->data[index] >= '0' && p->data[index] <= '9') { if (isnum == -1) { int num = 0; if ((num = strtol(&p->data[index], NULL, 10)) <= 255) { ascii = num; } } index++; isnum = 1; } if (p->data[index] != '\'' || isnum == -1) { error(4); } else { strAddChar(s1, ascii); len++; index++; } } } } s1->length = len; } }