mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-10-31 05:52:59 +00:00 
			
		
		
		
	number editor now accepts expressions
This commit is contained in:
		
							
								
								
									
										70
									
								
								dialogs.cpp
									
									
									
									
									
								
							
							
						
						
									
										70
									
								
								dialogs.cpp
									
									
									
									
									
								
							| @@ -599,6 +599,68 @@ namespace dialog { | |||||||
|    |    | ||||||
|   reaction_t extra_options; |   reaction_t extra_options; | ||||||
|  |  | ||||||
|  |   struct exp_parser { | ||||||
|  |     string s; | ||||||
|  |     int at; | ||||||
|  |     exp_parser() { at = 0; } | ||||||
|  |  | ||||||
|  |     bool ok() { return at == isize(s); } | ||||||
|  |     char next() { if(at == isize(s) || at == -1) return 0; else return s[at]; } | ||||||
|  |      | ||||||
|  |     bool eat(const char *c) { | ||||||
|  |       int orig_at = at; | ||||||
|  |       while(*c && *c == next()) at++, c++; | ||||||
|  |       if(*c == 0) return true; | ||||||
|  |       else at = orig_at; | ||||||
|  |       return false; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |     ld parse(int prio = 0) { | ||||||
|  |       ld res; | ||||||
|  |       if(eat("sin(")) res = sin(parsepar()); | ||||||
|  |       else if(eat("cos(")) res = cos(parsepar()); | ||||||
|  |       else if(eat("sinh(")) res = sinh(parsepar()); | ||||||
|  |       else if(eat("cosh(")) res = cosh(parsepar()); | ||||||
|  |       else if(eat("asin(")) res = asin(parsepar()); | ||||||
|  |       else if(eat("acos(")) res = acos(parsepar()); | ||||||
|  |       else if(eat("asinh(")) res = asinh(parsepar()); | ||||||
|  |       else if(eat("acosh(")) res = acosh(parsepar()); | ||||||
|  |       else if(eat("exp(")) res = exp(parsepar()); | ||||||
|  |       else if(eat("log(")) res = log(parsepar()); | ||||||
|  |       else if(next() == '(') at++, res = parsepar(); | ||||||
|  |       else { | ||||||
|  |         string number; | ||||||
|  |         while(true) { | ||||||
|  |           char c = next(); | ||||||
|  |           if((c >= '0' && c <= '9') || among(c, 'e', 'p', '.')) | ||||||
|  |             number += c, at++; | ||||||
|  |           else break; | ||||||
|  |           } | ||||||
|  |         if(number == "e") res = exp(1); | ||||||
|  |         else if(number == "p") res = M_PI; | ||||||
|  |         else if(number == "") at = -1; | ||||||
|  |         else if(number[0] >= 'a' && number[0] <= 'z') at = -1; | ||||||
|  |         else { std::stringstream ss; res = 0; ss << number; ss >> res; } | ||||||
|  |         } | ||||||
|  |       while(true) { | ||||||
|  |         if(next() == '+' && prio == 0) at++, res = res + parse(1); | ||||||
|  |         else if(next() == '-' && prio == 0) at++, res = res - parse(1); | ||||||
|  |         else if(next() == '*' && prio <= 1) at++, res = res * parse(2); | ||||||
|  |         else if(next() == '/' && prio <= 1) at++, res = res / parse(2); | ||||||
|  |         else if(next() == '^') at++, res = pow(res, parse(3)); | ||||||
|  |         else break; | ||||||
|  |         } | ||||||
|  |       return res; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |     ld parsepar() { | ||||||
|  |       ld res = parse(); | ||||||
|  |       if(next() != ')') { at = -1; return res; } | ||||||
|  |       at++; | ||||||
|  |       return res; | ||||||
|  |       }   | ||||||
|  |     }; | ||||||
|  |  | ||||||
|   void affect(char kind) { |   void affect(char kind) { | ||||||
|  |  | ||||||
|     if(ne.intval) { |     if(ne.intval) { | ||||||
| @@ -607,8 +669,10 @@ namespace dialog { | |||||||
|       } |       } | ||||||
|     else { |     else { | ||||||
|       if(kind == 's') { |       if(kind == 's') { | ||||||
|         ld x; |         exp_parser ep; | ||||||
|         sscanf(ne.s.c_str(), LDF, &x); |         ep.s = ne.s; | ||||||
|  |         ld x = ep.parse(); | ||||||
|  |         if(!ep.ok()) return; | ||||||
|         if(ne.sc.positive && x <= 0) return; |         if(ne.sc.positive && x <= 0) return; | ||||||
|         *ne.editwhat = x; |         *ne.editwhat = x; | ||||||
|         } |         } | ||||||
| @@ -730,7 +794,7 @@ namespace dialog { | |||||||
|      |      | ||||||
|     keyhandler = [] (int sym, int uni) { |     keyhandler = [] (int sym, int uni) { | ||||||
|       handleNavigation(sym, uni); |       handleNavigation(sym, uni); | ||||||
|       if((uni >= '0' && uni <= '9') || (uni == '.' && !ne.intval) || (uni == '-' && !ne.sc.positive)) { |       if((uni >= '0' && uni <= '9') || (uni == '.' && !ne.intval) || among(uni, '+', '-', '*', '/', '^', '(', ')') || (uni >= 'a' && uni <= 'z')) { | ||||||
|         ne.s += uni; |         ne.s += uni; | ||||||
|         affect('s'); |         affect('s'); | ||||||
|         } |         } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Zeno Rogue
					Zeno Rogue