1 /*
2 Qalculate
3
4 Copyright (C) 2003-2007, 2008, 2016-2021 Hanna Knutsson (hanna.knutsson@protonmail.com)
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 */
11
12 #include "support.h"
13
14 #include "Calculator.h"
15 #include "BuiltinFunctions.h"
16 #include "util.h"
17 #include "MathStructure.h"
18 #include "Unit.h"
19 #include "Variable.h"
20 #include "Function.h"
21 #include "DataSet.h"
22 #include "ExpressionItem.h"
23 #include "Prefix.h"
24 #include "Number.h"
25
26 #include <locale.h>
27 #include <unistd.h>
28
29 using std::string;
30 using std::cout;
31 using std::vector;
32 using std::endl;
33
34 #include "Calculator_p.h"
35
36 // determine if character is not a numerical digit in a specific number base (-1=base using digits other than 0-9, a-z, A-Z; -12=duodecimal)
is_not_number(char c,int base)37 bool is_not_number(char c, int base) {
38 // 0-9 is always treated as a digit
39 if(c >= '0' && c <= '9') return false;
40 // in non standard bases every character might be a digit
41 if(base == -1) return false;
42 // duodecimal bases uses 0-9, E, X
43 if(base == -12) return c != 'E' && c != 'X' && c != 'A' && c != 'B' && c != 'a' && c != 'b';
44 if(base <= 10) return true;
45 // bases 11-36 is case insensitive
46 if(base <= 36) {
47 if(c >= 'a' && c < 'a' + (base - 10)) return false;
48 if(c >= 'A' && c < 'A' + (base - 10)) return false;
49 return true;
50 }
51 // bases 37-62 is case sensitive
52 if(base <= 62) {
53 if(c >= 'a' && c < 'a' + (base - 36)) return false;
54 if(c >= 'A' && c < 'Z') return false;
55 return true;
56 }
57 return false;
58 }
59
addId(MathStructure * mstruct,bool persistent)60 size_t Calculator::addId(MathStructure *mstruct, bool persistent) {
61 size_t id = 0;
62 if(priv->freed_ids.size() > 0) {
63 id = priv->freed_ids.back();
64 priv->freed_ids.pop_back();
65 } else {
66 priv->ids_i++;
67 id = priv->ids_i;
68 }
69 priv->ids_p[id] = persistent;
70 priv->id_structs[id] = mstruct;
71 return id;
72 }
parseAddId(MathFunction * f,const string & str,const ParseOptions & po,bool persistent)73 size_t Calculator::parseAddId(MathFunction *f, const string &str, const ParseOptions &po, bool persistent) {
74 size_t id = 0;
75 if(priv->freed_ids.size() > 0) {
76 id = priv->freed_ids.back();
77 priv->freed_ids.pop_back();
78 } else {
79 priv->ids_i++;
80 id = priv->ids_i;
81 }
82 priv->ids_p[id] = persistent;
83 priv->id_structs[id] = new MathStructure();
84 f->parse(*priv->id_structs[id], str, po);
85 return id;
86 }
parseAddIdAppend(MathFunction * f,const MathStructure & append_mstruct,const string & str,const ParseOptions & po,bool persistent)87 size_t Calculator::parseAddIdAppend(MathFunction *f, const MathStructure &append_mstruct, const string &str, const ParseOptions &po, bool persistent) {
88 size_t id = 0;
89 if(priv->freed_ids.size() > 0) {
90 id = priv->freed_ids.back();
91 priv->freed_ids.pop_back();
92 } else {
93 priv->ids_i++;
94 id = priv->ids_i;
95 }
96 priv->ids_p[id] = persistent;
97 priv->id_structs[id] = new MathStructure();
98 f->parse(*priv->id_structs[id], str, po);
99 priv->id_structs[id]->addChild(append_mstruct);
100 return id;
101 }
parseAddVectorId(const string & str,const ParseOptions & po,bool persistent)102 size_t Calculator::parseAddVectorId(const string &str, const ParseOptions &po, bool persistent) {
103 size_t id = 0;
104 if(priv->freed_ids.size() > 0) {
105 id = priv->freed_ids.back();
106 priv->freed_ids.pop_back();
107 } else {
108 priv->ids_i++;
109 id = priv->ids_i;
110 }
111 priv->ids_p[id] = persistent;
112 priv->id_structs[id] = new MathStructure();
113 f_vector->args(str, *priv->id_structs[id], po);
114 return id;
115 }
getId(size_t id)116 MathStructure *Calculator::getId(size_t id) {
117 if(priv->id_structs.find(id) != priv->id_structs.end()) {
118 if(priv->ids_p[id]) {
119 return new MathStructure(*priv->id_structs[id]);
120 } else {
121 MathStructure *mstruct = priv->id_structs[id];
122 priv->freed_ids.push_back(id);
123 priv->id_structs.erase(id);
124 priv->ids_p.erase(id);
125 return mstruct;
126 }
127 }
128 return NULL;
129 }
130
delId(size_t id)131 void Calculator::delId(size_t id) {
132 if(priv->ids_p.find(id) != priv->ids_p.end()) {
133 priv->freed_ids.push_back(id);
134 priv->id_structs[id]->unref();
135 priv->id_structs.erase(id);
136 priv->ids_p.erase(id);
137 }
138 }
139
140 // case sensitive string comparison; compares whole name with str from str_index to str_index + name_length
compare_name(const string & name,const string & str,const size_t & name_length,const size_t & str_index,int base)141 bool compare_name(const string &name, const string &str, const size_t &name_length, const size_t &str_index, int base) {
142 if(name_length == 0) return false;
143 if(name[0] != str[str_index]) return false;
144 if(name_length == 1) {
145 if(base < 2 || base > 10) return is_not_number(str[str_index], base);
146 return true;
147 }
148 for(size_t i = 1; i < name_length; i++) {
149 if(name[i] != str[str_index + i]) return false;
150 }
151 // number base uses digits other than 0-9, check that at least one non-digit is used
152 if(base < 2 || base > 10) {
153 for(size_t i = 0; i < name_length; i++) {
154 if(is_not_number(str[str_index + i], base)) return true;
155 }
156 return false;
157 }
158 return true;
159 }
160
161 // case insensitive string comparison; compares whole name with str from str_index to str_index + name_length
compare_name_no_case(const string & name,const string & str,const size_t & name_length,const size_t & str_index,int base)162 size_t compare_name_no_case(const string &name, const string &str, const size_t &name_length, const size_t &str_index, int base) {
163 if(name_length == 0) return 0;
164 size_t is = str_index;
165 for(size_t i = 0; i < name_length; i++, is++) {
166 if(is >= str.length()) return 0;
167 if((name[i] < 0 && i + 1 < name_length) || (str[is] < 0 && is + 1 < str.length())) {
168 // assumed Unicode character found
169 size_t i2 = 1, is2 = 1;
170 // determine length of Unicode character(s)
171 if(name[i] < 0) {
172 while(i2 + i < name_length && name[i2 + i] < 0) {
173 i2++;
174 }
175 }
176 if(str[is] < 0) {
177 while(is2 + is < str.length() && str[is2 + is] < 0) {
178 is2++;
179 }
180 }
181 // compare characters
182 bool isequal = (i2 == is2);
183 if(isequal) {
184 for(size_t i3 = 0; i3 < i2; i3++) {
185 if(str[is + i3] != name[i + i3]) {
186 isequal = false;
187 break;
188 }
189 }
190 }
191 // get lower case character and compare again
192 if(!isequal) {
193 char *gstr1 = utf8_strdown(name.c_str() + (sizeof(char) * i), i2);
194 char *gstr2 = utf8_strdown(str.c_str() + (sizeof(char) * (is)), is2);
195 if(!gstr1 || !gstr2) return 0;
196 if(strcmp(gstr1, gstr2) != 0) {free(gstr1); free(gstr2); return 0;}
197 free(gstr1); free(gstr2);
198 }
199 i += i2 - 1;
200 is += is2 - 1;
201 } else if(name[i] != str[is] && !((name[i] >= 'a' && name[i] <= 'z') && name[i] - 32 == str[is]) && !((name[i] <= 'Z' && name[i] >= 'A') && name[i] + 32 == str[is])) {
202 return 0;
203 }
204 }
205 // number base uses digits other than 0-9, check that at least one non-digit is used
206 if(base < 2 || base > 10) {
207 for(size_t i = str_index; i < is; i++) {
208 if(is_not_number(str[i], base)) return is - str_index;
209 }
210 return 0;
211 }
212 return is - str_index;
213 }
214
215 const char *internal_signs[] = {SIGN_PLUSMINUS, "\b", "+/-", "\b", "⊻", "\a", "∠", "\x1c"};
216 #define INTERNAL_SIGNS_COUNT 8
217 #define INTERNAL_NUMBER_CHARS "\b"
218 #define INTERNAL_OPERATORS "\a\b%\x1c"
219 #define DUODECIMAL_CHARS "EXABab"
220
parseComments(string & str,const ParseOptions & po,bool * double_tag)221 string Calculator::parseComments(string &str, const ParseOptions &po, bool *double_tag) {
222
223 if(str.length() <= 1 || po.base == BASE_UNICODE || (po.base == BASE_CUSTOM && priv->custom_input_base_i > 62)) return "";
224
225 if(double_tag) *double_tag = false;
226
227 if(str[0] == '#') {
228 string from_str = unlocalizeExpression(str, po);
229 parseSigns(from_str);
230 size_t i = from_str.find_first_of(NOT_IN_NAMES NUMBERS);
231 if(from_str.length() == 1 || i == 0 || !getActiveExpressionItem(i == string::npos ? from_str : from_str.substr(0, i))) {
232 i = from_str.find_first_of(NOT_IN_NAMES);
233 if(from_str.length() == 1 || i == 0 || !getActiveExpressionItem(i == string::npos ? from_str : from_str.substr(0, i))) {
234 string to_str = str.substr(1);
235 str = "";
236 if(to_str[0] == '#') {
237 to_str.erase(0, 1);
238 if(double_tag) *double_tag = true;
239 }
240 remove_blank_ends(to_str);
241 return to_str;
242 }
243 }
244 }
245
246 size_t i = str.rfind("#");
247 if(i == string::npos || i == 0) return "";
248
249 // check if within quoted ranges
250 size_t quote_index = 0;
251 while(true) {
252 quote_index = str.find_first_of("\"\'", quote_index);
253 if(quote_index == string::npos || quote_index > i) {
254 break;
255 }
256 quote_index = str.find(str[quote_index], quote_index + 1);
257 if(quote_index == string::npos || quote_index > i) {
258 return "";
259 }
260 quote_index++;
261 }
262
263 string from_str = CALCULATOR->unlocalizeExpression(str, po);
264 parseSigns(from_str);
265 size_t i4 = from_str.rfind("#");
266 if(i4 != string::npos) {
267 size_t i2 = from_str.find_first_of(NOT_IN_NAMES NUMBERS, i4);
268 size_t i3 = from_str.find_last_of(NOT_IN_NAMES NUMBERS, i4);
269 if(i3 == string::npos) i3 = 0;
270 else i3++;
271 if((i2 == i4 && i3 == i4) || !getActiveExpressionItem(i2 == string::npos ? from_str.substr(i3) : from_str.substr(i3, i2 - i3 + 1))) {
272 i2 = from_str.find_first_of(NOT_IN_NAMES, i4);
273 i3 = from_str.find_last_of(NOT_IN_NAMES, i4);
274 if(i3 == string::npos) i3 = 0;
275 else i3++;
276 i3 = from_str.find_first_not_of(NUMBERS, i3);
277 if((i2 == i && i3 == i) || !getActiveExpressionItem(i2 == string::npos ? from_str.substr(i3) : from_str.substr(i3, i2 - i3 + 1))) {
278 string to_str = str.substr(i + 1);
279 str = str.substr(0, i);
280 if(to_str.length() > 1 && to_str[1] == '#') to_str = to_str.substr(1);
281 remove_blank_ends(to_str);
282 return to_str;
283 }
284 }
285 }
286 return "";
287 }
288
parseSigns(string & str,bool convert_to_internal_representation) const289 void Calculator::parseSigns(string &str, bool convert_to_internal_representation) const {
290
291 bool b_unicode = false;
292 for(size_t i = 0; i < str.length(); i++) {
293 if((unsigned char) str[i] >= 0xC0) {
294 b_unicode = true;
295 break;
296 }
297 }
298
299 if(b_unicode && str.find_first_of("\"\'") == string::npos) {
300 // replace unicode quotation marks
301 size_t ui = str.find("\xe2\x80");
302 bool b_double = false, b_single = false, b_angle = false;
303 while(ui != string::npos && ui + 2 < str.length()) {
304 if(str[ui + 2] >= -101 && str[ui + 2] <= -104) {
305 // single quotation marks
306 str.replace(ui, 3, "\'");
307 b_single = true;
308 } else if(str[ui + 2] >= -100 && str[ui + 2] <= -97) {
309 // double quotation marks
310 str.replace(ui, 3, "\"");
311 b_double = true;
312 } else if(str[ui + 2] == -70 || str[ui + 2] == -71) {
313 // single angle quotation marks
314 b_angle = true;
315 ui += 2;
316 } else {
317 ui += 2;
318 }
319 ui = str.find("\xe2\x80", ui + 1);
320 }
321 if(!b_single && b_angle) {
322 b_single = true;
323 gsub("‹", "\'", str);
324 gsub("›", "\'", str);
325 }
326 if(!b_double) {
327 gsub("«", "\"", str);
328 gsub("»", "\"", str);
329 } else if(!b_single) {
330 gsub("«", "\'", str);
331 gsub("»", "\'", str);
332 }
333 }
334
335 vector<size_t> q_begin;
336 vector<size_t> q_end;
337 // collect quoted ranges
338 size_t quote_index = 0;
339 while(true) {
340 quote_index = str.find_first_of("\"\'", quote_index);
341 if(quote_index == string::npos) {
342 break;
343 }
344 q_begin.push_back(quote_index);
345 quote_index = str.find(str[quote_index], quote_index + 1);
346 if(quote_index == string::npos) {
347 q_end.push_back(str.length() - 1);
348 break;
349 }
350 q_end.push_back(quote_index);
351 quote_index++;
352 }
353
354 // search and replace string alternatives
355 for(size_t i = 0; i < signs.size(); i++) {
356 if(b_unicode || signs[i][0] > 0) {
357 size_t ui = str.find(signs[i]);
358 size_t ui2 = 0;
359 while(ui != string::npos) {
360 // check that found index is outside quotes
361 for(; ui2 < q_end.size(); ui2++) {
362 if(ui >= q_begin[ui2]) {
363 if(ui <= q_end[ui2]) {
364 ui = str.find(signs[i], q_end[ui2] + 1);
365 if(ui == string::npos) break;
366 }
367 } else {
368 break;
369 }
370 }
371 if(ui == string::npos) break;
372 // adjust quotion mark indeces
373 int index_shift = real_signs[i].length() - signs[i].length();
374 for(size_t ui3 = ui2; ui3 < q_begin.size(); ui3++) {
375 q_begin[ui3] += index_shift;
376 q_end[ui3] += index_shift;
377 }
378 str.replace(ui, signs[i].length(), real_signs[i]);
379 ui = str.find(signs[i], ui + real_signs[i].length());
380 }
381 }
382 }
383
384 if(b_unicode) {
385
386 // replace Unicode exponents
387 size_t prev_ui = string::npos, space_n = 0;
388 while(true) {
389 // Unicode powers 0 and 4-9 use three chars and begin with \xe2\x81
390 size_t ui = str.find("\xe2\x81", prev_ui == string::npos ? 0 : prev_ui);
391 while(ui != string::npos && (ui == str.length() - 2 || (str[ui + 2] != -80 && (str[ui + 2] < -76 || str[ui + 2] > -66 || str[ui + 2] == -68)))) ui = str.find("\xe2\x81", ui + 3);
392 // Unicode powers 1-3 use two chars and begin with \xc2
393 size_t ui2 = str.find('\xc2', prev_ui == string::npos ? 0 : prev_ui);
394 while(ui2 != string::npos && (ui2 == str.length() - 1 || (str[ui2 + 1] != -71 && str[ui2 + 1] != -77 && str[ui2 + 1] != -78))) ui2 = str.find('\xc2', ui2 + 2);
395 if(ui2 != string::npos && (ui == string::npos || ui2 < ui)) ui = ui2;
396 if(ui != string::npos) {
397 // check that found index is outside quotes
398 for(size_t ui3 = 0; ui3 < q_end.size(); ui3++) {
399 if(ui <= q_end[ui3] && ui >= q_begin[ui3]) {
400 ui = str.find("\xe2\x81", q_end[ui3] + 1);
401 if(ui != string::npos && (ui == str.length() - 2 || (str[ui + 2] != -80 && (str[ui + 2] < -76 || str[ui + 2] > -66 || str[ui + 2] != -68)))) ui = string::npos;
402 ui2 = str.find('\xc2', q_end[ui3] + 1);
403 if(ui2 != string::npos && (ui2 == str.length() - 1 || (str[ui2 + 1] != -71 && str[ui2 + 1] != -77 && str[ui2 + 1] != -78))) ui2 = string::npos;
404 if(ui2 != string::npos && (ui == string::npos || ui2 < ui)) ui = ui2;
405 if(ui == string::npos) break;
406 }
407 }
408 }
409 if(ui == string::npos) break;
410 int index_shift = (str[ui] == '\xc2' ? -2 : -3);
411 if(ui == prev_ui) index_shift += 1;
412 else index_shift += 4;
413 // adjust quotion mark indeces
414 for(size_t ui3 = 0; ui3 < q_begin.size(); ui3++) {
415 if(q_begin[ui3] >= ui) {
416 q_begin[ui3] += index_shift;
417 q_end[ui3] += index_shift;
418 }
419 }
420 // perform replacement; if next to previous Unicode power combine the powers
421 if(str[ui] == '\xc2') {
422 if(str[ui + 1] == -71) str.replace(ui, 2, ui == prev_ui ? "1)" : "^(1)");
423 else if(str[ui + 1] == -78) str.replace(ui, 2, ui == prev_ui ? "2)" : "^(2)");
424 else if(str[ui + 1] == -77) str.replace(ui, 2, ui == prev_ui ? "3)" : "^(3)");
425 } else {
426 if(str[ui + 2] == -80) str.replace(ui, 3, ui == prev_ui ? "0)" : "^(0)");
427 else if(str[ui + 2] == -76) str.replace(ui, 3, ui == prev_ui ? "4)" : "^(4)");
428 else if(str[ui + 2] == -75) str.replace(ui, 3, ui == prev_ui ? "5)" : "^(5)");
429 else if(str[ui + 2] == -74) str.replace(ui, 3, ui == prev_ui ? "6)" : "^(6)");
430 else if(str[ui + 2] == -73) str.replace(ui, 3, ui == prev_ui ? "7)" : "^(7)");
431 else if(str[ui + 2] == -72) str.replace(ui, 3, ui == prev_ui ? "8)" : "^(8)");
432 else if(str[ui + 2] == -71) str.replace(ui, 3, ui == prev_ui ? "9)" : "^(9)");
433 else if(str[ui + 2] == -70) str.replace(ui, 3, ui == prev_ui ? "+)" : "^(+)");
434 else if(str[ui + 2] == -69) str.replace(ui, 3, ui == prev_ui ? "-)" : "^(-)");
435 else if(str[ui + 2] == -67) str.replace(ui, 3, ui == prev_ui ? "()" : "^(()");
436 else if(str[ui + 2] == -66) str.replace(ui, 3, ui == prev_ui ? "))" : "^())");
437 }
438 if(ui == prev_ui) {
439 str.erase(prev_ui - space_n - 1, 1);
440 prev_ui = ui + 1;
441 } else {
442 prev_ui = ui + 4;
443 }
444 space_n = 0;
445 while(prev_ui + 1 < str.length() && str[prev_ui] == SPACE_CH) {
446 space_n++;
447 prev_ui++;
448 }
449 }
450
451 // replace Unicode fractions with three chars
452 prev_ui = string::npos;
453 while(true) {
454 // three char Unicode fractions begin with \xe2\x85
455 size_t ui = str.find("\xe2\x85", prev_ui == string::npos ? 0 : prev_ui);
456 while(ui != string::npos && (ui == str.length() - 2 || str[ui + 2] < -112 || str[ui + 2] > -98)) ui = str.find("\xe2\x85", ui + 3);
457 if(ui != string::npos) {
458 // check that found index is outside quotes
459 for(size_t ui3 = 0; ui3 < q_end.size(); ui3++) {
460 if(ui <= q_end[ui3] && ui >= q_begin[ui3]) {
461 ui = str.find("\xe2\x85", q_end[ui3] + 1);
462 if(ui != string::npos && (ui == str.length() - 2 || str[ui + 2] < -112 || str[ui + 2] > -98)) ui = string::npos;
463 if(ui == string::npos) break;
464 }
465 }
466 }
467 if(ui == string::npos) break;
468 // check if previous non-whitespace character is a numeral digit
469 space_n = 0;
470 while(ui > 0 && ui - 1 - space_n != 0 && str[ui - 1 - space_n] == SPACE_CH) space_n++;
471 bool b_add = (ui > 0 && is_in(NUMBER_ELEMENTS, str[ui - 1 - space_n]));
472 if(b_add) {
473 size_t ui2 = str.find_last_not_of(NUMBER_ELEMENTS, ui - space_n - 1);
474 if(ui2 == string::npos) ui2 = 0;
475 else ui2++;
476 str.insert(ui2, "(");
477 ui += 1;
478 }
479 int index_shift = (b_add ? 7 : 5) - 3;
480 if(str[ui + 2] == -110) index_shift++;
481 // adjust quotion mark indeces
482 for(size_t ui2 = 0; ui2 < q_begin.size(); ui2++) {
483 if(q_begin[ui2] >= ui) {
484 q_begin[ui2] += index_shift;
485 q_end[ui2] += index_shift;
486 }
487 }
488 // perform replacement; interpret as addition if previous character is a numeral digit
489 if(str[ui + 2] == -98) str.replace(ui, 3, b_add ? "+(7/8))" : "(7/8)");
490 else if(str[ui + 2] == -99) str.replace(ui, 3, b_add ? "+(5/8))" : "(5/8)");
491 else if(str[ui + 2] == -100) str.replace(ui, 3, b_add ? "+(3/8))" : "(3/8)");
492 else if(str[ui + 2] == -101) str.replace(ui, 3, b_add ? "+(1/8))" : "(1/8)");
493 else if(str[ui + 2] == -102) str.replace(ui, 3, b_add ? "+(5/6))" : "(5/6)");
494 else if(str[ui + 2] == -103) str.replace(ui, 3, b_add ? "+(1/6))" : "(1/6)");
495 else if(str[ui + 2] == -104) str.replace(ui, 3, b_add ? "+(4/5))" : "(4/5)");
496 else if(str[ui + 2] == -105) str.replace(ui, 3, b_add ? "+(3/5))" : "(3/5)");
497 else if(str[ui + 2] == -106) str.replace(ui, 3, b_add ? "+(2/5))" : "(2/5)");
498 else if(str[ui + 2] == -107) str.replace(ui, 3, b_add ? "+(1/5))" : "(1/5)");
499 else if(str[ui + 2] == -108) str.replace(ui, 3, b_add ? "+(2/3))" : "(2/3)");
500 else if(str[ui + 2] == -109) str.replace(ui, 3, b_add ? "+(1/3))" : "(1/3)");
501 else if(str[ui + 2] == -110) {str.replace(ui, 3, b_add ? "+(1/10))" : "(1/10)"); ui++;}
502 else if(str[ui + 2] == -111) str.replace(ui, 3, b_add ? "+(1/9))" : "(1/9)");
503 else if(str[ui + 2] == -112) str.replace(ui, 3, b_add ? "+(1/7))" : "(1/7)");
504 if(b_add) prev_ui = ui + 7;
505 else prev_ui = ui + 5;
506 }
507
508 // replace Unicode fractions with two chars
509 prev_ui = string::npos;
510 while(true) {
511 // two char Unicode fractions begin with \xc2
512 size_t ui = str.find('\xc2', prev_ui == string::npos ? 0 : prev_ui);
513 while(ui != string::npos && (ui == str.length() - 1 || (str[ui + 1] != -66 && str[ui + 1] != -67 && str[ui + 1] != -68))) ui = str.find('\xc2', ui + 2);
514 if(ui != string::npos) {
515 // check that found index is outside quotes
516 for(size_t ui3 = 0; ui3 < q_end.size(); ui3++) {
517 if(ui <= q_end[ui3] && ui >= q_begin[ui3]) {
518 ui = str.find('\xc2', q_end[ui3] + 1);
519 if(ui != string::npos && (ui == str.length() - 1 || (str[ui + 1] != -66 && str[ui + 1] != -67 && str[ui + 1] != -68))) ui = string::npos;
520 if(ui == string::npos) break;
521 }
522 }
523 }
524 if(ui == string::npos) break;
525 // check if previous non-whitespace character is a numeral digit
526 space_n = 0;
527 while(ui > 0 && ui - 1 - space_n != 0 && str[ui - 1 - space_n] == SPACE_CH) space_n++;
528 bool b_add = (ui > 0 && is_in(NUMBER_ELEMENTS, str[ui - 1 - space_n]));
529 if(b_add) {
530 size_t ui2 = str.find_last_not_of(NUMBER_ELEMENTS, ui - space_n - 1);
531 if(ui2 == string::npos) ui2 = 0;
532 else ui2++;
533 str.insert(ui2, "(");
534 ui += 1;
535 }
536 int index_shift = (b_add ? 7 : 5) - 2;
537 // adjust quotion mark indeces
538 for(size_t ui2 = 0; ui2 < q_begin.size(); ui2++) {
539 if(q_begin[ui2] >= ui) {
540 q_begin[ui2] += index_shift;
541 q_end[ui2] += index_shift;
542 }
543 }
544 // perform replacement; interpret as addition if previous character is a numeral digit
545 if(str[ui + 1] == -66) str.replace(ui, 2, b_add ? "+(3/4))" : "(3/4)");
546 else if(str[ui + 1] == -67) str.replace(ui, 2, b_add ? "+(1/2))" : "(1/2)");
547 else if(str[ui + 1] == -68) str.replace(ui, 2, b_add ? "+(1/4))" : "(1/4)");
548 if(b_add) prev_ui = ui + 7;
549 else prev_ui = ui + 5;
550 }
551
552 }
553
554 if(convert_to_internal_representation) {
555 // remove superfluous whitespace
556 remove_blank_ends(str);
557 remove_duplicate_blanks(str);
558 // replace operators with multiple chars with internal single character version
559 for(size_t i = 0; i < INTERNAL_SIGNS_COUNT; i += 2) {
560 if(b_unicode || internal_signs[i][0] > 0) {
561 size_t ui = str.find(internal_signs[i]);
562 size_t ui2 = 0;
563 while(ui != string::npos) {
564 // check that found index is outside quotes
565 for(; ui2 < q_end.size(); ui2++) {
566 if(ui >= q_begin[ui2]) {
567 if(ui <= q_end[ui2]) {
568 ui = str.find(internal_signs[i], q_end[ui2] + 1);
569 if(ui == string::npos) break;
570 }
571 } else {
572 break;
573 }
574 }
575 if(ui == string::npos) break;
576 // adjust quotion mark indeces
577 int index_shift = strlen(internal_signs[i + 1]) - strlen(internal_signs[i]);
578 for(size_t ui3 = ui2; ui3 < q_begin.size(); ui3++) {
579 q_begin[ui3] += index_shift;
580 q_end[ui3] += index_shift;
581 }
582 // perform replacement and search for next occurrence
583 str.replace(ui, strlen(internal_signs[i]), internal_signs[i + 1]);
584 ui = str.find(internal_signs[i], ui + strlen(internal_signs[i + 1]));
585 }
586 }
587 }
588 }
589 }
590
591
parse(string str,const ParseOptions & po)592 MathStructure Calculator::parse(string str, const ParseOptions &po) {
593
594 MathStructure mstruct;
595 parse(&mstruct, str, po);
596 return mstruct;
597
598 }
599
replace_internal_operators(string & str)600 void replace_internal_operators(string &str) {
601 gsub("\a", " xor ", str);
602 gsub("\b", SIGN_PLUSMINUS, str);
603 gsub("\x1c", "∠", str);
604 remove_blank_ends(str);
605 }
606
parse(MathStructure * mstruct,string str,const ParseOptions & parseoptions)607 void Calculator::parse(MathStructure *mstruct, string str, const ParseOptions &parseoptions) {
608
609 ParseOptions po = parseoptions;
610
611 if(po.base == BASE_UNICODE || (po.base == BASE_CUSTOM && priv->custom_input_base_i > 62)) {
612 // Read whole expression as a number if the number base digits other than alphanumerical characters
613 mstruct->set(Number(str, po));
614 return;
615 }
616
617 if(po.base != BASE_DUODECIMAL && (str.find("↊") != string::npos || str.find("↋") != string::npos)) {
618 po.base = BASE_DUODECIMAL;
619 parse(mstruct, str, po);
620 return;
621 }
622
623 if(po.rpn) {po.parsing_mode = PARSING_MODE_RPN; po.rpn = false;}
624
625 MathStructure *unended_function = po.unended_function;
626 po.unended_function = NULL;
627
628 // use parse option number base to determine which characters are used as numerical digits and set base accordingly.
629 // (-1=base using digits other than 0-9, a-z, A-Z; -12=duodecimal)
630 int base = po.base;
631 if(base == BASE_CUSTOM) {
632 base = (int) priv->custom_input_base_i;
633 } else if(base == BASE_GOLDEN_RATIO || base == BASE_SUPER_GOLDEN_RATIO || base == BASE_SQRT2) {
634 base = 2;
635 } else if(base == BASE_PI) {
636 base = 4;
637 } else if(base == BASE_E) {
638 base = 3;
639 } else if(base == BASE_DUODECIMAL) {
640 base = -12;
641 } else if(base < 2 || base > 36) {
642 base = -1;
643 }
644
645 mstruct->clear();
646
647 const string *name = NULL;
648 string stmp, stmp2;
649
650 // search for degree sign in epxressions (affects interpretation of ' and ")
651 size_t i_degree = str.find(SIGN_DEGREE);
652 if(i_degree != string::npos && i_degree + strlen(SIGN_DEGREE) < str.length() && is_not_in(NOT_IN_NAMES INTERNAL_OPERATORS NUMBER_ELEMENTS, str[i_degree + strlen(SIGN_DEGREE)])) i_degree = string::npos;
653
654 if(base != -1 && base <= BASE_HEXADECIMAL) {
655 // replace single ' and " with prime and double prime (for ft/in or minutes/seconds of arc)
656 bool b_prime_quote = true;
657 size_t i_quote = str.find('\'', 0);
658 size_t i_dquote = str.find('\"', 0);
659 if(i_degree == string::npos) {
660 if(i_quote == 0 || i_dquote == 0) {
661 b_prime_quote = false;
662 } else if((i_quote != string::npos && i_quote < str.length() - 1 && str.find('\'', i_quote + 1) != string::npos) || (i_quote != string::npos && i_dquote == i_quote + 1) || (i_dquote != string::npos && i_dquote < str.length() - 1 && str.find('\"', i_dquote + 1) != string::npos)) {
663 b_prime_quote = false;
664 while(i_dquote != string::npos) {
665 i_quote = str.rfind('\'', i_dquote - 1);
666 if(i_quote != string::npos) {
667 size_t i_prev = str.find_last_not_of(SPACES, i_quote - 1);
668 if(i_prev != string::npos && is_in(NUMBER_ELEMENTS, str[i_prev])) {
669 if(is_in(NUMBER_ELEMENTS, str[str.find_first_not_of(SPACES, i_quote + 1)]) && str.find_first_not_of(SPACES NUMBER_ELEMENTS, i_quote + 1) == i_dquote) {
670 if(i_prev == 0) {
671 b_prime_quote = true;
672 break;
673 } else {
674 i_prev = str.find_last_not_of(NUMBER_ELEMENTS, i_prev - 1);
675 if(i_prev == string::npos || (str[i_prev] != '\"' && str[i_prev] != '\'')) {
676 b_prime_quote = true;
677 break;
678 }
679 }
680 }
681 }
682 }
683 i_dquote = str.find('\"', i_dquote + 2);
684 }
685 }
686 } else {
687 for(size_t i = 0; i < 2 && b_prime_quote; i++) {
688 if(i == 1) i_quote = i_dquote;
689 while(i_quote != string::npos) {
690 if(i_quote > 0 && (str[i_quote - 1] == LEFT_PARENTHESIS_CH || str[i_quote - 1] == COMMA_CH || is_in(SPACES, str[i_quote - 1]))) {
691 size_t i_bspace = 0;
692 if(str[i_quote - 1] == LEFT_PARENTHESIS_CH || str[i_quote - 1] == COMMA_CH || ((i_bspace = str.find_last_not_of(SPACES, i_quote - 1)) != string::npos && is_in(LEFT_PARENTHESIS COMMA, str[i_bspace]))) {
693 i_quote = str.find(i == 0 ? '\'' : '\"', i_quote + 1);
694 if(i_quote != string::npos) b_prime_quote = false;
695 break;
696 } else {
697 i_quote = str.find(i == 0 ? '\'' : '\"', i_quote + 1);
698 }
699 } else {
700 i_quote = str.find(i == 0 ? '\'' : '\"', i_quote + 1);
701 }
702 }
703 }
704 }
705 if(b_prime_quote) {
706 gsub("\'", "′", str);
707 gsub("\"", "″", str);
708 }
709 }
710
711 // replace alternative strings (primarily operators) with default ascii versions
712 parseSigns(str, true);
713
714 // parse quoted string as symbolic MathStructure
715 for(size_t str_index = 0; str_index < str.length(); str_index++) {
716 if(str[str_index] == '\"' || str[str_index] == '\'') {
717 if(str_index == str.length() - 1) {
718 str.erase(str_index, 1);
719 } else {
720 size_t i = str.find(str[str_index], str_index + 1);
721 size_t name_length;
722 if(i == string::npos) {
723 i = str.length();
724 name_length = i - str_index;
725 } else {
726 name_length = i - str_index + 1;
727 }
728 stmp = LEFT_PARENTHESIS ID_WRAP_LEFT;
729 MathStructure *mstruct = new MathStructure(str.substr(str_index + 1, i - str_index - 1));
730 stmp += i2s(addId(mstruct));
731 stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS;
732 str.replace(str_index, name_length, stmp);
733 str_index += stmp.length() - 1;
734 }
735 }
736 }
737
738
739 if(po.brackets_as_parentheses) {
740 // replace [ and ] with ( and )
741 gsub(LEFT_VECTOR_WRAP, LEFT_PARENTHESIS, str);
742 gsub(RIGHT_VECTOR_WRAP, RIGHT_PARENTHESIS, str);
743 }
744
745 // Transform var:=a to save(save, a)
746 size_t isave = 0;
747 if((isave = str.find(":=", 1)) != string::npos) {
748 string name = str.substr(0, isave);
749 string value = str.substr(isave + 2, str.length() - (isave + 2));
750 str = value;
751 str += COMMA;
752 str += name;
753 f_save->parse(*mstruct, str, po);
754 return;
755 }
756
757 if(po.default_dataset != NULL && str.length() > 1) {
758 size_t str_index = str.find(DOT_CH, 1);
759 while(str_index != string::npos) {
760 if(str_index + 1 < str.length() && ((is_not_number(str[str_index + 1], base) && is_not_in(INTERNAL_OPERATORS NOT_IN_NAMES, str[str_index + 1]) && is_not_in(INTERNAL_OPERATORS NOT_IN_NAMES, str[str_index - 1])) || (is_not_in(INTERNAL_OPERATORS NOT_IN_NAMES, str[str_index + 1]) && is_not_number(str[str_index - 1], base) && is_not_in(INTERNAL_OPERATORS NOT_IN_NAMES, str[str_index - 1])))) {
761 size_t dot_index = str.find_first_of(NOT_IN_NAMES INTERNAL_OPERATORS DOT, str_index + 1);
762 if(dot_index != string::npos && str[dot_index] == DOT_CH) {
763 str_index = dot_index;
764 } else {
765 size_t property_index = str.find_last_of(NOT_IN_NAMES INTERNAL_OPERATORS, str_index - 1);
766 if(property_index == string::npos) {
767 str.insert(0, 1, '.');
768 str.insert(0, po.default_dataset->referenceName());
769 str_index += po.default_dataset->referenceName().length() + 1;
770 } else {
771 str.insert(property_index + 1, 1, '.');
772 str.insert(property_index + 1, po.default_dataset->referenceName());
773 str_index += po.default_dataset->referenceName().length() + 1;
774 }
775 }
776 }
777 str_index = str.find(DOT_CH, str_index + 1);
778 }
779 }
780
781 //remove spaces in numbers
782 size_t space_i = 0;
783 if(po.parsing_mode != PARSING_MODE_RPN) {
784 space_i = str.find(SPACE_CH, 0);
785 while(space_i != string::npos) {
786 if(is_in(NUMBERS INTERNAL_NUMBER_CHARS DOT, str[space_i + 1]) && is_in(NUMBERS INTERNAL_NUMBER_CHARS DOT, str[space_i - 1])) {
787 str.erase(space_i, 1);
788 space_i--;
789 }
790 space_i = str.find(SPACE_CH, space_i + 1);
791 }
792 }
793
794 if(base != -1 && base <= BASE_HEXADECIMAL) {
795 // replace prime and double prime with feet and inches, or arcminues and arcseconds (if degree sign was previously found)
796 bool b_degree = (i_degree != string::npos);
797 size_t i_quote = str.find("′");
798 size_t i_dquote = str.find("″");
799 while(i_quote != string::npos || i_dquote != string::npos) {
800 size_t i_op = 0;
801 if(i_quote == string::npos || i_dquote < i_quote) {
802 bool b = false;
803 if(b_degree) {
804 i_degree = str.rfind(SIGN_DEGREE, i_dquote - 1);
805 if(i_degree != string::npos && i_degree > 0 && i_degree < i_dquote) {
806 size_t i_op = str.find_first_not_of(SPACE, i_degree + strlen(SIGN_DEGREE));
807 if(i_op != string::npos) {
808 i_op = str.find_first_not_of(SPACE, i_degree + strlen(SIGN_DEGREE));
809 if(is_in(NUMBER_ELEMENTS, str[i_op])) i_op = str.find_first_not_of(NUMBER_ELEMENTS SPACE, i_op);
810 else i_op = 0;
811 }
812 size_t i_prev = string::npos;
813 if(i_op == i_dquote) {
814 i_prev = str.find_last_not_of(SPACE, i_degree - 1);
815 if(i_prev != string::npos) {
816 if(is_in(NUMBER_ELEMENTS, str[i_prev])) {
817 i_prev = str.find_last_not_of(NUMBER_ELEMENTS SPACE, i_prev);
818 if(i_prev == string::npos) i_prev = 0;
819 else i_prev++;
820 } else {
821 i_prev = string::npos;
822 }
823 }
824 }
825 if(i_prev != string::npos) {
826 str.insert(i_prev, LEFT_PARENTHESIS);
827 i_degree++;
828 i_op++;
829 str.replace(i_op, strlen("″"), "arcsec" RIGHT_PARENTHESIS);
830 str.replace(i_degree, strlen(SIGN_DEGREE), "deg" PLUS);
831 b = true;
832 }
833 }
834 }
835 if(!b) {
836 if(str.length() >= i_dquote + strlen("″") && is_in(NUMBERS, str[i_dquote + strlen("″")])) str.insert(i_dquote + strlen("″"), " ");
837 str.replace(i_dquote, strlen("″"), b_degree ? "arcsec" : "in");
838 i_op = i_dquote;
839 }
840 } else {
841 bool b = false;
842 if(b_degree) {
843 i_degree = str.rfind(SIGN_DEGREE, i_quote - 1);
844 if(i_degree != string::npos && i_degree > 0 && i_degree < i_quote) {
845 size_t i_op = str.find_first_not_of(SPACE, i_degree + strlen(SIGN_DEGREE));
846 if(i_op != string::npos) {
847 i_op = str.find_first_not_of(SPACE, i_degree + strlen(SIGN_DEGREE));
848 if(is_in(NUMBER_ELEMENTS, str[i_op])) i_op = str.find_first_not_of(NUMBER_ELEMENTS SPACE, i_op);
849 else i_op = 0;
850 }
851 size_t i_prev = string::npos;
852 if(i_op == i_quote) {
853 i_prev = str.find_last_not_of(SPACE, i_degree - 1);
854 if(i_prev != string::npos) {
855 if(is_in(NUMBER_ELEMENTS, str[i_prev])) {
856 i_prev = str.find_last_not_of(NUMBER_ELEMENTS SPACE, i_prev);
857 if(i_prev == string::npos) i_prev = 0;
858 else i_prev++;
859 } else {
860 i_prev = string::npos;
861 }
862 }
863 }
864 if(i_prev != string::npos) {
865 str.insert(i_prev, LEFT_PARENTHESIS);
866 i_degree++;
867 i_quote++;
868 i_op++;
869 if(i_dquote != string::npos) {
870 i_dquote++;
871 size_t i_op2 = str.find_first_not_of(SPACE, i_quote + strlen("′"));
872 if(i_op2 != string::npos && is_in(NUMBER_ELEMENTS, str[i_op2])) i_op2 = str.find_first_not_of(NUMBER_ELEMENTS SPACE, i_op2);
873 else i_op2 = 0;
874 if(i_op2 == i_dquote) {
875 str.replace(i_dquote, strlen("″"), "arcsec" RIGHT_PARENTHESIS);
876 i_op = i_op2;
877 }
878 }
879 str.replace(i_quote, strlen("′"), i_op == i_quote ? "arcmin" RIGHT_PARENTHESIS : "arcmin" PLUS);
880 str.replace(i_degree, strlen(SIGN_DEGREE), "deg" PLUS);
881 b = true;
882 }
883 }
884 }
885 if(!b) {
886 i_op = str.find_first_not_of(SPACE, i_quote + strlen("′"));
887 if(i_op != string::npos && is_in(NUMBER_ELEMENTS, str[i_op])) i_op = str.find_first_not_of(NUMBER_ELEMENTS SPACE, i_op);
888 else i_op = 0;
889 size_t i_prev = string::npos;
890 if(((!b_degree && i_op == string::npos) || i_op == i_dquote) && i_quote != 0) {
891 i_prev = str.find_last_not_of(SPACE, i_quote - 1);
892 if(i_prev != string::npos) {
893 if(is_in(NUMBER_ELEMENTS, str[i_prev])) {
894 i_prev = str.find_last_not_of(NUMBER_ELEMENTS SPACE, i_prev);
895 if(i_prev == string::npos) i_prev = 0;
896 else i_prev++;
897 } else {
898 i_prev = string::npos;
899 }
900 }
901 }
902 if(i_prev != string::npos) {
903 str.insert(i_prev, LEFT_PARENTHESIS);
904 i_quote++;
905 if(i_op == string::npos) str += b_degree ? "arcsec" RIGHT_PARENTHESIS : "in" RIGHT_PARENTHESIS;
906 else str.replace(i_op + 1, strlen("″"), b_degree ? "arcsec" RIGHT_PARENTHESIS : "in" RIGHT_PARENTHESIS);
907 str.replace(i_quote, strlen("′"), b_degree ? "arcmin" PLUS : "ft" PLUS);
908 if(i_op == string::npos) break;
909 i_op++;
910 } else {
911 if(str.length() >= i_quote + strlen("′") && is_in(NUMBERS, str[i_quote + strlen("′")])) str.insert(i_quote + strlen("′"), " ");
912 str.replace(i_quote, strlen("′"), b_degree ? "arcmin" : "ft");
913 i_op = i_quote;
914 }
915 }
916 }
917 if(i_dquote != string::npos) i_dquote = str.find("″", i_op);
918 if(i_quote != string::npos) i_quote = str.find("′", i_op);
919 }
920 }
921
922 // Replace % with percent in case when it should not be interpreted as mod/rem
923 size_t i_mod = str.find("%");
924 if(i_mod != string::npos && !v_percent->hasName("%")) i_mod = string::npos;
925 while(i_mod != string::npos) {
926 if(po.parsing_mode == PARSING_MODE_RPN) {
927 if(i_mod == 0 || is_not_in(OPERATORS "\\" INTERNAL_OPERATORS SPACE, str[i_mod - 1])) {
928 str.replace(i_mod, 1, v_percent->referenceName());
929 i_mod += v_percent->referenceName().length() - 1;
930 }
931 } else if(i_mod == 0 || i_mod == str.length() - 1 || (is_in(RIGHT_PARENTHESIS RIGHT_VECTOR_WRAP COMMA OPERATORS "%\a\b", str[i_mod + 1]) && str[i_mod + 1] != BITWISE_NOT_CH && str[i_mod + 1] != NOT_CH) || is_in(LEFT_PARENTHESIS LEFT_VECTOR_WRAP COMMA OPERATORS "\a\b", str[i_mod - 1])) {
932 str.replace(i_mod, 1, v_percent->referenceName());
933 i_mod += v_percent->referenceName().length() - 1;
934 }
935 i_mod = str.find("%", i_mod + 1);
936 }
937
938 if(po.parsing_mode == PARSING_MODE_RPN) {
939 // add space between double operators in rpn mode in order to ensure that they are interpreted as two single operators
940 gsub("&&", "& &", str);
941 gsub("||", "| |", str);
942 gsub("\%\%", "\% \%", str);
943 }
944
945 for(size_t str_index = 0; str_index < str.length(); str_index++) {
946 if(str[str_index] == LEFT_VECTOR_WRAP_CH) {
947 // vector
948 int i4 = 1;
949 size_t i3 = str_index;
950 while(true) {
951 i3 = str.find_first_of(LEFT_VECTOR_WRAP RIGHT_VECTOR_WRAP, i3 + 1);
952 if(i3 == string::npos) {
953 for(; i4 > 0; i4--) {
954 str += RIGHT_VECTOR_WRAP;
955 }
956 i3 = str.length() - 1;
957 } else if(str[i3] == LEFT_VECTOR_WRAP_CH) {
958 i4++;
959 } else if(str[i3] == RIGHT_VECTOR_WRAP_CH) {
960 i4--;
961 if(i4 > 0) {
962 size_t i5 = str.find_first_not_of(SPACE, i3 + 1);
963 if(i5 != string::npos && str[i5] == LEFT_VECTOR_WRAP_CH) {
964 str.insert(i5, COMMA);
965 }
966 }
967 }
968 if(i4 == 0) {
969 stmp2 = str.substr(str_index + 1, i3 - str_index - 1);
970 stmp = LEFT_PARENTHESIS ID_WRAP_LEFT;
971 stmp += i2s(parseAddVectorId(stmp2, po));
972 stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS;
973 str.replace(str_index, i3 + 1 - str_index, stmp);
974 str_index += stmp.length() - 1;
975 break;
976 }
977 }
978 } else if(str[str_index] == '\\' && str_index + 1 < str.length() && (is_not_in(NOT_IN_NAMES INTERNAL_OPERATORS NUMBERS, str[str_index + 1]) || (po.parsing_mode != PARSING_MODE_RPN && str_index > 0 && is_in(NUMBERS SPACE PLUS MINUS BITWISE_NOT NOT LEFT_PARENTHESIS, str[str_index + 1])))) {
979 if(is_in(NUMBERS SPACE PLUS MINUS BITWISE_NOT NOT LEFT_PARENTHESIS, str[str_index + 1])) {
980 // replace \ followed by number with // for integer division
981 str.replace(str_index, 1, "//");
982 str_index++;
983 } else {
984 // replaced \ followed by a character with symbolic MathStructure
985 stmp = LEFT_PARENTHESIS ID_WRAP_LEFT;
986 size_t l = 1;
987 if(str[str_index + l] < 0) {
988 do {
989 l++;
990 } while(str_index + l < str.length() && str[str_index + l] < 0 && (unsigned char) str[str_index + l] < 0xC0);
991 l--;
992 }
993 MathStructure *mstruct = new MathStructure(str.substr(str_index + 1, l));
994 stmp += i2s(addId(mstruct));
995 stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS;
996 str.replace(str_index, l + 1, stmp);
997 str_index += stmp.length() - l;
998 }
999 } else if(str[str_index] == '!' && po.functions_enabled) {
1000 // replace ! with factorial function when appropriate
1001 if(str_index > 0 && (str.length() - str_index == 1 || str[str_index + 1] != EQUALS_CH)) {
1002 stmp2 = "";
1003 size_t i5 = str.find_last_not_of(SPACE, str_index - 1);
1004 size_t i3;
1005 if(i5 == string::npos) {
1006 } else if(str[i5] == RIGHT_PARENTHESIS_CH) {
1007 if(i5 == 0) {
1008 stmp2 = str.substr(0, i5 + 1);
1009 } else {
1010 i3 = i5 - 1;
1011 size_t i4 = 1;
1012 while(true) {
1013 i3 = str.find_last_of(LEFT_PARENTHESIS RIGHT_PARENTHESIS, i3);
1014 if(i3 == string::npos) {
1015 stmp2 = str.substr(0, i5 + 1);
1016 break;
1017 }
1018 if(str[i3] == RIGHT_PARENTHESIS_CH) {
1019 i4++;
1020 } else {
1021 i4--;
1022 if(i4 == 0) {
1023 stmp2 = str.substr(i3, i5 + 1 - i3);
1024 break;
1025 }
1026 }
1027 if(i3 == 0) {
1028 stmp2 = str.substr(0, i5 + 1);
1029 break;
1030 }
1031 i3--;
1032 }
1033 }
1034 } else if(str[i5] == ID_WRAP_RIGHT_CH && (i3 = str.find_last_of(ID_WRAP_LEFT, i5 - 1)) != string::npos) {
1035 stmp2 = str.substr(i3, i5 + 1 - i3);
1036 } else if(is_not_in(RESERVED OPERATORS INTERNAL_OPERATORS SPACES VECTOR_WRAPS PARENTHESISS COMMAS, str[i5])) {
1037 i3 = str.find_last_of(RESERVED OPERATORS INTERNAL_OPERATORS SPACES VECTOR_WRAPS PARENTHESISS COMMAS, i5);
1038 if(i3 == string::npos) {
1039 stmp2 = str.substr(0, i5 + 1);
1040 } else {
1041 stmp2 = str.substr(i3 + 1, i5 - i3);
1042 }
1043 }
1044 if(!stmp2.empty()) {
1045 stmp = LEFT_PARENTHESIS ID_WRAP_LEFT;
1046 int ifac = 1;
1047 i3 = str_index + 1;
1048 size_t i4 = i3;
1049 while((i3 = str.find_first_not_of(SPACE, i3)) != string::npos && str[i3] == '!') {
1050 ifac++;
1051 i3++;
1052 i4 = i3;
1053 }
1054 if(ifac == 2) stmp += i2s(parseAddId(f_factorial2, stmp2, po));
1055 else if(ifac == 1) stmp += i2s(parseAddId(f_factorial, stmp2, po));
1056 else stmp += i2s(parseAddIdAppend(f_multifactorial, MathStructure(ifac, 1, 0), stmp2, po));
1057 stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS;
1058 str.replace(i5 - stmp2.length() + 1, stmp2.length() + i4 - i5 - 1, stmp);
1059 str_index = stmp.length() + i5 - stmp2.length();
1060 }
1061 }
1062 } else if(po.parsing_mode != PARSING_MODE_RPN && (str[str_index] == 'c' || str[str_index] == 'C') && str.length() > str_index + 6 && str[str_index + 5] == SPACE_CH && (str_index == 0 || is_in(OPERATORS INTERNAL_OPERATORS PARENTHESISS, str[str_index - 1])) && compare_name_no_case("compl", str, 5, str_index, base)) {
1063 // interprate "compl" followed by space as bitwise not
1064 str.replace(str_index, 6, BITWISE_NOT);
1065 } else if(str[str_index] == SPACE_CH) {
1066 size_t i = str.find(SPACE, str_index + 1);
1067 if(po.parsing_mode == PARSING_MODE_RPN && i == string::npos) i = str.length();
1068 if(i != string::npos) {
1069 // replace text operators, surrounded by space, with default operator characters
1070 i -= str_index + 1;
1071 size_t il = 0;
1072 if(i == per_str_len && (il = compare_name_no_case(per_str, str, per_str_len, str_index + 1, base))) {
1073 str.replace(str_index + 1, il, DIVISION);
1074 str_index++;
1075 } else if(i == times_str_len && (il = compare_name_no_case(times_str, str, times_str_len, str_index + 1, base))) {
1076 str.replace(str_index + 1, il, MULTIPLICATION);
1077 str_index++;
1078 } else if(i == plus_str_len && (il = compare_name_no_case(plus_str, str, plus_str_len, str_index + 1, base))) {
1079 str.replace(str_index + 1, il, PLUS);
1080 str_index++;
1081 } else if(i == minus_str_len && (il = compare_name_no_case(minus_str, str, minus_str_len, str_index + 1, base))) {
1082 str.replace(str_index + 1, il, MINUS);
1083 str_index++;
1084 } else if(and_str_len > 0 && i == and_str_len && (il = compare_name_no_case(and_str, str, and_str_len, str_index + 1, base))) {
1085 str.replace(str_index + 1, il, LOGICAL_AND);
1086 str_index += 2;
1087 } else if(i == AND_str_len && (il = compare_name_no_case(AND_str, str, AND_str_len, str_index + 1, base))) {
1088 str.replace(str_index + 1, il, LOGICAL_AND);
1089 str_index += 2;
1090 } else if(or_str_len > 0 && i == or_str_len && (il = compare_name_no_case(or_str, str, or_str_len, str_index + 1, base))) {
1091 str.replace(str_index + 1, il, LOGICAL_OR);
1092 str_index += 2;
1093 } else if(i == OR_str_len && (il = compare_name_no_case(OR_str, str, OR_str_len, str_index + 1, base))) {
1094 str.replace(str_index + 1, il, LOGICAL_OR);
1095 str_index += 2;
1096 } else if(i == XOR_str_len && (il = compare_name_no_case(XOR_str, str, XOR_str_len, str_index + 1, base))) {
1097 str.replace(str_index + 1, il, "\a");
1098 str_index++;
1099 } else if(i == 5 && (il = compare_name_no_case("bitor", str, 5, str_index + 1, base))) {
1100 str.replace(str_index + 1, il, BITWISE_OR);
1101 str_index++;
1102 } else if(i == 6 && (il = compare_name_no_case("bitand", str, 6, str_index + 1, base))) {
1103 str.replace(str_index + 1, il, BITWISE_AND);
1104 str_index++;
1105 } else if(i == 3 && (il = compare_name_no_case("mod", str, 3, str_index + 1, base))) {
1106 str.replace(str_index + 1, il, "\%\%");
1107 str_index += 2;
1108 } else if(i == 3 && (il = compare_name_no_case("rem", str, 3, str_index + 1, base))) {
1109 str.replace(str_index + 1, il, "%");
1110 str_index++;
1111 } else if(i == 3 && (il = compare_name_no_case("div", str, 3, str_index + 1, base))) {
1112 if(po.parsing_mode == PARSING_MODE_RPN) {
1113 str.replace(str_index + 1, il, "\\");
1114 str_index++;
1115 } else {
1116 str.replace(str_index + 1, il, "//");
1117 str_index += 2;
1118 }
1119 }
1120 }
1121 } else if(str_index > 0 && base >= 2 && base <= 10 && is_in(EXPS, str[str_index]) && str_index + 1 < str.length() && (is_in(NUMBER_ELEMENTS, str[str_index + 1]) || (is_in(PLUS MINUS, str[str_index + 1]) && str_index + 2 < str.length() && is_in(NUMBER_ELEMENTS, str[str_index + 2]))) && is_in(NUMBER_ELEMENTS, str[str_index - 1])) {
1122 //don't do anything when e is used instead of E for EXP
1123 } else if(base <= 33 && str[str_index] == '0' && (str_index == 0 || is_in(NOT_IN_NAMES INTERNAL_OPERATORS, str[str_index - 1]))) {
1124 if(str_index + 2 < str.length() && (str[str_index + 1] == 'x' || str[str_index + 1] == 'X') && is_in(NUMBER_ELEMENTS "abcdefABCDEF", str[str_index + 2])) {
1125 //hexadecimal number 0x...
1126 if(po.base == BASE_HEXADECIMAL) {
1127 str.erase(str_index, 2);
1128 } else {
1129 size_t i;
1130 if(po.parsing_mode == PARSING_MODE_RPN) i = str.find_first_not_of(NUMBER_ELEMENTS "abcdefABCDEF", str_index + 2);
1131 else i = str.find_first_not_of(SPACE NUMBER_ELEMENTS "abcdefABCDEF", str_index + 2);
1132 size_t name_length;
1133 if(i == string::npos) {
1134 i = str.length();
1135 } else if(po.parsing_mode != PARSING_MODE_RPN && is_not_in(ILLEGAL_IN_UNITNAMES, str[i]) && is_in("abcdefABCDEF", str[i - 1])) {
1136 size_t i2 = str.find_last_not_of("abcdefABCDEF", i - 1);
1137 if(i2 != string::npos && i2 > str_index + 2 && is_in(SPACE, str[i2])) {
1138 i = i2;
1139 }
1140 }
1141 while(str[i - 1] == SPACE_CH) i--;
1142 name_length = i - str_index;
1143 ParseOptions po_hex = po;
1144 po_hex.base = BASE_HEXADECIMAL;
1145 stmp = LEFT_PARENTHESIS ID_WRAP_LEFT;
1146 MathStructure *mstruct = new MathStructure(Number(str.substr(str_index, i - str_index), po_hex));
1147 stmp += i2s(addId(mstruct));
1148 stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS;
1149 str.replace(str_index, name_length, stmp);
1150 str_index += stmp.length() - 1;
1151 }
1152
1153 } else if(base <= 12 && str_index + 2 < str.length() && (str[str_index + 1] == 'b' || str[str_index + 1] == 'B') && is_in("01", str[str_index + 2])) {
1154 //binary number 0b...
1155 if(po.base == BASE_BINARY) {
1156 str.erase(str_index, 2);
1157 } else {
1158 size_t i;
1159 if(po.parsing_mode == PARSING_MODE_RPN) i = str.find_first_not_of(NUMBER_ELEMENTS, str_index + 2);
1160 else i = str.find_first_not_of(SPACE NUMBER_ELEMENTS, str_index + 2);
1161 size_t name_length;
1162 if(i == string::npos) i = str.length();
1163 while(str[i - 1] == SPACE_CH) i--;
1164 name_length = i - str_index;
1165 ParseOptions po_bin = po;
1166 po_bin.base = BASE_BINARY;
1167 stmp = LEFT_PARENTHESIS ID_WRAP_LEFT;
1168 MathStructure *mstruct = new MathStructure(Number(str.substr(str_index, i - str_index), po_bin));
1169 stmp += i2s(addId(mstruct));
1170 stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS;
1171 str.replace(str_index, name_length, stmp);
1172 str_index += stmp.length() - 1;
1173 }
1174 } else if(base <= 14 && str_index + 2 < str.length() && (str[str_index + 1] == 'd' || str[str_index + 1] == 'D') && is_in(NUMBERS DUODECIMAL_CHARS, str[str_index + 2])) {
1175 //duodecimal number 0d...
1176 if(po.base == BASE_DUODECIMAL) {
1177 str.erase(str_index, 2);
1178 } else {
1179 size_t i;
1180 if(po.parsing_mode == PARSING_MODE_RPN) i = str.find_first_not_of(NUMBER_ELEMENTS DUODECIMAL_CHARS, str_index + 2);
1181 else i = str.find_first_not_of(SPACE NUMBER_ELEMENTS DUODECIMAL_CHARS, str_index + 2);
1182 size_t name_length;
1183 if(i == string::npos) i = str.length();
1184 while(str[i - 1] == SPACE_CH) i--;
1185 name_length = i - str_index;
1186 ParseOptions po_duo = po;
1187 po_duo.base = BASE_DUODECIMAL;
1188 stmp = LEFT_PARENTHESIS ID_WRAP_LEFT;
1189 MathStructure *mstruct = new MathStructure(Number(str.substr(str_index, i - str_index), po_duo));
1190 stmp += i2s(addId(mstruct));
1191 stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS;
1192 str.replace(str_index, name_length, stmp);
1193 str_index += stmp.length() - 1;
1194 }
1195 } else if(base <= 24 && str_index + 2 < str.length() && (str[str_index + 1] == 'o' || str[str_index + 1] == 'O') && is_in(NUMBERS, str[str_index + 2])) {
1196 //octal number 0o...
1197 if(po.base == BASE_OCTAL) {
1198 str.erase(str_index, 2);
1199 } else {
1200 size_t i;
1201 if(po.parsing_mode == PARSING_MODE_RPN) i = str.find_first_not_of(NUMBER_ELEMENTS, str_index + 2);
1202 else i = str.find_first_not_of(SPACE NUMBER_ELEMENTS, str_index + 2);
1203 size_t name_length;
1204 if(i == string::npos) i = str.length();
1205 while(str[i - 1] == SPACE_CH) i--;
1206 name_length = i - str_index;
1207 ParseOptions po_oct = po;
1208 po_oct.base = BASE_OCTAL;
1209 stmp = LEFT_PARENTHESIS ID_WRAP_LEFT;
1210 MathStructure *mstruct = new MathStructure(Number(str.substr(str_index, i - str_index), po_oct));
1211 stmp += i2s(addId(mstruct));
1212 stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS;
1213 str.replace(str_index, name_length, stmp);
1214 str_index += stmp.length() - 1;
1215 }
1216 }
1217 } else if(is_not_in(NUMBERS INTERNAL_OPERATORS NOT_IN_NAMES, str[str_index])) {
1218 // dx/dy derivative notation
1219 if((str[str_index] == 'd' && is_not_number('d', base)) || (str[str_index] == -50 && str_index + 1 < str.length() && str[str_index + 1] == -108) || (str[str_index] == -16 && str_index + 3 < str.length() && str[str_index + 1] == -99 && str[str_index + 2] == -102 && str[str_index + 3] == -85)) {
1220 size_t d_len = 1;
1221 if(str[str_index] == -50) d_len = 2;
1222 else if(str[str_index] == -16) d_len = 4;
1223 if(str_index + (d_len * 2) + 1 < str.length() && (str[str_index + d_len] == '/' || (str[str_index + d_len + 1] == '/' && is_in("xyz", str[str_index + d_len]) && str_index + (d_len * 2) + 2 < str.length()))) {
1224 size_t i_div = str_index + d_len;
1225 if(str[str_index + d_len] != '/') i_div++;
1226 bool b = true;
1227 for(size_t i_d = 0; i_d < d_len; i_d++) {
1228 if(str[i_div + 1 + i_d] != str[str_index + i_d]) {
1229 b = false;
1230 break;
1231 }
1232 }
1233 if(b && is_in("xyz", str[i_div + d_len + 1]) && (str.length() == i_div + d_len + 2 || str[i_div + d_len + 2] == SPACE_CH || str[i_div + d_len + 2] == LEFT_PARENTHESIS_CH)) {
1234 size_t i3 = i_div + d_len + 2;
1235 if(i3 < str.length()) i3++;
1236 int nr_of_p = 1;
1237 size_t i7 = i3;
1238 for(; i7 < str.length(); i7++) {
1239 if(str[i7] == LEFT_PARENTHESIS_CH) {
1240 nr_of_p++;
1241 } else if(str[i7] == RIGHT_PARENTHESIS_CH) {
1242 nr_of_p--;
1243 if(nr_of_p == 0) break;
1244 }
1245 }
1246 if(nr_of_p > 0) nr_of_p--;
1247 if(i3 == i7) stmp2 = "";
1248 else stmp2 = str.substr(i3, i7 - i3);
1249 while(nr_of_p > 0) {stmp2 += ')'; nr_of_p--;}
1250 stmp2 += COMMA_CH;
1251 stmp2 += str[i_div + d_len + 1];
1252 stmp = LEFT_PARENTHESIS ID_WRAP_LEFT;
1253 stmp += i2s(parseAddId(f_diff, stmp2, po));
1254 stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS;
1255 str.replace(str_index, i7 - str_index, stmp);
1256 str_index += stmp.length() - 1;
1257 continue;
1258 }
1259 }
1260 }
1261 // search for variable, function, unit, prefix names
1262 bool p_mode = false;
1263 void *best_p_object = NULL;
1264 const string *best_p_name = NULL;
1265 Prefix *best_p = NULL;
1266 size_t best_pl = 0;
1267 size_t best_pnl = 0;
1268 bool moved_forward = false;
1269 const string *found_function_name = NULL;
1270 bool case_sensitive = false;
1271 size_t found_function_name_length = 0;
1272 void *found_function = NULL, *object = NULL;
1273 int vt2 = -1;
1274 size_t ufv_index;
1275 size_t name_length;
1276 size_t vt3 = 0;
1277 char ufvt = 0;
1278 size_t last_name_char = str.find_first_of(NOT_IN_NAMES INTERNAL_OPERATORS, str_index + 1);
1279 if(last_name_char == string::npos) {
1280 last_name_char = str.length() - 1;
1281 } else {
1282 last_name_char--;
1283 }
1284 size_t last_unit_char = str.find_last_not_of(NUMBERS, last_name_char);
1285 size_t name_chars_left = last_name_char - str_index + 1;
1286 size_t unit_chars_left = last_unit_char - str_index + 1;
1287 if(name_chars_left <= UFV_LENGTHS) {
1288 ufv_index = name_chars_left - 1;
1289 vt2 = 0;
1290 } else {
1291 ufv_index = 0;
1292 }
1293 Prefix *p = NULL;
1294 while(vt2 < 4) {
1295 name = NULL;
1296 p = NULL;
1297 switch(vt2) {
1298 case -1: {
1299 if(ufv_index < ufvl.size()) {
1300 switch(ufvl_t[ufv_index]) {
1301 case 'v': {
1302 if(po.variables_enabled && !p_mode) {
1303 name = &((ExpressionItem*) ufvl[ufv_index])->getName(ufvl_i[ufv_index]).name;
1304 case_sensitive = ((ExpressionItem*) ufvl[ufv_index])->getName(ufvl_i[ufv_index]).case_sensitive;
1305 name_length = name->length();
1306 if(name_length < found_function_name_length) {
1307 name = NULL;
1308 } else if(po.limit_implicit_multiplication) {
1309 if(name_length != name_chars_left && name_length != unit_chars_left) name = NULL;
1310 } else if(name_length > name_chars_left) {
1311 name = NULL;
1312 }
1313 }
1314 break;
1315 }
1316 case 'f': {
1317 if(po.functions_enabled && !found_function_name && !p_mode) {
1318 name = &((ExpressionItem*) ufvl[ufv_index])->getName(ufvl_i[ufv_index]).name;
1319 case_sensitive = ((ExpressionItem*) ufvl[ufv_index])->getName(ufvl_i[ufv_index]).case_sensitive;
1320 name_length = name->length();
1321 if(po.limit_implicit_multiplication) {
1322 if(name_length != name_chars_left && name_length != unit_chars_left) name = NULL;
1323 } else if(name_length > name_chars_left || name_length < found_function_name_length) {
1324 name = NULL;
1325 }
1326 }
1327 break;
1328 }
1329 case 'u': {
1330 if(po.units_enabled && !p_mode) {
1331 name = &((ExpressionItem*) ufvl[ufv_index])->getName(ufvl_i[ufv_index]).name;
1332 case_sensitive = ((ExpressionItem*) ufvl[ufv_index])->getName(ufvl_i[ufv_index]).case_sensitive;
1333 name_length = name->length();
1334 if(name_length < found_function_name_length) {
1335 name = NULL;
1336 } else if(po.limit_implicit_multiplication || ((ExpressionItem*) ufvl[ufv_index])->getName(ufvl_i[ufv_index]).plural) {
1337 if(name_length != unit_chars_left) name = NULL;
1338 } else if(name_length > unit_chars_left) {
1339 name = NULL;
1340 }
1341 }
1342 break;
1343 }
1344 case 'p': {
1345 if(!p && po.units_enabled) {
1346 name = &((Prefix*) ufvl[ufv_index])->shortName();
1347 name_length = name->length();
1348 if(name_length >= unit_chars_left || name_length < found_function_name_length) {
1349 name = NULL;
1350 }
1351 }
1352 case_sensitive = true;
1353 break;
1354 }
1355 case 'P': {
1356 if(!p && po.units_enabled) {
1357 name = &((Prefix*) ufvl[ufv_index])->longName();
1358 name_length = name->length();
1359 if(name_length > unit_chars_left || name_length < found_function_name_length) {
1360 name = NULL;
1361 }
1362 }
1363 case_sensitive = false;
1364 break;
1365 }
1366 case 'q': {
1367 if(!p && po.units_enabled) {
1368 name = &((Prefix*) ufvl[ufv_index])->unicodeName();
1369 name_length = name->length();
1370 if(name_length >= unit_chars_left || name_length < found_function_name_length) {
1371 name = NULL;
1372 }
1373 }
1374 case_sensitive = true;
1375 break;
1376 }
1377 }
1378 ufvt = ufvl_t[ufv_index];
1379 object = ufvl[ufv_index];
1380 ufv_index++;
1381 break;
1382 } else {
1383 if(found_function_name) {
1384 vt2 = 4;
1385 break;
1386 }
1387 vt2 = 0;
1388 vt3 = 0;
1389 if(po.limit_implicit_multiplication && unit_chars_left <= UFV_LENGTHS) {
1390 ufv_index = unit_chars_left - 1;
1391 } else {
1392 ufv_index = UFV_LENGTHS - 1;
1393 }
1394 }
1395 }
1396 case 0: {
1397 if(po.units_enabled && vt3 < ufv[vt2][ufv_index].size()) {
1398 object = ufv[vt2][ufv_index][vt3];
1399 switch(ufv_i[vt2][ufv_index][vt3]) {
1400 case 1: {
1401 ufvt = 'P';
1402 name = &((Prefix*) object)->longName();
1403 name_length = name->length();
1404 case_sensitive = false;
1405 break;
1406 }
1407 case 2: {
1408 if(ufv_index >= unit_chars_left - 1) break;
1409 ufvt = 'p';
1410 name = &((Prefix*) object)->shortName();
1411 name_length = name->length();
1412 case_sensitive = true;
1413 break;
1414 }
1415 case 3: {
1416 if(ufv_index >= unit_chars_left - 1) break;
1417 ufvt = 'q';
1418 name = &((Prefix*) object)->unicodeName();
1419 name_length = name->length();
1420 case_sensitive = true;
1421 break;
1422 }
1423 }
1424 vt3++;
1425 break;
1426 }
1427 vt2 = 1;
1428 vt3 = 0;
1429 }
1430 case 1: {
1431 if(!found_function_name && po.functions_enabled && !p_mode && (!po.limit_implicit_multiplication || ufv_index + 1 == unit_chars_left || ufv_index + 1 == name_chars_left) && vt3 < ufv[vt2][ufv_index].size()) {
1432 object = ufv[vt2][ufv_index][vt3];
1433 ufvt = 'f';
1434 name = &((MathFunction*) object)->getName(ufv_i[vt2][ufv_index][vt3]).name;
1435 name_length = name->length();
1436 case_sensitive = ((MathFunction*) object)->getName(ufv_i[vt2][ufv_index][vt3]).case_sensitive;
1437 vt3++;
1438 break;
1439 }
1440 vt2 = 2;
1441 vt3 = 0;
1442 }
1443 case 2: {
1444 if(po.units_enabled && !p_mode && (!po.limit_implicit_multiplication || ufv_index + 1 == unit_chars_left) && ufv_index < unit_chars_left && vt3 < ufv[vt2][ufv_index].size()) {
1445 object = ufv[vt2][ufv_index][vt3];
1446 if(ufv_index + 1 == unit_chars_left || !((Unit*) object)->getName(ufv_i[vt2][ufv_index][vt3]).plural) {
1447 ufvt = 'u';
1448 name = &((Unit*) object)->getName(ufv_i[vt2][ufv_index][vt3]).name;
1449 name_length = name->length();
1450 case_sensitive = ((Unit*) object)->getName(ufv_i[vt2][ufv_index][vt3]).case_sensitive;
1451 }
1452 vt3++;
1453 break;
1454 }
1455 vt2 = 3;
1456 vt3 = 0;
1457 }
1458 case 3: {
1459 if(po.variables_enabled && !p_mode && (!po.limit_implicit_multiplication || ufv_index + 1 == unit_chars_left || ufv_index + 1 == name_chars_left) && vt3 < ufv[vt2][ufv_index].size()) {
1460 object = ufv[vt2][ufv_index][vt3];
1461 ufvt = 'v';
1462 name = &((Variable*) object)->getName(ufv_i[vt2][ufv_index][vt3]).name;
1463 name_length = name->length();
1464 case_sensitive = ((Variable*) object)->getName(ufv_i[vt2][ufv_index][vt3]).case_sensitive;
1465 vt3++;
1466 break;
1467 }
1468 if(ufv_index == 0 || found_function_name) {
1469 vt2 = 4;
1470 } else {
1471 ufv_index--;
1472 vt3 = 0;
1473 vt2 = 0;
1474 }
1475 }
1476 }
1477 if(name && name_length >= found_function_name_length && ((case_sensitive && compare_name(*name, str, name_length, str_index, base)) || (!case_sensitive && (name_length = compare_name_no_case(*name, str, name_length, str_index, base))))) {
1478 moved_forward = false;
1479 switch(ufvt) {
1480 case 'v': {
1481 stmp = LEFT_PARENTHESIS ID_WRAP_LEFT;
1482 stmp += i2s(addId(new MathStructure((Variable*) object)));
1483 stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS;
1484 str.replace(str_index, name_length, stmp);
1485 str_index += stmp.length();
1486 moved_forward = true;
1487 break;
1488 }
1489 case 'f': {
1490 if(((ExpressionItem*) object)->subtype() == SUBTYPE_DATA_SET && str[str_index + name_length] == DOT_CH) {
1491 str[str_index + name_length] = LEFT_PARENTHESIS_CH;
1492 size_t dot2_index = str.find(DOT_CH, str_index + name_length + 1);
1493 str[dot2_index] = COMMA_CH;
1494 size_t end_index = str.find_first_of(NOT_IN_NAMES INTERNAL_OPERATORS, dot2_index + 1);
1495 if(end_index == string::npos) str += RIGHT_PARENTHESIS_CH;
1496 else str.insert(end_index, 1, RIGHT_PARENTHESIS_CH);
1497 }
1498 size_t not_space_index;
1499 if((not_space_index = str.find_first_not_of(SPACES, str_index + name_length)) == string::npos || str[not_space_index] != LEFT_PARENTHESIS_CH) {
1500 found_function = object;
1501 found_function_name = name;
1502 found_function_name_length = name_length;
1503 break;
1504 }
1505 set_function:
1506 MathFunction *f = (MathFunction*) object;
1507 if(str_index + name_length + 2 < str.length() && str[str_index + name_length] == POWER_CH && (f->id() == FUNCTION_ID_SIN || f->id() == FUNCTION_ID_COS || f->id() == FUNCTION_ID_TAN || f->id() == FUNCTION_ID_SINH || f->id() == FUNCTION_ID_COSH || f->id() == FUNCTION_ID_TANH) && str[str_index + name_length + 1] == MINUS_CH && str[str_index + name_length + 2] == '1' && (str_index + name_length + 3 == str.length() || is_not_in(NUMBER_ELEMENTS, str[str_index + name_length + 3]))) {
1508 name_length += 3;
1509 if(f->id() == FUNCTION_ID_SIN) f = f_asin;
1510 else if(f->id() == FUNCTION_ID_COS) f = f_acos;
1511 else if(f->id() == FUNCTION_ID_TAN) f = f_atan;
1512 else if(f->id() == FUNCTION_ID_SINH) f = f_asinh;
1513 else if(f->id() == FUNCTION_ID_COSH) f = f_acosh;
1514 else if(f->id() == FUNCTION_ID_TANH) f = f_atanh;
1515 }
1516 int i4 = -1;
1517 size_t i6;
1518 if(f->args() == 0) {
1519 size_t i7 = str.find_first_not_of(SPACES, str_index + name_length);
1520 if(i7 != string::npos && str[i7] == LEFT_PARENTHESIS_CH) {
1521 i7 = str.find_first_not_of(SPACES, i7 + 1);
1522 if(i7 != string::npos && str[i7] == RIGHT_PARENTHESIS_CH) {
1523 i4 = i7 - str_index + 1;
1524 }
1525 }
1526 stmp = LEFT_PARENTHESIS ID_WRAP_LEFT;
1527 stmp += i2s(parseAddId(f, empty_string, po));
1528 stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS;
1529 if(i4 < 0) i4 = name_length;
1530 } else if(po.parsing_mode == PARSING_MODE_CHAIN && f->minargs() == 1 && str_index > 0 && (i6 = str.find_last_not_of(SPACE, str_index - 1)) != string::npos && str[i6] != LEFT_PARENTHESIS_CH && is_not_in(OPERATORS INTERNAL_OPERATORS, str[i6]) && (str_index + name_length >= str.length() || (str.find_first_not_of(SPACE, str_index + name_length) == string::npos || is_in(OPERATORS INTERNAL_OPERATORS, str[str.find_first_not_of(SPACE, str_index + name_length)])))) {
1531 size_t i7 = i6;
1532 int nr_of_p = 0;
1533 while(true) {
1534 if(str[i7] == LEFT_PARENTHESIS_CH) {
1535 if(nr_of_p == 0) {i7++; break;}
1536 nr_of_p--;
1537 if(nr_of_p == 0) {break;}
1538 } else if(str[i7] == RIGHT_PARENTHESIS_CH) {
1539 if(nr_of_p == 0 && i7 != i6) {i7++; break;}
1540 nr_of_p++;
1541 } else if(nr_of_p == 0 && is_in(PLUS MINUS, str[i7])) {
1542 if(i7 != 0) i6 = str.find_last_not_of(SPACE, i7 - 1);
1543 if(i7 == 0 || is_not_in(OPERATORS INTERNAL_OPERATORS, str[i6])) {
1544 i7++;
1545 break;
1546 }
1547 } else if(nr_of_p == 0 && is_in("*/&|=><^%\x1c", str[i7])) {
1548 i7++;
1549 break;
1550 }
1551 if(i7 == 0) break;
1552 i7--;
1553 }
1554 stmp2 = str.substr(i7, str_index - i7);
1555 stmp = LEFT_PARENTHESIS ID_WRAP_LEFT;
1556 if(f->id() == FUNCTION_ID_VECTOR) stmp += i2s(parseAddVectorId(stmp2, po));
1557 else stmp += i2s(parseAddId(f, stmp2, po));
1558 stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS;
1559 str.replace(i7, str_index + name_length - i7, stmp);
1560 str_index += name_length;
1561 moved_forward = true;
1562 } else if(po.parsing_mode == PARSING_MODE_RPN && f->args() == 1 && str_index > 0 && str[str_index - 1] != LEFT_PARENTHESIS_CH && (str_index + name_length >= str.length() || str[str_index + name_length] != LEFT_PARENTHESIS_CH) && (i6 = str.find_last_not_of(SPACE, str_index - 1)) != string::npos) {
1563 size_t i7 = i6;
1564 int nr_of_p = 0, nr_of_op = 0;
1565 bool b_started = false;
1566 while(i7 != 0) {
1567 if(nr_of_p > 0) {
1568 if(str[i7] == LEFT_PARENTHESIS_CH) {
1569 nr_of_p--;
1570 if(nr_of_p == 0 && nr_of_op == 0) break;
1571 } else if(str[i7] == RIGHT_PARENTHESIS_CH) {
1572 nr_of_p++;
1573 }
1574 } else if(nr_of_p == 0 && is_in(OPERATORS INTERNAL_OPERATORS SPACE RIGHT_PARENTHESIS, str[i7])) {
1575 if(nr_of_op == 0 && b_started) {
1576 i7++;
1577 break;
1578 } else {
1579 if(is_in(OPERATORS INTERNAL_OPERATORS, str[i7])) {
1580 nr_of_op++;
1581 b_started = false;
1582 } else if(str[i7] == RIGHT_PARENTHESIS_CH) {
1583 nr_of_p++;
1584 b_started = true;
1585 } else if(b_started) {
1586 nr_of_op--;
1587 b_started = false;
1588 }
1589 }
1590 } else {
1591 b_started = true;
1592 }
1593 i7--;
1594 }
1595 stmp2 = str.substr(i7, i6 - i7 + 1);
1596 stmp = LEFT_PARENTHESIS ID_WRAP_LEFT;
1597 if(f->id() == FUNCTION_ID_VECTOR) stmp += i2s(parseAddVectorId(stmp2, po));
1598 else stmp += i2s(parseAddId(f, stmp2, po));
1599 stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS;
1600 str.replace(i7, str_index + name_length - i7, stmp);
1601 str_index += name_length;
1602 moved_forward = true;
1603 } else {
1604 bool b = false, b_unended_function = false, b_comma_before = false, b_power_before = false;
1605 //bool b_space_first = false;
1606 size_t i5 = 1;
1607 int arg_i = f->args();
1608 i6 = 0;
1609 while(!b) {
1610 if(i6 + str_index + name_length >= str.length()) {
1611 b = true;
1612 i5 = 2;
1613 i6++;
1614 b_unended_function = true;
1615 break;
1616 } else {
1617 char c = str[str_index + name_length + i6];
1618 if(c == LEFT_PARENTHESIS_CH) {
1619 if(i5 < 2) b = true;
1620 else if(i5 == 2 && po.parsing_mode >= PARSING_MODE_CONVENTIONAL && !b_power_before) b = true;
1621 else i5++;
1622 } else if(c == RIGHT_PARENTHESIS_CH) {
1623 if(i5 <= 2) b = true;
1624 else i5--;
1625 } else if(c == POWER_CH) {
1626 if(i5 < 2) i5 = 2;
1627 b_power_before = true;
1628 } else if(!b_comma_before && !b_power_before && c == ' ' && arg_i <= 1) {
1629 //if(i5 < 2) b_space_first = true;
1630 if(i5 == 2) b = true;
1631 } else if(!b_comma_before && i5 == 2 && arg_i <= 1 && is_in(OPERATORS INTERNAL_OPERATORS, c) && c != POWER_CH && (!b_power_before || (c != MINUS_CH && c != PLUS_CH))) {
1632 b = true;
1633 } else if(c == COMMA_CH) {
1634 if(i5 == 2) arg_i--;
1635 b_comma_before = true;
1636 if(i5 < 2) i5 = 2;
1637 } else if(i5 < 2) {
1638 i5 = 2;
1639 }
1640 if(c != COMMA_CH && c != ' ') b_comma_before = false;
1641 if(c != POWER_CH && c != ' ') b_power_before = false;
1642 }
1643 i6++;
1644 }
1645 if(b && i5 >= 2) {
1646 stmp2 = str.substr(str_index + name_length, i6 - 1);
1647 stmp = LEFT_PARENTHESIS ID_WRAP_LEFT;
1648 if(b_unended_function && unended_function) {
1649 po.unended_function = unended_function;
1650 }
1651 if(f->id() == FUNCTION_ID_VECTOR) {
1652 stmp += i2s(parseAddVectorId(stmp2, po));
1653 } else if((f->id() == FUNCTION_ID_INTERVAL || f->id() == FUNCTION_ID_UNCERTAINTY) && po.read_precision != DONT_READ_PRECISION) {
1654 ParseOptions po2 = po;
1655 po2.read_precision = DONT_READ_PRECISION;
1656 stmp += i2s(parseAddId(f, stmp2, po2));
1657 } else {
1658 stmp += i2s(parseAddId(f, stmp2, po));
1659 }
1660 po.unended_function = NULL;
1661 stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS;
1662 i4 = i6 + 1 + name_length - 2;
1663 b = false;
1664 }
1665 size_t i9 = i6;
1666 if(b) {
1667 b = false;
1668 i6 = i6 + 1 + str_index + name_length;
1669 size_t i7 = i6 - 1;
1670 size_t i8 = i7;
1671 while(true) {
1672 i5 = str.find(RIGHT_PARENTHESIS_CH, i7);
1673 if(i5 == string::npos) {
1674 b_unended_function = true;
1675 //str.append(1, RIGHT_PARENTHESIS_CH);
1676 //i5 = str.length() - 1;
1677 i5 = str.length();
1678 }
1679 if(i5 < (i6 = str.find(LEFT_PARENTHESIS_CH, i8)) || i6 == string::npos) {
1680 i6 = i5;
1681 b = true;
1682 break;
1683 }
1684 i7 = i5 + 1;
1685 i8 = i6 + 1;
1686 }
1687 if(!b) {
1688 b_unended_function = false;
1689 }
1690 }
1691 if(b) {
1692 stmp2 = str.substr(str_index + name_length + i9, i6 - (str_index + name_length + i9));
1693 stmp = LEFT_PARENTHESIS ID_WRAP_LEFT;
1694 if(b_unended_function && unended_function) {
1695 po.unended_function = unended_function;
1696 }
1697 if(f->id() == FUNCTION_ID_VECTOR) {
1698 stmp += i2s(parseAddVectorId(stmp2, po));
1699 } else if((f->id() == FUNCTION_ID_INTERVAL || f->id() == FUNCTION_ID_UNCERTAINTY) && po.read_precision != DONT_READ_PRECISION) {
1700 ParseOptions po2 = po;
1701 po2.read_precision = DONT_READ_PRECISION;
1702 stmp += i2s(parseAddId(f, stmp2, po2));
1703 } else {
1704 stmp += i2s(parseAddId(f, stmp2, po));
1705 }
1706 po.unended_function = NULL;
1707 stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS;
1708 i4 = i6 + 1 - str_index;
1709 }
1710 }
1711 if(i4 > 0) {
1712 str.replace(str_index, i4, stmp);
1713 str_index += stmp.length();
1714 moved_forward = true;
1715 }
1716 break;
1717 }
1718 case 'u': {
1719 replace_text_by_unit_place:
1720 stmp = LEFT_PARENTHESIS ID_WRAP_LEFT;
1721 stmp += i2s(addId(new MathStructure((Unit*) object, p)));
1722 stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS;
1723 str.replace(str_index, name_length, stmp);
1724 if(str.length() > str_index + stmp.length() && is_in("23", str[str_index + stmp.length()]) && (str.length() == str_index + stmp.length() + 1 || is_not_in(NUMBER_ELEMENTS, str[str_index + stmp.length() + 1])) && (!name || *name != SIGN_DEGREE) && !((Unit*) object)->isCurrency()) {
1725 str.insert(str_index + stmp.length(), 1, POWER_CH);
1726 if(po.parsing_mode == PARSING_MODE_CHAIN) {
1727 str.insert(str_index + stmp.length() + 2, 1, RIGHT_PARENTHESIS_CH);
1728 str.insert(str_index, 1, LEFT_PARENTHESIS_CH);
1729 str_index++;
1730 }
1731 }
1732 str_index += stmp.length();
1733 moved_forward = true;
1734 p = NULL;
1735 break;
1736 }
1737 case 'p': {}
1738 case 'q': {}
1739 case 'P': {
1740 p = (Prefix*) object;
1741 if(str_index + name_length == str.length() || is_in(NOT_IN_NAMES INTERNAL_OPERATORS, str[str_index + name_length])) {
1742 if(ufvt == 'P') {
1743 stmp = LEFT_PARENTHESIS ID_WRAP_LEFT;
1744 switch(p->type()) {
1745 case PREFIX_DECIMAL: {
1746 MathStructure *m_prefix = new MathStructure(10, 1, 0);
1747 m_prefix->raise(Number(((DecimalPrefix*) p)->exponent(), 1));
1748 stmp += i2s(addId(m_prefix));
1749 break;
1750 }
1751 case PREFIX_BINARY: {
1752 MathStructure *m_prefix = new MathStructure(2, 1, 0);
1753 m_prefix->raise(Number(((BinaryPrefix*) p)->exponent(), 1));
1754 stmp += i2s(addId(m_prefix));
1755 break;
1756 }
1757 default: {
1758 stmp += i2s(addId(new MathStructure(p->value())));
1759 }
1760 }
1761 stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS;
1762 str.replace(str_index, name_length, stmp);
1763 str_index += stmp.length();
1764 moved_forward = true;
1765 }
1766 break;
1767 }
1768 str_index += name_length;
1769 unit_chars_left = last_unit_char - str_index + 1;
1770 size_t name_length_old = name_length;
1771 int index = 0;
1772 if(unit_chars_left > UFV_LENGTHS) {
1773 for(size_t ufv_index2 = 0; ufv_index2 < ufvl.size(); ufv_index2++) {
1774 name = NULL;
1775 switch(ufvl_t[ufv_index2]) {
1776 case 'u': {
1777 name = &((Unit*) ufvl[ufv_index2])->getName(ufvl_i[ufv_index2]).name;
1778 case_sensitive = ((Unit*) ufvl[ufv_index2])->getName(ufvl_i[ufv_index2]).case_sensitive;
1779 name_length = name->length();
1780 if(po.limit_implicit_multiplication || ((Unit*) ufvl[ufv_index2])->getName(ufvl_i[ufv_index2]).plural) {
1781 if(name_length != unit_chars_left) name = NULL;
1782 } else if(name_length > unit_chars_left) {
1783 name = NULL;
1784 }
1785 break;
1786 }
1787 }
1788 if(name && ((case_sensitive && compare_name(*name, str, name_length, str_index, base)) || (!case_sensitive && (name_length = compare_name_no_case(*name, str, name_length, str_index, base))))) {
1789 if((!p_mode && name_length_old > 1) || (p_mode && (name_length + name_length_old > best_pl || ((ufvt != 'P' || !((Unit*) ufvl[ufv_index2])->getName(ufvl_i[ufv_index2]).abbreviation) && name_length + name_length_old == best_pl)))) {
1790 p_mode = true;
1791 best_p = p;
1792 best_p_object = ufvl[ufv_index2];
1793 best_p_name = name;
1794 best_pl = name_length + name_length_old;
1795 best_pnl = name_length_old;
1796 index = -1;
1797 break;
1798 }
1799 if(!p_mode) {
1800 str.erase(str_index - name_length_old, name_length_old);
1801 str_index -= name_length_old;
1802 object = ufvl[ufv_index2];
1803 goto replace_text_by_unit_place;
1804 }
1805 }
1806 }
1807 }
1808 if(index < 0) {
1809 } else if(UFV_LENGTHS >= unit_chars_left) {
1810 index = unit_chars_left - 1;
1811 } else if(po.limit_implicit_multiplication) {
1812 index = -1;
1813 } else {
1814 index = UFV_LENGTHS - 1;
1815 }
1816 for(; index >= 0; index--) {
1817 for(size_t ufv_index2 = 0; ufv_index2 < ufv[2][index].size(); ufv_index2++) {
1818 name = &((Unit*) ufv[2][index][ufv_index2])->getName(ufv_i[2][index][ufv_index2]).name;
1819 case_sensitive = ((Unit*) ufv[2][index][ufv_index2])->getName(ufv_i[2][index][ufv_index2]).case_sensitive;
1820 name_length = name->length();
1821 if(index + 1 == (int) unit_chars_left || !((Unit*) ufv[2][index][ufv_index2])->getName(ufv_i[2][index][ufv_index2]).plural) {
1822 if(name_length <= unit_chars_left && ((case_sensitive && compare_name(*name, str, name_length, str_index, base)) || (!case_sensitive && (name_length = compare_name_no_case(*name, str, name_length, str_index, base))))) {
1823 if((!p_mode && name_length_old > 1) || (p_mode && (name_length + name_length_old > best_pl || ((ufvt != 'P' || !((Unit*) ufv[2][index][ufv_index2])->getName(ufv_i[2][index][ufv_index2]).abbreviation) && name_length + name_length_old == best_pl)))) {
1824 p_mode = true;
1825 best_p = p;
1826 best_p_object = ufv[2][index][ufv_index2];
1827 best_p_name = name;
1828 best_pl = name_length + name_length_old;
1829 best_pnl = name_length_old;
1830 index = -1;
1831 }
1832 if(!p_mode) {
1833 str.erase(str_index - name_length_old, name_length_old);
1834 str_index -= name_length_old;
1835 object = ufv[2][index][ufv_index2];
1836 goto replace_text_by_unit_place;
1837 }
1838 }
1839 }
1840 }
1841 if(po.limit_implicit_multiplication || (p_mode && index + 1 + name_length_old < best_pl)) {
1842 break;
1843 }
1844 }
1845 str_index -= name_length_old;
1846 unit_chars_left = last_unit_char - str_index + 1;
1847 break;
1848 }
1849 }
1850 if(moved_forward) {
1851 str_index--;
1852 break;
1853 }
1854 }
1855 }
1856 if(!moved_forward && p_mode) {
1857 object = best_p_object;
1858 name = best_p_name;
1859 p = best_p;
1860 str.erase(str_index, best_pnl);
1861 name_length = best_pl - best_pnl;
1862 goto replace_text_by_unit_place;
1863 } else if(!moved_forward && found_function) {
1864 object = found_function;
1865 name = found_function_name;
1866 name_length = found_function_name_length;
1867 goto set_function;
1868 }
1869 if(!moved_forward) {
1870 bool b = po.unknowns_enabled && is_not_number(str[str_index], base) && !(str_index > 0 && is_in(EXPS, str[str_index]) && str_index + 1 < str.length() && (is_in(NUMBER_ELEMENTS, str[str_index + 1]) || (is_in(PLUS MINUS, str[str_index + 1]) && str_index + 2 < str.length() && is_in(NUMBER_ELEMENTS, str[str_index + 2]))) && is_in(NUMBER_ELEMENTS, str[str_index - 1]));
1871 if(po.limit_implicit_multiplication) {
1872 if(b) {
1873 stmp = LEFT_PARENTHESIS ID_WRAP_LEFT;
1874 stmp += i2s(addId(new MathStructure(str.substr(str_index, unit_chars_left))));
1875 stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS;
1876 str.replace(str_index, unit_chars_left, stmp);
1877 str_index += stmp.length() - 1;
1878 } else {
1879 str_index += unit_chars_left - 1;
1880 }
1881 } else if(b) {
1882 size_t i = 1;
1883 if(str[str_index + 1] < 0) {
1884 i++;
1885 while(i <= unit_chars_left && (unsigned char) str[str_index + i] >= 0x80 && (unsigned char) str[str_index + i] <= 0xBF) {
1886 i++;
1887 }
1888 }
1889 stmp = LEFT_PARENTHESIS ID_WRAP_LEFT;
1890 stmp += i2s(addId(new MathStructure(str.substr(str_index, i))));
1891 stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS;
1892 str.replace(str_index, i, stmp);
1893 str_index += stmp.length() - 1;
1894 }
1895 }
1896 }
1897 }
1898
1899 size_t comma_i = str.find(COMMA, 0);
1900 while(comma_i != string::npos) {
1901 int i3 = 1;
1902 size_t left_par_i = comma_i;
1903 while(left_par_i > 0) {
1904 left_par_i = str.find_last_of(LEFT_PARENTHESIS RIGHT_PARENTHESIS, left_par_i - 1);
1905 if(left_par_i == string::npos) break;
1906 if(str[left_par_i] == LEFT_PARENTHESIS_CH) {
1907 i3--;
1908 if(i3 == 0) break;
1909 } else if(str[left_par_i] == RIGHT_PARENTHESIS_CH) {
1910 i3++;
1911 }
1912 }
1913 if(i3 > 0) {
1914 str.insert(0, i3, LEFT_PARENTHESIS_CH);
1915 comma_i += i3;
1916 i3 = 0;
1917 left_par_i = 0;
1918 }
1919 if(i3 == 0) {
1920 i3 = 1;
1921 size_t right_par_i = comma_i;
1922 while(true) {
1923 right_par_i = str.find_first_of(LEFT_PARENTHESIS RIGHT_PARENTHESIS, right_par_i + 1);
1924 if(right_par_i == string::npos) {
1925 for(; i3 > 0; i3--) {
1926 str += RIGHT_PARENTHESIS;
1927 }
1928 right_par_i = str.length() - 1;
1929 } else if(str[right_par_i] == LEFT_PARENTHESIS_CH) {
1930 i3++;
1931 } else if(str[right_par_i] == RIGHT_PARENTHESIS_CH) {
1932 i3--;
1933 }
1934 if(i3 == 0) {
1935 stmp2 = str.substr(left_par_i + 1, right_par_i - left_par_i - 1);
1936 stmp = LEFT_PARENTHESIS ID_WRAP_LEFT;
1937 stmp += i2s(parseAddVectorId(stmp2, po));
1938 stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS;
1939 str.replace(left_par_i, right_par_i + 1 - left_par_i, stmp);
1940 comma_i = left_par_i + stmp.length() - 1;
1941 break;
1942 }
1943 }
1944 }
1945 comma_i = str.find(COMMA, comma_i + 1);
1946 }
1947
1948 if(po.parsing_mode == PARSING_MODE_RPN) {
1949 size_t rpn_i = str.find(SPACE, 0);
1950 while(rpn_i != string::npos) {
1951 if(rpn_i == 0 || rpn_i + 1 == str.length() || is_in("~+-*/^\a\b\\\x1c", str[rpn_i - 1]) || (is_in("%&|", str[rpn_i - 1]) && str[rpn_i + 1] != str[rpn_i - 1]) || (is_in("!><=", str[rpn_i - 1]) && is_not_in("=<>", str[rpn_i + 1])) || (is_in(SPACE OPERATORS INTERNAL_OPERATORS, str[rpn_i + 1]) && (str[rpn_i - 1] == SPACE_CH || (str[rpn_i - 1] != str[rpn_i + 1] && is_not_in("!><=", str[rpn_i - 1]))))) {
1952 str.erase(rpn_i, 1);
1953 } else {
1954 rpn_i++;
1955 }
1956 rpn_i = str.find(SPACE, rpn_i);
1957 }
1958 } else if(po.parsing_mode != PARSING_MODE_ADAPTIVE) {
1959 remove_blanks(str);
1960 } else {
1961 //remove spaces between next to operators (except '/') and before/after parentheses
1962 space_i = str.find(SPACE_CH, 0);
1963 while(space_i != string::npos) {
1964 if((str[space_i + 1] != DIVISION_CH && is_in(OPERATORS INTERNAL_OPERATORS RIGHT_PARENTHESIS, str[space_i + 1])) || (str[space_i - 1] != DIVISION_CH && is_in(OPERATORS INTERNAL_OPERATORS LEFT_PARENTHESIS, str[space_i - 1]))) {
1965 str.erase(space_i, 1);
1966 space_i--;
1967 }
1968 space_i = str.find(SPACE_CH, space_i + 1);
1969 }
1970 }
1971
1972 parseOperators(mstruct, str, po);
1973
1974 }
1975
1976 #define BASE_2_10 ((po.base >= 2 && po.base <= 10) || (po.base < BASE_CUSTOM && po.base != BASE_UNICODE && po.base != BASE_BIJECTIVE_26) || (po.base == BASE_CUSTOM && priv->custom_input_base_i <= 10))
1977
parseNumber(MathStructure * mstruct,string str,const ParseOptions & po)1978 bool Calculator::parseNumber(MathStructure *mstruct, string str, const ParseOptions &po) {
1979
1980 mstruct->clear();
1981 if(str.empty()) return false;
1982
1983 // check that string contains characters other than operators and whitespace
1984 if(str.find_first_not_of(OPERATORS "\a%\x1c" SPACE) == string::npos && (po.base != BASE_ROMAN_NUMERALS || str.find("|") == string::npos)) {
1985 replace_internal_operators(str);
1986 error(false, _("Misplaced operator(s) \"%s\" ignored"), str.c_str(), NULL);
1987 return false;
1988 }
1989
1990 int minus_count = 0;
1991 bool has_sign = false, had_non_sign = false, b_dot = false, b_exp = false, after_sign_e = false;
1992 int i_colon = 0;
1993 size_t i = 0;
1994
1995 while(i < str.length()) {
1996 if(!had_non_sign && str[i] == MINUS_CH) {
1997 // count minuses in front of the number
1998 has_sign = true;
1999 minus_count++;
2000 str.erase(i, 1);
2001 } else if(!had_non_sign && str[i] == PLUS_CH) {
2002 // + in front of the number is ignored
2003 has_sign = true;
2004 str.erase(i, 1);
2005 } else if(str[i] == SPACE_CH) {
2006 // ignore whitespace
2007 str.erase(i, 1);
2008 } else if(had_non_sign && !b_exp && BASE_2_10 && (str[i] == EXP_CH || str[i] == EXP2_CH)) {
2009 // scientific e-notation
2010 b_exp = true;
2011 had_non_sign = true;
2012 after_sign_e = true;
2013 i++;
2014 } else if(after_sign_e && (str[i] == MINUS_CH || str[i] == PLUS_CH)) {
2015 after_sign_e = false;
2016 i++;
2017 } else if(po.preserve_format && str[i] == DOT_CH) {
2018 b_dot = true;
2019 had_non_sign = true;
2020 after_sign_e = false;
2021 i++;
2022 } else if(po.preserve_format && (!b_dot || i_colon > 0) && str[i] == ':') {
2023 // sexagesimal colon; dots are not allowed in first part of a sexagesimal number
2024 i_colon++;
2025 had_non_sign = true;
2026 after_sign_e = false;
2027 i++;
2028 } else if(str[i] == COMMA_CH && DOT_S == ".") {
2029 // comma is ignored of decimal separator is dot
2030 str.erase(i, 1);
2031 after_sign_e = false;
2032 had_non_sign = true;
2033 } else if(is_in(OPERATORS, str[i]) && (po.base != BASE_ROMAN_NUMERALS || (str[i] != '(' && str[i] != ')' && str[i] != '|'))) {
2034 // ignore operators
2035 error(false, _("Misplaced '%c' ignored"), str[i], NULL);
2036 str.erase(i, 1);
2037 } else if(str[i] == '\a') {
2038 // ignore operators
2039 error(false, _("Misplaced operator(s) \"%s\" ignored"), "xor", NULL);
2040 str.erase(i, 1);
2041 } else if(str[i] == '\x1c') {
2042 // ignore operators
2043 error(false, _("Misplaced operator(s) \"%s\" ignored"), "∠", NULL);
2044 str.erase(i, 1);
2045 } else if(str[i] == '\b') {
2046 // +/-
2047 b_exp = false;
2048 had_non_sign = false;
2049 after_sign_e = false;
2050 i++;
2051 } else {
2052 had_non_sign = true;
2053 after_sign_e = false;
2054 i++;
2055 }
2056 }
2057 if(str.empty()) {
2058 if(minus_count % 2 == 1 && !po.preserve_format) {
2059 mstruct->set(-1, 1, 0);
2060 } else if(has_sign) {
2061 mstruct->set(1, 1, 0);
2062 if(po.preserve_format) {
2063 while(minus_count > 0) {
2064 mstruct->transform(STRUCT_NEGATE);
2065 minus_count--;
2066 }
2067 }
2068 }
2069 return false;
2070 }
2071 // numbers in brackets is an internal reference to a stored MathStructure object
2072 if(str[0] == ID_WRAP_LEFT_CH && str.length() > 2 && str[str.length() - 1] == ID_WRAP_RIGHT_CH) {
2073 int id = s2i(str.substr(1, str.length() - 2));
2074 MathStructure *m_temp = getId((size_t) id);
2075 if(!m_temp) {
2076 mstruct->setUndefined();
2077 error(true, _("Internal id %s does not exist."), i2s(id).c_str(), NULL);
2078 return true;
2079 }
2080 mstruct->set_nocopy(*m_temp);
2081 m_temp->unref();
2082 if(po.preserve_format) {
2083 while(minus_count > 0) {
2084 mstruct->transform(STRUCT_NEGATE);
2085 minus_count--;
2086 }
2087 } else if(minus_count % 2 == 1) {
2088 mstruct->negate();
2089 }
2090 return true;
2091 }
2092
2093 // handle non-digits if number base is 2-10 or duodecimal
2094 size_t itmp;
2095 if((BASE_2_10 || po.base == BASE_DUODECIMAL) && (itmp = str.find_first_not_of(po.base == BASE_DUODECIMAL ? NUMBER_ELEMENTS INTERNAL_NUMBER_CHARS MINUS DUODECIMAL_CHARS : NUMBER_ELEMENTS INTERNAL_NUMBER_CHARS EXPS MINUS, 0)) != string::npos) {
2096 if(itmp == 0) {
2097 error(true, _("\"%s\" is not a valid variable/function/unit."), str.c_str(), NULL);
2098 if(minus_count % 2 == 1 && !po.preserve_format) {
2099 mstruct->set(-1, 1, 0);
2100 } else if(has_sign) {
2101 mstruct->set(1, 1, 0);
2102 if(po.preserve_format) {
2103 while(minus_count > 0) {
2104 mstruct->transform(STRUCT_NEGATE);
2105 minus_count--;
2106 }
2107 }
2108 }
2109 return false;
2110 } else {
2111 string stmp = str.substr(itmp, str.length() - itmp);
2112 error(true, _("Trailing characters \"%s\" (not a valid variable/function/unit) in number \"%s\" was ignored."), stmp.c_str(), str.c_str(), NULL);
2113 str.erase(itmp, str.length() - itmp);
2114 }
2115 }
2116
2117 // replace internal +/- operator
2118 gsub("\b", "±", str);
2119
2120 // parse number
2121 Number nr(str, po);
2122
2123 // handle - in front of the number (even number of minuses equals plus, odd number equals a single minus)
2124 if(!po.preserve_format && minus_count % 2 == 1) {
2125 nr.negate();
2126 }
2127
2128 if(i_colon && nr.isRational() && !nr.isInteger()) {
2129 // if po.preserve_format is true, parse sexagesimal number as division
2130 Number nr_num(nr.numerator()), nr_den(1, 1, 0);
2131 while(i_colon) {
2132 nr_den *= 60;
2133 i_colon--;
2134 }
2135 nr_num *= nr_den;
2136 nr_num /= nr.denominator();
2137 mstruct->set(nr_num);
2138 mstruct->transform(STRUCT_DIVISION, nr_den);
2139 } else {
2140 mstruct->set(nr);
2141 }
2142 if(po.preserve_format) {
2143 // handle multiple - in front of the number (treated as a single sign if po.preserve_format is false)
2144 while(minus_count > 0) {
2145 mstruct->transform(STRUCT_NEGATE);
2146 minus_count--;
2147 }
2148 }
2149 return true;
2150
2151 }
2152
parseAdd(string & str,MathStructure * mstruct,const ParseOptions & po)2153 bool Calculator::parseAdd(string &str, MathStructure *mstruct, const ParseOptions &po) {
2154 if(str.length() > 0) {
2155 size_t i;
2156 if(BASE_2_10) {
2157 i = str.find_first_of(SPACE MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS PARENTHESISS EXPS ID_WRAP_LEFT, 1);
2158 } else {
2159 i = str.find_first_of(SPACE MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS PARENTHESISS ID_WRAP_LEFT, 1);
2160 }
2161 if(i == string::npos && str[0] != LOGICAL_NOT_CH && str[0] != BITWISE_NOT_CH && !(str[0] == ID_WRAP_LEFT_CH && str.find(ID_WRAP_RIGHT) < str.length() - 1) && (!BASE_2_10 || (str[0] != EXP_CH && str[0] != EXP2_CH))) {
2162 return parseNumber(mstruct, str, po);
2163 } else {
2164 return parseOperators(mstruct, str, po);
2165 }
2166 }
2167 return false;
2168 }
parseAdd(string & str,MathStructure * mstruct,const ParseOptions & po,MathOperation s,bool append)2169 bool Calculator::parseAdd(string &str, MathStructure *mstruct, const ParseOptions &po, MathOperation s, bool append) {
2170 if(str.length() > 0) {
2171 size_t i;
2172 if(BASE_2_10) {
2173 i = str.find_first_of(SPACE MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS PARENTHESISS EXPS ID_WRAP_LEFT, 1);
2174 } else {
2175 i = str.find_first_of(SPACE MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS PARENTHESISS ID_WRAP_LEFT, 1);
2176 }
2177 if(i == string::npos && str[0] != LOGICAL_NOT_CH && str[0] != BITWISE_NOT_CH && !(str[0] == ID_WRAP_LEFT_CH && str.find(ID_WRAP_RIGHT) < str.length() - 1) && (!BASE_2_10 || (str[0] != EXP_CH && str[0] != EXP2_CH))) {
2178 if(s == OPERATION_EXP10 && po.read_precision == ALWAYS_READ_PRECISION) {
2179 ParseOptions po2 = po;
2180 po2.read_precision = READ_PRECISION_WHEN_DECIMALS;
2181 MathStructure *mstruct2 = new MathStructure();
2182 if(!parseNumber(mstruct2, str, po2)) {
2183 mstruct2->unref();
2184 return false;
2185 }
2186 mstruct->add_nocopy(mstruct2, s, append);
2187 } else {
2188 MathStructure *mstruct2 = new MathStructure();
2189 if(!parseNumber(mstruct2, str, po)) {
2190 mstruct2->unref();
2191 return false;
2192 }
2193 if(s == OPERATION_EXP10 && !po.preserve_format && mstruct->isNumber() && mstruct2->isNumber()) {
2194 mstruct->number().exp10(mstruct2->number());
2195 mstruct->numberUpdated();
2196 mstruct->mergePrecision(*mstruct2);
2197 } else if(s == OPERATION_DIVIDE && po.preserve_format) {
2198 mstruct->transform_nocopy(STRUCT_DIVISION, mstruct2);
2199 } else if(s == OPERATION_SUBTRACT && po.preserve_format) {
2200 mstruct2->transform(STRUCT_NEGATE);
2201 mstruct->add_nocopy(mstruct2, OPERATION_ADD, append);
2202 } else {
2203 mstruct->add_nocopy(mstruct2, s, append);
2204 }
2205 }
2206 } else {
2207 MathStructure *mstruct2 = new MathStructure();
2208 if(!parseOperators(mstruct2, str, po)) {
2209 mstruct2->unref();
2210 return false;
2211 }
2212 if(s == OPERATION_DIVIDE && po.preserve_format) {
2213 mstruct->transform_nocopy(STRUCT_DIVISION, mstruct2);
2214 } else if(s == OPERATION_SUBTRACT && po.preserve_format) {
2215 mstruct2->transform(STRUCT_NEGATE);
2216 mstruct->add_nocopy(mstruct2, OPERATION_ADD, append);
2217 } else {
2218 mstruct->add_nocopy(mstruct2, s, append);
2219 }
2220 }
2221 }
2222 return true;
2223 }
2224
get_out_of_negate(MathStructure & mstruct,int * i_neg)2225 MathStructure *get_out_of_negate(MathStructure &mstruct, int *i_neg) {
2226 if(mstruct.isNegate() || (mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isMinusOne())) {
2227 if(i_neg) (*i_neg)++;
2228 return get_out_of_negate(mstruct.last(), i_neg);
2229 }
2230 return &mstruct;
2231 }
2232
parseOperators(MathStructure * mstruct,string str,const ParseOptions & po)2233 bool Calculator::parseOperators(MathStructure *mstruct, string str, const ParseOptions &po) {
2234 string save_str = str;
2235 mstruct->clear();
2236 size_t i = 0, i2 = 0, i3 = 0;
2237 string str2, str3;
2238 bool extended_roman = (po.base == BASE_ROMAN_NUMERALS && (i = str.find("|")) != string::npos && i + 1 < str.length() && str[i + 1] == RIGHT_PARENTHESIS_CH);
2239 while(!extended_roman) {
2240 //find first right parenthesis and then the last left parenthesis before
2241 i2 = str.find(RIGHT_PARENTHESIS_CH);
2242 if(i2 == string::npos) {
2243 i = str.rfind(LEFT_PARENTHESIS_CH);
2244 if(i == string::npos) {
2245 //if no parenthesis break
2246 break;
2247 } else {
2248 //right parenthesis missing -- append
2249 str += RIGHT_PARENTHESIS_CH;
2250 i2 = str.length() - 1;
2251 }
2252 } else {
2253 if(i2 > 0) {
2254 i = str.rfind(LEFT_PARENTHESIS_CH, i2 - 1);
2255 } else {
2256 i = string::npos;
2257 }
2258 if(i == string::npos) {
2259 //left parenthesis missing -- prepend
2260 str.insert(str.begin(), 1, LEFT_PARENTHESIS_CH);
2261 i = 0;
2262 i2++;
2263 }
2264 }
2265 while(true) {
2266 //remove unnecessary double parenthesis and the found parenthesis
2267 if(i > 0 && i2 + 1 < str.length() && str[i - 1] == LEFT_PARENTHESIS_CH && str[i2 + 1] == RIGHT_PARENTHESIS_CH) {
2268 str.erase(str.begin() + (i - 1));
2269 i--; i2--;
2270 str.erase(str.begin() + (i2 + 1));
2271 } else {
2272 break;
2273 }
2274 }
2275 if(i > 0 && is_not_in(MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS PARENTHESISS SPACE, str[i - 1]) && (!BASE_2_10 || (str[i - 1] != EXP_CH && str[i - 1] != EXP2_CH))) {
2276 if(po.parsing_mode == PARSING_MODE_RPN) {
2277 str.insert(i2 + 1, MULTIPLICATION);
2278 str.insert(i, SPACE);
2279 i++;
2280 i2++;
2281 }
2282 }
2283 if(i2 + 1 < str.length() && is_not_in(MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS PARENTHESISS SPACE, str[i2 + 1]) && (!BASE_2_10 || (str[i2 + 1] != EXP_CH && str[i2 + 1] != EXP2_CH))) {
2284 if(po.parsing_mode == PARSING_MODE_RPN) {
2285 i3 = str.find(SPACE, i2 + 1);
2286 if(i3 == string::npos) {
2287 str += MULTIPLICATION;
2288 } else {
2289 str.replace(i3, 1, MULTIPLICATION);
2290 }
2291 str.insert(i2 + 1, SPACE);
2292 }
2293 }
2294 if(po.parsing_mode == PARSING_MODE_RPN && i > 0 && i2 + 1 == str.length() && is_not_in(PARENTHESISS SPACE, str[i - 1])) {
2295 str += MULTIPLICATION_CH;
2296 }
2297 str2 = str.substr(i + 1, i2 - (i + 1));
2298 MathStructure *mstruct2 = new MathStructure();
2299 if(str2.empty()) {
2300 error(false, _("Empty expression in parentheses interpreted as zero."), NULL);
2301 } else {
2302 parseOperators(mstruct2, str2, po);
2303 }
2304 mstruct2->setInParentheses(true);
2305 str2 = ID_WRAP_LEFT;
2306 str2 += i2s(addId(mstruct2));
2307 str2 += ID_WRAP_RIGHT;
2308 str.replace(i, i2 - i + 1, str2);
2309 mstruct->clear();
2310 }
2311 bool b_abs_or = false, b_bit_or = false;
2312 i = 0;
2313 if(po.parsing_mode != PARSING_MODE_RPN) {
2314 // determine if | is used for absolute value
2315 while(po.base != BASE_ROMAN_NUMERALS && (i = str.find('|', i)) != string::npos) {
2316 if(i == 0 || i == str.length() - 1 || is_in(OPERATORS INTERNAL_OPERATORS SPACE, str[i - 1])) {b_abs_or = true; break;}
2317 if(str[i + 1] == '|') {
2318 if(i == str.length() - 2) {b_abs_or = true; break;}
2319 if(b_bit_or) {
2320 b_abs_or = true;
2321 break;
2322 }
2323 i += 2;
2324 } else {
2325 b_bit_or = true;
2326 i++;
2327 }
2328 }
2329 }
2330 if(b_abs_or) {
2331 // |x|=abs(x)
2332 while((i = str.find('|', 0)) != string::npos && i + 1 != str.length()) {
2333 if(str[i + 1] == '|') {
2334 size_t depth = 1;
2335 i2 = i;
2336 while((i2 = str.find("||", i2 + 2)) != string::npos) {
2337 if(is_in(OPERATORS INTERNAL_OPERATORS, str[i2 - 1])) depth++;
2338 else depth--;
2339 if(depth == 0) break;
2340 }
2341 if(i2 == string::npos) str2 = str.substr(i + 2);
2342 else str2 = str.substr(i + 2, i2 - (i + 2));
2343 str3 = ID_WRAP_LEFT;
2344 str3 += i2s(parseAddId(f_magnitude, str2, po));
2345 str3 += ID_WRAP_RIGHT;
2346 if(i2 == string::npos) str.replace(i, str.length() - i, str3);
2347 else str.replace(i, i2 - i + 2, str3);
2348 } else {
2349 size_t depth = 1;
2350 i2 = i;
2351 while((i2 = str.find('|', i2 + 1)) != string::npos) {
2352 if(is_in(OPERATORS INTERNAL_OPERATORS, str[i2 - 1])) depth++;
2353 else depth--;
2354 if(depth == 0) break;
2355 }
2356 if(i2 == string::npos) str2 = str.substr(i + 1);
2357 else str2 = str.substr(i + 1, i2 - (i + 1));
2358 str3 = ID_WRAP_LEFT;
2359 str3 += i2s(parseAddId(f_abs, str2, po));
2360 str3 += ID_WRAP_RIGHT;
2361 if(i2 == string::npos) str.replace(i, str.length() - i, str3);
2362 else str.replace(i, i2 - i + 1, str3);
2363 }
2364 }
2365 }
2366 if(po.parsing_mode == PARSING_MODE_RPN) {
2367 // parse operators with RPN syntax
2368 i = 0;
2369 i3 = 0;
2370 ParseOptions po2 = po;
2371 po2.rpn = false;
2372 po2.parsing_mode = PARSING_MODE_CONVENTIONAL;
2373 vector<MathStructure*> mstack;
2374 bool b = false;
2375 char last_operator = 0;
2376 char last_operator2 = 0;
2377 while(true) {
2378 i = str.find_first_of(OPERATORS "\a%\x1c" SPACE "\\", i3 + 1);
2379 if(i == string::npos) {
2380 if(!b) {
2381 parseAdd(str, mstruct, po2);
2382 return true;
2383 }
2384 if(i3 != 0) {
2385 str2 = str.substr(i3 + 1, str.length() - i3 - 1);
2386 } else {
2387 str2 = str.substr(i3, str.length() - i3);
2388 }
2389 remove_blank_ends(str2);
2390 if(!str2.empty()) {
2391 error(false, _("RPN syntax error. Values left at the end of the RPN expression."), NULL);
2392 } else if(mstack.size() > 1) {
2393 if(last_operator == 0 && mstack.size() > 1) {
2394 error(false, _("Unused stack values."), NULL);
2395 } else {
2396 while(mstack.size() > 1) {
2397 switch(last_operator) {
2398 case PLUS_CH: {
2399 mstack[mstack.size() - 2]->add_nocopy(mstack.back());
2400 mstack.pop_back();
2401 break;
2402 }
2403 case MINUS_CH: {
2404 if(po.preserve_format) {
2405 mstack.back()->transform(STRUCT_NEGATE);
2406 mstack[mstack.size() - 2]->add_nocopy(mstack.back());
2407 } else {
2408 mstack[mstack.size() - 2]->subtract_nocopy(mstack.back());
2409 }
2410 mstack.pop_back();
2411 break;
2412 }
2413 case MULTIPLICATION_CH: {
2414 mstack[mstack.size() - 2]->multiply_nocopy(mstack.back());
2415 mstack.pop_back();
2416 break;
2417 }
2418 case DIVISION_CH: {
2419 if(po.preserve_format) {
2420 mstack[mstack.size() - 2]->transform_nocopy(STRUCT_DIVISION, mstack.back());
2421 } else {
2422 mstack[mstack.size() - 2]->divide_nocopy(mstack.back());
2423 }
2424 mstack.pop_back();
2425 break;
2426 }
2427 case POWER_CH: {
2428 mstack[mstack.size() - 2]->raise_nocopy(mstack.back());
2429 mstack.pop_back();
2430 break;
2431 }
2432 case AND_CH: {
2433 mstack[mstack.size() - 2]->transform_nocopy(STRUCT_BITWISE_AND, mstack.back());
2434 mstack.pop_back();
2435 break;
2436 }
2437 case OR_CH: {
2438 mstack[mstack.size() - 2]->transform_nocopy(STRUCT_BITWISE_OR, mstack.back());
2439 mstack.pop_back();
2440 break;
2441 }
2442 case GREATER_CH: {
2443 if(last_operator2 == GREATER_CH) {
2444 if(po.preserve_format) mstack.back()->transform(STRUCT_NEGATE);
2445 else mstack.back()->negate();
2446 mstack[mstack.size() - 2]->transform(f_shift);
2447 mstack[mstack.size() - 2]->addChild_nocopy(mstack.back());
2448 mstack[mstack.size() - 2]->addChild(m_one);
2449 } else if(last_operator2 == EQUALS_CH) {
2450 mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_EQUALS_GREATER);
2451 } else {
2452 mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_GREATER);
2453 }
2454 mstack.pop_back();
2455 break;
2456 }
2457 case LESS_CH: {
2458 if(last_operator2 == LESS_CH) {
2459 mstack[mstack.size() - 2]->transform(f_shift);
2460 mstack[mstack.size() - 2]->addChild_nocopy(mstack.back());
2461 mstack[mstack.size() - 2]->addChild(m_one);
2462 } else if(last_operator2 == EQUALS_CH) {
2463 mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_EQUALS_LESS);
2464 } else {
2465 mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_LESS);
2466 }
2467 mstack.pop_back();
2468 break;
2469 }
2470 case NOT_CH: {
2471 mstack.back()->transform(STRUCT_LOGICAL_NOT);
2472 break;
2473 }
2474 case EQUALS_CH: {
2475 if(last_operator2 == NOT_CH) {
2476 mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_NOT_EQUALS);
2477 } else {
2478 mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_EQUALS);
2479 }
2480 mstack.pop_back();
2481 break;
2482 }
2483 case BITWISE_NOT_CH: {
2484 mstack.back()->transform(STRUCT_BITWISE_NOT);
2485 error(false, _("Unused stack values."), NULL);
2486 break;
2487 }
2488 case '\x1c': {
2489 if(po.angle_unit != ANGLE_UNIT_NONE && po.angle_unit != ANGLE_UNIT_RADIANS && mstack.back()->contains(getRadUnit(), false, true, true) <= 0 && mstack.back()->contains(getGraUnit(), false, true, true) <= 0 && mstack.back()->contains(getDegUnit(), false, true, true) <= 0) {
2490 switch(po.angle_unit) {
2491 case ANGLE_UNIT_DEGREES: {mstack.back()->multiply(getDegUnit()); break;}
2492 case ANGLE_UNIT_GRADIANS: {mstack.back()->multiply(getGraUnit()); break;}
2493 default: {}
2494 }
2495 }
2496 mstack.back()->transform(priv->f_cis);
2497 mstack[mstack.size() - 2]->transform_nocopy(STRUCT_MULTIPLICATION, mstack.back());
2498 mstack.pop_back();
2499 break;
2500 }
2501 case '\a': {
2502 mstack[mstack.size() - 2]->transform_nocopy(STRUCT_BITWISE_XOR, mstack.back());
2503 mstack.pop_back();
2504 break;
2505 }
2506 case '%': {
2507 if(last_operator2 == '%') {
2508 mstack[mstack.size() - 2]->transform(f_mod);
2509 } else {
2510 mstack[mstack.size() - 2]->transform(f_rem);
2511 }
2512 mstack[mstack.size() - 2]->addChild_nocopy(mstack.back());
2513 mstack.pop_back();
2514 break;
2515 }
2516 case '\\': {
2517 if(po.preserve_format) {
2518 mstack[mstack.size() - 2]->transform_nocopy(STRUCT_DIVISION, mstack.back());
2519 } else {
2520 mstack[mstack.size() - 2]->divide_nocopy(mstack.back());
2521 }
2522 mstack[mstack.size() - 2]->transform(f_trunc);
2523 mstack.pop_back();
2524 break;
2525 }
2526 default: {
2527 error(true, _("RPN syntax error. Operator '%c' not supported."), last_operator, NULL);
2528 mstack.pop_back();
2529 break;
2530 }
2531 }
2532 if(last_operator == NOT_CH || last_operator == BITWISE_NOT_CH) break;
2533 }
2534 }
2535 } else if(mstack.size() == 1) {
2536 if(last_operator == NOT_CH) {
2537 mstack.back()->transform(STRUCT_LOGICAL_NOT);
2538 } else if(last_operator == BITWISE_NOT_CH) {
2539 mstack.back()->transform(STRUCT_BITWISE_NOT);
2540 }
2541 }
2542 mstruct->set_nocopy(*mstack.back());
2543 while(!mstack.empty()) {
2544 mstack.back()->unref();
2545 mstack.pop_back();
2546 }
2547 return true;
2548 }
2549 b = true;
2550 if(i3 != 0) {
2551 str2 = str.substr(i3 + 1, i - i3 - 1);
2552 } else {
2553 str2 = str.substr(i3, i - i3);
2554 }
2555 remove_blank_ends(str2);
2556 if(!str2.empty()) {
2557 mstack.push_back(new MathStructure());
2558 if((str[i] == GREATER_CH || str[i] == LESS_CH) && po2.base < 10 && po2.base >= 2 && i + 1 < str.length() && str[i + 1] == str[i] && str2.find_first_not_of(NUMBERS SPACE PLUS MINUS) == string::npos) {
2559 for(i = 0; i < str2.size(); i++) {
2560 if(str2[i] >= '0' && str2[i] <= '9' && po.base <= str2[i] - '0') {
2561 po2.base = BASE_DECIMAL;
2562 break;
2563 }
2564 }
2565 parseAdd(str2, mstack.back(), po2);
2566 po2.base = po.base;
2567 } else {
2568 parseAdd(str2, mstack.back(), po2);
2569 }
2570 }
2571 if(str[i] != SPACE_CH) {
2572 if(mstack.size() < 1) {
2573 error(true, _("RPN syntax error. Stack is empty."), NULL);
2574 } else if(mstack.size() < 2) {
2575 if(str[i] == NOT_CH) {
2576 mstack.back()->transform(STRUCT_LOGICAL_NOT);
2577 } else if(str[i] == MINUS_CH) {
2578 if(po.preserve_format) mstack.back()->transform(STRUCT_NEGATE);
2579 else mstack.back()->negate();
2580 } else if(str[i] == BITWISE_NOT_CH) {
2581 mstack.back()->transform(STRUCT_BITWISE_NOT);
2582 } else if(str[i] == '\x1c') {
2583 if(po.angle_unit != ANGLE_UNIT_NONE && po.angle_unit != ANGLE_UNIT_RADIANS && mstack.back()->contains(getRadUnit(), false, true, true) <= 0 && mstack.back()->contains(getGraUnit(), false, true, true) <= 0 && mstack.back()->contains(getDegUnit(), false, true, true) <= 0) {
2584 switch(po.angle_unit) {
2585 case ANGLE_UNIT_DEGREES: {mstack.back()->multiply(getDegUnit()); break;}
2586 case ANGLE_UNIT_GRADIANS: {mstack.back()->multiply(getGraUnit()); break;}
2587 default: {}
2588 }
2589 }
2590 mstack.back()->transform(priv->f_cis);
2591 mstack.back()->multiply(m_one);
2592 if(po.preserve_format) mstack.back()->swapChildren(1, 2);
2593 } else {
2594 error(false, _("RPN syntax error. Operator ignored as there where only one stack value."), NULL);
2595 }
2596 } else {
2597 switch(str[i]) {
2598 case PLUS_CH: {
2599 mstack[mstack.size() - 2]->add_nocopy(mstack.back());
2600 mstack.pop_back();
2601 break;
2602 }
2603 case MINUS_CH: {
2604 if(po.preserve_format) {
2605 mstack.back()->transform(STRUCT_NEGATE);
2606 mstack[mstack.size() - 2]->add_nocopy(mstack.back());
2607 } else {
2608 mstack[mstack.size() - 2]->subtract_nocopy(mstack.back());
2609 }
2610 mstack.pop_back();
2611 break;
2612 }
2613 case MULTIPLICATION_CH: {
2614 mstack[mstack.size() - 2]->multiply_nocopy(mstack.back());
2615 mstack.pop_back();
2616 break;
2617 }
2618 case DIVISION_CH: {
2619 if(po.preserve_format) {
2620 mstack[mstack.size() - 2]->transform_nocopy(STRUCT_DIVISION, mstack.back());
2621 } else {
2622 mstack[mstack.size() - 2]->divide_nocopy(mstack.back());
2623 }
2624 mstack.pop_back();
2625 break;
2626 }
2627 case POWER_CH: {
2628 mstack[mstack.size() - 2]->raise_nocopy(mstack.back());
2629 mstack.pop_back();
2630 break;
2631 }
2632 case AND_CH: {
2633 if(i + 1 < str.length() && str[i + 1] == AND_CH) {
2634 mstack[mstack.size() - 2]->transform_nocopy(STRUCT_LOGICAL_AND, mstack.back());
2635 } else {
2636 mstack[mstack.size() - 2]->transform_nocopy(STRUCT_BITWISE_AND, mstack.back());
2637 }
2638 mstack.pop_back();
2639 break;
2640 }
2641 case OR_CH: {
2642 if(i + 1 < str.length() && str[i + 1] == OR_CH) {
2643 mstack[mstack.size() - 2]->transform_nocopy(STRUCT_LOGICAL_OR, mstack.back());
2644 } else {
2645 mstack[mstack.size() - 2]->transform_nocopy(STRUCT_BITWISE_OR, mstack.back());
2646 }
2647 mstack.pop_back();
2648 break;
2649 }
2650 case GREATER_CH: {
2651 if(i + 1 < str.length() && str[i + 1] == GREATER_CH) {
2652 if(po.preserve_format) mstack.back()->transform(STRUCT_NEGATE);
2653 else mstack.back()->negate();
2654 mstack[mstack.size() - 2]->transform(f_shift);
2655 mstack[mstack.size() - 2]->addChild_nocopy(mstack.back());
2656 mstack[mstack.size() - 2]->addChild(m_one);
2657 } else if(i + 1 < str.length() && str[i + 1] == EQUALS_CH) {
2658 mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_EQUALS_GREATER);
2659 } else {
2660 mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_GREATER);
2661 }
2662 mstack.pop_back();
2663 break;
2664 }
2665 case LESS_CH: {
2666 if(i + 1 < str.length() && str[i + 1] == LESS_CH) {
2667 mstack[mstack.size() - 2]->transform(f_shift);
2668 mstack[mstack.size() - 2]->addChild_nocopy(mstack.back());
2669 mstack[mstack.size() - 2]->addChild(m_one);
2670 } else if(i + 1 < str.length() && str[i + 1] == EQUALS_CH) {
2671 mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_EQUALS_LESS);
2672 } else {
2673 mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_LESS);
2674 }
2675 mstack.pop_back();
2676 break;
2677 }
2678 case NOT_CH: {
2679 mstack.back()->transform(STRUCT_LOGICAL_NOT);
2680 break;
2681 }
2682 case EQUALS_CH: {
2683 if(i + 1 < str.length() && str[i + 1] == NOT_CH) {
2684 mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_NOT_EQUALS);
2685 mstack.pop_back();
2686 } else {
2687 mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_EQUALS);
2688 }
2689 mstack.pop_back();
2690 break;
2691 }
2692 case BITWISE_NOT_CH: {
2693 mstack.back()->transform(STRUCT_BITWISE_NOT);
2694 break;
2695 }
2696 case '\x1c': {
2697 if(po.angle_unit != ANGLE_UNIT_NONE && po.angle_unit != ANGLE_UNIT_RADIANS && mstack.back()->contains(getRadUnit(), false, true, true) <= 0 && mstack.back()->contains(getGraUnit(), false, true, true) <= 0 && mstack.back()->contains(getDegUnit(), false, true, true) <= 0) {
2698 switch(po.angle_unit) {
2699 case ANGLE_UNIT_DEGREES: {mstack.back()->multiply(getDegUnit()); break;}
2700 case ANGLE_UNIT_GRADIANS: {mstack.back()->multiply(getGraUnit()); break;}
2701 default: {}
2702 }
2703 }
2704 mstack.back()->transform(priv->f_cis);
2705 mstack[mstack.size() - 2]->transform_nocopy(STRUCT_MULTIPLICATION, mstack.back());
2706 mstack.pop_back();
2707 break;
2708 }
2709 case '\a': {
2710 mstack[mstack.size() - 2]->transform_nocopy(STRUCT_BITWISE_XOR, mstack.back());
2711 mstack.pop_back();
2712 break;
2713 }
2714 case '%': {
2715 if(i + 1 < str.length() && str[i + 1] == '%') {
2716 mstack[mstack.size() - 2]->transform(f_mod);
2717 } else {
2718 mstack[mstack.size() - 2]->transform(f_rem);
2719 }
2720 mstack[mstack.size() - 2]->addChild_nocopy(mstack.back());
2721 mstack.pop_back();
2722 break;
2723 }
2724 case '\\': {
2725 if(po.preserve_format) {
2726 mstack[mstack.size() - 2]->transform_nocopy(STRUCT_DIVISION, mstack.back());
2727 } else {
2728 mstack[mstack.size() - 2]->divide_nocopy(mstack.back());
2729 }
2730 mstack[mstack.size() - 2]->transform(f_trunc);
2731 mstack.pop_back();
2732 break;
2733 }
2734 default: {
2735 error(true, _("RPN syntax error. Operator '%c' not supported."), str[i], NULL);
2736 mstack.pop_back();
2737 break;
2738 }
2739 }
2740 last_operator = str[i];
2741 if(i + 1 < str.length()) last_operator2 = str[i + 1];
2742 else last_operator2 = 0;
2743 if((last_operator2 == EQUALS_CH && (last_operator == GREATER_CH || last_operator == LESS_CH || last_operator == EQUALS_CH)) || (last_operator2 == NOT_CH && last_operator == EQUALS_CH) || (last_operator == last_operator2 && (last_operator == GREATER_CH || last_operator == LESS_CH || last_operator == '%' || last_operator == AND_CH || last_operator == OR_CH))) {
2744 i++;
2745 }
2746 }
2747 }
2748 i3 = i;
2749 }
2750 }
2751 if(po.parsing_mode == PARSING_MODE_RPN) remove_blanks(str);
2752
2753 i = 0;
2754 i3 = 0;
2755
2756 // Parse && as logical and
2757 if((i = str.find(LOGICAL_AND, 1)) != string::npos && i + 2 != str.length()) {
2758 bool b = false, append = false;
2759 while(i != string::npos && i + 2 != str.length()) {
2760 str2 = str.substr(0, i);
2761 str = str.substr(i + 2, str.length() - (i + 2));
2762 if(b) {
2763 parseAdd(str2, mstruct, po, OPERATION_LOGICAL_AND, append);
2764 append = true;
2765 } else {
2766 parseAdd(str2, mstruct, po);
2767 b = true;
2768 }
2769 i = str.find(LOGICAL_AND, 1);
2770 }
2771 if(b) {
2772 parseAdd(str, mstruct, po, OPERATION_LOGICAL_AND, append);
2773 } else {
2774 parseAdd(str, mstruct, po);
2775 }
2776 return true;
2777 }
2778 // Parse || as logical or
2779 if(po.base != BASE_ROMAN_NUMERALS && (i = str.find(LOGICAL_OR, 1)) != string::npos && i + 2 != str.length()) {
2780 bool b = false, append = false;
2781 while(i != string::npos && i + 2 != str.length()) {
2782 str2 = str.substr(0, i);
2783 str = str.substr(i + 2, str.length() - (i + 2));
2784 if(b) {
2785 parseAdd(str2, mstruct, po, OPERATION_LOGICAL_OR, append);
2786 append = true;
2787 } else {
2788 parseAdd(str2, mstruct, po);
2789 b = true;
2790 }
2791 i = str.find(LOGICAL_OR, 1);
2792 }
2793 if(b) {
2794 parseAdd(str, mstruct, po, OPERATION_LOGICAL_OR, append);
2795 } else {
2796 parseAdd(str, mstruct, po);
2797 }
2798 return true;
2799 }
2800 /*if((i = str.find(LOGICAL_XOR, 1)) != string::npos && i + strlen(LOGICAL_XOR) != str.length()) {
2801 str2 = str.substr(0, i);
2802 str = str.substr(i + strlen(LOGICAL_XOR), str.length() - (i + strlen(LOGICAL_XOR)));
2803 parseAdd(str2, mstruct, po);
2804 parseAdd(str, mstruct, po, OPERATION_LOGICAL_XOR);
2805 return true;
2806 }*/
2807 // Parse | as bitwise or
2808 if(po.parsing_mode != PARSING_MODE_CHAIN && po.base != BASE_ROMAN_NUMERALS && (i = str.find(BITWISE_OR, 1)) != string::npos && i + 1 != str.length()) {
2809 bool b = false, append = false;
2810 while(i != string::npos && i + 1 != str.length()) {
2811 str2 = str.substr(0, i);
2812 str = str.substr(i + 1, str.length() - (i + 1));
2813 if(b) {
2814 parseAdd(str2, mstruct, po, OPERATION_BITWISE_OR, append);
2815 append = true;
2816 } else {
2817 parseAdd(str2, mstruct, po);
2818 b = true;
2819 }
2820 i = str.find(BITWISE_OR, 1);
2821 }
2822 if(b) {
2823 parseAdd(str, mstruct, po, OPERATION_BITWISE_OR, append);
2824 } else {
2825 parseAdd(str, mstruct, po);
2826 }
2827 return true;
2828 }
2829 // Parse \a (internal single character substitution for xor operators) as bitwise xor
2830 if(po.parsing_mode != PARSING_MODE_CHAIN && (i = str.find('\a', 1)) != string::npos && i + 1 != str.length()) {
2831 str2 = str.substr(0, i);
2832 str = str.substr(i + 1, str.length() - (i + 1));
2833 parseAdd(str2, mstruct, po);
2834 parseAdd(str, mstruct, po, OPERATION_BITWISE_XOR);
2835 return true;
2836 }
2837 // Parse & as bitwise and
2838 if(po.parsing_mode != PARSING_MODE_CHAIN && (i = str.find(BITWISE_AND, 1)) != string::npos && i + 1 != str.length()) {
2839 bool b = false, append = false;
2840 while(i != string::npos && i + 1 != str.length()) {
2841 str2 = str.substr(0, i);
2842 str = str.substr(i + 1, str.length() - (i + 1));
2843 if(b) {
2844 parseAdd(str2, mstruct, po, OPERATION_BITWISE_AND, append);
2845 append = true;
2846 } else {
2847 parseAdd(str2, mstruct, po);
2848 b = true;
2849 }
2850 i = str.find(BITWISE_AND, 1);
2851 }
2852 if(b) {
2853 parseAdd(str, mstruct, po, OPERATION_BITWISE_AND, append);
2854 } else {
2855 parseAdd(str, mstruct, po);
2856 }
2857 return true;
2858 }
2859 // Parse comparison operators (>, >=, <, <=, =, !=)
2860 if((i = str.find_first_of(LESS GREATER EQUALS NOT, 0)) != string::npos) {
2861 while(i != string::npos && ((str[i] == LOGICAL_NOT_CH && (i + 1 >= str.length() || str[i + 1] != EQUALS_CH)) || (str[i] == LESS_CH && i + 1 < str.length() && str[i + 1] == LESS_CH) || (str[i] == GREATER_CH && i + 1 < str.length() && str[i + 1] == GREATER_CH))) {
2862 i = str.find_first_of(LESS GREATER NOT EQUALS, i + 2);
2863 }
2864 }
2865 if(i != string::npos) {
2866 bool b = false;
2867 bool c = false;
2868 while(i != string::npos && str[i] == NOT_CH && str.length() > i + 1 && str[i + 1] == NOT_CH) {
2869 i++;
2870 if(i + 1 == str.length()) {
2871 c = true;
2872 }
2873 }
2874 MathOperation s = OPERATION_ADD;
2875 while(!c) {
2876 while(i != string::npos && ((str[i] == LOGICAL_NOT_CH && (i + 1 >= str.length() || str[i + 1] != EQUALS_CH)) || (str[i] == LESS_CH && i + 1 < str.length() && str[i + 1] == LESS_CH) || (str[i] == GREATER_CH && i + 1 < str.length() && str[i + 1] == GREATER_CH))) {
2877 i = str.find_first_of(LESS GREATER NOT EQUALS, i + 2);
2878 while(i != string::npos && str[i] == NOT_CH && str.length() > i + 1 && str[i + 1] == NOT_CH) {
2879 i++;
2880 if(i + 1 == str.length()) {
2881 i = string::npos;
2882 }
2883 }
2884 }
2885 if(i == string::npos) {
2886 str2 = str.substr(0, str.length());
2887 } else {
2888 str2 = str.substr(0, i);
2889 }
2890 if(b) {
2891 switch(i3) {
2892 case EQUALS_CH: {s = OPERATION_EQUALS; break;}
2893 case GREATER_CH: {s = OPERATION_GREATER; break;}
2894 case LESS_CH: {s = OPERATION_LESS; break;}
2895 case GREATER_CH * EQUALS_CH: {s = OPERATION_EQUALS_GREATER; break;}
2896 case LESS_CH * EQUALS_CH: {s = OPERATION_EQUALS_LESS; break;}
2897 case GREATER_CH * LESS_CH: {s = OPERATION_NOT_EQUALS; break;}
2898 }
2899 parseAdd(str2, mstruct, po, s);
2900 }
2901 if(i == string::npos) {
2902 return true;
2903 }
2904 if(!b) {
2905 parseAdd(str2, mstruct, po);
2906 b = true;
2907 }
2908 if(str.length() > i + 1 && is_in(LESS GREATER NOT EQUALS, str[i + 1])) {
2909 if(str[i] == str[i + 1]) {
2910 i3 = str[i];
2911 } else {
2912 i3 = str[i] * str[i + 1];
2913 if(i3 == NOT_CH * EQUALS_CH) {
2914 i3 = GREATER_CH * LESS_CH;
2915 } else if(i3 == NOT_CH * LESS_CH) {
2916 i3 = GREATER_CH;
2917 } else if(i3 == NOT_CH * GREATER_CH) {
2918 i3 = LESS_CH;
2919 }
2920 }
2921 i++;
2922 } else {
2923 i3 = str[i];
2924 }
2925 str = str.substr(i + 1, str.length() - (i + 1));
2926 i = str.find_first_of(LESS GREATER NOT EQUALS, 0);
2927 while(i != string::npos && str[i] == NOT_CH && str.length() > i + 1 && str[i + 1] == NOT_CH) {
2928 i++;
2929 if(i + 1 == str.length()) {
2930 i = string::npos;
2931 }
2932 }
2933 }
2934 }
2935
2936 if(po.parsing_mode == PARSING_MODE_CHAIN) {
2937 char c_operator = 0, prev_operator = 0;
2938 bool append = false;
2939 while(true) {
2940 i3 = str.find_first_not_of(OPERATORS INTERNAL_OPERATORS, 0);
2941 if(i3 == string::npos) i = string::npos;
2942 else i = str.find_first_of(PLUS MINUS MULTIPLICATION DIVISION POWER BITWISE_AND BITWISE_OR "<>%\x1c", i3);
2943 i3 = str.find_first_not_of(OPERATORS INTERNAL_OPERATORS, i);
2944 if(i3 == string::npos) i = string::npos;
2945 if(c_operator == 0) {
2946 if(i == string::npos) break;
2947 str2 = str.substr(0, i);
2948 parseAdd(str2, mstruct, po);
2949 } else {
2950 if(i == string::npos) str2 = str;
2951 else str2 = str.substr(0, i);
2952 append = c_operator == prev_operator || ((c_operator == DIVISION_CH || c_operator == MULTIPLICATION_CH || c_operator == '%') && (prev_operator == DIVISION_CH || prev_operator == MULTIPLICATION_CH || prev_operator == '%')) || ((c_operator == PLUS_CH || c_operator == MINUS_CH) && (prev_operator == PLUS_CH || prev_operator == MINUS_CH));
2953 switch(c_operator) {
2954 case MINUS_CH: {}
2955 case PLUS_CH: {
2956 if(parseAdd(str2, mstruct, po, c_operator == PLUS_CH ? OPERATION_ADD : OPERATION_SUBTRACT, append)) {
2957 int i_neg = 0;
2958 MathStructure *mstruct_a = get_out_of_negate(mstruct->last(), &i_neg);
2959 MathStructure *mstruct_b = mstruct_a;
2960 if(mstruct_a->isMultiplication() && mstruct_a->size() >= 2) mstruct_b = &mstruct_a->last();
2961 if(mstruct_b->isVariable() && (mstruct_b->variable() == v_percent || mstruct_b->variable() == v_permille || mstruct_b->variable() == v_permyriad)) {
2962 Variable *v = mstruct_b->variable();
2963 bool b_neg = (i_neg % 2 == 1);
2964 while(i_neg > 0) {
2965 mstruct->last().setToChild(mstruct->last().size());
2966 i_neg--;
2967 }
2968 if(mstruct->last().isVariable()) {
2969 mstruct->last().multiply(m_one);
2970 mstruct->last().swapChildren(1, 2);
2971 }
2972 if(mstruct->last().size() > 2) {
2973 mstruct->last().delChild(mstruct->last().size());
2974 mstruct->last().multiply(v);
2975 }
2976 if(mstruct->last()[0].isNumber()) {
2977 if(b_neg) mstruct->last()[0].number().negate();
2978 if(v == v_percent) mstruct->last()[0].number().add(100);
2979 else if(v == v_permille) mstruct->last()[0].number().add(1000);
2980 else mstruct->last()[0].number().add(10000);
2981 } else {
2982 if(b_neg && po.preserve_format) mstruct->last()[0].transform(STRUCT_NEGATE);
2983 else if(b_neg) mstruct->last()[0].negate();
2984 if(v == v_percent) mstruct->last()[0] += Number(100, 1);
2985 else if(v == v_permille) mstruct->last()[0] += Number(1000, 1);
2986 else mstruct->last()[0] += Number(10000, 1);
2987 mstruct->last()[0].swapChildren(1, 2);
2988 }
2989 if(mstruct->size() == 2) {
2990 mstruct->setType(STRUCT_MULTIPLICATION);
2991 } else {
2992 MathStructure *mpercent = &mstruct->last();
2993 mpercent->ref();
2994 mstruct->delChild(mstruct->size());
2995 mstruct->multiply_nocopy(mpercent);
2996 }
2997 }
2998 }
2999 break;
3000 }
3001 case MULTIPLICATION_CH: {
3002 parseAdd(str2, mstruct, po, OPERATION_MULTIPLY, append);
3003 break;
3004 }
3005 case DIVISION_CH: {
3006 if(str2[0] == DIVISION_CH) {
3007 str2.erase(0, 1);
3008 parseAdd(str2, mstruct, po, OPERATION_DIVIDE, append);
3009 mstruct->transform(f_trunc);
3010 } else {
3011 parseAdd(str2, mstruct, po, OPERATION_DIVIDE, append);
3012 }
3013 break;
3014 }
3015 case '%': {
3016 if(str2[0] == '%') {
3017 str2.erase(0, 1);
3018 MathStructure *mstruct2 = new MathStructure();
3019 parseAdd(str2, mstruct2, po);
3020 mstruct->transform(f_mod);
3021 mstruct->addChild_nocopy(mstruct2);
3022 } else {
3023 MathStructure *mstruct2 = new MathStructure();
3024 parseAdd(str2, mstruct2, po);
3025 mstruct->transform(f_rem);
3026 mstruct->addChild_nocopy(mstruct2);
3027 }
3028 break;
3029 }
3030 case POWER_CH: {
3031 parseAdd(str2, mstruct, po, OPERATION_RAISE);
3032 break;
3033 }
3034 case AND_CH: {
3035 parseAdd(str2, mstruct, po, OPERATION_BITWISE_AND, append);
3036 break;
3037 }
3038 case OR_CH: {
3039 parseAdd(str2, mstruct, po, OPERATION_BITWISE_OR, append);
3040 break;
3041 }
3042 case '<': {}
3043 case '>': {
3044 MathStructure mstruct2;
3045 bool b_neg = (c_operator == '>');
3046 str2.erase(0, 1);
3047 bool b = false;
3048 if(po.base < 10 && po.base >= 2 && str2.find_first_not_of(NUMBERS SPACE PLUS MINUS) == string::npos) {
3049 for(i = 0; i < str2.size(); i++) {
3050 if(str2[i] >= '0' && str2[i] <= '9' && po.base <= str2[i] - '0') {
3051 ParseOptions po2 = po;
3052 po2.base = BASE_DECIMAL;
3053 parseAdd(str2, &mstruct2, po2);
3054 if(b_neg) {
3055 if(po.preserve_format) mstruct2.transform(STRUCT_NEGATE);
3056 else mstruct2.negate();
3057 }
3058 mstruct->transform(f_shift);
3059 mstruct->addChild(mstruct2);
3060 mstruct->addChild(m_one);
3061 b = true;
3062 break;
3063 }
3064 }
3065 }
3066 if(!b) {
3067 parseAdd(str2, &mstruct2, po);
3068 if(b_neg) {
3069 if(po.preserve_format) mstruct2.transform(STRUCT_NEGATE);
3070 else mstruct2.negate();
3071 }
3072 mstruct->transform(f_shift);
3073 mstruct->addChild(mstruct2);
3074 mstruct->addChild(m_one);
3075 }
3076 break;
3077 }
3078 case '\x1c': {
3079 if(parseAdd(str2, mstruct, po, OPERATION_MULTIPLY)) {
3080 if(po.angle_unit != ANGLE_UNIT_NONE && po.angle_unit != ANGLE_UNIT_RADIANS && mstruct->last().contains(getRadUnit(), false, true, true) <= 0 && mstruct->last().contains(getGraUnit(), false, true, true) <= 0 && mstruct->last().contains(getDegUnit(), false, true, true) <= 0) {
3081 switch(po.angle_unit) {
3082 case ANGLE_UNIT_DEGREES: {mstruct->last().multiply(getDegUnit()); break;}
3083 case ANGLE_UNIT_GRADIANS: {mstruct->last().multiply(getGraUnit()); break;}
3084 default: {}
3085 }
3086 }
3087 mstruct->last().transform(priv->f_cis);
3088 }
3089 break;
3090 }
3091 }
3092 }
3093 if(i == string::npos) return true;
3094 prev_operator = c_operator;
3095 c_operator = str[i];
3096 str = str.substr(i + 1);
3097 }
3098 }
3099
3100 if(po.parsing_mode != PARSING_MODE_CHAIN) {
3101
3102 // Parse << and >> as bitwise shift
3103 i = str.find(SHIFT_LEFT, 1);
3104 i2 = str.find(SHIFT_RIGHT, 1);
3105 if(i2 != string::npos && (i == string::npos || i2 < i)) i = i2;
3106 if(i != string::npos && i + 2 != str.length()) {
3107 MathStructure mstruct1, mstruct2;
3108 bool b_neg = (str[i] == '>');
3109 str2 = str.substr(0, i);
3110 str = str.substr(i + 2, str.length() - (i + 2));
3111 parseAdd(str2, &mstruct1, po);
3112 if(po.base < 10 && po.base >= 2 && str.find_first_not_of(NUMBERS SPACE PLUS MINUS) == string::npos) {
3113 for(i = 0; i < str.size(); i++) {
3114 if(str[i] >= '0' && str[i] <= '9' && po.base <= str[i] - '0') {
3115 ParseOptions po2 = po;
3116 po2.base = BASE_DECIMAL;
3117 parseAdd(str, &mstruct2, po2);
3118 if(b_neg) {
3119 if(po.preserve_format) mstruct2.transform(STRUCT_NEGATE);
3120 else mstruct2.negate();
3121 }
3122 mstruct->set(f_shift, &mstruct1, &mstruct2, &m_one, NULL);
3123 return true;
3124 }
3125 }
3126 }
3127 parseAdd(str, &mstruct2, po);
3128 if(b_neg) {
3129 if(po.preserve_format) mstruct2.transform(STRUCT_NEGATE);
3130 else mstruct2.negate();
3131 }
3132 mstruct->set(f_shift, &mstruct1, &mstruct2, &m_one, NULL);
3133 return true;
3134 }
3135
3136 // Parse addition and subtraction
3137 if((i = str.find_first_of(PLUS MINUS, 1)) != string::npos && i + 1 != str.length()) {
3138 bool b = false, c = false, append = false, do_percent = true;
3139 bool min = false;
3140 while(i != string::npos && i + 1 != str.length()) {
3141 if(is_not_in(MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS EXPS, str[i - 1])) {
3142 str2 = str.substr(0, i);
3143 if(!c && b) {
3144 bool b_add;
3145 if(min) {
3146 b_add = parseAdd(str2, mstruct, po, OPERATION_SUBTRACT, append) && mstruct->isAddition();
3147 } else {
3148 b_add = parseAdd(str2, mstruct, po, OPERATION_ADD, append) && mstruct->isAddition();
3149 }
3150 append = true;
3151 if(b_add && do_percent) {
3152 int i_neg = 0;
3153 MathStructure *mstruct_a = get_out_of_negate(mstruct->last(), &i_neg);
3154 MathStructure *mstruct_b = mstruct_a;
3155 if(mstruct_a->isMultiplication() && mstruct_a->size() >= 2) mstruct_b = &mstruct_a->last();
3156 if(mstruct_b->isVariable() && (mstruct_b->variable() == v_percent || mstruct_b->variable() == v_permille || mstruct_b->variable() == v_permyriad)) {
3157 Variable *v = mstruct_b->variable();
3158 bool b_neg = (i_neg % 2 == 1);
3159 while(i_neg > 0) {
3160 mstruct->last().setToChild(mstruct->last().size());
3161 i_neg--;
3162 }
3163 if(mstruct->last().isVariable()) {
3164 mstruct->last().multiply(m_one);
3165 mstruct->last().swapChildren(1, 2);
3166 }
3167 if(mstruct->last().size() > 2) {
3168 mstruct->last().delChild(mstruct->last().size());
3169 mstruct->last().multiply(v);
3170 }
3171 if(mstruct->last()[0].isNumber()) {
3172 if(b_neg) mstruct->last()[0].number().negate();
3173 if(v == v_percent) mstruct->last()[0].number().add(100);
3174 else if(v == v_permille) mstruct->last()[0].number().add(1000);
3175 else mstruct->last()[0].number().add(10000);
3176 } else {
3177 if(b_neg && po.preserve_format) mstruct->last()[0].transform(STRUCT_NEGATE);
3178 else if(b_neg) mstruct->last()[0].negate();
3179 if(v == v_percent) mstruct->last()[0] += Number(100, 1);
3180 else if(v == v_permille) mstruct->last()[0] += Number(1000, 1);
3181 else mstruct->last()[0] += Number(10000, 1);
3182 mstruct->last()[0].swapChildren(1, 2);
3183 }
3184 if(mstruct->size() == 2) {
3185 mstruct->setType(STRUCT_MULTIPLICATION);
3186 } else {
3187 MathStructure *mpercent = &mstruct->last();
3188 mpercent->ref();
3189 mstruct->delChild(mstruct->size());
3190 mstruct->multiply_nocopy(mpercent);
3191 }
3192 }
3193 }
3194 } else {
3195 if(!b && str2.empty()) {
3196 c = true;
3197 } else {
3198 parseAdd(str2, mstruct, po);
3199 MathStructure *mstruct_a = get_out_of_negate(*mstruct, NULL);
3200 if((str2.length() < 3 || str2[0] != ID_WRAP_LEFT_CH || str2[str2.length() - 1] != ID_WRAP_RIGHT_CH || str.find(ID_WRAP_LEFT_CH, 1) != string::npos) && mstruct_a->isMultiplication()) mstruct_a = &mstruct_a->last();
3201 if(mstruct_a->isVariable() && (mstruct_a->variable() == v_percent || mstruct_a->variable() == v_permille || mstruct_a->variable() == v_permyriad)) do_percent = false;
3202 if(c && min) {
3203 if(po.preserve_format) mstruct->transform(STRUCT_NEGATE);
3204 else mstruct->negate();
3205 }
3206 c = false;
3207 }
3208 b = true;
3209 }
3210 min = str[i] == MINUS_CH;
3211 str = str.substr(i + 1, str.length() - (i + 1));
3212 i = str.find_first_of(PLUS MINUS, 1);
3213 } else {
3214 i = str.find_first_of(PLUS MINUS, i + 1);
3215 }
3216 }
3217 if(b) {
3218 if(c) {
3219 b = parseAdd(str, mstruct, po);
3220 if(min) {
3221 if(po.preserve_format) mstruct->transform(STRUCT_NEGATE);
3222 else mstruct->negate();
3223 }
3224 return b;
3225 } else {
3226 bool b_add;
3227 if(min) {
3228 b_add = parseAdd(str, mstruct, po, OPERATION_SUBTRACT, append) && mstruct->isAddition();
3229 } else {
3230 b_add = parseAdd(str, mstruct, po, OPERATION_ADD, append) && mstruct->isAddition();
3231 }
3232 if(b_add && do_percent) {
3233 int i_neg = 0;
3234 MathStructure *mstruct_a = get_out_of_negate(mstruct->last(), &i_neg);
3235 MathStructure *mstruct_b = mstruct_a;
3236 if(mstruct_a->isMultiplication() && mstruct_a->size() >= 2) mstruct_b = &mstruct_a->last();
3237 if(mstruct_b->isVariable() && (mstruct_b->variable() == v_percent || mstruct_b->variable() == v_permille || mstruct_b->variable() == v_permyriad)) {
3238 Variable *v = mstruct_b->variable();
3239 bool b_neg = (i_neg % 2 == 1);
3240 while(i_neg > 0) {
3241 mstruct->last().setToChild(mstruct->last().size());
3242 i_neg--;
3243 }
3244 if(mstruct->last().isVariable()) {
3245 mstruct->last().multiply(m_one);
3246 mstruct->last().swapChildren(1, 2);
3247 }
3248 if(mstruct->last().size() > 2) {
3249 mstruct->last().delChild(mstruct->last().size());
3250 mstruct->last().multiply(v);
3251 }
3252 if(mstruct->last()[0].isNumber()) {
3253 if(b_neg) mstruct->last()[0].number().negate();
3254 if(v == v_percent) mstruct->last()[0].number().add(100);
3255 else if(v == v_permille) mstruct->last()[0].number().add(1000);
3256 else mstruct->last()[0].number().add(10000);
3257 } else {
3258 if(b_neg && po.preserve_format) mstruct->last()[0].transform(STRUCT_NEGATE);
3259 else if(b_neg) mstruct->last()[0].negate();
3260 if(v == v_percent) mstruct->last()[0] += Number(100, 1);
3261 else if(v == v_permille) mstruct->last()[0] += Number(1000, 1);
3262 else mstruct->last()[0] += Number(10000, 1);
3263 mstruct->last()[0].swapChildren(1, 2);
3264 }
3265 if(mstruct->size() == 2) {
3266 mstruct->setType(STRUCT_MULTIPLICATION);
3267 } else {
3268 MathStructure *mpercent = &mstruct->last();
3269 mpercent->ref();
3270 mstruct->delChild(mstruct->size());
3271 mstruct->multiply_nocopy(mpercent);
3272 }
3273 }
3274 }
3275 }
3276 return true;
3277 }
3278 }
3279
3280 // In adaptive parsing mode division might be handled differentiately depending on usage of whitespace characters, e.g. 5/2 m = (5/2)*m, 5/2m=5/(2m)
3281 if(po.parsing_mode == PARSING_MODE_ADAPTIVE && (i = str.find(DIVISION_CH, 1)) != string::npos && i + 1 != str.length()) {
3282 while(i != string::npos && i + 1 != str.length()) {
3283 bool b = false;
3284 if(i > 2 && i < str.length() - 3 && str[i + 1] == ID_WRAP_LEFT_CH) {
3285 i2 = i;
3286 b = true;
3287 bool had_unit = false, had_nonunit = false;
3288 MathStructure *m_temp = NULL, *m_temp2 = NULL;
3289 while(b) {
3290 b = false;
3291 size_t i4 = i2;
3292 if(i2 > 2 && str[i2 - 1] == ID_WRAP_RIGHT_CH) {
3293 b = true;
3294 } else if(i2 > 4 && str[i2 - 3] == ID_WRAP_RIGHT_CH && str[i2 - 2] == POWER_CH && is_in(NUMBERS, str[i2 - 1])) {
3295 b = true;
3296 i4 -= 2;
3297 }
3298 if(!b) {
3299 if((i2 > 1 && is_not_in(OPERATORS INTERNAL_OPERATORS MULTIPLICATION_2, str[i2 - 1])) || (i2 > 2 && str[i2 - 1] == MULTIPLICATION_2_CH && is_not_in(OPERATORS INTERNAL_OPERATORS, str[i2 - 2]))) had_nonunit = true;
3300 break;
3301 }
3302 i2 = str.rfind(ID_WRAP_LEFT_CH, i4 - 2);
3303 m_temp = NULL;
3304 if(i2 != string::npos) {
3305 int id = s2i(str.substr(i2 + 1, (i4 - 1) - (i2 + 1)));
3306 if(priv->id_structs.find(id) != priv->id_structs.end()) m_temp = priv->id_structs[id];
3307 }
3308 if(!m_temp || !m_temp->isUnit()) {
3309 had_nonunit = true;
3310 break;
3311 }
3312 had_unit = true;
3313 }
3314 i3 = i;
3315 b = had_unit && had_nonunit;
3316 had_unit = false;
3317 while(b) {
3318 size_t i4 = i3;
3319 i3 = str.find(ID_WRAP_RIGHT_CH, i4 + 2);
3320 m_temp2 = NULL;
3321 if(i3 != string::npos) {
3322 int id = s2i(str.substr(i4 + 2, (i3 - 1) - (i4 + 1)));
3323 if(priv->id_structs.find(id) != priv->id_structs.end()) m_temp2 = priv->id_structs[id];
3324 }
3325 if(!m_temp2 || !m_temp2->isUnit()) {
3326 b = false;
3327 break;
3328 }
3329 had_unit = true;
3330 b = false;
3331 if(i3 < str.length() - 3 && str[i3 + 1] == ID_WRAP_LEFT_CH) {
3332 b = true;
3333 } else if(i3 < str.length() - 5 && str[i3 + 3] == ID_WRAP_LEFT_CH && str[i3 + 1] == POWER_CH && is_in(NUMBERS, str[i3 + 2])) {
3334 b = true;
3335 i3 += 2;
3336 }
3337 }
3338 b = had_unit;
3339 if(b) {
3340 if(i3 < str.length() - 2 && str[i3 + 1] == POWER_CH && is_in(NUMBERS, str[i3 + 2])) {
3341 i3 += 2;
3342 while(i3 < str.length() - 1 && is_in(NUMBERS, str[i3 + 1])) i3++;
3343 }
3344 if(i3 == str.length() - 1 || (str[i3 + 1] != POWER_CH && str[i3 + 1] != DIVISION_CH)) {
3345 MathStructure *mstruct2 = new MathStructure();
3346 str2 = str.substr(i2, i - i2);
3347 parseAdd(str2, mstruct2, po);
3348 str2 = str.substr(i + 1, i3 - i);
3349 parseAdd(str2, mstruct2, po, OPERATION_DIVIDE);
3350 str2 = ID_WRAP_LEFT;
3351 str2 += i2s(addId(mstruct2));
3352 str2 += ID_WRAP_RIGHT;
3353 str.replace(i2, i3 - i2 + 1, str2);
3354 } else {
3355 b = false;
3356 }
3357 }
3358 }
3359 if(!b) {
3360 i2 = str.find_last_not_of(NUMBERS INTERNAL_NUMBER_CHARS PLUS MINUS EXPS, i - 1);
3361 if(i2 == string::npos || (i2 != i - 1 && str[i2] == MULTIPLICATION_2_CH)) b = true;
3362 i2 = str.rfind(MULTIPLICATION_2_CH, i - 1);
3363 if(i2 == string::npos) b = true;
3364 if(b) {
3365 i3 = str.find_first_of(MULTIPLICATION_2 "%" MULTIPLICATION DIVISION, i + 1);
3366 if(i3 == string::npos || i3 == i + 1 || str[i3] != MULTIPLICATION_2_CH) b = false;
3367 if(i3 < str.length() + 1 && (str[i3 + 1] == '%' || str[i3 + 1] == DIVISION_CH || str[i3 + 1] == MULTIPLICATION_CH || str[i3 + 1] == POWER_CH)) b = false;
3368 }
3369 if(b) {
3370 if(i3 != string::npos) str[i3] = MULTIPLICATION_CH;
3371 if(i2 != string::npos) str[i2] = MULTIPLICATION_CH;
3372 } else {
3373 if(str[i + 1] == MULTIPLICATION_2_CH) {
3374 str.erase(i + 1, 1);
3375 }
3376 if(str[i - 1] == MULTIPLICATION_2_CH) {
3377 str.erase(i - 1, 1);
3378 i--;
3379 }
3380 }
3381 }
3382 i = str.find(DIVISION_CH, i + 1);
3383 }
3384 }
3385 if(po.parsing_mode == PARSING_MODE_ADAPTIVE) remove_blanks(str);
3386
3387 // In conventional parsing mode there is not difference between implicit and explicit multiplication
3388 if(po.parsing_mode >= PARSING_MODE_CONVENTIONAL) {
3389 if((i = str.find(ID_WRAP_RIGHT_CH, 1)) != string::npos && i + 1 != str.length()) {
3390 while(i != string::npos && i + 1 != str.length()) {
3391 if(is_in(NUMBERS ID_WRAP_LEFT, str[i + 1])) {
3392 str.insert(i + 1, 1, MULTIPLICATION_CH);
3393 i++;
3394 }
3395 i = str.find(ID_WRAP_RIGHT_CH, i + 1);
3396 }
3397 }
3398 if((i = str.find(ID_WRAP_LEFT_CH, 1)) != string::npos) {
3399 while(i != string::npos) {
3400 if(is_in(NUMBERS, str[i - 1])) {
3401 str.insert(i, 1, MULTIPLICATION_CH);
3402 i++;
3403 }
3404 i = str.find(ID_WRAP_LEFT_CH, i + 1);
3405 }
3406 }
3407 }
3408
3409 // Parse explicit multiplication, division, and mod
3410 if((i = str.find_first_of(MULTIPLICATION DIVISION "%", 0)) != string::npos && i + 1 != str.length()) {
3411 bool b = false, append = false;
3412 int type = 0;
3413 while(i != string::npos && i + 1 != str.length()) {
3414 if(i < 1) {
3415 if(i < 1 && str.find_first_not_of(MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS EXPS) == string::npos) {
3416 replace_internal_operators(str);
3417 error(false, _("Misplaced operator(s) \"%s\" ignored"), str.c_str(), NULL);
3418 return b;
3419 }
3420 i = 1;
3421 while(i < str.length() && is_in(MULTIPLICATION DIVISION "%", str[i])) {
3422 i++;
3423 }
3424 string errstr = str.substr(0, i);
3425 gsub("\a", str.find_first_of(OPERATORS "%") != string::npos ? " xor " : "xor", errstr);
3426 error(false, _("Misplaced operator(s) \"%s\" ignored"), errstr.c_str(), NULL);
3427 str = str.substr(i, str.length() - i);
3428 i = str.find_first_of(MULTIPLICATION DIVISION "%", 0);
3429 } else {
3430 str2 = str.substr(0, i);
3431 if(b) {
3432 switch(type) {
3433 case 1: {
3434 parseAdd(str2, mstruct, po, OPERATION_DIVIDE, append);
3435 if(po.parsing_mode == PARSING_MODE_ADAPTIVE && !str2.empty() && str2[0] != LEFT_PARENTHESIS_CH) {
3436 MathStructure *mden = NULL, *mnum = NULL;
3437 if(po.preserve_format && mstruct->isDivision()) {
3438 mden = &(*mstruct)[1];
3439 mnum = &(*mstruct)[0];
3440 } else if(!po.preserve_format && mstruct->isMultiplication() && mstruct->size() >= 2 && mstruct->last().isPower()) {
3441 mden = &mstruct->last()[0];
3442 mnum = &(*mstruct)[mstruct->size() - 2];
3443 }
3444 while(mnum && mnum->isMultiplication() && mnum->size() > 0) mnum = &mnum->last();
3445 if(mden && mden->isMultiplication() && (mden->size() != 2 || !(*mden)[0].isNumber() || !(*mden)[1].isUnit_exp() || !mnum->isUnit_exp())) {
3446 bool b_warn = str2[0] != ID_WRAP_LEFT_CH;
3447 if(!b_warn && str2.length() > 2) {
3448 size_t i3 = str2.find_first_not_of(NUMBERS, 1);
3449 b_warn = (i3 != string::npos && i3 != str2.length() - 1);
3450 }
3451 if(b_warn) error(false, _("The expression is ambiguous (be careful when combining implicit multiplication and division)."), NULL);
3452 }
3453 }
3454 break;
3455 }
3456 case 2: {
3457 MathStructure *mstruct2 = new MathStructure();
3458 parseAdd(str2, mstruct2, po);
3459 mstruct->transform(f_rem);
3460 mstruct->addChild_nocopy(mstruct2);
3461 break;
3462 }
3463 case 3: {
3464 parseAdd(str2, mstruct, po, OPERATION_DIVIDE, append);
3465 mstruct->transform(f_trunc);
3466 break;
3467 }
3468 case 4: {
3469 MathStructure *mstruct2 = new MathStructure();
3470 parseAdd(str2, mstruct2, po);
3471 mstruct->transform(f_mod);
3472 mstruct->addChild_nocopy(mstruct2);
3473 break;
3474 }
3475 default: {
3476 parseAdd(str2, mstruct, po, OPERATION_MULTIPLY, append);
3477 }
3478 }
3479 append = true;
3480 } else {
3481 parseAdd(str2, mstruct, po);
3482 b = true;
3483 }
3484 if(str[i] == DIVISION_CH) {
3485 if(str[i + 1] == DIVISION_CH) {type = 3; i++;}
3486 else type = 1;
3487 } else if(str[i] == '%') {
3488 if(str[i + 1] == '%') {type = 4; i++;}
3489 else type = 2;
3490 } else {
3491 type = 0;
3492 }
3493 if(is_in(MULTIPLICATION DIVISION "%", str[i + 1])) {
3494 i2 = 1;
3495 while(i2 + i + 1 != str.length() && is_in(MULTIPLICATION DIVISION "%", str[i2 + i + 1])) {
3496 i2++;
3497 }
3498 string errstr = str.substr(i, i2);
3499 gsub("\a", str.find_first_of(OPERATORS "%") != string::npos ? " xor " : "xor", errstr);
3500 error(false, _("Misplaced operator(s) \"%s\" ignored"), errstr.c_str(), NULL);
3501 i += i2;
3502 }
3503 str = str.substr(i + 1, str.length() - (i + 1));
3504 i = str.find_first_of(MULTIPLICATION DIVISION "%", 0);
3505 }
3506 }
3507 if(b) {
3508 switch(type) {
3509 case 1: {
3510 parseAdd(str, mstruct, po, OPERATION_DIVIDE, append);
3511 if(po.parsing_mode == PARSING_MODE_ADAPTIVE && !str.empty() && str[0] != LEFT_PARENTHESIS_CH) {
3512 MathStructure *mden = NULL, *mnum = NULL;
3513 if(po.preserve_format && mstruct->isDivision()) {
3514 mden = &(*mstruct)[1];
3515 mnum = &(*mstruct)[0];
3516 } else if(!po.preserve_format && mstruct->isMultiplication() && mstruct->size() >= 2 && mstruct->last().isPower()) {
3517 mden = &mstruct->last()[0];
3518 mnum = &(*mstruct)[mstruct->size() - 2];
3519 }
3520 while(mnum && mnum->isMultiplication() && mnum->size() > 0) mnum = &mnum->last();
3521 if(mden && mden->isMultiplication() && (mden->size() != 2 || !(*mden)[0].isNumber() || !(*mden)[1].isUnit_exp() || !mnum->isUnit_exp())) {
3522 bool b_warn = str[0] != ID_WRAP_LEFT_CH;
3523 if(!b_warn && str.length() > 2) {
3524 size_t i3 = str.find_first_not_of(NUMBERS, 1);
3525 b_warn = (i3 != string::npos && i3 != str.length() - 1);
3526 }
3527 if(b_warn) error(false, _("The expression is ambiguous (be careful when combining implicit multiplication and division)."), NULL);
3528 }
3529 }
3530 break;
3531 }
3532 case 2: {
3533 MathStructure *mstruct2 = new MathStructure();
3534 parseAdd(str, mstruct2, po);
3535 mstruct->transform(f_rem);
3536 mstruct->addChild_nocopy(mstruct2);
3537 break;
3538 }
3539 case 3: {
3540 parseAdd(str, mstruct, po, OPERATION_DIVIDE, append);
3541 mstruct->transform(f_trunc);
3542 break;
3543 }
3544 case 4: {
3545 MathStructure *mstruct2 = new MathStructure();
3546 parseAdd(str, mstruct2, po);
3547 mstruct->transform(f_mod);
3548 mstruct->addChild_nocopy(mstruct2);
3549 break;
3550 }
3551 default: {
3552 parseAdd(str, mstruct, po, OPERATION_MULTIPLY, append);
3553 }
3554 }
3555 return true;
3556 }
3557 }
3558 }
3559
3560 // Parse \x1c (internal single substitution character for angle operator) for complex angle format
3561 if((i = str.find('\x1c', 0)) != string::npos && i + 1 != str.length() && (po.parsing_mode != PARSING_MODE_CHAIN || i == 0)) {
3562 if(i != 0) str2 = str.substr(0, i);
3563 str = str.substr(i + 1, str.length() - (i + 1));
3564 if(i != 0) parseAdd(str2, mstruct, po);
3565 else mstruct->set(1, 1, 0);
3566 if(parseAdd(str, mstruct, po, OPERATION_MULTIPLY)) {
3567 if(po.angle_unit != ANGLE_UNIT_NONE && po.angle_unit != ANGLE_UNIT_RADIANS && mstruct->last().contains(getRadUnit(), false, true, true) <= 0 && mstruct->last().contains(getGraUnit(), false, true, true) <= 0 && mstruct->last().contains(getDegUnit(), false, true, true) <= 0) {
3568 switch(po.angle_unit) {
3569 case ANGLE_UNIT_DEGREES: {mstruct->last().multiply(getDegUnit()); break;}
3570 case ANGLE_UNIT_GRADIANS: {mstruct->last().multiply(getGraUnit()); break;}
3571 default: {}
3572 }
3573 }
3574 mstruct->last().transform(priv->f_cis);
3575 }
3576 return true;
3577 }
3578
3579 if(str.empty()) return false;
3580
3581 // Check if only operators are left
3582 if(str.find_first_not_of(OPERATORS INTERNAL_OPERATORS SPACE) == string::npos && (po.base != BASE_ROMAN_NUMERALS || str.find_first_of("(|)") == string::npos)) {
3583 replace_internal_operators(str);
3584 error(false, _("Misplaced operator(s) \"%s\" ignored"), str.c_str(), NULL);
3585 return false;
3586 }
3587
3588 // Number signs (+ and - at the beginning of the string)
3589 i = 0;
3590 bool ret = true;
3591 bool has_sign = false;
3592 int minus_count = 0;
3593 while(i < str.length()) {
3594 if(str[i] == MINUS_CH) {
3595 has_sign = true;
3596 minus_count++;
3597 str.erase(i, 1);
3598 } else if(str[i] == PLUS_CH) {
3599 has_sign = true;
3600 str.erase(i, 1);
3601 } else if(str[i] == SPACE_CH) {
3602 str.erase(i, 1);
3603 } else if(str[i] == BITWISE_NOT_CH || str[i] == LOGICAL_NOT_CH) {
3604 break;
3605 } else if(is_in(OPERATORS INTERNAL_OPERATORS, str[i]) && (po.base != BASE_ROMAN_NUMERALS || (str[i] != '(' && str[i] != ')' && str[i] != '|'))) {
3606 if(str[i] == '\a') error(false, _("Misplaced operator(s) \"%s\" ignored"), "xor", NULL);
3607 else if(str[i] == '\b') error(false, _("Misplaced operator(s) \"%s\" ignored"), SIGN_PLUSMINUS, NULL);
3608 else if(str[i] == '\x1c') error(false, _("Misplaced operator(s) \"%s\" ignored"), "∠", NULL);
3609 else error(false, _("Misplaced '%c' ignored"), str[i], NULL);
3610 str.erase(i, 1);
3611 } else {
3612 break;
3613 }
3614 }
3615
3616 // Parse ~ and ! at the beginning of the string as bitwise not and logical not
3617 if(!str.empty() && (str[0] == BITWISE_NOT_CH || str[0] == LOGICAL_NOT_CH)) {
3618 bool bit = (str[0] == BITWISE_NOT_CH);
3619 str.erase(0, 1);
3620 parseAdd(str, mstruct, po);
3621 if(bit) mstruct->setBitwiseNot();
3622 else mstruct->setLogicalNot();
3623 if(po.preserve_format) {
3624 while(minus_count > 0) {
3625 mstruct->transform(STRUCT_NEGATE);
3626 minus_count--;
3627 }
3628 } else if(minus_count % 2 == 1) {
3629 mstruct->negate();
3630 }
3631 return true;
3632 }
3633
3634 if(str.empty()) {
3635 if(minus_count % 2 == 1 && !po.preserve_format) {
3636 mstruct->set(-1, 1, 0);
3637 } else if(has_sign) {
3638 mstruct->set(1, 1, 0);
3639 if(po.preserve_format) {
3640 while(minus_count > 0) {
3641 mstruct->transform(STRUCT_NEGATE);
3642 minus_count--;
3643 }
3644 }
3645 }
3646 return false;
3647 }
3648
3649 // Implicit multiplication
3650 if((i = str.find(ID_WRAP_RIGHT_CH, 1)) != string::npos && i + 1 != str.length()) {
3651 bool b = false, append = false;
3652 while(i != string::npos && i + 1 != str.length()) {
3653 if(str[i + 1] != POWER_CH && str[i + 1] != '\b') {
3654 str2 = str.substr(0, i + 1);
3655 str = str.substr(i + 1, str.length() - (i + 1));
3656 if(b) {
3657 parseAdd(str2, mstruct, po, OPERATION_MULTIPLY, append);
3658 append = true;
3659 } else {
3660 parseAdd(str2, mstruct, po);
3661 b = true;
3662 }
3663 i = str.find(ID_WRAP_RIGHT_CH, 1);
3664 } else {
3665 i = str.find(ID_WRAP_RIGHT_CH, i + 1);
3666 }
3667 }
3668 if(b) {
3669 parseAdd(str, mstruct, po, OPERATION_MULTIPLY, append);
3670 if(po.parsing_mode == PARSING_MODE_ADAPTIVE && mstruct->isMultiplication() && mstruct->size() >= 2 && !(*mstruct)[0].inParentheses()) {
3671 Unit *u1 = NULL; Prefix *p1 = NULL;
3672 bool b_plus = false;
3673 // In adaptive parsing mode, parse 5m 2cm as 5m+2cm, 5ft 2in as 5ft+2in, and similar
3674 if((*mstruct)[0].isMultiplication() && (*mstruct)[0].size() == 2 && (*mstruct)[0][0].isNumber() && (*mstruct)[0][1].isUnit()) {u1 = (*mstruct)[0][1].unit(); p1 = (*mstruct)[0][1].prefix();}
3675 if(u1 && u1->subtype() == SUBTYPE_BASE_UNIT && (u1->referenceName() == "m" || (!p1 && u1->referenceName() == "L")) && (!p1 || (p1->type() == PREFIX_DECIMAL && ((DecimalPrefix*) p1)->exponent() <= 3 && ((DecimalPrefix*) p1)->exponent() > -3))) {
3676 b_plus = true;
3677 for(size_t i2 = 1; i2 < mstruct->size(); i2++) {
3678 if(!(*mstruct)[i2].inParentheses() && (*mstruct)[i2].isMultiplication() && (*mstruct)[i2].size() == 2 && (*mstruct)[i2][0].isNumber() && (*mstruct)[i2][1].isUnit() && (*mstruct)[i2][1].unit() == u1) {
3679 Prefix *p2 = (*mstruct)[i2][1].prefix();
3680 if(p1 && p2) b_plus = p1->type() == PREFIX_DECIMAL && p2->type() == PREFIX_DECIMAL && ((DecimalPrefix*) p1)->exponent() > ((DecimalPrefix*) p2)->exponent() && ((DecimalPrefix*) p2)->exponent() >= -3;
3681 else if(p2) b_plus = p2->type() == PREFIX_DECIMAL && ((DecimalPrefix*) p2)->exponent() < 0 && ((DecimalPrefix*) p2)->exponent() >= -3;
3682 else if(p1) b_plus = p1->type() == PREFIX_DECIMAL && ((DecimalPrefix*) p1)->exponent() > 1;
3683 else b_plus = false;
3684 if(!b_plus) break;
3685 p1 = p2;
3686 } else {
3687 b_plus = false;
3688 break;
3689 }
3690 }
3691 } else if(u1 && !p1 && u1->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) u1)->mixWithBase()) {
3692 b_plus = true;
3693 for(size_t i2 = 1; i2 < mstruct->size(); i2++) {
3694 if(!(*mstruct)[i2].inParentheses() && (*mstruct)[i2].isMultiplication() && (*mstruct)[i2].size() == 2 && (*mstruct)[i2][0].isNumber() && (*mstruct)[i2][1].isUnit() && u1->isChildOf((*mstruct)[i2][1].unit()) && !(*mstruct)[i2][1].prefix() && (i2 == mstruct->size() - 1 || ((*mstruct)[i2][1].unit()->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) (*mstruct)[i2][1].unit())->mixWithBase()))) {
3695 while(((AliasUnit*) u1)->firstBaseUnit() != (*mstruct)[i2][1].unit()) {
3696 u1 = ((AliasUnit*) u1)->firstBaseUnit();
3697 if(u1->subtype() != SUBTYPE_ALIAS_UNIT || !((AliasUnit*) u1)->mixWithBase()) {
3698 b_plus = false;
3699 break;
3700 }
3701 }
3702 if(!b_plus) break;
3703 u1 = (*mstruct)[i2][1].unit();
3704 } else {
3705 b_plus = false;
3706 break;
3707 }
3708 }
3709 }
3710 if(b_plus) mstruct->setType(STRUCT_ADDITION);
3711 }
3712 if(po.preserve_format) {
3713 while(minus_count > 0) {
3714 mstruct->transform(STRUCT_NEGATE);
3715 minus_count--;
3716 }
3717 } else if(minus_count % 2 == 1) {
3718 mstruct->negate();
3719 }
3720 return true;
3721 }
3722 }
3723 // Implicit multiplication
3724 if((i = str.find(ID_WRAP_LEFT_CH, 1)) != string::npos) {
3725 bool b = false, append = false;
3726 while(i != string::npos) {
3727 if(str[i - 1] != POWER_CH && (i < 2 || str[i - 1] != MINUS_CH || str[i - 2] != POWER_CH) && str[i - 1] != '\b') {
3728 str2 = str.substr(0, i);
3729 str = str.substr(i, str.length() - i);
3730 if(b) {
3731 parseAdd(str2, mstruct, po, OPERATION_MULTIPLY, append);
3732 append = true;
3733 } else {
3734 parseAdd(str2, mstruct, po);
3735 b = true;
3736 }
3737 i = str.find(ID_WRAP_LEFT_CH, 1);
3738 } else {
3739 i = str.find(ID_WRAP_LEFT_CH, i + 1);
3740 }
3741 }
3742 if(b) {
3743 parseAdd(str, mstruct, po, OPERATION_MULTIPLY, append);
3744 if(po.preserve_format) {
3745 while(minus_count > 0) {
3746 mstruct->transform(STRUCT_NEGATE);
3747 minus_count--;
3748 }
3749 } else if(minus_count % 2 == 1) {
3750 mstruct->negate();
3751 }
3752 return true;
3753 }
3754 }
3755 if((i = str.find(POWER_CH, 1)) != string::npos && i + 1 != str.length()) {
3756 // Parse exponentiation (^)
3757 str2 = str.substr(0, i);
3758 str = str.substr(i + 1, str.length() - (i + 1));
3759 parseAdd(str2, mstruct, po);
3760 parseAdd(str, mstruct, po, OPERATION_RAISE);
3761 } else if((i = str.find("\b", 1)) != string::npos && i + 1 != str.length()) {
3762 // Parse uncertainty (using \b as internal single substitution character for +/-)
3763 str2 = str.substr(0, i);
3764 str = str.substr(i + 1, str.length() - (i + 1));
3765 MathStructure *mstruct2 = new MathStructure;
3766 if(po.read_precision != DONT_READ_PRECISION) {
3767 ParseOptions po2 = po;
3768 po2.read_precision = DONT_READ_PRECISION;
3769 parseAdd(str2, mstruct, po2);
3770 parseAdd(str, mstruct2, po2);
3771 } else {
3772 parseAdd(str2, mstruct, po);
3773 parseAdd(str, mstruct2, po);
3774 }
3775 mstruct->transform(f_uncertainty);
3776 mstruct->addChild_nocopy(mstruct2);
3777 mstruct->addChild(m_zero);
3778 } else if(BASE_2_10 && (i = str.find_first_of(EXPS, 0)) != string::npos && i + 1 != str.length() && str.find("\b") == string::npos) {
3779 // Parse scientific e-notation
3780 if(i == 0) {
3781 mstruct->set(1, 1, 0);
3782 CALCULATOR->error(false, _("%s interpreted as 10^%s (1%s)"), str.c_str(), str.find_first_not_of(NUMBERS, 1) == string::npos ? str.substr(1, str.length() - 1).c_str() : (string("(") + str.substr(1, str.length() - 1) + string(")")).c_str(), str.c_str(), NULL);
3783 } else {
3784 str2 = str.substr(0, i);
3785 parseAdd(str2, mstruct, po);
3786 }
3787 str = str.substr(i + 1, str.length() - (i + 1));
3788 parseAdd(str, mstruct, po, OPERATION_EXP10);
3789 if(i == 0 && mstruct->isMultiplication() && mstruct->size() == 2 && (*mstruct)[0].isOne()) mstruct->setToChild(2);
3790 } else if((i = str.find(ID_WRAP_LEFT_CH, 1)) != string::npos && i + 1 != str.length() && str.find(ID_WRAP_RIGHT_CH, i + 1) && str.find_first_not_of(PLUS MINUS, 0) != i) {
3791 // Implicit multiplication
3792 str2 = str.substr(0, i);
3793 str = str.substr(i, str.length() - i);
3794 parseAdd(str2, mstruct, po);
3795 parseAdd(str, mstruct, po, OPERATION_MULTIPLY);
3796 } else if(str.length() > 0 && str[0] == ID_WRAP_LEFT_CH && (i = str.find(ID_WRAP_RIGHT_CH, 1)) != string::npos && i + 1 != str.length()) {
3797 // Implicit multiplication
3798 str2 = str.substr(0, i + 1);
3799 str = str.substr(i + 1, str.length() - (i + 1));
3800 parseAdd(str2, mstruct, po);
3801 parseAdd(str, mstruct, po, OPERATION_MULTIPLY);
3802 } else {
3803 // Parse as number
3804 ret = parseNumber(mstruct, str, po);
3805 }
3806 if(po.preserve_format) {
3807 while(minus_count > 0) {
3808 mstruct->transform(STRUCT_NEGATE);
3809 minus_count--;
3810 }
3811 } else if(minus_count % 2 == 1) {
3812 mstruct->negate();
3813 }
3814 return ret;
3815 }
3816
3817