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