| char rcsid_lex[] = "$Id$"; |
| |
| #include <ctype.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include "b.h" |
| #include "fe.h" |
| #include "y.tab.h" |
| |
| static char buf[BUFSIZ]; |
| |
| static int yyline = 1; |
| |
| typedef int (*ReadFn) ARGS((void)); |
| |
| static char *StrCopy ARGS((char *)); |
| static int code_get ARGS((void)); |
| static int simple_get ARGS((void)); |
| static void ReadCharString ARGS((ReadFn, int)); |
| static void ReadCodeBlock ARGS((void)); |
| static void ReadOldComment ARGS((ReadFn)); |
| |
| static char * |
| StrCopy(s) char *s; |
| { |
| char *t = (char *)zalloc(strlen(s) + 1); |
| strcpy(t,s); |
| return t; |
| } |
| |
| static int |
| simple_get() |
| { |
| int ch; |
| if ((ch = getchar()) == '\n') { |
| yyline++; |
| } |
| return ch; |
| } |
| |
| static int |
| code_get() |
| { |
| int ch; |
| if ((ch = getchar()) == '\n') { |
| yyline++; |
| } |
| if (ch != EOF) { |
| fputc(ch, outfile); |
| } |
| return ch; |
| } |
| |
| void |
| yypurge() |
| { |
| while (code_get() != EOF) ; |
| } |
| |
| |
| static void |
| ReadCharString(rdfn, which) ReadFn rdfn; int which; |
| { |
| int ch; |
| int backslash = 0; |
| int firstline = yyline; |
| |
| while ((ch = rdfn()) != EOF) { |
| if (ch == which && !backslash) { |
| return; |
| } |
| if (ch == '\\' && !backslash) { |
| backslash = 1; |
| } else { |
| backslash = 0; |
| } |
| } |
| yyerror1("Unexpected EOF in string on line "); |
| fprintf(stderr, "%d\n", firstline); |
| exit(1); |
| } |
| |
| static void |
| ReadOldComment(rdfn) ReadFn rdfn; |
| { |
| /* will not work for comments delimiter in string */ |
| |
| int ch; |
| int starred = 0; |
| int firstline = yyline; |
| |
| while ((ch = rdfn()) != EOF) { |
| if (ch == '*') { |
| starred = 1; |
| } else if (ch == '/' && starred) { |
| return; |
| } else { |
| starred = 0; |
| } |
| } |
| yyerror1("Unexpected EOF in comment on line "); |
| fprintf(stderr, "%d\n", firstline); |
| exit(1); |
| } |
| |
| static void |
| ReadCodeBlock() |
| { |
| int ch; |
| int firstline = yyline; |
| |
| while ((ch = getchar()) != EOF) { |
| if (ch == '%') { |
| ch = getchar(); |
| if (ch != '}') { |
| yyerror("bad %%"); |
| } |
| return; |
| } |
| fputc(ch, outfile); |
| if (ch == '\n') { |
| yyline++; |
| } |
| if (ch == '"' || ch == '\'') { |
| ReadCharString(code_get, ch); |
| } else if (ch == '/') { |
| ch = getchar(); |
| if (ch == '*') { |
| fputc(ch, outfile); |
| ReadOldComment(code_get); |
| continue; |
| } else { |
| ungetc(ch, stdin); |
| } |
| } |
| } |
| yyerror1("Unclosed block of C code started on line "); |
| fprintf(stderr, "%d\n", firstline); |
| exit(1); |
| } |
| |
| static int done; |
| void |
| yyfinished() |
| { |
| done = 1; |
| } |
| |
| int |
| yylex() |
| { |
| int ch; |
| char *ptr = buf; |
| |
| if (done) return 0; |
| while ((ch = getchar()) != EOF) { |
| switch (ch) { |
| case ' ': |
| case '\f': |
| case '\t': |
| continue; |
| case '\n': |
| yyline++; |
| continue; |
| case '(': |
| case ')': |
| case ',': |
| case ':': |
| case ';': |
| case '=': |
| return(ch); |
| case '/': |
| ch = getchar(); |
| if (ch == '*') { |
| ReadOldComment(simple_get); |
| continue; |
| } else { |
| ungetc(ch, stdin); |
| yyerror("illegal char /"); |
| continue; |
| } |
| case '%': |
| ch = getchar(); |
| switch (ch) { |
| case '%': |
| return (K_PPERCENT); |
| case '{': |
| ReadCodeBlock(); |
| continue; |
| case 's': |
| case 'g': |
| case 't': |
| do { |
| if (ptr >= &buf[BUFSIZ]) { |
| yyerror("ID too long"); |
| return(ERROR); |
| } else { |
| *ptr++ = ch; |
| } |
| ch = getchar(); |
| } while (isalpha(ch) || isdigit(ch) || ch == '_'); |
| ungetc(ch, stdin); |
| *ptr = '\0'; |
| if (!strcmp(buf, "term")) return K_TERM; |
| if (!strcmp(buf, "start")) return K_START; |
| if (!strcmp(buf, "gram")) return K_GRAM; |
| yyerror("illegal character after %%"); |
| continue; |
| default: |
| yyerror("illegal character after %%"); |
| continue; |
| } |
| default: |
| if (isalpha(ch) ) { |
| do { |
| if (ptr >= &buf[BUFSIZ]) { |
| yyerror("ID too long"); |
| return(ERROR); |
| } else { |
| *ptr++ = ch; |
| } |
| ch = getchar(); |
| } while (isalpha(ch) || isdigit(ch) || ch == '_'); |
| ungetc(ch, stdin); |
| *ptr = '\0'; |
| yylval.y_string = StrCopy(buf); |
| return(ID); |
| } |
| if (isdigit(ch)) { |
| int val=0; |
| do { |
| val *= 10; |
| val += (ch - '0'); |
| ch = getchar(); |
| } while (isdigit(ch)); |
| ungetc(ch, stdin); |
| yylval.y_int = val; |
| return(INT); |
| } |
| yyerror1("illegal char "); |
| fprintf(stderr, "(\\%03o)\n", ch); |
| exit(1); |
| } |
| } |
| return(0); |
| } |
| |
| void |
| yyerror1(str) char *str; |
| { |
| fprintf(stderr, "line %d: %s", yyline, str); |
| } |
| |
| void |
| yyerror(str) char *str; |
| { |
| yyerror1(str); |
| fprintf(stderr, "\n"); |
| exit(1); |
| } |