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