📄 reader.c
字号:
#include "defs.h"#include "mstring.h"/* The line size must be a positive integer. One hundred was chosen *//* because few lines in Yacc input grammars exceed 100 characters. *//* Note that if a line exceeds LINESIZE characters, the line buffer *//* will be expanded to accomodate it. */#define LINESIZE 100/* the maximum nember of arguments (inherited attributes) to a non-terminal *//* this is a hard limit, but seems more than adequate */#define MAXARGS 20char *cache;int cinc, cache_size;int ntags, tagmax, havetags=0;char **tag_table;char saw_eof, unionized;char *cptr, *line;int linesize;FILE *inc_file = NULL;char inc_file_name[LINESIZE];int inc_save_lineno;int in_ifdef = 0;int ifdef_skip;#define MAX_DEFD_VARS 1000char *defd_vars[MAX_DEFD_VARS] = {NULL};bucket *goal;int prec;int gensym;char last_was_action;int maxitems;bucket **pitem;int maxrules;bucket **plhs;int name_pool_size;char *name_pool;char line_format[] = "#line %d \"%s\"\n";int cachec(int c){ assert(cinc >= 0); if (cinc >= cache_size) { if (!(cache = REALLOC(cache, cache_size += 256))) no_space(); } return cache[cinc++] = c;}/* * Get line * Return: 1 - reg. line finished with '\n'. * 0 - EOF. */char *get_line() { extern int Eflag; FILE *f; int c; int i; /* VM: input from main or include file */ NextLine:; f = inc_file ? inc_file : input_file; i = 0; if (saw_eof || (c = getc(f)) == EOF) { /* VM: end of include file */ if(inc_file) { fclose(inc_file); inc_file = NULL; lineno = inc_save_lineno; goto NextLine; } if (line) FREE(line); saw_eof = 1; return line = cptr = 0; } if (line == 0 || linesize != (LINESIZE + 1)) { if (line) FREE(line); linesize = LINESIZE + 1; if (!(line = MALLOC(linesize))) no_space(); } ++lineno; while ((line[i] = c) != '\n') { if (++i + 1 >= linesize) if (!(line = REALLOC(line, linesize += LINESIZE))) no_space(); if ((c = getc(f)) == EOF) { c = '\n'; saw_eof = 1; } } line[i+1] = 0; /* VM: process %ifdef line */ if(strncmp(&line[0], "%ifdef ", 7)==0) { char var_name[80]; int ii=0; char **ps; for(i=7; line[i]!='\n' && line[i]!=' '; i++, ii++) { var_name[ii] = line[i]; } var_name[ii] = 0; if(in_ifdef) { error(lineno, 0, 0, "Cannot have nested %%ifdef"); } /* Find the preprocessor variable */ for(ps=&defd_vars[0]; *ps; ps++) { if(strcmp(*ps,var_name)==0) { break; } } in_ifdef = 1; if(*ps) { ifdef_skip = 0; } else { ifdef_skip = 1; } goto NextLine; } /* VM: process %endif line */ if(strncmp(&line[0], "%endif", 6)==0) { if(!in_ifdef) { error(lineno, 0, 0, "There is no corresponding %%ifdef for %%endif"); } in_ifdef = 0; goto NextLine; } /* VM: skip ordinary lines if ordered by %endif */ if(in_ifdef && ifdef_skip) { goto NextLine; } /* VM: Process %include line */ if(strncmp(&line[0], "%include ", 9)==0) { int ii=0; for(i=9; line[i]!='\n' && line[i]!=' '; i++, ii++) { inc_file_name[ii] = line[i]; } inc_file_name[ii] = 0; if(inc_file) { error(lineno, 0, 0, "Nested include lines are not allowed"); } inc_file = fopen(inc_file_name, "r"); if(inc_file==NULL) { error(lineno, 0, 0, "Cannot open include file %s", inc_file_name); } inc_save_lineno = lineno; lineno = 0; goto NextLine; } /* VM: process %define line */ if(strncmp(&line[0], "%define ", 8)==0) { char var_name[80]; int ii=0; char **ps; for(i=8; line[i]!='\n' && line[i]!=' '; i++, ii++) { var_name[ii] = line[i]; } var_name[ii] = 0; /* Find the preprocessor variable */ for(ps=&defd_vars[0]; *ps; ps++) { if(strcmp(*ps,var_name)==0) { error(lineno, 0, 0, "Preprocessor variable %s already defined", var_name); } } *ps = MALLOC(strlen(var_name)+1); strcpy(*ps, var_name); *++ps = NULL; goto NextLine; } if(Eflag) { printf("YPP: %s", line); } return cptr = line;}char *dup_line(){ register char *p, *s, *t; if (line == 0) return (0); s = line; while (*s != '\n') ++s; if (!(p = MALLOC(s - line + 1))) no_space(); s = line; t = p; while ((*t++ = *s++) != '\n'); return (p);}char *skip_comment(){ register char *s; int st_lineno = lineno; char *st_line = dup_line(); char *st_cptr = st_line + (cptr - line); s = cptr + 2; while (s[0] != '*' || s[1] != '/') { if (*s == '\n') { if ((s = get_line()) == 0) unterminated_comment(st_lineno, st_line, st_cptr); } else ++s; } FREE(st_line); return cptr = s + 2;}int nextc(){ register char *s; if (line == 0 && get_line() == 0) return (EOF); s = cptr; for (;;) { switch (*s) { case '\n': if ((s = get_line()) == 0) return EOF; break; case ' ': case '\t': case '\f': case '\r': case '\v': case ',': case ';': ++s; break; case '\\': cptr = s; return ('%'); case '/': if (s[1] == '*') { cptr = s; s = skip_comment(); break; } else if (s[1] == '/') { if ((s = get_line()) == 0) return EOF; break; } /* fall through */ default: cptr = s; return (*s); } }}static struct keyword { char name[12]; int token; } keywords[] = { { "binary", NONASSOC }, { "ident", IDENT }, { "left", LEFT }, { "nonassoc", NONASSOC }, { "right", RIGHT }, { "start", START }, { "term", TOKEN }, { "token", TOKEN }, { "type", TYPE }, { "union", UNION },};int keyword(){ register int c; char *t_cptr = cptr; struct keyword *key; c = *++cptr; if (isalpha(c)) { cinc = 0; while (isalnum(c) || c == '_' || c == '.' || c == '$') { cachec(tolower(c)); c = *++cptr; } cachec(NUL); if ((key = bsearch(cache, keywords, sizeof(keywords)/sizeof(*key), sizeof(*key), strcmp))) return key->token; } else { ++cptr; if (c == '{') return (TEXT); if (c == '%' || c == '\\') return (MARK); if (c == '<') return (LEFT); if (c == '>') return (RIGHT); if (c == '0') return (TOKEN); if (c == '2') return (NONASSOC); } syntax_error(lineno, line, t_cptr); /*NOTREACHED*/ return 0;}void copy_ident(){ register int c; register FILE *f = output_file; if ((c = nextc()) == EOF) unexpected_EOF(); if (c != '"') syntax_error(lineno, line, cptr); ++outline; fprintf(f, "#ident \""); for (;;) { c = *++cptr; if (c == '\n') { fprintf(f, "\"\n"); return; } putc(c, f); if (c == '"') { putc('\n', f); ++cptr; return; } }}#define OUTC(c) do { /* output a character on f1 and f2, if non-null */ \ int _c = (c); \ putc(_c, f1); \ if (f2) putc(_c, f2); \ } while(0)void copy_string(int quote, FILE *f1, FILE *f2){register int c;int s_lineno = lineno;char *s_line = dup_line();char *s_cptr = s_line + (cptr - line - 1); for (;;) { OUTC(c = *cptr++); if (c == quote) { FREE(s_line); return; } if (c == '\n') unterminated_string(s_lineno, s_line, s_cptr); if (c == '\\') { OUTC(c = *cptr++); if (c == '\n') { if (get_line() == 0) unterminated_string(s_lineno, s_line, s_cptr); } } }}void copy_comment(FILE *f1, FILE *f2){register int c; if ((c = *cptr) == '/') { OUTC('*'); while ((c = *++cptr) != '\n') { OUTC(c); if (c == '*' && cptr[1] == '/') OUTC(' '); } OUTC('*'); OUTC('/'); } else if (c == '*') { int c_lineno = lineno; char *c_line = dup_line(); char *c_cptr = c_line + (cptr - line - 1); OUTC(c); while ((c = *++cptr) != '*' || cptr[1] != '/') { OUTC(c); if (c == '\n') { if (get_line() == 0) unterminated_comment(c_lineno, c_line, c_cptr); } } OUTC(c); OUTC('/'); FREE(c_line); cptr += 2; }}#undef OUTCvoid copy_text(){ register int c; register FILE *f = text_file; int need_newline = 0; int t_lineno = lineno; char *t_line = dup_line(); char *t_cptr = t_line + (cptr - line - 2); if (*cptr == '\n') { if (get_line() == 0) unterminated_text(t_lineno, t_line, t_cptr); } if (!lflag) fprintf(f, line_format, lineno, (inc_file?inc_file_name:input_file_name));loop: switch (c = *cptr++) { case '\n': putc('\n', f); need_newline = 0; if (get_line()) goto loop; unterminated_text(t_lineno, t_line, t_cptr); case '\'': case '"': putc(c, f); copy_string(c, f, 0); need_newline = 1; goto loop; case '/': putc(c, f); copy_comment(f, 0); need_newline = 1; goto loop; case '%': case '\\': if (*cptr == '}') { if (need_newline) putc('\n', f); ++cptr; FREE(t_line); return; } /* fall through */ default: putc(c, f); need_newline = 1; goto loop; }}void copy_union(){ register int c; int depth; int u_lineno = lineno; char *u_line = dup_line(); char *u_cptr = u_line + (cptr - line - 6); if (unionized) over_unionized(cptr - 6); unionized = 1; if (!lflag) fprintf(text_file, line_format, lineno, (inc_file?inc_file_name:input_file_name)); fprintf(text_file, "typedef union"); if (dflag) fprintf(union_file, "typedef union"); depth = 0;loop: c = *cptr++; putc(c, text_file); if (dflag) putc(c, union_file); switch (c) { case '\n': get_line(); if (line == 0) unterminated_union(u_lineno, u_line, u_cptr); goto loop; case '{': ++depth; goto loop; case '}': if (--depth == 0) { fprintf(text_file, " YYSTYPE;\n"); FREE(u_line); return; } goto loop; case '\'': case '"': copy_string(c, text_file, dflag ? union_file : 0); goto loop; case '/': copy_comment(text_file, dflag ? union_file : 0); goto loop; default: goto loop; }}int hexval(int c){ if (c >= '0' && c <= '9') return (c - '0'); if (c >= 'A' && c <= 'F') return (c - 'A' + 10); if (c >= 'a' && c <= 'f') return (c - 'a' + 10); return (-1);}bucket *get_literal(){ register int c, quote; register int i; register int n; register char *s; register bucket *bp; int s_lineno = lineno; char *s_line = dup_line(); char *s_cptr = s_line + (cptr - line); quote = *cptr++; cinc = 0; for (;;) { c = *cptr++; if (c == quote) break; if (c == '\n') unterminated_string(s_lineno, s_line, s_cptr); if (c == '\\') { char *c_cptr = cptr - 1; c = *cptr++; switch (c) { case '\n': get_line(); if (line == 0) unterminated_string(s_lineno, s_line, s_cptr); continue; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': n = c - '0'; c = *cptr; if (IS_OCTAL(c)) { n = (n << 3) + (c - '0'); c = *++cptr; if (IS_OCTAL(c)) { n = (n << 3) + (c - '0'); ++cptr; } } if (n > MAXCHAR) illegal_character(c_cptr); c = n; break; case 'x': c = *cptr++; n = hexval(c); if (n < 0 || n >= 16) illegal_character(c_cptr); for (;;) { c = *cptr; i = hexval(c); if (i < 0 || i >= 16) break; ++cptr; n = (n << 4) + i; if (n > MAXCHAR) illegal_character(c_cptr); } c = n; break; case 'a': c = 7; 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; } } cachec(c); } FREE(s_line); n = cinc; s = MALLOC(n); if (s == 0) no_space(); for (i = 0; i < n; ++i) s[i] = cache[i]; cinc = 0; if (n == 1) cachec('\''); else cachec('"'); for (i = 0; i < n; ++i) { c = ((unsigned char *)s)[i]; if (c == '\\' || c == cache[0]) { cachec('\\'); cachec(c); } else if (isprint(c)) cachec(c); else { cachec('\\'); switch (c) { case 7: cachec('a'); break; case '\b': cachec('b'); break; case '\f': cachec('f'); break; case '\n': cachec('n'); break; case '\r': cachec('r'); break; case '\t': cachec('t'); break; case '\v': cachec('v'); break; default: cachec(((c >> 6) & 7) + '0'); cachec(((c >> 3) & 7) + '0'); cachec((c & 7) + '0'); break; } } } if (n == 1) cachec('\''); else cachec('"'); cachec(NUL); bp = lookup(cache); bp->class = TERM; if (n == 1 && bp->value == UNDEFINED) bp->value = *(unsigned char *)s; FREE(s); return (bp);}int is_reserved(char *name){ char *s; if (strcmp(name, ".") == 0 || strcmp(name, "$accept") == 0 || strcmp(name, "$end") == 0) return (1); if (name[0] == '$' && name[1] == '$' && isdigit(name[2])) { s = name + 3; while (isdigit(*s)) ++s; if (*s == NUL) return (1); } return (0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -