[英]Parse and calculate boolean expression in C
我有一个具有布尔表达式的文件,格式如下:
x0 x3+x4
x1+x2
这些对应于:
x0 AND x3 OR x4
x1 OR x2
假设我们知道表达式的数量(N = 2)和x的数量(M = 5)。 我想要一个大小为N的数组A和一个大小为M的数组Y。数组A应该包含在:
A[0] = y[0] && y[3] || y[4]
A[1] = y[1] || y[2]
等等。
到目前为止,我已经实现了一个python脚本,该脚本使用给定的数组(使用表达式初始化)来生成.c文件。 但这意味着我需要为每个不同的实例重新编译程序。 我想避免这种情况。 任何想法都欢迎。
有没有“肮脏的”或快速的技巧可以做到这一点? 如果可能的话,我想只使用C。 提前致谢。
这是C语言解决方案的要点。它假设一个字母的变量名和一个字母的运算符。 (为了好玩,我包括了一个“ not”运算符和用于子表达式的括号。)它处理以下形式的字符串:
a&b|(~c&~a)
(其中a..z对应于OP的X和Y实体),并计算表达式的布尔值。
这是作为经典的递归下降解析器实现的; 请参见在8位嵌入式系统上是否可以使用flex / bison的替代方案? 有关一般如何执行此操作的更多详细信息。
我对它进行了编码,以指出这对于表达式来说有多简单。 这是未经测试的; OP可以分担他的工作。
#define syntax_error -1 // result of parser if expression is malformed
bool variable_values[26]; // one for each letter a-z; initialized before parsing starts
char* expression; // pointer to the expression string being processed
int scan; // used to scan across the expression
#define reject_character() scan-- // used to back up scan when lexical error encountered
#define skip_blanks() { while (expression[scan]==' ') scan++; }
int boolean_primitive()
// returns result of a subexpression consisting of just variable names or constants
{ int subexpression_result;
skip_blanks();
switch (expression[scan++])
{ case 'a','b', ... 'z': // variable name
return variable_values[expression[scan-1]-"a"]; // look up value of variable
case '0': // constant for "false"
return 0;
case '1': // constant for "true"
return 1;
default:
return syntax_error;
}
}
int boolean_term()
// returns result of expression involving NOT or (...)
{ int subexpression_result;
skip_blanks();
switch (expression[scan++])
{ case '~': // not operator
subexpression_result=boolean_primitive();
if (subexpression_result==syntax_error)
return syntax_error;
return !subexpression_result;
case '(': // nested expression
subexpression_result=boolean_or_sequence();
if (subexpression_result==syntax_error)
return syntax_error;
skip_blanks();
if (expression[scan++]==')')
return subexpression_result;
else return syntax_error;
default:
reject_character();
return boolean_primitive();
}
}
int boolean_and_sequence()
// returns result of expression of form s1 & s2 & ...
{ int subexpression_result=boolean_term();
if (subexpression_result==syntax_error)
return syntax_error;
skip_blanks();
while (expression[scan++]=='&') // "and" operator?
{ int subexpression2_result=boolean_term();
if (subexpression2_result==syntax_error)
return syntax_error;
subexpression_result&=subexpression2_result;
skip_blanks();
}
reject_character; // undo overscan for '&'
return subexpression_result;
}
int boolean_or_sequence()
// returns result of expression of form of s1 | s2 | ...
{ int subexpression_result=boolean_and_sequence();
if (subexpression_result==syntax_error)
return syntax_error;
skip_blanks();
while (expression[scan++]=='|') // "or" operator?
{ int subexpression2_result=boolean_primitive();
if (subexpression2_result==syntax_error)
return syntax_error;
subexpression_result|=subexpression2_result;
skip_blanks();
}
reject_character; // undo overscan for '|'
return subexpression_result;
}
int calculate_boolean_expression(char* expression_to_evaluate)
// returns int==0 for boolean false;
// int==1 for boolean true
// int==-1 for malformed expression
{ int subexpression_result;
scan=1;
expression=expression_to_evaluate;
subexpression_result=boolean_or_sequence();
if (subexpression_result==syntax_error)
return syntax_error;
skip_blanks();
if (expression[scan]==0) // expression ends without excess junk in string?
return subexpression_result;
else return syntax_error;
}
初始化变量值后,可以这样调用它:
int the_answer=calculate_boolean_expression(&some_expression_string);
显然,您想检查答案以查看解析器是否发现语法错误。
如果您坚持认为,可以通过将所有全局变量作为参数传递来避免全局变量。
在C语言中,返回/检查语法错误是尴尬的,并且由于调用子解析器反复需要对其进行检查,因此使实现混乱。 实现此可抛出异常会更好,但C不允许这样做。 您可以使用longjmp进行伪造。
无论它们是什么,您都必须对其进行扩展以处理您的(多字符)词汇复杂性。 为了快速而肮脏,坚持使用单字符运算符/操作数是很干净的。 处理多字符词素的秘诀是针对您希望遇到的每个词素进行测试,然后简单地将“扫描”指针备份到失败的词素的开头。 我为此使用了宏“拒绝”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.