2002-10-17 Dietmar Maurer <dietmar@ximian.com>
[mono.git] / mono / monoburg / monoburg.y
1 %{
2 /*
3  * monoburg.y: yacc input grammer
4  *
5  * Author:
6  *   Dietmar Maurer (dietmar@ximian.com)
7  *
8  * (C) 2001 Ximian, Inc.
9  */
10
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <ctype.h>
16 #include <assert.h>
17 #include <stdarg.h>
18
19 #include "monoburg.h"
20   
21 static int yylineno = 0;
22 static int yylinepos = 0;
23
24 %}
25
26 %union {
27   char *text;
28   int   ivalue;
29   Tree  *tree;
30 }
31
32 %token <text> IDENT
33 %token <text> CODE
34 %token <text> STRING
35 %token  START
36 %token  COST
37 %token  TERM
38 %token  TERMPREFIX
39 %token <ivalue> INTEGER
40
41 %type   <tree>          tree
42 %type   <text>          optcost
43 %type   <text>          optcfunc
44 %type   <text>          optcode
45
46 %%
47
48 decls   : /* empty */ 
49         | START IDENT { start_nonterm ($2); } decls
50         | TERM  tlist decls
51         | TERMPREFIX plist decls
52         | IDENT ':' tree optcost optcode optcfunc { create_rule ($1, $3, $5, $4, $6); } decls 
53         ;
54
55 optcode : /* empty */ { $$ = NULL; }
56         | CODE 
57         ;
58
59 plist   : /* empty */
60         | plist IDENT { create_term_prefix ($2);}
61         ;
62
63 tlist   : /* empty */
64         | tlist IDENT { create_term ($2, -1);}
65         | tlist IDENT '=' INTEGER { create_term ($2, $4); }
66         ;
67
68 tree    : IDENT { $$ = create_tree ($1, NULL, NULL); }
69         | IDENT '(' tree ')' { $$ = create_tree ($1, $3, NULL); }
70         | IDENT '(' tree ',' tree ')' { $$ = create_tree ($1, $3, $5); }
71         ;
72
73 optcost : /* empty */ {$$ = NULL; }
74         | STRING
75         | INTEGER { $$ = g_strdup_printf ("%d", $1); }
76         ;
77
78 optcfunc : /*empty */ { $$ = NULL; }
79          | COST CODE { $$ = $2; }
80          ;
81 %%
82
83 static char input[2048];
84 static char *next = input;
85
86 void 
87 yyerror (char *fmt, ...)
88 {
89   va_list ap;
90
91   va_start(ap, fmt);
92
93   fprintf (stderr, "line %d(%d): ", yylineno, yylinepos);
94   vfprintf (stderr, fmt, ap);
95   fprintf(stderr, "\n");
96
97   va_end (ap);
98
99   exit (-1);
100 }
101
102 static int state = 0;
103
104 void
105 reset_parser ()
106 {
107   state = 0;
108 }
109
110 static char
111 nextchar ()
112 {
113   int next_state ;
114   gboolean ll;
115
116     if (!*next) {
117       next = input;
118       *next = 0;
119       do {
120         if (!fgets (input, sizeof (input), inputfd))
121           return 0;
122
123         ll = (input [0] == '%' && input [1] == '%');
124         next_state = state;
125
126         switch (state) {
127         case 0:
128           if (ll) {
129             next_state = 1;
130           } else 
131             fputs (input, outputfd);
132           break;
133         case 1:
134           if (ll) {
135             next_state = 2;
136             *next = 0;
137           }
138           break;
139         default:
140           return 0;
141         }
142         ll = state != 1 || input[0] == '#';
143         state = next_state;
144         yylineno++;
145       } while (next_state == 2 || ll);
146     } 
147
148     return *next++;
149 }
150
151 void
152 yyparsetail (void)
153 {
154   fputs (input, outputfd);
155   while (fgets (input, sizeof (input), inputfd))
156     fputs (input, outputfd);
157 }
158
159 int 
160 yylex (void) 
161 {
162   char c;
163
164   do {
165
166     if (!(c = nextchar ()))
167       return 0;
168
169     yylinepos = next - input + 1;
170
171     if (isspace (c))
172       continue;
173
174     if (c == '%') {
175       if (!strncmp (next, "start", 5) && isspace (next[5])) {
176         next += 5;
177         return START;
178       }
179
180       if (!strncmp (next, "termprefix", 10) && isspace (next[10])) {
181         next += 10;
182         return TERMPREFIX;
183       }
184
185       if (!strncmp (next, "term", 4) && isspace (next[4])) {
186         next += 4;
187         return TERM;
188       }
189       return c;
190     }
191
192     if (isdigit (c)) {
193             int num = 0;
194
195             do {
196                     num = 10*num + (c - '0');
197             } while (isdigit (c = (*next++)));
198
199             yylval.ivalue = num;
200             return INTEGER;
201     }
202
203     if (isalpha (c)) {
204       char *n = next;
205       int l;
206
207       if (!strncmp (next - 1, "cost", 4) && isspace (next[3])) {
208         next += 4;
209         return COST;
210       }
211
212       while (isalpha (*n) || isdigit (*n) || *n == '_') 
213               n++;
214
215       l = n - next + 1;
216       yylval.text = g_strndup (next - 1, l);
217       next = n;
218       return IDENT;
219     }
220     
221     if (c == '"') {
222       int i = 0;
223       static char buf [100000];
224  
225       while ((c = *next++) != '"' && c)
226         buf [i++] = c;
227       
228       buf [i] = '\0';
229       yylval.text = g_strdup (buf);
230
231       return STRING;
232     }
233
234     if (c == '{') {
235       int i = 0, d = 1;
236       static char buf [100000];
237  
238       while (d && (c = nextchar ())) {
239         buf [i++] = c;
240         assert (i < sizeof (buf));
241
242         switch (c) {
243         case '{': d++; break;
244         case '}': d--; break;
245         default:
246                 break;
247         }
248       }
249       buf [--i] = '\0';
250       yylval.text = g_strdup (buf);
251
252       return CODE;
253     }
254     
255     return c;
256   
257   } while (1);
258 }
259