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