char *text;
int ivalue;
Tree *tree;
+ Rule *rule;
+ GList *rule_list;
}
%token <text> IDENT
%token START
%token COST
%token TERM
+%token TERMPREFIX
%token <ivalue> INTEGER
%type <tree> tree
%type <text> optcost
%type <text> optcfunc
%type <text> optcode
+%type <rule> rule
+%type <rule_list> rule_list
%%
decls : /* empty */
| START IDENT { start_nonterm ($2); } decls
| TERM tlist decls
- | IDENT ':' tree optcost optcode optcfunc { create_rule ($1, $3, $5, $4, $6); } decls
+ | TERMPREFIX plist decls
+ | rule_list optcost optcode optcfunc {
+ GList *tmp;
+ for (tmp = $1; tmp; tmp = tmp->next) {
+ rule_add (tmp->data, $3, $2, $4);
+ }
+ g_list_free ($1);
+ } decls
;
-optcode : /* empty */ { $$ = NULL }
+rule : IDENT ':' tree { $$ = make_rule ($1, $3); }
+ ;
+
+rule_list : rule { $$ = g_list_append (NULL, $1); }
+ | rule ',' rule_list { $$ = g_list_prepend ($3, $1); }
+ ;
+
+optcode : /* empty */ { $$ = NULL; }
| CODE
;
+plist : /* empty */
+ | plist IDENT { create_term_prefix ($2);}
+ ;
+
tlist : /* empty */
| tlist IDENT { create_term ($2, -1);}
| tlist IDENT '=' INTEGER { create_term ($2, $4); }
state = 0;
}
+struct pplist {
+ struct pplist *next;
+ gboolean ignore;
+};
+
+static struct pplist *pp = NULL;
+
+static char*
+getvar (const char *input)
+{
+ char *var = g_strchug (g_strdup (input));
+ char *ptr;
+
+ for (ptr = var; *ptr && *ptr != '\n'; ++ptr) {
+ if (g_ascii_isspace (*ptr)) {
+ break;
+ }
+ }
+ *ptr = '\0';
+
+ return var;
+}
+
+static void
+push_if (char *input, gboolean flip)
+{
+ struct pplist *new_pp = g_new (struct pplist, 1);
+ char *var = getvar (input);
+
+ new_pp->ignore = (g_hash_table_lookup (definedvars, var) == NULL) ^ flip;
+ new_pp->next = pp;
+
+ new_pp->ignore |= (pp ? pp->ignore : 0);
+ pp = new_pp;
+ g_free (var);
+}
+
+static void
+flip_if ()
+{
+ if (!pp)
+ yyerror ("%%else without %%if");
+
+ pp->ignore = !pp->ignore | (pp->next ? pp->next->ignore : 0);
+}
+
+static void
+pop_if ()
+{
+ struct pplist *prev_pp = pp;
+
+ if (!pp)
+ yyerror ("%%endif without %%if");
+
+ pp = pp->next;
+ g_free (prev_pp);
+}
+
static char
nextchar ()
{
ll = (input [0] == '%' && input [1] == '%');
next_state = state;
+ if (state == 1) {
+ if (!ll && input [0] == '%') {
+ if (!strncmp (&input [1], "ifdef", 5)) {
+ push_if (&input [6], FALSE);
+ ll = TRUE;
+ continue;
+ }
+ else if (!strncmp (&input [1], "ifndef", 6)) {
+ push_if (&input [7], TRUE);
+ ll = TRUE;
+ continue;
+ }
+ else if (!strncmp (&input [1], "else", 4)) {
+ flip_if ();
+ ll = TRUE;
+ continue;
+ }
+ else if (!strncmp (&input [1], "endif", 5)) {
+ pop_if ();
+ ll = TRUE;
+ continue;
+ }
+ }
+ if (pp && pp->ignore) {
+ ll = TRUE;
+ continue;
+ }
+ }
+
switch (state) {
case 0:
if (ll) {
next_state = 1;
- } else
+ } else
fputs (input, outputfd);
break;
case 1:
fputs (input, outputfd);
while (fgets (input, sizeof (input), inputfd))
fputs (input, outputfd);
+ input [0] = '\0';
}
int
return START;
}
+ if (!strncmp (next, "termprefix", 10) && isspace (next[10])) {
+ next += 10;
+ return TERMPREFIX;
+ }
+
if (!strncmp (next, "term", 4) && isspace (next[4])) {
next += 4;
return TERM;