abd0cedd61
rather than the size. Much cleaner and simpler.
233 lines
6.6 KiB
Plaintext
233 lines
6.6 KiB
Plaintext
%{
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <limits.h>
|
|
#include "iburg.h"
|
|
#include "astring.h"
|
|
|
|
#define YYDEBUG 1
|
|
|
|
extern int yylex(void);
|
|
|
|
%}
|
|
%union {
|
|
arith n;
|
|
const char* string;
|
|
Nonterm nonterm;
|
|
Tree tree;
|
|
Rule rule;
|
|
struct reg* reg;
|
|
struct stringlist* stringlist;
|
|
struct terminfo terminfo;
|
|
struct expr* expr;
|
|
struct constraint* constraint;
|
|
}
|
|
|
|
%term ALIASES
|
|
%term COPY
|
|
%term CORRUPTED
|
|
%term COST
|
|
%term DECLARATIONS
|
|
%term EMIT
|
|
%term EQUALS
|
|
%term FRAGMENT
|
|
%term NAMED
|
|
%term NOTEQUALS
|
|
%term PATTERNS
|
|
%term PREFERS
|
|
%term REGISTERS
|
|
%term WHEN
|
|
%term WITH
|
|
|
|
%token <n> INT
|
|
%token <string> ID
|
|
%token <string> QFRAGMENT
|
|
|
|
%type <constraint> constraint
|
|
%type <constraint> constraints
|
|
%type <expr> predicate
|
|
%type <expr> predicate_arg
|
|
%type <expr> predicate_args
|
|
%type <nonterm> declaration
|
|
%type <reg> register
|
|
%type <rule> pattern
|
|
%type <rule> pattern_constraints
|
|
%type <rule> pattern_emit
|
|
%type <string> nodename
|
|
%type <stringlist> aliases
|
|
%type <stringlist> names
|
|
%type <stringlist> qfragments
|
|
%type <terminfo> terminfo
|
|
%type <tree> rhs
|
|
%%
|
|
|
|
spec
|
|
: REGISTERS registers
|
|
DECLARATIONS declarations
|
|
PATTERNS patterns
|
|
;
|
|
|
|
registers
|
|
: /* nothing */
|
|
| registers register ';'
|
|
| register ';'
|
|
;
|
|
|
|
register
|
|
: ID { $$ = makereg($1); }
|
|
| register NAMED '(' names ')' { $$ = $1; setregnames($$, $4); }
|
|
| register ALIASES '(' aliases ')' { $$ = $1; addregaliases($$, $4); }
|
|
| register ID { $$ = $1; addregattr($1, $2, false); }
|
|
| register ID '!' { $$ = $1; addregattr($1, $2, true); }
|
|
;
|
|
|
|
names
|
|
: QFRAGMENT { $$ = calloc(1, sizeof(*$$)); stringlist_add($$, $1); }
|
|
| names ',' QFRAGMENT { $$ = $1; stringlist_add($$, $3); }
|
|
;
|
|
|
|
aliases
|
|
: ID { $$ = calloc(1, sizeof(*$$)); stringlist_add($$, $1); }
|
|
| aliases ',' ID { $$ = $1; stringlist_add($$, $3); }
|
|
;
|
|
|
|
declarations
|
|
: /* nothing */
|
|
| declarations declaration ';'
|
|
| declaration ';'
|
|
;
|
|
|
|
declaration
|
|
: ID { $$ = nonterm($1, true); }
|
|
| declaration FRAGMENT { $$ = $1; $$->is_fragment = true; }
|
|
;
|
|
|
|
patterns
|
|
: /* nothing */
|
|
| patterns pattern ';'
|
|
| patterns ';'
|
|
;
|
|
|
|
pattern
|
|
: terminfo '=' rhs { nonterm($1.name, false); $$ = rule(&$1, $3); }
|
|
| rhs { $$ = rule(NULL, $1); }
|
|
| pattern PREFERS predicate { $$ = $1; array_append(&$$->prefers, $3); }
|
|
| pattern WHEN predicate { $$ = $1; array_append(&$$->requires, $3); }
|
|
| pattern COST INT { $$ = $1; $$->cost = $3; }
|
|
| pattern_constraints { $$ = $1; }
|
|
| pattern_emit { $$ = $1; }
|
|
;
|
|
|
|
rhs
|
|
: terminfo { $$ = tree(&$1, NULL, NULL); }
|
|
| terminfo '(' rhs ')' { $$ = tree(&$1, $3, NULL); }
|
|
| terminfo '(' rhs ',' rhs ')' { $$ = tree(&$1, $3, $5); }
|
|
;
|
|
|
|
terminfo
|
|
: nodename { $$.name = $1; }
|
|
| '(' ID ')' nodename { $$.attr = $2; $$.name = $4; }
|
|
| ID ':' nodename { $$.label = $1; $$.name = $3; }
|
|
| ID ':' '(' ID ')' nodename { $$.label = $1; $$.attr = $4; $$.name = $6; }
|
|
;
|
|
|
|
nodename
|
|
: ID { $$ = $1; }
|
|
| ID '.' ID { $$ = aprintf("%s.%s", $1, $3); }
|
|
;
|
|
|
|
pattern_emit
|
|
: pattern EMIT qfragments {
|
|
$$ = $1;
|
|
if (!$$->lhs->is_fragment)
|
|
stringlist_add($3, "\n");
|
|
stringlist_addall(&$$->code, $3);
|
|
}
|
|
;
|
|
|
|
pattern_constraints
|
|
: pattern WITH constraints {
|
|
struct constraint* c = $3;
|
|
$$ = $1;
|
|
while (c)
|
|
{
|
|
array_append(&$$->constraints, c);
|
|
c = c->next;
|
|
}
|
|
}
|
|
;
|
|
|
|
constraints
|
|
: constraint { $$ = $1; }
|
|
| constraints ',' constraint { $$ = $3; $$->next = $1; }
|
|
;
|
|
|
|
constraint
|
|
: '(' constraint ')' { $$ = $2; }
|
|
| '%' ID EQUALS '%' ID { $$ = calloc(1, sizeof(*$$));
|
|
$$->type = CONSTRAINT_EQUALS; $$->left = $2; $$->right = $5; }
|
|
| CORRUPTED '(' ID ')' { $$ = calloc(1, sizeof(*$$));
|
|
$$->type = CONSTRAINT_CORRUPTED_ATTR; $$->left = $3; }
|
|
;
|
|
|
|
qfragments
|
|
: /* nothing */ { $$ = calloc(1, sizeof *$$); }
|
|
| qfragments QFRAGMENT { $$ = $1; stringlist_add($$, $2); }
|
|
;
|
|
|
|
predicate
|
|
: ID '(' predicate_args ')' {
|
|
$$ = calloc(1, sizeof *$$);
|
|
$$->type = PREDICATE_FUNCTION;
|
|
$$->u.name = $1;
|
|
$$->next = $3;
|
|
}
|
|
;
|
|
|
|
predicate_args
|
|
: /* nothing */ { $$ = NULL; }
|
|
| predicate_arg { $$ = $1; }
|
|
| predicate_arg ',' predicate_args { $$ = $1; $$->next = $3; }
|
|
;
|
|
|
|
predicate_arg
|
|
: '%' ID { $$ = calloc(1, sizeof *$$); $$->type = PREDICATE_NODE; $$->u.name = $2; }
|
|
| INT { $$ = calloc(1, sizeof *$$); $$->type = PREDICATE_NUMBER; $$->u.number = $1; }
|
|
;
|
|
|
|
%%
|
|
#include <stdarg.h>
|
|
#include <ctype.h>
|
|
|
|
int errcnt = 0;
|
|
static char buf[BUFSIZ], *bp = buf;
|
|
static int ppercent = 0;
|
|
|
|
void yyerror(char *fmt, ...) {
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
if (yylineno > 0)
|
|
fprintf(stderr, "line %d: ", yylineno);
|
|
vfprintf(stderr, fmt, ap);
|
|
if (fmt[strlen(fmt)-1] != '\n')
|
|
fprintf(stderr, "\n");
|
|
errcnt++;
|
|
exit(1);
|
|
}
|
|
|
|
void yywarn(char *fmt, ...) {
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
if (yylineno > 0)
|
|
fprintf(stderr, "line %d: ", yylineno);
|
|
fprintf(stderr, "warning: ");
|
|
vfprintf(stderr, fmt, ap);
|
|
}
|
|
|
|
/* vim: set sw=4 ts=4 expandtab : */
|