Warning, /education/labplot/src/backend/gsl/parser_parallel.y is written in an unsupported language. File is not indexed.
0001 /*************************************************************************** 0002 File : parser.y 0003 Project : LabPlot 0004 Description : Parser for mathematical expressions 0005 -------------------------------------------------------------------- 0006 Copyright : (C) 2014 Alexander Semke (alexander.semke@web.de) 0007 Copyright : (C) 2014-2016 Stefan Gerlach (stefan.gerlach@uni.kn) 0008 0009 ***************************************************************************/ 0010 0011 /*************************************************************************** 0012 * * 0013 * This program is free software; you can redistribute it and/or modify * 0014 * it under the terms of the GNU General Public License as published by * 0015 * the Free Software Foundation; either version 2 of the License, or * 0016 * (at your option) any later version. * 0017 * * 0018 * This program is distributed in the hope that it will be useful, * 0019 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0020 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0021 * GNU General Public License for more details. * 0022 * * 0023 * You should have received a copy of the GNU General Public License * 0024 * along with this program; if not, write to the Free Software * 0025 * Foundation, Inc., 51 Franklin Street, Fifth Floor, * 0026 * Boston, MA 02110-1301 USA * 0027 * * 0028 ***************************************************************************/ 0029 0030 /* TODO: not working yet! */ 0031 0032 0033 %{ 0034 #include <string.h> 0035 #include <strings.h> /* bzero */ 0036 #include <ctype.h> 0037 #include <stdlib.h> 0038 #include <locale.h> 0039 #ifndef HAVE_WINDOWS 0040 #include <xlocale.h> 0041 #endif 0042 #include "constants.h" 0043 #include "functions.h" 0044 #include "parser.h" 0045 0046 /* Enable Parser DEBUGGING */ 0047 /* 0048 #define PDEBUG 0049 */ 0050 0051 #ifdef PDEBUG 0052 #define pdebug(...) fprintf(stderr, __VA_ARGS__) 0053 #else 0054 /*#define pdebug(...) do {} while (0)*/ 0055 #define pdebug(...) {} 0056 #endif 0057 0058 #define YYERROR_VERBOSE 1 0059 0060 /* params passed to yylex (and yyerror) */ 0061 typedef struct param { 0062 unsigned int pos; /* current position in string */ 0063 char *string; /* the string to parse */ 0064 symrec *sym_table; /* the symbol table */ 0065 } param; 0066 0067 int yyerror(param *p, const char *err); 0068 int yylex(param *p); 0069 0070 double res; 0071 %} 0072 0073 %lex-param {param *p} 0074 %parse-param {param *p} 0075 0076 %union { 0077 double dval; /* For returning numbers */ 0078 symrec *tptr; /* For returning symbol-table pointers */ 0079 } 0080 0081 %token <dval> NUM /* Simple double precision number */ 0082 %token <tptr> VAR FNCT /* Variable and Function */ 0083 %type <dval> expr 0084 0085 %right '=' 0086 %left '-' '+' 0087 %left '*' '/' 0088 %left NEG /* Negation--unary minus */ 0089 %right '^' /* Exponential */ 0090 0091 %% 0092 input: /* empty */ 0093 | input line 0094 ; 0095 0096 line: '\n' 0097 | expr '\n' { res=$1; } 0098 | error '\n' { yyerrok; } 0099 ; 0100 0101 expr: NUM { $$ = $1; } 0102 | VAR { $$ = $1->value.var; } 0103 | VAR '=' expr { $$ = $3; $1->value.var = $3; } 0104 | FNCT '(' ')' { $$ = (*($1->value.fnctptr))(); } 0105 | FNCT '(' expr ')' { $$ = (*($1->value.fnctptr))($3); } 0106 | FNCT '(' expr ',' expr ')' { $$ = (*($1->value.fnctptr))($3,$5); } 0107 | FNCT '(' expr ',' expr ','expr ')' { $$ = (*($1->value.fnctptr))($3,$5,$7); } 0108 | FNCT '(' expr ',' expr ',' expr ','expr ')' { $$ = (*($1->value.fnctptr))($3,$5,$7,$9); } 0109 | expr '+' expr { $$ = $1 + $3; } 0110 | expr '-' expr { $$ = $1 - $3; } 0111 | expr '*' expr { $$ = $1 * $3; } 0112 | expr '/' expr { $$ = $1 / $3; } 0113 | '-' expr %prec NEG{ $$ = -$2; } 0114 | expr '^' expr { $$ = pow ($1, $3); } 0115 | expr '*' '*' expr { $$ = pow ($1, $4); } 0116 | '(' expr ')' { $$ = $2; } 0117 ; 0118 0119 %% 0120 0121 /* global symbol table */ 0122 symrec *symbol_table = 0; 0123 0124 int parse_errors(void) { 0125 return yynerrs; 0126 } 0127 0128 int yyerror(param *p, const char *s) { 0129 printf("PARSER ERROR: %s @ position %d of string %s", s, p->pos, p->string); 0130 return 0; 0131 } 0132 0133 symrec* putsym(symrec *sym_table, const char *sym_name, int sym_type) { 0134 /*pdebug("PARSER: putsym(): sym_name = %s\n", sym_name);*/ 0135 0136 symrec *ptr = (symrec *) malloc(sizeof(symrec)); 0137 ptr->name = (char *) malloc(strlen(sym_name) + 1); 0138 strcpy(ptr->name, sym_name); 0139 ptr->type = sym_type; 0140 ptr->value.var = 0; /* set value to 0 even if fctn. */ 0141 ptr->next = (struct symrec *)sym_table; 0142 sym_table = ptr; 0143 0144 /*pdebug("PARSER: putsym() DONE sym_table = %p\n", sym_table);*/ 0145 return ptr; 0146 } 0147 0148 symrec* getsym(symrec *sym_table, const char *sym_name) { 0149 /*pdebug("PARSER: getsym(): sym_name = %s, sym_table = %p\n", sym_name, sym_table);*/ 0150 0151 symrec *ptr; 0152 for (ptr = sym_table; ptr != 0; ptr = (symrec *)ptr->next) { 0153 /*pdebug("%s ", ptr->name);*/ 0154 if (strcmp(ptr->name, sym_name) == 0) { 0155 /*pdebug("PARSER: symbol \'%s\' found\n", sym_name);*/ 0156 return ptr; 0157 } 0158 } 0159 0160 /*pdebug("PARSER: symbol \'%s\' not found\n", sym_name);*/ 0161 return 0; 0162 } 0163 0164 /* put arithmetic functions in table. */ 0165 symrec* init_table() { 0166 pdebug("PARSER: init_table()\n"); 0167 0168 symrec *ptr = 0; 0169 int i; 0170 /* add functions */ 0171 for (i = 0; _functions[i].name != 0; i++) { 0172 ptr = putsym(ptr, _functions[i].name, FNCT); 0173 ptr->value.fnctptr = _functions[i].fnct; 0174 } 0175 /* add constants */ 0176 for (i = 0; _constants[i].name != 0; i++) { 0177 ptr = putsym(ptr, _constants[i].name, VAR); 0178 ptr->value.var = _constants[i].value; 0179 } 0180 pdebug("PARSER: init_table() DONE sym_table = %p\n", ptr); 0181 return ptr; 0182 } 0183 0184 void delete_table(symrec *sym_table) { 0185 symrec *tmp; 0186 while(sym_table) { 0187 tmp = sym_table; 0188 sym_table = sym_table->next; 0189 free(tmp->name); 0190 free(tmp); 0191 } 0192 } 0193 0194 symrec* assign_variable(symrec *sym_table, parser_var var) { 0195 /*pdebug("PARSER: assign_variable(): symb_name = %s value = %g sym_table = %p\n", var.name, var.value, sym_table);*/ 0196 0197 symrec* ptr = getsym(sym_table, var.name); 0198 if (!ptr) { 0199 /*pdebug("PARSER: calling putsym(): symb_name = %s\n", var.name);*/ 0200 ptr = putsym(sym_table, var.name, VAR); 0201 } 0202 ptr->value.var = var.value; 0203 0204 return ptr; 0205 }; 0206 0207 static int getcharstr(param *p) { 0208 /*pdebug("PARSER: getcharstr() pos = %d\n", p->pos);*/ 0209 0210 if (p->string[p->pos] == '\0') 0211 return EOF; 0212 return (int) p->string[(p->pos)++]; 0213 } 0214 0215 static void ungetcstr(unsigned int *pos) { 0216 if (*pos > 0) 0217 (*pos)--; 0218 } 0219 0220 int init_parser() { 0221 symbol_table = init_table(); 0222 return 0; 0223 } 0224 0225 int finish_parser() { 0226 if (symbol_table != 0) 0227 delete_table(symbol_table); 0228 symbol_table = 0; 0229 0230 return 0; 0231 } 0232 0233 double parse_with_vars(const char *str, const parser_var *vars, int nvars) { 0234 pdebug("\nPARSER: parse(\"%s\") len=%zu\n", str, strlen(str)); 0235 int i; 0236 for(i = 0; i < nvars; i++) /*assign vars */ 0237 pdebug("var %d of name %s with value %g\n", i, vars[i].name, vars[i].value); 0238 0239 /* parameter for yylex */ 0240 param p; 0241 p.pos = 0; 0242 /* leave space to terminate string by "\n\0" */ 0243 size_t slen = strlen(str) + 2; 0244 p.string = (char *)malloc(slen*sizeof(char)); 0245 /* If there is no global symbol table: create own */ 0246 if (symbol_table == 0) 0247 p.sym_table = init_table(); 0248 0249 for(i = 0; i < nvars; i++) { /*assign vars */ 0250 pdebug("assign %s the value %g\n", vars[i].name, vars[i].value); 0251 if (symbol_table == 0) 0252 p.sym_table = assign_variable(p.sym_table, vars[i]); 0253 else 0254 symbol_table = assign_variable(symbol_table, vars[i]); 0255 } 0256 0257 strncpy(p.string, str, slen); 0258 p.string[strlen(p.string)] = '\n'; 0259 /*pdebug(" slen = %zu, strlen(str) = %zu, strlen(p.string) = %zu\n", slen, strlen(str), strlen(p.string));*/ 0260 0261 yyparse(&p); 0262 0263 /*pdebug("PARSER: parse() DONE (res = %g, parse errors = %d)\n", res, parse_errors());*/ 0264 free(p.string); 0265 if (symbol_table == 0) 0266 delete_table(p.sym_table); 0267 0268 return res; 0269 } 0270 0271 double parse(const char *str) { 0272 return parse_with_vars(str, 0, 0); 0273 } 0274 0275 int yylex(param *p) { 0276 pdebug("PARSER: yylex()\n"); 0277 int c; 0278 0279 /* skip white spaces */ 0280 while ((c = getcharstr(p)) == ' ' || c == '\t'); 0281 0282 /* finish if reached EOF */ 0283 if (c == EOF) { 0284 pdebug("FINISHED\n"); 0285 return 0; 0286 } 0287 0288 pdebug("PARSER: reading character: %c\n", c); 0289 0290 /* process numbers */ 0291 if (isdigit(c)) { 0292 pdebug("PARSER: reading number (starts with digit)\n"); 0293 ungetcstr(&(p->pos)); 0294 char *s = &p->string[p->pos]; 0295 0296 /* convert to double */ 0297 char *remain; 0298 #if defined(_WIN32) || defined(__APPLE__) 0299 double result = strtod(s, &remain); 0300 #else 0301 /* use same locale for all languages: '.' as decimal point */ 0302 locale_t locale = newlocale(LC_NUMERIC_MASK, "C", NULL); 0303 0304 double result = strtod_l(s, &remain, locale); 0305 freelocale(locale); 0306 #endif 0307 pdebug("PARSER: reading: %s", s); 0308 pdebug("PARSER: remain = %s", remain); 0309 0310 /* check conversion */ 0311 if(strlen(s) == strlen(remain)) 0312 return 0; 0313 0314 pdebug("PARSER: result = %g\n", result); 0315 0316 yylval.dval = result; 0317 p->pos += strlen(s) - strlen(remain); 0318 0319 return NUM; 0320 } 0321 0322 if (isalpha (c) || c == '.') { 0323 pdebug("PARSER: reading identifier (starts with alpha)\n"); 0324 static char *symbuf = 0; 0325 static int length = 0; 0326 int i=0; 0327 0328 /* Initially make the buffer long enough for a 4-character symbol name */ 0329 if (length == 0) 0330 length = 20, symbuf = (char *)malloc(length + 1); 0331 0332 do { 0333 /* If buffer is full, make it bigger */ 0334 if (i == length) { 0335 length *= 2; 0336 symbuf = (char *)realloc(symbuf, length + 1); 0337 } 0338 /* Add this character to the buffer */ 0339 symbuf[i++] = c; 0340 /* Get another character */ 0341 c = getcharstr(p); 0342 } 0343 while (c != EOF && (isalnum(c) || c == '_' || c == '.')); 0344 0345 ungetcstr(&(p->pos)); 0346 symbuf[i] = '\0'; 0347 0348 /*pdebug("PARSER: search for symbol: sym_table = %p\n", p->sym_table);*/ 0349 symrec *s; 0350 if (symbol_table != 0) 0351 s = getsym(symbol_table, symbuf); 0352 else 0353 s = getsym(p->sym_table, symbuf); 0354 if(s == 0) { /* symbol unknown */ 0355 pdebug("PARSER: ERROR: symbol \"%s\" UNKNOWN\n", symbuf); 0356 return 0; 0357 } 0358 /* old behavior */ 0359 /* if (s == 0) 0360 s = putsym (symbuf, VAR); */ 0361 yylval.tptr = s; 0362 return s->type; 0363 } 0364 0365 /* else: single operator */ 0366 pdebug("PARSER: single operator\n"); 0367 return c; 0368 }