📄 scan.c
字号:
state = S_NUMPT; break; } /* go to fraction state */ if ((ccl == C_LETTER) /* if a letter */ || (ccl == C_SIGN)) { /* or a sign follows, */ state = S_ID; break; } /* go to 'identifier' state */ if ((c == '>') /* if a '>' follows and previous */ && (scan->value[0] == '-')) { /* char was a minus sign */ *p = '\0'; scan->len = 2; return scan->token = T_RGT; } UNGETC(scan, c); /* otherwise put back last character, */ *--p = '\0'; /* terminate string in buffer */ scan->len = (int)(p -scan->value); /* set string length */ return scan->token = T_ID; /* and return 'identifier' */ case S_CMPOP: /* --- comparison operator read */ if ((c == '-') /* if a minus sign follows and */ && (scan->value[0] == '<')) { /* prev. char was a '<' */ *p++ = '-'; scan->token = T_LFT; } else if (c == '=') { /* if an equal sign follows */ *p++ = '='; scan->token = T_CMP; } else { /* if anything else follows */ UNGETC(scan, c); scan->token = scan->value[0]; } *p = '\0'; /* terminate string in buffer */ scan->len = (int)(p -scan->value); /* set string length */ return scan->token; /* and return the token read */ case S_STRING: /* --- quoted string */ if ((c == '\n') || (c == EOF)) /* if end of line or file, */ return scan->token = E_UNTSTR; /* string is unterminated */ if (c != quote) { /* if not at end of string */ if (p >= end) return scan->token = E_BUFOVF; if (c == '\\') { /* if escaped character follows, */ state = S_ESC; break; } /* go to escaped char state */ *p++ = c; break; /* otherwise buffer character */ } /* if at end of string, */ *p = '\0'; /* terminate string in buffer */ scan->len = (int)(p -scan->value); /* set string length */ return scan->token = T_ID; /* and return 'identifier' */ case S_ESC: /* --- after '\' in quoted string */ if ((c >= '0') && (c <= '7')) { /* if octal digit, */ ec = c -'0'; state = S_OCT1; break; }/* evaluate digit */ if (c == 'x') { /* if hexadecimal character code, */ state = S_HEX1; break;} /* go to hexadecimal evaluation */ switch (c) { /* evaluate character after '\' */ case 'a': c = '\a'; break; case 'b': c = '\b'; break; case 'f': c = '\f'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'v': c = '\v'; break; case '\n': c = -1; break; default : break; } /* get escaped character */ if (c >= 0) *p++ = c; /* and store it, then */ state = S_STRING; break;/* return to quoted string state */ case S_OCT1: /* --- escaped octal number 1 */ if ((c >= '0') /* if an octal digit follows, */ && (c <= '7')) { /* evaluate it */ ec = ec *8 +c -'0'; state = S_OCT2; break; } UNGETC(scan, c); /* otherwise put back last character */ *p++ = ec; /* store escaped character and */ state = S_STRING; break;/* return to quoted string state */ case S_OCT2: /* --- escaped octal number 2 */ if ((c >= '0') || (c <= '7')) ec = ec *8 +c -'0'; /* if octal digit, evaluate it */ else UNGETC(scan, c); /* otherwise put back last character */ *p++ = ec; /* store escaped character and */ state = S_STRING; break;/* return to quoted string state */ case S_HEX1: /* --- escaped hexadecimal number 1 */ if (ccl == C_DIGIT) { /* if hexadecimal digit, evaluate it */ ec = c -'0'; state = S_HEX2; break; } if ((c >= 'a') && (c <= 'f')) { ec = c -'a' +10; state = S_HEX2; break; } if ((c >= 'A') && (c <= 'F')) { ec = c -'A' +10; state = S_HEX2; break; } UNGETC(scan, c); /* otherwise put back last character */ *p++ = 'x'; /* store escaped character ('x') and */ state = S_STRING; break;/* return to quoted string state */ case S_HEX2: /* --- escaped hexadecimal number 2 */ if (ccl == C_DIGIT) /* if hexadecimal digit, evaluate it */ ec = ec*16 +c -'0'; else if ((c >= 'a') && (c <= 'f')) ec = ec*16 +c -'a' +10; else if ((c >= 'A') && (c <= 'F')) ec = ec*16 +c -'A' +10; else UNGETC(scan, c); /* otherwise put back last character */ *p++ = ec; /* store escaped character and */ state = S_STRING; break;/* return to quoted string state */ case S_SLASH: /* --- slash '/' */ if (c == '/') { /* if C++ style comment, then */ state = S_CPPCOM; break; } /* skip to end of line */ if (c == '*') { /* if C style comment */ scan->start = scan->line; level = 1; state = S_CCOM1; break; /* note start line, init. level */ } /* and go to first 'comment' state */ UNGETC(scan, c); /* otherwise put back last character */ *p++ = '/'; *p = '\0'; /* store character in buffer */ scan->len = 1; /* set string length and */ return scan->token = '/'; /* return `character' */ case S_CPPCOM: /* --- C++ style comment */ if ((c == '\n') /* if at end of line */ || (c == EOF)) /* or at end of file */ state = S_SPACE; /* return to white space skipping */ break; /* (skip to end of line) */ case S_CCOM1: /* --- C style comment 1 */ if (c == EOF) /* if end of file, abort */ return scan->token = E_UNTCOM; if (c == '*') /* if possibly 'end of comment', */ state = S_CCOM2; /* go to 2nd 'comment' state */ else if (c == '/') /* if possibly 'start of comment', */ state = S_CCOM3; /* go to 3rd 'comment' state */ break; case S_CCOM2: /* --- C style comment 2 */ if (c == EOF) /* if end of file, abort */ return scan->token = E_UNTCOM; if (c == '/') { /* if end of comment found */ if (--level <= 0) state = S_SPACE; else state = S_CCOM1; } else if (c != '*') /* if end of comment impossible */ state = S_CCOM1; /* return to comment skipping */ break; /* (possible start of comment) */ case S_CCOM3: /* --- C style comment 3 */ if (c == EOF) /* if end of file, abort */ return scan->token = E_UNTCOM; if (c == '*') { /* if start of comment found */ level++; state = S_CCOM1; } else if (c != '/') /* if start of comment impossible */ state = S_CCOM1; /* return to comment skipping */ break; /* (possible end of comment) */ default: /* if state is illegal, abort */ return scan->token = E_STATE; } /* switch() */ } /* while(1) */} /* sc_next() *//*--------------------------------------------------------------------*/int sc_nexter (SCAN *scan){ /* --- get next token error reporting */ if (sc_next(scan) < 0) return sc_error(scan, scan->token); return scan->token; /* get next token, report error, */} /* sc_nexter() */ /* and return next token *//*--------------------------------------------------------------------*/int sc_back (SCAN *scan){ /* --- go back one token */ if (scan->back) /* a second step backwards */ return scan->token; /* is impossible, so do nothing */ scan->back = -1; /* set the step backward flag */ return _swap(scan); /* swap the token information */} /* sc_back() */ /* and return the previous token *//*--------------------------------------------------------------------*/int sc_eof (SCAN *scan){ /* --- check for end of file */ if (scan->token == T_EOF) return 1; sc_error(scan, E_GARBAGE); /* check for end of file */ return 0; /* and report an error */} /* sc_eof() */ /* if it is not reached *//*--------------------------------------------------------------------*/int sc_recover (SCAN *scan, int stop, int beg, int end, int level){ /* --- recover from an error */ while ((scan->token != stop) /* while at stop token */ && (scan->token != T_EOF)) { /* and not at end of file */ if (scan->token == beg) /* if begin level token found, */ level++; /* increment level counter */ else if ((scan->token == end) /* if end level token found */ && (--level <= 0)) /* and on level to return to, */ break; /* abort loop */ if (sc_next(scan) < 0) return scan->token; } /* consume token */ if (scan->token != T_EOF) /* if not at end of file, */ sc_next(scan); /* consume token (stop or end) */ return scan->token; /* return the next token */} /* sc_recover() *//*--------------------------------------------------------------------*/void sc_errfile (SCAN *scan, FILE *file, int lncnt){ /* --- set file for error output */ assert(scan); /* check the function arguments */ scan->errfile = (file) ? file : stderr; scan->lncnt = lncnt; /* set file and line count */} /* sc_errfile() *//*--------------------------------------------------------------------*/void sc_errmsgs (SCAN *scan, const char *msgs[], int cnt){ /* --- set additonal error messages */ assert(scan); /* check the function arguments */ scan->msgs = msgs; /* note error message vector */ scan->msgcnt = cnt; /* and number of error messages */} /* sc_errmsgs() *//*--------------------------------------------------------------------*/int sc_error (SCAN *scan, int code, ...){ /* --- print an error message */ va_list args; /* variable argument list */ const char *msg; /* error message */ int c, pc; /* the illegal character */ int tmp; /* temporary buffer */ assert(scan); /* check the function arguments */ if (scan->lncnt <= 0) /* if line count is zero or negative, */ putc('\n', scan->errfile); /* start a new output line */ fprintf(scan->errfile, FILETXT" %s", scan->fname); /* print the file name */ if ((code != E_NONE) /* if an error occurred, */ && (code != E_FOPEN) /* but not 'file open failed' */ && (code != E_UNTCOM)) { /* and not 'unterminated comment' */ fputs((scan->lncnt > 2) ? ",\n" : ", ", scan->errfile); fprintf(scan->errfile, LINETXT" %d", scan->line); } /* print line number */ fputs((scan->lncnt > 1) ? ":\n" : ": ", scan->errfile); if (code >= 0) code = E_NONE; /* check error code and */ tmp = MSGOFFSET -code; /* get error message text */ if (code > E_UNKNOWN) msg = _errmsgs[-code]; else if (tmp < scan->msgcnt) msg = scan->msgs[tmp]; else msg = NULL; if (!msg) msg = _errmsgs[-(code = E_UNKNOWN)]; switch (code) { /* special error handling */ case E_ILLCHR: c = pc = (unsigned char)scan->value[0]; if (c < ' ') pc = ' '; fprintf (scan->errfile, msg, pc, c); break; case E_UNTCOM: fprintf (scan->errfile, msg, scan->start); break; default : va_start(args, code); /* get variable arguments */ vfprintf(scan->errfile, msg, args); va_end(args); break; /* print error message and */ } /* end variable argument evaluation */ if (scan->lncnt > 0) /* if line count is positive, */ putc('\n', scan->errfile); /* terminate output line */ return code; /* return error code */} /* sc_error() */#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -