/* Skip blanks and whitespace. Expand this function to skip comments too. */ void skipblanks () { int c; while ((c = peekchar()) != EOF && (c == ' ' || c == '\n' || c == '\t' || c == '{' || (c == '(' && peek2char() == '*'))){ // { } comments if((c = peekchar()) == '{'){ while((c = peekchar()) != '}'){ getchar(); } } // (* *) comments int loop = 1; if((c = peekchar()) == '(' && (c = peek2char()) == '*'){ getchar(); // ( while(loop){ getchar(); // * if(peekchar() == '*' && peek2char() == ')'){ //exit getchar(); //grab *, then stop looping loop = 0; } } } getchar(); // will grab last ) and } } }
/* Skip whitespace and comments. Moves the stream pointer * to right before the next valid character. */ void skipblanks () { int c, d; boolean done = FALSE; while ((c = peekchar()) != EOF && (c == ' ' || c == '\n' || c == '\t' || c == 13 || c == '(' || c == '{')) { /* Comment is of the form {}; parse through it. */ if (c == '{') { c = getchar(); done = FALSE; while (!done) { c = getchar(); if (c == EOF) { EOFFLG = 1; done = TRUE; } if (c == '}') { done = TRUE; } } } /* Comment is of the form (**). Check the next character to confirm * that this is actually a comment before parsing through it. */ if (c == '(' && (d = peek2char()) == '*') { getchar(); getchar(); done = FALSE; while (!done) { c = getchar(); if (c == EOF) { EOFFLG = 1; done = TRUE; } if (c == '*' && (d = peekchar()) == ')') { getchar(); done = TRUE; } } } else if (c == '(') { /* Not a comment. Break. */ break; } getchar(); } }
TOKEN getstring (TOKEN tok){ //assuming no empty strings, no s := '' char string[16]; int index = 0, loop = 1; int c; getchar(); //grab first apostrophe while(loop){ c = getchar(); //first character of string, assuming at least length 1 //escaped apostrophe if(peekchar() == '\''){ if(peek2char() != '\''){ getchar(); //if not at max string if(index < 15){ string[index] = c; string[index+1] = 0; //not escaped, null terminate string } loop = 0; } else{ //escaped, grab one apostrophe getchar(); string[index] = c; index++; } } else{ //normal character //if not at max string if(index < 15){ string[index] = c; index++; } } string[15] = 0; //null terminate, special condition where string is too large } strcpy(tok->stringval, string); tok->tokentype = STRINGTOK; tok->datatype = STRINGTYPE; }
//capturing only 8 significant digits right now. double check this. TOKEN number (TOKEN tok) { long num = 0; int c, charval; char integ[100]; char frac[100]; //null terminate these when done int decFound = 0, index = 0, decIndex = 0, integCount = 0, fracCount = 0, eFound = 0, i = 0; int tens = 0; //num * 10^0 initially int sigOffset = 0; //subtract from index to get number of significant digits int expo = 0; int startSig = 0; //once a significant figure is foundm, set to 1 int zerosAfterDec = 0; //counts the number of zeros after the decimal. use when there are only 0's before decimal int zerosBeforeDec = 0; //counts the number of zeros skipped before the decimal point. while ((c = peekchar()) != EOF && ((CHARCLASS[c] == NUMERIC) || c == '.' || c == 'e')){ while(((c = peekchar()) == '0' || c == '.') && !startSig){ //while(((c = peekchar()) == '0' || c == '.') && !startSig && CHARCLASS[c] == NUMERIC){ <- this does not work. dont try again c = getchar(); if(c == '.' && peekchar() == '.'){ //put back '.' and this number is done ungetc(c, stdin); tok->tokentype = NUMBERTOK; tok->datatype = INTEGER; tok->intval = num; return tok; //special condition for 0 followed by .. delimiter } if(c == '.'){ decFound = 1; decIndex = index; } else if(decFound && c == '0'){ //this is messing with frac[] array. something with decIndex i think... zerosAfterDec++; } else if(!decFound && c == '0'){ zerosBeforeDec++; } index++; } //printf("zerosAfterDec = %d, zerosBeforeDec = %d\n", zerosAfterDec, zerosBeforeDec); if(c == '.' && peek2char() == '.') break; startSig = 1; sigOffset = index; c = getchar(); if(c == 'e'){ expo = exponent(); eFound = 1; } else if(c == '.'){ decIndex = index; decFound = 1; } else if(CHARCLASS[c] == NUMERIC){ if(!decFound){ //adding integer part charval = (c - '0'); num = num * 10 + charval; integ[index - zerosBeforeDec] = c; integCount++; } else if(decFound && c != '.'){ frac[index - decIndex - zerosAfterDec - 1] = c; fracCount++; } } else //special case for 0 and trimming non significant digits ungetc(c, stdin); index++; } //if integer, check for overflow char maxint[10] = "2147483647"; int greater = 0; if(!decFound && integCount > 0){ if(integCount > 10) printf("ERROR: INTEGER OVERFLOW FOR FOLLOWING TOKEN\n"); if(integCount == 10){ int i = 0; while(integ[i] == maxint[i] && i < integCount) i++; if(i != integCount){ if(integ[i] > maxint[i]) printf("ERROR: INTEGER OVERFLOW FOR FOLLOWING TOKEN\n"); } } } //if decFound && integCount > 8. truncate and modify exponent char integ2[8]; if(decFound && integCount > 8){ fracCount = 0; //all 8 significant digits will be in integ[] expo += integCount - 8; integCount = 8; //recalculate num i = 0; num = 0; for(; i < 8; i++){ charval = integ[i] - '0'; num = num * 10 + charval; } } /* if(decFound && fracCount > 8){ integCount = 0; expo -= fracCount - 8; fracCount = 8; } */ tok->tokentype = NUMBERTOK; if(!decFound && !eFound){ tok->datatype = INTEGER; tok->intval = num; } else{ float mult = 0.1f; float fNum = num/1.0; int j = 0; for(; j < fracCount; j++){ fNum = fNum + (frac[j] - '0')*mult; mult /= 10; } if((expo - zerosAfterDec) > 38 || (expo - zerosAfterDec) < -38) printf("ERROR: FLOAT OVERFLOW FOR FOLLOWING TOKEN\n"); fNum = fNum * pow(10.0, expo/1.0) * pow(10.0, -zerosAfterDec/1.0); //adding in multiplication by factor of 10 tok->datatype = REAL; tok->realval = fNum; } return (tok); }
/* Reads the number(s) starting from the current stream pointer location. * If the number is an integer, stores it in the argument TOKEN's intval * var. If it is a float, stores it in the argument TOKEN's realval var. * * Checks for overflow for (unsigned) integers and over-/underflow in floats. * * Returns the TOKEN given in the argument. */ TOKEN number(TOKEN tok) { int c, cclass, cint, d, dclass; double num = 0; boolean is_real = FALSE; /* For real numbers (i.e., when the input token has a '.' in it). */ boolean use_e = FALSE; /* For when a token represents a number in (scientific) E notation. */ boolean e_mult = FALSE; /* Flag used to determine which direction to shift the decimal point. */ double frac = 0; /* For the numbers to the right of the decimal place. Is always < 1. */ double counter = 1; int num_insig_figs = 0; /* Used when checking for over-/underflow. */ while ((c = peekchar()) != EOF) { cclass = CHARCLASS[c]; if (cclass != NUMERIC && c != '.' && c != 'e' && c != 'E') { break; } else if (c == 'e' || c == 'E') { d = peek2char(); dclass = CHARCLASS[d]; if (dclass != NUMERIC && d != '+' && d != '-') { break; // should throw an error } if (d == '+') { getchar(); e_mult = TRUE; } else if (d == '-') { getchar(); } else if (dclass == NUMERIC) { e_mult = TRUE; } // getchar(); // c = peek2char(); // if ((cclass = CHARCLASS[c]) != NUMERIC) { //printf("\tfuckles; curr d is %c, curr c is %c\n", d, c); // break; // } // CALL "PEEK3CHAR" TO SEE IF AT LEAST ONE DIGIT AFTER PLUS/MINUS SIGN? use_e = TRUE; /* The number being processed is a float. Since the value of everything * to the right of the decimal point is not computed until after this * loop, and its value is needed before that time, compute it now. */ if (is_real) { double temp = 1; //printf("hi\n"); int i; for (i = 1; i < counter; i++) { temp *= 10; } num = num + (frac / temp); frac = 0; counter = 1; is_real = FALSE; } } else if (c == '.') { d = peek2char(); if (d == EOF || d == '.' || (dclass = CHARCLASS[d]) != NUMERIC) { break; // should throw an error } is_real = TRUE; } else { cint = (c - '0'); if (use_e) { frac = frac * 10 + cint; } else if (is_real) { frac = frac * 10 + cint; counter++; if (num == 0) { num_insig_figs++; } } else { num = num * 10 + cint; num_insig_figs++; } } getchar(); } tok->tokentype = NUMBERTOK; //printf("frac is %f, num insig figs is %d, use_e is %d\n", frac, num_insig_figs, use_e); if (use_e) { tok->datatype = REAL; /* Ignore insignificant figures when checking for over-/underflow. */ if ((num_insig_figs - frac) > FLT_MAX_10_EXP || (num_insig_figs - frac) < FLT_MIN_10_EXP) { //printf("\tin use_e: frac is %f, num insig figs is %d\n", frac, num_insig_figs); printf("Floating number out of range\n"); tok->realval = 0; } else { int i; for (i = 0; i < frac; i++) { if (e_mult) { num *= 10; } else { num /= 10; } } tok->realval = num; } } else if (is_real) { tok->datatype = REAL; /* Ignore insignificant figures when checking for over-/underflow. */ if ((num_insig_figs - counter) > FLT_MAX_10_EXP || (num_insig_figs - counter) < FLT_MIN_10_EXP) { // last test needed? //printf("\tin is_real: frac is %f, num insig figs is %d\n", frac, num_insig_figs); printf("Floating number out of range\n"); tok->realval = 0; } else { double temp = 1; int i; for (i = 1; i < counter; i++) { temp *= 10; } tok->realval = num + (frac / temp); } } else { tok->datatype = INTEGER; if (num > INT_UNSIGNED_MAX) { printf("Integer number out of range\n"); tok->intval = INT_UNSIGNED_MAX; // return gettoken(); // enable if don't want out-of-range msg to be printed; disable prev line } else { tok->intval = num; } } return tok; }
/* Reads the string starting from the current stream pointer * location. Stores the string in the argument TOKEN's * tokenstring[] var. Truncates strings if they are greater than * 15 characters in length. Returns the TOKEN given in the argument. */ TOKEN getstring (TOKEN tok) { int c, d, cclass; int counter = 0; c = peekchar(); if (c == '\'') { // consume the first apostrophe getchar(); } else { // ???????????????????????????????? } while ((c = peekchar()) != EOF && (d = peek2char()) != EOF && counter < 15) { // cclass = CHARCLASS[c]; // if (c != '\'' && cclass != ALPHA && cclass != NUMERIC) { // break; // } /* Double apostrophe found. */ if (c == '\'' && d == '\'') { getchar(); getchar(); tok->tokenval.tokenstring[counter] = '\''; counter++; continue; } else if (c == '\'' && d != '\'') { /* End of string reached. Break. */ getchar(); counter++; break; } else { tok->tokenval.tokenstring[counter] = c; } getchar(); // should it be looping until it finds the last single apostrophe? /* Token may be longer than 15 characters; if it is, parse * through the rest of it. */ if (counter == 14) { c = peekchar(); d = peek2char(); while (c != '\'' && d != '\'' && d != EOF) { // check c != eof? getchar(); c = peekchar(); d = peek2char(); } // add eof check here? getchar(); getchar(); } counter++; } tok->tokenval.tokenstring[counter] = '\0'; tok->tokentype = STRINGTOK; return tok; }