I am using "tinyexpr", a cute library that can solve mathematical formulas in a string and I extended it such that it does logical operations with two operands as well. However I wasn't sure how to handle the logical NOT as it is performed on a single operand, which is why I just created a small function that does just that outside of tinyexpr:
void handle_logical_not (char * expr)
{
int i;
for(i = 0; expr[i] != '\0'; i++)
{
if(expr[i] == '!')
{
i++;
if(expr[i] == '!')
{
handle_logical_not(&expr[i]); /* Recursively handle subexpressions */
}
if( (expr[i] >= '0' && expr[i] <= '9') || (expr[i] == '-' && (expr[i+1] >= '0' && expr[i+1] <= '9')) )
{
long int val = 0;
char* end = NULL;
size_t len = 0;
if(expr[i] == '0') val = strtol(&expr[i], &end, 8);
else val = strtol(&expr[i], &end, 10);
expr[i-1] = '0' + !val;
len = (uintptr_t)&expr[MAX_EXPR] - (uintptr_t)end;
memmove(&expr[i], end, len);
}
}
}
}
You will normally pass a statically allocated string (an expression) to this function and it modifies it directly if it detects a logical NOT operation. For example "!0+!0+!!0"
and the function will replace it like that: "1+1+0"
Then you can pass the potentially modified string to tinyexpr for further evaluation. Sadly, this obviously adds an additional complexity overhead.
Remarks and Flaws:
- As a bonus it adds a case for octal values.
- It does not skip whitespace characters
!(1 + 1)
? \$\endgroup\$!(1)
would not be parsed at all. Parenthesizes are not considered and arithmetic is calculated afterwards in the application I am working on. I actually had a remark about that, but I removed it without consideration. \$\endgroup\$