Mercurial > audlegacy-plugins
annotate src/paranormal/libcalc/parser.yacc @ 3203:f5456241bff9 default tip
changed include path from audacious to audlegacy.
| author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
|---|---|
| date | Tue, 10 Nov 2009 05:19:25 +0900 |
| 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 } |
