Mercurial > audlegacy-plugins
annotate src/paranormal/libcalc/parser.yacc @ 1833:15e7d3473974
paranormal: MK2
author | William Pitcock <nenolod@atheme.org> |
---|---|
date | Mon, 24 Sep 2007 13:57:28 -0500 |
parents | 117ae74e2715 |
children |
rev | line source |
---|---|
282 | 1 /* parser.y -- Bison parser for libexp |
2 * | |
3 * Copyright (C) 2001 Janusz Gregorczyk <jgregor@kki.net.pl> | |
4 * | |
5 * This file is part of xvs. | |
6 * | |
7 * This program is free software; you can redistribute it and/or modify | |
8 * it under the terms of the GNU General Public License as published by | |
9 * the Free Software Foundation; either version 2 of the License, or | |
10 * (at your option) any later version. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 * GNU General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU General Public License | |
18 * along with this program; if not, write to the Free Software | |
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
20 */ | |
21 | |
295 | 22 /* suppress conflict warnings */ |
23 %expect 37 | |
24 | |
282 | 25 /* C declarations. */ |
26 %{ | |
27 #include <ctype.h> | |
28 #include <glib.h> | |
29 #include <locale.h> | |
30 #include <math.h> | |
31 #include <stdio.h> | |
32 #include <string.h> | |
33 | |
34 #include "dict.h" | |
35 #include "execute.h" | |
36 #include "function.h" | |
37 #include "parser.h" | |
38 #include "storage.h" | |
39 | |
40 #define YYPARSE_PARAM yyparam | |
41 #define YYLEX_PARAM yyparam | |
42 | |
43 static gboolean expr_add_compile (expression_t *expr, symbol_dict_t *dict, | |
44 char *str); | |
45 | |
46 #define GENERATE(str) if (!expr_add_compile (((parser_control *)yyparam)->expr, \ | |
47 ((parser_control *)yyparam)->dict, str)) \ | |
48 YYABORT; | |
49 %} | |
50 | |
51 %pure_parser | |
52 | |
53 /* Data types. */ | |
54 %union { | |
55 char *s_value; | |
56 char c_value; | |
57 double d_value; | |
58 int i_value; | |
59 } | |
60 | |
61 /* Terminal symbols. */ | |
62 %token <s_value> NAME | |
63 %token <d_value> NUMBER | |
64 | |
65 /* Precedence rules. */ | |
66 %right '=' | |
67 %left '-' '+' | |
68 %left '*' '/' | |
69 %left NEG | |
70 %right '^' | |
71 | |
72 /* Grammar follows */ | |
73 %% | |
74 | |
75 /* Input consits of a (possibly empty) list of expressions. */ | |
76 input: /* empty */ | |
77 | input expression_list | |
78 ; | |
79 | |
80 /* expression_list is a ';' separated list of expressions. */ | |
81 expression_list: /* empty */ | |
82 | expression | |
83 { } | |
84 | expression_list ';' | |
85 | error ';' | |
86 { yyerrok; } | |
87 | |
88 /* argument list is a comma separated list od expressions */ | |
89 argument_list: | |
90 expression | |
91 { | |
92 } | |
93 | argument_list ',' expression | |
94 { | |
95 } | |
96 | |
97 /* expression is a C-like expression. */ | |
98 expression: NUMBER | |
99 { | |
100 char *buf = g_strdup_printf ("c%f:", $1); | |
101 GENERATE (buf); | |
102 g_free (buf); | |
103 } | |
104 | NAME | |
105 { | |
106 char *buf = g_strdup_printf ("l%s:", $1); | |
107 GENERATE (buf); | |
108 g_free (buf); | |
109 } | |
110 | NAME '=' expression | |
111 { | |
112 char *buf = g_strdup_printf ("s%s:", $1); | |
113 GENERATE (buf); | |
114 g_free (buf); | |
115 } | |
116 | NAME '(' argument_list ')' | |
117 { | |
118 char *buf = g_strdup_printf ("f%s:", $1); | |
119 GENERATE (buf); | |
120 g_free (buf); | |
121 } | |
122 | |
123 | expression '>' expression | |
124 { GENERATE (">"); } | |
125 | expression '<' expression | |
126 { GENERATE ("<"); } | |
127 | |
128 | expression '+' expression | |
129 { GENERATE ("+"); } | |
130 | expression '-' expression | |
131 { GENERATE ("-"); } | |
132 | expression '*' expression | |
133 { GENERATE ("*"); } | |
134 | expression '/' expression | |
135 { GENERATE ("/"); } | |
136 | '-' expression %prec NEG | |
137 { GENERATE ("n"); } | |
138 | expression '^' expression | |
139 { GENERATE ("^"); } | |
140 | '(' expression ')' | |
141 { } | |
142 ; | |
143 | |
144 %% | |
145 /* End of grammar */ | |
146 | |
147 /* Called by yyparse on error. */ | |
148 int yyerror (char *s) { | |
149 /* Ignore errors, just print a warning. */ | |
150 g_warning ("%s\n", s); | |
151 return 0; | |
152 } | |
153 | |
154 int yylex (YYSTYPE *yylval, void *yyparam) { | |
155 int c; | |
156 parser_control *pc = (parser_control *) yyparam; | |
157 | |
158 /* Ignore whitespace, get first nonwhite character. */ | |
342
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
159 while ((c = vfs_getc (pc->input)) == ' ' || c == '\t' || c == '\n'); |
282 | 160 |
161 /* End of input ? */ | |
162 if (c == EOF) | |
163 return 0; | |
342
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
164 |
282 | 165 /* Char starts a number => parse the number. */ |
166 if (isdigit (c)) { | |
342
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
167 vfs_fseek (pc->input, -1, SEEK_CUR); /* Put the char back. */ |
282 | 168 { |
169 char *old_locale, *saved_locale; | |
170 | |
171 old_locale = setlocale (LC_ALL, NULL); | |
172 saved_locale = g_strdup (old_locale); | |
173 setlocale (LC_ALL, "C"); | |
342
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
174 sscanf (((VFSBuffer *)(pc->input->handle))->iter, "%lf", &yylval->d_value); |
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
175 |
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
176 while (isdigit(c) || c == '.') |
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
177 { |
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
178 c = vfs_getc(pc->input); |
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
179 } |
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
180 |
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
181 vfs_fseek(pc->input, -1, SEEK_CUR); |
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
182 |
282 | 183 setlocale (LC_ALL, saved_locale); |
184 g_free (saved_locale); | |
185 } | |
186 return NUMBER; | |
187 } | |
188 | |
189 /* Char starts an identifier => read the name. */ | |
190 if (isalpha (c)) { | |
191 GString *sym_name; | |
192 | |
193 sym_name = g_string_new (NULL); | |
194 | |
195 do { | |
196 sym_name = g_string_append_c (sym_name, c); | |
197 | |
198 /* Get another character. */ | |
342
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
199 c = vfs_getc (pc->input); |
282 | 200 } while (c != EOF && isalnum (c)); |
201 | |
342
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
202 vfs_fseek (pc->input, -1, SEEK_CUR); |
282 | 203 |
204 yylval->s_value = sym_name->str; | |
205 | |
206 g_string_free (sym_name, FALSE); | |
207 | |
208 return NAME; | |
209 } | |
210 | |
211 /* Any other character is a token by itself. */ | |
212 return c; | |
213 } | |
214 | |
215 static int load_name (char *str, char **name) { | |
216 int count = 0; | |
217 GString *new = g_string_new (NULL); | |
218 | |
219 while (*str != 0 && *str != ':') { | |
220 g_string_append_c (new, *str++); | |
221 count++; | |
222 } | |
223 | |
224 *name = new->str; | |
225 g_string_free (new, FALSE); | |
226 | |
227 return count; | |
228 } | |
229 | |
230 static gboolean expr_add_compile (expression_t *expr, symbol_dict_t *dict, | |
231 char *str) { | |
232 char op; | |
233 double dval; | |
234 int i; | |
235 char *name; | |
236 | |
237 while ((op = *str++)) { | |
238 switch (op) { | |
239 case 'c': /* A constant. */ | |
240 store_byte (expr, 'c'); | |
241 sscanf (str, "%lf%n", &dval, &i); | |
242 str += i; | |
243 store_double (expr, dval); | |
244 str++; /* Skip ';' */ | |
245 break; | |
246 | |
247 case 'f': /* A function call. */ | |
248 store_byte (expr, 'f'); | |
249 str += load_name (str, &name); | |
250 i = function_lookup (name); | |
251 if (i < 0) return FALSE; /* Fail on error. */ | |
252 store_int (expr, i); | |
253 g_free (name); | |
254 str++; /* Skip ';' */ | |
255 break; | |
256 | |
257 case 'l': /* Load a variable. */ | |
258 case 's': /* Store a variable. */ | |
259 store_byte (expr, op); | |
260 str += load_name (str, &name); | |
261 i = dict_lookup (dict, name); | |
262 store_int (expr, i); | |
263 g_free (name); | |
264 str++; /* Skip ';' */ | |
265 break; | |
266 | |
267 default: /* Copy verbatim. */ | |
268 store_byte (expr, op); | |
269 break; | |
270 } | |
271 } | |
272 | |
273 return TRUE; | |
274 } | |
275 | |
342
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
276 expression_t *expr_compile_string (const char* str, symbol_dict_t *dict) |
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
277 { |
282 | 278 parser_control pc; |
342
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
279 VFSFile *stream; |
282 | 280 |
342
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
281 g_return_val_if_fail(str != NULL && dict != NULL, NULL); |
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
282 |
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
283 stream = vfs_buffer_new_from_string ( (char *) str ); |
282 | 284 |
285 pc.input = stream; | |
286 pc.expr = expr_new (); | |
287 pc.dict = dict; | |
288 | |
289 if (yyparse (&pc) != 0) { | |
290 /* Check for error. */ | |
291 expr_free (pc.expr); | |
292 pc.expr = NULL; | |
293 } | |
294 | |
342
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
295 vfs_fclose (stream); |
282 | 296 |
297 return pc.expr; | |
298 } |