2007-04-19 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / monoburg / monoburg.y
index 2ca7b7d64d997196f61ab76991389bac42abd5e2..83186439c8f1b772b62a0cfbdd68ee598f6a67a7 100644 (file)
@@ -27,6 +27,8 @@ static int yylinepos = 0;
   char *text;
   int   ivalue;
   Tree  *tree;
+  Rule  *rule;
+  GList *rule_list;
 }
 
 %token <text> IDENT
@@ -35,25 +37,46 @@ static int yylinepos = 0;
 %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); }
@@ -101,6 +124,64 @@ reset_parser ()
   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 ()
 {
@@ -117,11 +198,40 @@ 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:
@@ -148,6 +258,7 @@ yyparsetail (void)
   fputs (input, outputfd);
   while (fgets (input, sizeof (input), inputfd))
     fputs (input, outputfd);
+  input [0] = '\0';
 }
 
 int 
@@ -171,6 +282,11 @@ yylex (void)
        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;