Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

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 }