parser:: error handling now uses exceptions

This commit is contained in:
Zeno Rogue 2019-12-23 21:44:51 +01:00
parent a83220c34e
commit 15000034fd
6 changed files with 63 additions and 29 deletions

View File

@ -79,7 +79,15 @@ EX namespace arg {
EX const char* argcs() { return args().c_str(); }
EX int argi() { return atoi(argcs()); }
EX unsigned arghex() { return strtoll(argcs(), NULL, 16); }
EX ld argf() { return parseld(args()); }
EX ld argf() {
try {
return parseld(args());
}
catch(hr_parse_exception& ex) {
println(hlog, "error parsing commandline parameters: ", ex.s);
exit(1);
}
}
EX bool argis(const string& s) { if(args()[0] == '-' && args()[1] == '-') return args().substr(1) == s; return args() == s; }
EX void shift_arg_formula(ld& x, const reaction_t& r IS(reaction_t())) {

View File

@ -743,17 +743,20 @@ EX namespace dialog {
}
EX void apply_edit() {
exp_parser ep;
ep.s = ne.s;
ld x = real(ep.parse());
if(!ep.ok()) return;
if(ne.sc.positive && x <= 0) return;
*ne.editwhat = x;
if(ne.intval) *ne.intval = ldtoint(*ne.editwhat);
#if CAP_ANIMATIONS
if(ne.animatable) anims::animate_parameter(*ne.editwhat, ne.s, reaction ? reaction : reaction_final);
#endif
if(reaction) reaction();
try {
exp_parser ep;
ep.s = ne.s;
ld x = ep.rparse();
if(ne.sc.positive && x <= 0) return;
*ne.editwhat = x;
if(ne.intval) *ne.intval = ldtoint(*ne.editwhat);
#if CAP_ANIMATIONS
if(ne.animatable) anims::animate_parameter(*ne.editwhat, ne.s, reaction ? reaction : reaction_final);
#endif
if(reaction) reaction();
}
catch(hr_parse_exception&) {
}
}
EX void bound_low(ld val) {

View File

@ -833,7 +833,13 @@ EX void applymodel(hyperpoint H, hyperpoint& ret) {
ep.extra_params["uy"] = H[1];
ep.extra_params["uz"] = H[2];
ep.s = models::formula;
cld res = ep.parse();
cld res;
try {
res = ep.parse();
}
catch(hr_parse_exception&) {
res = 0;
}
ret[0] = real(res);
ret[1] = imag(res);
ret[2] = 0;

View File

@ -1577,7 +1577,12 @@ EX namespace patterns {
}
ep.s = formula;
return ep.parse();
try {
return ep.parse();
}
catch(hr_parse_exception& ex) {
return 0;
}
}
EX hookset<int(cell*)> *hooks_generate_canvas;

View File

@ -575,7 +575,12 @@ void apply_animated_parameters() {
ap_changes = 0;
for(auto &ap: aps) {
if(*ap.value != ap.last) continue;
*ap.value = parseld(ap.formula);
try {
*ap.value = parseld(ap.formula);
}
catch(hr_parse_exception&) {
continue;
}
if(*ap.value != ap.last) {
if(ap.reaction) ap.reaction();
ap_changes++;

View File

@ -121,6 +121,11 @@ EX bool appears(const string& haystack, const string& needle) {
}
#if HDR
struct hr_parse_exception : hr_exception {
string s;
hr_parse_exception(const string& z) : s(z) {}
};
struct exp_parser {
string s;
int at;
@ -129,7 +134,7 @@ struct exp_parser {
map<string, cld> extra_params;
bool ok() { return at == isize(s); }
char next(int step=0) { if(at >= isize(s)-step || at == -1) return 0; else return s[at+step]; }
char next(int step=0) { if(at >= isize(s)-step) return 0; else return s[at+step]; }
bool eat(const char *c) {
int orig_at = at;
@ -150,10 +155,14 @@ struct exp_parser {
cld parsepar() {
cld res = parse();
if(next() != ')') { at = -1; return res; }
at++;
force_eat(")");
return res;
}
void force_eat(const char *c) {
skip_white();
if(!eat(c)) throw hr_parse_exception("expected: " + string(c));
}
};
#endif
@ -188,24 +197,24 @@ cld exp_parser::parse(int prio) {
else if(eat("to01(")) { res = parsepar(); return atan(res) / ld(M_PI) + ld(0.5); }
else if(eat("ifp(")) {
cld cond = parse(0);
if(snext() != ',') {at = -1; return 0; } at++;
force_eat(",");
cld yes = parse(0);
if(snext() != ',') {at = -1; return 0; } at++;
force_eat(",");
cld no = parsepar();
return real(cond) > 0 ? yes : no;
}
else if(eat("wallif(")) {
cld val0 = parse(0);
if(snext() != ',') {at = -1; return 0; } at++;
force_eat(",");
cld val1 = parsepar();
if(real(extra_params["p"]) >= 3.5) return val0;
else return val1;
}
else if(eat("rgb(")) {
cld val0 = parse(0);
if(snext() != ',') {at = -1; return 0; } at++;
force_eat(",");
cld val1 = parse(0);
if(snext() != ',') {at = -1; return 0; } at++;
force_eat(",");
cld val2 = parsepar();
switch(int(real(extra_params["p"]) + .5)) {
case 1: return val0;
@ -223,11 +232,9 @@ cld exp_parser::parse(int prio) {
name += c, at++;
else break;
}
if(snext() != '=') { at = -1; return 0; }
at++;
force_eat("=");
cld val = parse(0);
if(snext() != ',') { at = -1; return 0; }
at++;
force_eat(",");
dynamicval<cld> d(extra_params[name], val);
return parsepar();
}
@ -250,7 +257,7 @@ cld exp_parser::parse(int prio) {
else if(number == "i") res = cld(0, 1);
else if(number == "p" || number == "pi") res = M_PI;
else if(number == "" && next() == '-') { at++; res = -parse(prio); }
else if(number == "") at = -1;
else if(number == "") throw hr_parse_exception("number missing");
else if(number == "s") res = ticks / 1000.;
else if(number == "ms") res = ticks;
else if(number[0] == '0' && number[1] == 'x') res = strtoll(number.c_str()+2, NULL, 16);
@ -262,7 +269,7 @@ cld exp_parser::parse(int prio) {
else if(number == "shot") res = inHighQual ? 1 : 0;
else if(extra_params.count(number)) res = extra_params[number];
else if(params.count(number)) res = params.at(number);
else if(number[0] >= 'a' && number[0] <= 'z') at = -1;
else if(number[0] >= 'a' && number[0] <= 'z') throw hr_parse_exception("unknown value: " + number);
else { std::stringstream ss; res = 0; ss << number; ss >> res; }
}
while(true) {