Mercurial > audlegacy-plugins
annotate src/rovascope/libcalc/parser.y @ 702:d25b51e90542 trunk
[svn] - remove %expect 37
author | nenolod |
---|---|
date | Thu, 22 Feb 2007 07:19:39 -0800 |
parents | 290588854a9d |
children | 541854f0605c |
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 | |
22 /* C declarations. */ | |
23 %{ | |
24 #include <ctype.h> | |
25 #include <glib.h> | |
26 #include <locale.h> | |
27 #include <math.h> | |
28 #include <stdio.h> | |
29 #include <string.h> | |
30 | |
31 #include "dict.h" | |
32 #include "execute.h" | |
33 #include "function.h" | |
34 #include "parser.h" | |
35 #include "storage.h" | |
36 | |
37 #define YYPARSE_PARAM yyparam | |
38 #define YYLEX_PARAM yyparam | |
39 | |
40 static gboolean expr_add_compile (expression_t *expr, symbol_dict_t *dict, | |
41 char *str); | |
42 | |
43 #define GENERATE(str) if (!expr_add_compile (((parser_control *)yyparam)->expr, \ | |
44 ((parser_control *)yyparam)->dict, str)) \ | |
45 YYABORT; | |
46 %} | |
47 | |
48 %pure_parser | |
49 | |
50 /* Data types. */ | |
51 %union { | |
52 char *s_value; | |
53 char c_value; | |
54 double d_value; | |
55 int i_value; | |
56 } | |
57 | |
58 /* Terminal symbols. */ | |
59 %token <s_value> NAME | |
60 %token <d_value> NUMBER | |
61 | |
62 /* Precedence rules. */ | |
63 %right '=' | |
64 %left '-' '+' | |
65 %left '*' '/' | |
66 %left NEG | |
67 %right '^' | |
68 | |
69 /* Grammar follows */ | |
70 %% | |
71 | |
72 /* Input consits of a (possibly empty) list of expressions. */ | |
73 input: /* empty */ | |
74 | input expression_list | |
75 ; | |
76 | |
77 /* expression_list is a ';' separated list of expressions. */ | |
78 expression_list: /* empty */ | |
79 | expression | |
80 { } | |
81 | expression_list ';' | |
82 | error ';' | |
83 { yyerrok; } | |
84 | |
85 /* argument list is a comma separated list od expressions */ | |
86 argument_list: | |
87 expression | |
88 { | |
89 } | |
90 | argument_list ',' expression | |
91 { | |
92 } | |
93 | |
94 /* expression is a C-like expression. */ | |
95 expression: NUMBER | |
96 { | |
97 char *buf = g_strdup_printf ("c%f:", $1); | |
98 GENERATE (buf); | |
99 g_free (buf); | |
100 } | |
101 | NAME | |
102 { | |
103 char *buf = g_strdup_printf ("l%s:", $1); | |
104 GENERATE (buf); | |
105 g_free (buf); | |
106 } | |
107 | NAME '=' expression | |
108 { | |
109 char *buf = g_strdup_printf ("s%s:", $1); | |
110 GENERATE (buf); | |
111 g_free (buf); | |
112 } | |
113 | NAME '(' argument_list ')' | |
114 { | |
115 char *buf = g_strdup_printf ("f%s:", $1); | |
116 GENERATE (buf); | |
117 g_free (buf); | |
118 } | |
119 | |
120 | expression '>' expression | |
121 { GENERATE (">"); } | |
122 | expression '<' expression | |
123 { GENERATE ("<"); } | |
124 | |
125 | expression '+' expression | |
126 { GENERATE ("+"); } | |
127 | expression '-' expression | |
128 { GENERATE ("-"); } | |
129 | expression '*' expression | |
130 { GENERATE ("*"); } | |
131 | expression '/' expression | |
132 { GENERATE ("/"); } | |
133 | '-' expression %prec NEG | |
134 { GENERATE ("n"); } | |
135 | expression '^' expression | |
136 { GENERATE ("^"); } | |
137 | '(' expression ')' | |
138 { } | |
139 ; | |
140 | |
141 %% | |
142 /* End of grammar */ | |
143 | |
144 /* Called by yyparse on error. */ | |
145 int yyerror (char *s) { | |
146 /* Ignore errors, just print a warning. */ | |
147 g_warning ("%s\n", s); | |
148 return 0; | |
149 } | |
150 | |
151 int yylex (YYSTYPE *yylval, void *yyparam) { | |
152 int c; | |
153 parser_control *pc = (parser_control *) yyparam; | |
154 | |
155 /* Ignore whitespace, get first nonwhite character. */ | |
342
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
156 while ((c = vfs_getc (pc->input)) == ' ' || c == '\t' || c == '\n'); |
282 | 157 |
158 /* End of input ? */ | |
159 if (c == EOF) | |
160 return 0; | |
342
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
161 |
282 | 162 /* Char starts a number => parse the number. */ |
163 if (isdigit (c)) { | |
342
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
164 vfs_fseek (pc->input, -1, SEEK_CUR); /* Put the char back. */ |
282 | 165 { |
166 char *old_locale, *saved_locale; | |
167 | |
168 old_locale = setlocale (LC_ALL, NULL); | |
169 saved_locale = g_strdup (old_locale); | |
170 setlocale (LC_ALL, "C"); | |
342
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
171 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
|
172 |
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
173 while (isdigit(c) || c == '.') |
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
174 { |
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
175 c = vfs_getc(pc->input); |
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
176 } |
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 vfs_fseek(pc->input, -1, SEEK_CUR); |
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
179 |
282 | 180 setlocale (LC_ALL, saved_locale); |
181 g_free (saved_locale); | |
182 } | |
183 return NUMBER; | |
184 } | |
185 | |
186 /* Char starts an identifier => read the name. */ | |
187 if (isalpha (c)) { | |
188 GString *sym_name; | |
189 | |
190 sym_name = g_string_new (NULL); | |
191 | |
192 do { | |
193 sym_name = g_string_append_c (sym_name, c); | |
194 | |
195 /* Get another character. */ | |
342
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
196 c = vfs_getc (pc->input); |
282 | 197 } while (c != EOF && isalnum (c)); |
198 | |
342
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
199 vfs_fseek (pc->input, -1, SEEK_CUR); |
282 | 200 |
201 yylval->s_value = sym_name->str; | |
202 | |
203 g_string_free (sym_name, FALSE); | |
204 | |
205 return NAME; | |
206 } | |
207 | |
208 /* Any other character is a token by itself. */ | |
209 return c; | |
210 } | |
211 | |
212 static int load_name (char *str, char **name) { | |
213 int count = 0; | |
214 GString *new = g_string_new (NULL); | |
215 | |
216 while (*str != 0 && *str != ':') { | |
217 g_string_append_c (new, *str++); | |
218 count++; | |
219 } | |
220 | |
221 *name = new->str; | |
222 g_string_free (new, FALSE); | |
223 | |
224 return count; | |
225 } | |
226 | |
227 static gboolean expr_add_compile (expression_t *expr, symbol_dict_t *dict, | |
228 char *str) { | |
229 char op; | |
230 double dval; | |
231 int i; | |
232 char *name; | |
233 | |
234 while ((op = *str++)) { | |
235 switch (op) { | |
236 case 'c': /* A constant. */ | |
237 store_byte (expr, 'c'); | |
238 sscanf (str, "%lf%n", &dval, &i); | |
239 str += i; | |
240 store_double (expr, dval); | |
241 str++; /* Skip ';' */ | |
242 break; | |
243 | |
244 case 'f': /* A function call. */ | |
245 store_byte (expr, 'f'); | |
246 str += load_name (str, &name); | |
247 i = function_lookup (name); | |
248 if (i < 0) return FALSE; /* Fail on error. */ | |
249 store_int (expr, i); | |
250 g_free (name); | |
251 str++; /* Skip ';' */ | |
252 break; | |
253 | |
254 case 'l': /* Load a variable. */ | |
255 case 's': /* Store a variable. */ | |
256 store_byte (expr, op); | |
257 str += load_name (str, &name); | |
258 i = dict_lookup (dict, name); | |
259 store_int (expr, i); | |
260 g_free (name); | |
261 str++; /* Skip ';' */ | |
262 break; | |
263 | |
264 default: /* Copy verbatim. */ | |
265 store_byte (expr, op); | |
266 break; | |
267 } | |
268 } | |
269 | |
270 return TRUE; | |
271 } | |
272 | |
342
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
273 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
|
274 { |
282 | 275 parser_control pc; |
342
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
276 VFSFile *stream; |
282 | 277 |
342
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
278 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
|
279 |
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
280 stream = vfs_buffer_new_from_string ( (char *) str ); |
282 | 281 |
282 pc.input = stream; | |
283 pc.expr = expr_new (); | |
284 pc.dict = dict; | |
285 | |
286 if (yyparse (&pc) != 0) { | |
287 /* Check for error. */ | |
288 expr_free (pc.expr); | |
289 pc.expr = NULL; | |
290 } | |
291 | |
342
17311560f45f
[svn] - port from fmemopen() to vfs_buffer_new_from_string().
nenolod
parents:
295
diff
changeset
|
292 vfs_fclose (stream); |
282 | 293 |
294 return pc.expr; | |
295 } |