Chris Lattner | 633a5b1 | 2002-09-17 23:03:30 +0000 | [diff] [blame^] | 1 | char rcsid_lex[] = "$Id$"; |
| 2 | |
| 3 | #include <ctype.h> |
| 4 | #include <stdio.h> |
| 5 | #include <string.h> |
| 6 | #include "b.h" |
| 7 | #include "fe.h" |
| 8 | #include "y.tab.h" |
| 9 | |
| 10 | static char buf[BUFSIZ]; |
| 11 | |
| 12 | static int yyline = 1; |
| 13 | |
| 14 | typedef int (*ReadFn) ARGS((void)); |
| 15 | |
| 16 | static char *StrCopy ARGS((char *)); |
| 17 | static int code_get ARGS((void)); |
| 18 | static int simple_get ARGS((void)); |
| 19 | static void ReadCharString ARGS((ReadFn, int)); |
| 20 | static void ReadCodeBlock ARGS((void)); |
| 21 | static void ReadOldComment ARGS((ReadFn)); |
| 22 | |
| 23 | static char * |
| 24 | StrCopy(s) char *s; |
| 25 | { |
| 26 | char *t = (char *)zalloc(strlen(s) + 1); |
| 27 | strcpy(t,s); |
| 28 | return t; |
| 29 | } |
| 30 | |
| 31 | static int |
| 32 | simple_get() |
| 33 | { |
| 34 | int ch; |
| 35 | if ((ch = getchar()) == '\n') { |
| 36 | yyline++; |
| 37 | } |
| 38 | return ch; |
| 39 | } |
| 40 | |
| 41 | static int |
| 42 | code_get() |
| 43 | { |
| 44 | int ch; |
| 45 | if ((ch = getchar()) == '\n') { |
| 46 | yyline++; |
| 47 | } |
| 48 | if (ch != EOF) { |
| 49 | fputc(ch, outfile); |
| 50 | } |
| 51 | return ch; |
| 52 | } |
| 53 | |
| 54 | void |
| 55 | yypurge() |
| 56 | { |
| 57 | while (code_get() != EOF) ; |
| 58 | } |
| 59 | |
| 60 | |
| 61 | static void |
| 62 | ReadCharString(rdfn, which) ReadFn rdfn; int which; |
| 63 | { |
| 64 | int ch; |
| 65 | int backslash = 0; |
| 66 | int firstline = yyline; |
| 67 | |
| 68 | while ((ch = rdfn()) != EOF) { |
| 69 | if (ch == which && !backslash) { |
| 70 | return; |
| 71 | } |
| 72 | if (ch == '\\' && !backslash) { |
| 73 | backslash = 1; |
| 74 | } else { |
| 75 | backslash = 0; |
| 76 | } |
| 77 | } |
| 78 | yyerror1("Unexpected EOF in string on line "); |
| 79 | fprintf(stderr, "%d\n", firstline); |
| 80 | exit(1); |
| 81 | } |
| 82 | |
| 83 | static void |
| 84 | ReadOldComment(rdfn) ReadFn rdfn; |
| 85 | { |
| 86 | /* will not work for comments delimiter in string */ |
| 87 | |
| 88 | int ch; |
| 89 | int starred = 0; |
| 90 | int firstline = yyline; |
| 91 | |
| 92 | while ((ch = rdfn()) != EOF) { |
| 93 | if (ch == '*') { |
| 94 | starred = 1; |
| 95 | } else if (ch == '/' && starred) { |
| 96 | return; |
| 97 | } else { |
| 98 | starred = 0; |
| 99 | } |
| 100 | } |
| 101 | yyerror1("Unexpected EOF in comment on line "); |
| 102 | fprintf(stderr, "%d\n", firstline); |
| 103 | exit(1); |
| 104 | } |
| 105 | |
| 106 | static void |
| 107 | ReadCodeBlock() |
| 108 | { |
| 109 | int ch; |
| 110 | int firstline = yyline; |
| 111 | |
| 112 | while ((ch = getchar()) != EOF) { |
| 113 | if (ch == '%') { |
| 114 | ch = getchar(); |
| 115 | if (ch != '}') { |
| 116 | yyerror("bad %%"); |
| 117 | } |
| 118 | return; |
| 119 | } |
| 120 | fputc(ch, outfile); |
| 121 | if (ch == '\n') { |
| 122 | yyline++; |
| 123 | } |
| 124 | if (ch == '"' || ch == '\'') { |
| 125 | ReadCharString(code_get, ch); |
| 126 | } else if (ch == '/') { |
| 127 | ch = getchar(); |
| 128 | if (ch == '*') { |
| 129 | fputc(ch, outfile); |
| 130 | ReadOldComment(code_get); |
| 131 | continue; |
| 132 | } else { |
| 133 | ungetc(ch, stdin); |
| 134 | } |
| 135 | } |
| 136 | } |
| 137 | yyerror1("Unclosed block of C code started on line "); |
| 138 | fprintf(stderr, "%d\n", firstline); |
| 139 | exit(1); |
| 140 | } |
| 141 | |
| 142 | static int done; |
| 143 | void |
| 144 | yyfinished() |
| 145 | { |
| 146 | done = 1; |
| 147 | } |
| 148 | |
| 149 | int |
| 150 | yylex() |
| 151 | { |
| 152 | int ch; |
| 153 | char *ptr = buf; |
| 154 | |
| 155 | if (done) return 0; |
| 156 | while ((ch = getchar()) != EOF) { |
| 157 | switch (ch) { |
| 158 | case ' ': |
| 159 | case '\f': |
| 160 | case '\t': |
| 161 | continue; |
| 162 | case '\n': |
| 163 | yyline++; |
| 164 | continue; |
| 165 | case '(': |
| 166 | case ')': |
| 167 | case ',': |
| 168 | case ':': |
| 169 | case ';': |
| 170 | case '=': |
| 171 | return(ch); |
| 172 | case '/': |
| 173 | ch = getchar(); |
| 174 | if (ch == '*') { |
| 175 | ReadOldComment(simple_get); |
| 176 | continue; |
| 177 | } else { |
| 178 | ungetc(ch, stdin); |
| 179 | yyerror("illegal char /"); |
| 180 | continue; |
| 181 | } |
| 182 | case '%': |
| 183 | ch = getchar(); |
| 184 | switch (ch) { |
| 185 | case '%': |
| 186 | return (K_PPERCENT); |
| 187 | case '{': |
| 188 | ReadCodeBlock(); |
| 189 | continue; |
| 190 | case 's': |
| 191 | case 'g': |
| 192 | case 't': |
| 193 | do { |
| 194 | if (ptr >= &buf[BUFSIZ]) { |
| 195 | yyerror("ID too long"); |
| 196 | return(ERROR); |
| 197 | } else { |
| 198 | *ptr++ = ch; |
| 199 | } |
| 200 | ch = getchar(); |
| 201 | } while (isalpha(ch) || isdigit(ch) || ch == '_'); |
| 202 | ungetc(ch, stdin); |
| 203 | *ptr = '\0'; |
| 204 | if (!strcmp(buf, "term")) return K_TERM; |
| 205 | if (!strcmp(buf, "start")) return K_START; |
| 206 | if (!strcmp(buf, "gram")) return K_GRAM; |
| 207 | yyerror("illegal character after %%"); |
| 208 | continue; |
| 209 | default: |
| 210 | yyerror("illegal character after %%"); |
| 211 | continue; |
| 212 | } |
| 213 | default: |
| 214 | if (isalpha(ch) ) { |
| 215 | do { |
| 216 | if (ptr >= &buf[BUFSIZ]) { |
| 217 | yyerror("ID too long"); |
| 218 | return(ERROR); |
| 219 | } else { |
| 220 | *ptr++ = ch; |
| 221 | } |
| 222 | ch = getchar(); |
| 223 | } while (isalpha(ch) || isdigit(ch) || ch == '_'); |
| 224 | ungetc(ch, stdin); |
| 225 | *ptr = '\0'; |
| 226 | yylval.y_string = StrCopy(buf); |
| 227 | return(ID); |
| 228 | } |
| 229 | if (isdigit(ch)) { |
| 230 | int val=0; |
| 231 | do { |
| 232 | val *= 10; |
| 233 | val += (ch - '0'); |
| 234 | ch = getchar(); |
| 235 | } while (isdigit(ch)); |
| 236 | ungetc(ch, stdin); |
| 237 | yylval.y_int = val; |
| 238 | return(INT); |
| 239 | } |
| 240 | yyerror1("illegal char "); |
| 241 | fprintf(stderr, "(\\%03o)\n", ch); |
| 242 | exit(1); |
| 243 | } |
| 244 | } |
| 245 | return(0); |
| 246 | } |
| 247 | |
| 248 | void |
| 249 | yyerror1(str) char *str; |
| 250 | { |
| 251 | fprintf(stderr, "line %d: %s", yyline, str); |
| 252 | } |
| 253 | |
| 254 | void |
| 255 | yyerror(str) char *str; |
| 256 | { |
| 257 | yyerror1(str); |
| 258 | fprintf(stderr, "\n"); |
| 259 | exit(1); |
| 260 | } |