gram.y (4247B)
1 %{ 2 #include <stdio.h> 3 #include "lburg.h" 4 static char rcsid[] = "$Id: gram.y 145 2001-10-17 21:53:10Z timo $"; 5 /*lint -e616 -e527 -e652 -esym(552,yynerrs) -esym(563,yynewstate,yyerrlab) */ 6 static int yylineno = 0; 7 %} 8 %union { 9 int n; 10 char *string; 11 Tree tree; 12 } 13 %term TERMINAL 14 %term START 15 %term PPERCENT 16 17 %token <string> ID TEMPLATE CODE 18 %token <n> INT 19 %type <string> nonterm cost 20 %type <tree> tree 21 %% 22 spec : decls PPERCENT rules { yylineno = 0; } 23 | decls { yylineno = 0; } 24 ; 25 26 decls : /* lambda */ 27 | decls decl 28 ; 29 30 decl : TERMINAL blist '\n' 31 | START nonterm '\n' { 32 if (nonterm($2)->number != 1) 33 yyerror("redeclaration of the start symbol\n"); 34 } 35 | '\n' 36 | error '\n' { yyerrok; } 37 ; 38 39 blist : /* lambda */ 40 | blist ID '=' INT { term($2, $4); } 41 ; 42 43 rules : /* lambda */ 44 | rules nonterm ':' tree TEMPLATE cost '\n' { rule($2, $4, $5, $6); } 45 | rules '\n' 46 | rules error '\n' { yyerrok; } 47 ; 48 49 nonterm : ID { nonterm($$ = $1); } 50 ; 51 52 tree : ID { $$ = tree($1, 0, 0); } 53 | ID '(' tree ')' { $$ = tree($1, $3, 0); } 54 | ID '(' tree ',' tree ')' { $$ = tree($1, $3, $5); } 55 ; 56 57 cost : CODE { if (*$1 == 0) $$ = "0"; } 58 ; 59 %% 60 #include <assert.h> 61 #include <stdarg.h> 62 #include <ctype.h> 63 #include <string.h> 64 #include <limits.h> 65 66 int errcnt = 0; 67 FILE *infp = NULL; 68 FILE *outfp = NULL; 69 static char buf[BUFSIZ], *bp = buf; 70 static int ppercent = 0; 71 static int code = 0; 72 73 static int get(void) { 74 if (*bp == 0) { 75 bp = buf; 76 *bp = 0; 77 if (fgets(buf, sizeof buf, infp) == NULL) 78 return EOF; 79 yylineno++; 80 while (buf[0] == '%' && buf[1] == '{' && buf[2] == '\n') { 81 for (;;) { 82 if (fgets(buf, sizeof buf, infp) == NULL) { 83 yywarn("unterminated %{...%}\n"); 84 return EOF; 85 } 86 yylineno++; 87 if (strcmp(buf, "%}\n") == 0) 88 break; 89 fputs(buf, outfp); 90 } 91 if (fgets(buf, sizeof buf, infp) == NULL) 92 return EOF; 93 yylineno++; 94 } 95 } 96 return *bp++; 97 } 98 99 void yyerror(char *fmt, ...) { 100 va_list ap; 101 102 va_start(ap, fmt); 103 if (yylineno > 0) 104 fprintf(stderr, "line %d: ", yylineno); 105 vfprintf(stderr, fmt, ap); 106 if (fmt[strlen(fmt)-1] != '\n') 107 fprintf(stderr, "\n"); 108 errcnt++; 109 va_end(ap); 110 } 111 112 int yylex(void) { 113 int c; 114 115 if (code) { 116 char *p; 117 bp += strspn(bp, " \t\f"); 118 p = strchr(bp, '\n'); 119 if (p == NULL) 120 p = strchr(bp, '\n'); 121 while (p > bp && isspace(p[-1])) 122 p--; 123 yylval.string = alloc(p - bp + 1); 124 strncpy(yylval.string, bp, p - bp); 125 yylval.string[p - bp] = 0; 126 bp = p; 127 code--; 128 return CODE; 129 } 130 while ((c = get()) != EOF) { 131 switch (c) { 132 case ' ': case '\f': case '\t': 133 continue; 134 case '\n': 135 case '(': case ')': case ',': 136 case ':': case '=': 137 return c; 138 } 139 if (c == '%' && *bp == '%') { 140 bp++; 141 return ppercent++ ? 0 : PPERCENT; 142 } else if (c == '%' && strncmp(bp, "term", 4) == 0 143 && isspace(bp[4])) { 144 bp += 4; 145 return TERMINAL; 146 } else if (c == '%' && strncmp(bp, "start", 5) == 0 147 && isspace(bp[5])) { 148 bp += 5; 149 return START; 150 } else if (c == '"') { 151 char *p = strchr(bp, '"'); 152 if (p == NULL) { 153 yyerror("missing \" in assembler template\n"); 154 p = strchr(bp, '\n'); 155 if (p == NULL) 156 p = strchr(bp, '\0'); 157 } 158 assert(p); 159 yylval.string = alloc(p - bp + 1); 160 strncpy(yylval.string, bp, p - bp); 161 yylval.string[p - bp] = 0; 162 bp = *p == '"' ? p + 1 : p; 163 code++; 164 return TEMPLATE; 165 } else if (isdigit(c)) { 166 int n = 0; 167 do { 168 int d = c - '0'; 169 if (n > (INT_MAX - d)/10) 170 yyerror("integer greater than %d\n", INT_MAX); 171 else 172 n = 10*n + d; 173 c = get(); 174 } while (c != EOF && isdigit(c)); 175 bp--; 176 yylval.n = n; 177 return INT; 178 } else if (isalpha(c)) { 179 char *p = bp - 1; 180 while (isalpha(*bp) || isdigit(*bp) || *bp == '_') 181 bp++; 182 yylval.string = alloc(bp - p + 1); 183 strncpy(yylval.string, p, bp - p); 184 yylval.string[bp - p] = 0; 185 return ID; 186 } else if (isprint(c)) 187 yyerror("invalid character `%c'\n", c); 188 else 189 yyerror("invalid character `\\%03o'\n", (unsigned char)c); 190 } 191 return 0; 192 } 193 194 void yywarn(char *fmt, ...) { 195 va_list ap; 196 197 va_start(ap, fmt); 198 if (yylineno > 0) 199 fprintf(stderr, "line %d: ", yylineno); 200 fprintf(stderr, "warning: "); 201 vfprintf(stderr, fmt, ap); 202 }