* TreeView.cs: When calling ExpandAll, set SelectedNode to the top
[mono.git] / mono / monoburg / monoburg.y
index 3aec74faccb00394b37932ca87aec7df834aac7a..7802fd81b529cf30ca1b85447cfb1799afd0f00a 100644 (file)
@@ -8,9 +8,13 @@
  * (C) 2001 Ximian, Inc.
  */
 
+#include <config.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 #include <ctype.h>
 #include <assert.h>
 #include <stdarg.h>
@@ -26,31 +30,56 @@ static int yylinepos = 0;
   char *text;
   int   ivalue;
   Tree  *tree;
+  Rule  *rule;
+  GList *rule_list;
 }
 
 %token <text> IDENT
 %token <text> CODE
 %token <text> STRING
 %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 { create_rule ($1, $3, $5, $4); } 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); }
@@ -61,22 +90,16 @@ tree        : IDENT { $$ = create_tree ($1, NULL, NULL); }
        | IDENT '(' tree ',' tree ')' { $$ = create_tree ($1, $3, $5); }
        ;
 
-optcost : /* empty */ {$$ = "0"; }
+optcost : /* empty */ {$$ = NULL; }
        | STRING
        | INTEGER { $$ = g_strdup_printf ("%d", $1); }
        ;
 
+optcfunc : /*empty */ { $$ = NULL; }
+        | COST CODE { $$ = $2; }
+        ;
 %%
 
-static char *
-strndup (const char *s, int n)
-{
-  char *ns = malloc (n + 1);
-  strncpy (ns, s, n);
-  ns [n + 1] = '\0';
-  return ns;
-}
-
 static char input[2048];
 static char *next = input;
 
@@ -96,10 +119,75 @@ yyerror (char *fmt, ...)
   exit (-1);
 }
 
+static int state = 0;
+
+void
+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 ()
 {
-  static int state = 0;
   int next_state ;
   gboolean ll;
 
@@ -110,19 +198,50 @@ nextchar ()
        if (!fgets (input, sizeof (input), inputfd))
          return 0;
 
-       ll = (input [0] == '%' && input [1] == '%' && isspace (input [2]));
+       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 
-           fputs (input, stdout);
+         } else
+           fputs (input, outputfd);
          break;
        case 1:
-         if (ll)
+         if (ll) {
            next_state = 2;
+           *next = 0;
+         }
          break;
        default:
          return 0;
@@ -139,9 +258,10 @@ nextchar ()
 void
 yyparsetail (void)
 {
-  fputs (input, stdout);
+  fputs (input, outputfd);
   while (fgets (input, sizeof (input), inputfd))
-    fputs (input, stdout);
+    fputs (input, outputfd);
+  input [0] = '\0';
 }
 
 int 
@@ -165,6 +285,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;
@@ -177,7 +302,7 @@ yylex (void)
 
            do {
                    num = 10*num + (c - '0');
-           } while ((c = isdigit (*next++)));
+           } while (isdigit (c = (*next++)));
 
            yylval.ivalue = num;
            return INTEGER;
@@ -187,18 +312,17 @@ yylex (void)
       char *n = next;
       int l;
 
-      //if (!strncmp (next - 1, "cost", 4) && isspace (next[3])) {
-      //next += 4;
-      //return COST;
-      //}
+      if (!strncmp (next - 1, "cost", 4) && isspace (next[3])) {
+       next += 4;
+       return COST;
+      }
 
-      while (isalpha (*n) || isdigit (*n) || (*n == '_')
+      while (isalpha (*n) || isdigit (*n) || *n == '_'
              n++;
 
       l = n - next + 1;
-      yylval.text = strndup (next - 1, l);
-      next += l - 1;
-
+      yylval.text = g_strndup (next - 1, l);
+      next = n;
       return IDENT;
     }
     
@@ -209,8 +333,8 @@ yylex (void)
       while ((c = *next++) != '"' && c)
        buf [i++] = c;
       
-      buf [--i] = '\0';
-      yylval.text = strdup (buf);
+      buf [i] = '\0';
+      yylval.text = g_strdup (buf);
 
       return STRING;
     }
@@ -227,10 +351,11 @@ yylex (void)
        case '{': d++; break;
        case '}': d--; break;
        default:
+               break;
        }
       }
       buf [--i] = '\0';
-      yylval.text = strdup (buf);
+      yylval.text = g_strdup (buf);
 
       return CODE;
     }