%{
|
%{
|
#include
|
#include
|
#include
|
#include
|
#include "lburg.h"
|
#include "lburg.h"
|
static char rcsid[] = "$Id: gram.y,v 2.5 1997/11/21 18:59:34 drh Exp $";
|
static char rcsid[] = "$Id: gram.y,v 2.5 1997/11/21 18:59:34 drh Exp $";
|
/*lint -e616 -e527 -e652 -esym(552,yynerrs) -esym(563,yynewstate,yyerrlab) */
|
/*lint -e616 -e527 -e652 -esym(552,yynerrs) -esym(563,yynewstate,yyerrlab) */
|
static int yylineno = 0;
|
static int yylineno = 0;
|
%}
|
%}
|
%union {
|
%union {
|
int n;
|
int n;
|
char *string;
|
char *string;
|
Tree tree;
|
Tree tree;
|
}
|
}
|
%term TERMINAL
|
%term TERMINAL
|
%term START
|
%term START
|
%term PPERCENT
|
%term PPERCENT
|
|
|
%token ID TEMPLATE CODE
|
%token ID TEMPLATE CODE
|
%token INT
|
%token INT
|
%type nonterm cost
|
%type nonterm cost
|
%type tree
|
%type tree
|
%%
|
%%
|
spec : decls PPERCENT rules { yylineno = 0; }
|
spec : decls PPERCENT rules { yylineno = 0; }
|
| decls { yylineno = 0; }
|
| decls { yylineno = 0; }
|
;
|
;
|
|
|
decls : /* lambda */
|
decls : /* lambda */
|
| decls decl
|
| decls decl
|
;
|
;
|
|
|
decl : TERMINAL blist '\n'
|
decl : TERMINAL blist '\n'
|
| START nonterm '\n' {
|
| START nonterm '\n' {
|
if (nonterm($2)->number != 1)
|
if (nonterm($2)->number != 1)
|
yyerror("redeclaration of the start symbol\n");
|
yyerror("redeclaration of the start symbol\n");
|
}
|
}
|
| '\n'
|
| '\n'
|
| error '\n' { yyerrok; }
|
| error '\n' { yyerrok; }
|
;
|
;
|
|
|
blist : /* lambda */
|
blist : /* lambda */
|
| blist ID '=' INT { term($2, $4); }
|
| blist ID '=' INT { term($2, $4); }
|
;
|
;
|
|
|
rules : /* lambda */
|
rules : /* lambda */
|
| rules nonterm ':' tree TEMPLATE cost '\n' { rule($2, $4, $5, $6); }
|
| rules nonterm ':' tree TEMPLATE cost '\n' { rule($2, $4, $5, $6); }
|
| rules '\n'
|
| rules '\n'
|
| rules error '\n' { yyerrok; }
|
| rules error '\n' { yyerrok; }
|
;
|
;
|
|
|
nonterm : ID { nonterm($$ = $1); }
|
nonterm : ID { nonterm($$ = $1); }
|
;
|
;
|
|
|
tree : ID { $$ = tree($1, 0, 0); }
|
tree : ID { $$ = tree($1, 0, 0); }
|
| ID '(' tree ')' { $$ = tree($1, $3, 0); }
|
| ID '(' tree ')' { $$ = tree($1, $3, 0); }
|
| ID '(' tree ',' tree ')' { $$ = tree($1, $3, $5); }
|
| ID '(' tree ',' tree ')' { $$ = tree($1, $3, $5); }
|
;
|
;
|
|
|
cost : CODE { if (*$1 == 0) $$ = "0"; }
|
cost : CODE { if (*$1 == 0) $$ = "0"; }
|
;
|
;
|
%%
|
%%
|
#include
|
#include
|
#include
|
#include
|
#include
|
#include
|
#include
|
#include
|
#include
|
#include
|
|
|
int errcnt = 0;
|
int errcnt = 0;
|
FILE *infp = NULL;
|
FILE *infp = NULL;
|
FILE *outfp = NULL;
|
FILE *outfp = NULL;
|
static char buf[BUFSIZ], *bp = buf;
|
static char buf[BUFSIZ], *bp = buf;
|
static int ppercent = 0;
|
static int ppercent = 0;
|
static int code = 0;
|
static int code = 0;
|
|
|
static int get(void) {
|
static int get(void) {
|
if (*bp == 0) {
|
if (*bp == 0) {
|
bp = buf;
|
bp = buf;
|
*bp = 0;
|
*bp = 0;
|
if (fgets(buf, sizeof buf, infp) == NULL)
|
if (fgets(buf, sizeof buf, infp) == NULL)
|
return EOF;
|
return EOF;
|
yylineno++;
|
yylineno++;
|
while (buf[0] == '%' && buf[1] == '{' && buf[2] == '\n') {
|
while (buf[0] == '%' && buf[1] == '{' && buf[2] == '\n') {
|
for (;;) {
|
for (;;) {
|
if (fgets(buf, sizeof buf, infp) == NULL) {
|
if (fgets(buf, sizeof buf, infp) == NULL) {
|
yywarn("unterminated %{...%}\n");
|
yywarn("unterminated %{...%}\n");
|
return EOF;
|
return EOF;
|
}
|
}
|
yylineno++;
|
yylineno++;
|
if (strcmp(buf, "%}\n") == 0)
|
if (strcmp(buf, "%}\n") == 0)
|
break;
|
break;
|
fputs(buf, outfp);
|
fputs(buf, outfp);
|
}
|
}
|
if (fgets(buf, sizeof buf, infp) == NULL)
|
if (fgets(buf, sizeof buf, infp) == NULL)
|
return EOF;
|
return EOF;
|
yylineno++;
|
yylineno++;
|
}
|
}
|
}
|
}
|
return *bp++;
|
return *bp++;
|
}
|
}
|
|
|
void yyerror(char *fmt, ...) {
|
void yyerror(char *fmt, ...) {
|
va_list ap;
|
va_list ap;
|
|
|
va_start(ap, fmt);
|
va_start(ap, fmt);
|
if (yylineno > 0)
|
if (yylineno > 0)
|
fprintf(stderr, "line %d: ", yylineno);
|
fprintf(stderr, "line %d: ", yylineno);
|
vfprintf(stderr, fmt, ap);
|
vfprintf(stderr, fmt, ap);
|
if (fmt[strlen(fmt)-1] != '\n')
|
if (fmt[strlen(fmt)-1] != '\n')
|
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
errcnt++;
|
errcnt++;
|
va_end(ap);
|
va_end(ap);
|
}
|
}
|
|
|
int yylex(void) {
|
int yylex(void) {
|
int c;
|
int c;
|
|
|
if (code) {
|
if (code) {
|
char *p;
|
char *p;
|
bp += strspn(bp, " \t\f");
|
bp += strspn(bp, " \t\f");
|
p = strchr(bp, '\n');
|
p = strchr(bp, '\n');
|
if (p == NULL)
|
if (p == NULL)
|
p = strchr(bp, '\n');
|
p = strchr(bp, '\n');
|
while (p > bp && isspace(p[-1]))
|
while (p > bp && isspace(p[-1]))
|
p--;
|
p--;
|
yylval.string = alloc(p - bp + 1);
|
yylval.string = alloc(p - bp + 1);
|
strncpy(yylval.string, bp, p - bp);
|
strncpy(yylval.string, bp, p - bp);
|
yylval.string[p - bp] = 0;
|
yylval.string[p - bp] = 0;
|
bp = p;
|
bp = p;
|
code--;
|
code--;
|
return CODE;
|
return CODE;
|
}
|
}
|
while ((c = get()) != EOF) {
|
while ((c = get()) != EOF) {
|
switch (c) {
|
switch (c) {
|
case ' ': case '\f': case '\t':
|
case ' ': case '\f': case '\t':
|
continue;
|
continue;
|
case '\n':
|
case '\n':
|
case '(': case ')': case ',':
|
case '(': case ')': case ',':
|
case ':': case '=':
|
case ':': case '=':
|
return c;
|
return c;
|
}
|
}
|
if (c == '%' && *bp == '%') {
|
if (c == '%' && *bp == '%') {
|
bp++;
|
bp++;
|
return ppercent++ ? 0 : PPERCENT;
|
return ppercent++ ? 0 : PPERCENT;
|
} else if (c == '%' && strncmp(bp, "term", 4) == 0
|
} else if (c == '%' && strncmp(bp, "term", 4) == 0
|
&& isspace(bp[4])) {
|
&& isspace(bp[4])) {
|
bp += 4;
|
bp += 4;
|
return TERMINAL;
|
return TERMINAL;
|
} else if (c == '%' && strncmp(bp, "start", 5) == 0
|
} else if (c == '%' && strncmp(bp, "start", 5) == 0
|
&& isspace(bp[5])) {
|
&& isspace(bp[5])) {
|
bp += 5;
|
bp += 5;
|
return START;
|
return START;
|
} else if (c == '"') {
|
} else if (c == '"') {
|
char *p = strchr(bp, '"');
|
char *p = strchr(bp, '"');
|
if (p == NULL) {
|
if (p == NULL) {
|
yyerror("missing \" in assembler template\n");
|
yyerror("missing \" in assembler template\n");
|
p = strchr(bp, '\n');
|
p = strchr(bp, '\n');
|
if (p == NULL)
|
if (p == NULL)
|
p = strchr(bp, '\0');
|
p = strchr(bp, '\0');
|
}
|
}
|
assert(p);
|
assert(p);
|
yylval.string = alloc(p - bp + 1);
|
yylval.string = alloc(p - bp + 1);
|
strncpy(yylval.string, bp, p - bp);
|
strncpy(yylval.string, bp, p - bp);
|
yylval.string[p - bp] = 0;
|
yylval.string[p - bp] = 0;
|
bp = *p == '"' ? p + 1 : p;
|
bp = *p == '"' ? p + 1 : p;
|
code++;
|
code++;
|
return TEMPLATE;
|
return TEMPLATE;
|
} else if (isdigit(c)) {
|
} else if (isdigit(c)) {
|
int n = 0;
|
int n = 0;
|
do {
|
do {
|
int d = c - '0';
|
int d = c - '0';
|
if (n > (INT_MAX - d)/10)
|
if (n > (INT_MAX - d)/10)
|
yyerror("integer greater than %d\n", INT_MAX);
|
yyerror("integer greater than %d\n", INT_MAX);
|
else
|
else
|
n = 10*n + d;
|
n = 10*n + d;
|
c = get();
|
c = get();
|
} while (c != EOF && isdigit(c));
|
} while (c != EOF && isdigit(c));
|
bp--;
|
bp--;
|
yylval.n = n;
|
yylval.n = n;
|
return INT;
|
return INT;
|
} else if (isalpha(c)) {
|
} else if (isalpha(c)) {
|
char *p = bp - 1;
|
char *p = bp - 1;
|
while (isalpha(*bp) || isdigit(*bp) || *bp == '_')
|
while (isalpha(*bp) || isdigit(*bp) || *bp == '_')
|
bp++;
|
bp++;
|
yylval.string = alloc(bp - p + 1);
|
yylval.string = alloc(bp - p + 1);
|
strncpy(yylval.string, p, bp - p);
|
strncpy(yylval.string, p, bp - p);
|
yylval.string[bp - p] = 0;
|
yylval.string[bp - p] = 0;
|
return ID;
|
return ID;
|
} else if (isprint(c))
|
} else if (isprint(c))
|
yyerror("invalid character `%c'\n", c);
|
yyerror("invalid character `%c'\n", c);
|
else
|
else
|
yyerror("invalid character `\\%03o'\n", (unsigned char)c);
|
yyerror("invalid character `\\%03o'\n", (unsigned char)c);
|
}
|
}
|
return 0;
|
return 0;
|
}
|
}
|
|
|
void yywarn(char *fmt, ...) {
|
void yywarn(char *fmt, ...) {
|
va_list ap;
|
va_list ap;
|
|
|
va_start(ap, fmt);
|
va_start(ap, fmt);
|
if (yylineno > 0)
|
if (yylineno > 0)
|
fprintf(stderr, "line %d: ", yylineno);
|
fprintf(stderr, "line %d: ", yylineno);
|
fprintf(stderr, "warning: ");
|
fprintf(stderr, "warning: ");
|
vfprintf(stderr, fmt, ap);
|
vfprintf(stderr, fmt, ap);
|
}
|
}
|
|
|