📄 scanner.c
字号:
r = namebuf; do { *r++ = *q++; } while (isalnum(*q)); *r = '\0'; i = 0; match = false; foreach(Name, n, pl) if (streq(ident(n), namebuf)) { match = true; break; } ++i; endfor if (match) { r = actual[i]; } else { r = namebuf; } while (*r != '\0') { *p++ = *r++; } } else { *p++ = *q++; } } *p = '\0'; insertinput(buf); }}/* * Parser error handling. */public yyerror(s)String s;{ register char *p; register integer start; if (streq(s, "syntax error")) { beginerrmsg(); p = prevchar; start = p - &scanner_linebuf[0]; if (p > &scanner_linebuf[0]) { while (lexclass[*p] == WHITE and p > &scanner_linebuf[0]) { --p; } } fprintf(stderr, "%s", scanner_linebuf); if (start != 0) { fprintf(stderr, "%*c", start, ' '); } if (p == &scanner_linebuf[0]) { fprintf(stderr, "^ unrecognized command"); } else { fprintf(stderr, "^ syntax error"); } enderrmsg(); } else { error(s); }}/* * Eat the current line. */public gobble (){ curchar = scanner_linebuf; scanner_linebuf[0] = '\0';}/* * Scan an identifier. * * If chkalias is true, check first to see if it's an alias. * Otherwise, check to see if it's a keyword. */private Token getident (chkalias)boolean chkalias;{ char buf[1024]; register char *p, *q; register Token t; List pl; String str; p = curchar; q = buf; if (shellmode) { do { if (*p == '\\' && *(p+1) == '\n') break; if (*p == '\\' && *(p+1) != '\n') ++p; *q++ = *p++; } while (index(" \t\n!&<>*[]()'\"", *p) == nil); } else { do { *q++ = *p++; } while (isalnum(*p)); } curchar = p; *q = '\0'; yylval.y_name = identname(buf, false); if (chkalias) { if (findalias(yylval.y_name, &pl, &str)) { expand(pl, str); while (lexclass[*curchar] == WHITE) { ++curchar; } if (pl == nil) { t = getident(false); } else { t = getident(true); } } else if (shellmode) { t = NAME; } else { t = findkeyword(yylval.y_name, NAME); } } else if (shellmode) { t = NAME; } else { t = findkeyword(yylval.y_name, NAME); } return t;}/* * Scan a number. */private Token getnum(){ char buf[1024]; register Char *p, *q; register Token t; Integer base; p = curchar; q = buf; if (*p == '0') { if (*(p+1) == 'x') { p += 2; base = 16; } else if (*(p+1) == 't') { base = 10; } else if (varIsSet("$hexin")) { base = 16; } else { base = 8; } } else if (varIsSet("$hexin")) { base = 16; } else if (varIsSet("$octin")) { base = 8; } else { base = 10; } if (base == 16) { do { *q++ = *p++; } while (ishexdigit(*p)); } else { do { *q++ = *p++; } while (isdigit(*p)); } if (*p == '.') { do { *q++ = *p++; } while (isdigit(*p)); if (*p == 'e' or *p == 'E') { p++; if (*p == '+' or *p == '-' or isdigit(*p)) { *q++ = 'e'; do { *q++ = *p++; } while (isdigit(*p)); } } *q = '\0'; yylval.y_real = atof(buf); t = REAL; } else { *q = '\0'; switch (base) { case 10: yylval.y_int = atol(buf); break; case 8: yylval.y_int = octal(buf); break; case 16: yylval.y_int = hex(buf); break; default: badcaseval(base); } t = INT; } curchar = p; return t;}/* * Convert a string of octal digits to an integer. */private int octal(s)String s;{ register Char *p; register Integer n; n = 0; for (p = s; *p != '\0'; p++) { n = 8*n + (*p - '0'); } return n;}/* * Convert a string of hexadecimal digits to an integer. */private int hex(s)String s;{ register Char *p; register Integer n; n = 0; for (p = s; *p != '\0'; p++) { n *= 16; if (*p >= 'a' and *p <= 'f') { n += (*p - 'a' + 10); } else if (*p >= 'A' and *p <= 'F') { n += (*p - 'A' + 10); } else { n += (*p - '0'); } } return n;}/* * Scan a string. */private Token getstring (quote)char quote;{ register char *p, *q; char buf[MAXLINESIZE]; boolean endofstring; Token t; p = curchar; q = buf; endofstring = false; while (not endofstring) { if (*p == '\\' and *(p+1) == '\n') { if (fgets(scanner_linebuf, MAXLINESIZE, in) == nil) { error("non-terminated string"); } p = &scanner_linebuf[0] - 1; } else if (*p == '\n' or *p == '\0') { error("non-terminated string"); endofstring = true; } else if (*p == quote) { endofstring = true; } else { curchar = p; *q++ = charcon(p); p = curchar; } p++; } curchar = p; *q = '\0'; if (quote == '\'' and buf[1] == '\0') { yylval.y_char = buf[0]; t = CHAR; } else { yylval.y_string = strdup(buf); t = STRING; } return t;}/* * Process a character constant. * Watch out for backslashes. */private char charcon (s)String s;{ register char *p, *q; char c, buf[10]; p = s; if (*p == '\\') { ++p; switch (*p) { case '\\': c = '\\'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case '\'': case '"': c = *p; break; default: if (isdigit(*p)) { q = buf; do { *q++ = *p++; } while (isdigit(*p)); *q = '\0'; c = (char) octal(buf); } --p; break; } curchar = p; } else { c = *p; } return c;}/* * Input file management routines. */public setinput(filename)Filename filename;{ File f; f = fopen(filename, "r"); if (f == nil) { error("can't open %s", filename); } else { if (curinclindex >= MAXINCLDEPTH) { error("unreasonable input nesting on \"%s\"", filename); } inclinfo[curinclindex].savefile = in; inclinfo[curinclindex].savefn = errfilename; inclinfo[curinclindex].savelineno = errlineno; curinclindex++; in = f; errfilename = filename; errlineno = 1; }}private Boolean eofinput(){ register Boolean b; if (curinclindex == 0) { if (isterm(in)) { putchar('\n'); clearerr(in); b = false; } else { b = true; } } else { fclose(in); --curinclindex; in = inclinfo[curinclindex].savefile; errfilename = inclinfo[curinclindex].savefn; errlineno = inclinfo[curinclindex].savelineno; b = false; } return b;}/* * Pop the current input. Return whether successful. */public Boolean popinput(){ Boolean b; if (curinclindex == 0) { b = false; } else { b = (Boolean) (not eofinput()); } return b;}/* * Return whether we are currently reading from standard input. */public Boolean isstdin(){ return (Boolean) (in == stdin);}/* * Send the current line to the shell. */public shellline(){ register char *p; p = curchar; while (*p != '\0' and (*p == '\n' or lexclass[*p] == WHITE)) { ++p; } shell(p); if (*p == '\0' and isterm(in)) { putchar('\n'); } erecover();}/* * Read the rest of the current line in "shell mode". */public beginshellmode(){ shellmode = true;}/* * Print out a token for debugging. */public print_token(f, t)File f;Token t;{ if (t == '\n') { fprintf(f, "char '\\n'"); } else if (t == EOF) { fprintf(f, "EOF"); } else if (t < 256) { fprintf(f, "char '%c'", t); } else { fprintf(f, "\"%s\"", keywdstring(t)); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -