读书人

求教C++高手一个编写逻辑运算符分析算

发布时间: 2012-10-10 13:58:11 作者: rapoo

求教C++高手一个编写逻辑运算符分析算法的问题
最近有一个项目需要自定义一种脚本语言,脚本语言中可能包含&& || () 等逻辑运算符。

现在需要编写一个算法来parse脚本语言,通过包含的逻辑运算符决定脚本的执行顺序。

比如说有脚本如下
press:OK||(press:Yes&&Key:A)
press:Back
其中press:OK press:Yes Key:A等的执行结果均为布尔值。

像这样的算法应该怎样编写才比较合理呢。尝试写了几种,总是会出现一些没考虑到的情况。
小弟在这方面经验不足,还请大拿指点一下。
谢谢。

[解决办法]

探讨

引用:

1、|| && ( 等需要首先分离出来。
2、按照执行顺序,表达式重新排序。
3、分析布尔值。

1和3没什么问题,主要是2。算法思路不清晰。。

[解决办法]
说下我的思路,先用正则表达式把串中的特殊字符 即操作数和操作符分离,定义优先级表,最后再计算
[解决办法]
感觉还是先把需要转换的逻辑 转换成一个相对应的表 然后再处理各种情况 这样能容易些以后扩展也方便
[解决办法]
c写的话,建议你用一天时间学习EBNF,一天时间学习flex+bison,然后半天时间写出来就好了。
[解决办法]
这种简单的表达式不太需要按编译原理那套走,下面是busybox expr源码,可以参考。
C/C++ code
* *//* This program evaluates expressions.  Each token (operator, operand, * parenthesis) of the expression must be a seperate argument.  The * parser used is a reasonably general one, though any incarnation of * it is language-specific.  It is especially nice for expressions. * * No parse tree is needed; a new node is evaluated immediately. * One function can handle multiple operators all of equal precedence, * provided they all associate ((x op x) op x). *//* no getopt needed */#include <stdio.h>#include <string.h>#include <stdlib.h>#include <regex.h>#include <sys/types.h>#include "busybox.h"/* The kinds of value we can have.  */enum valtype {    integer,    string};typedef enum valtype TYPE;/* A value is.... */struct valinfo {    TYPE type;            /* Which kind. */    union {                /* The value itself. */        int i;        char *s;    } u;};typedef struct valinfo VALUE;/* The arguments given to the program, minus the program name.  */static char **args;static VALUE *docolon (VALUE *sv, VALUE *pv);static VALUE *eval (void);static VALUE *int_value (int i);static VALUE *str_value (char *s);static int nextarg (char *str);static int null (VALUE *v);static int toarith (VALUE *v);static void freev (VALUE *v);static void tostring (VALUE *v);int expr_main (int argc, char **argv){    VALUE *v;    if (argc == 1) {        error_msg_and_die("too few arguments");    }    args = argv + 1;    v = eval ();    if (*args)        error_msg_and_die ("syntax error");    if (v->type == integer)        printf ("%d\n", v->u.i);    else        puts (v->u.s);    exit (null (v));}/* Return a VALUE for I.  */static VALUE *int_value (int i){    VALUE *v;    v = xmalloc (sizeof(VALUE));    v->type = integer;    v->u.i = i;    return v;}/* Return a VALUE for S.  */static VALUE *str_value (char *s){    VALUE *v;    v = xmalloc (sizeof(VALUE));    v->type = string;    v->u.s = strdup (s);    return v;}/* Free VALUE V, including structure components.  */static void freev (VALUE *v){    if (v->type == string)        free (v->u.s);    free (v);}/* Return nonzero if V is a null-string or zero-number.  */static int null (VALUE *v){    switch (v->type) {        case integer:            return v->u.i == 0;        case string:            return v->u.s[0] == '\0' || strcmp (v->u.s, "0") == 0;        default:            abort ();    }}/* Coerce V to a string value (can't fail).  */static void tostring (VALUE *v){    char *temp;    if (v->type == integer) {        temp = xmalloc (4 * (sizeof (int) / sizeof (char)));        sprintf (temp, "%d", v->u.i);        v->u.s = temp;        v->type = string;    }}/* Coerce V to an integer value.  Return 1 on success, 0 on failure.  */static int toarith (VALUE *v){    int i;    switch (v->type) {        case integer:            return 1;        case string:            i = 0;            /* Don't interpret the empty string as an integer.  */            if (v->u.s == 0)                return 0;            i = atoi(v->u.s);            free (v->u.s);            v->u.i = i;            v->type = integer;            return 1;        default:            abort ();    }}/* Return nonzero if the next token matches STR exactly.   STR must not be NULL.  */static intnextarg (char *str){    if (*args == NULL)        return 0;    return strcmp (*args, str) == 0;}/* The comparison operator handling functions.  */#define cmpf(name, rel)                    \static int name (l, r) VALUE *l; VALUE *r;        \{                            \    if (l->type == string || r->type == string) {        \        tostring (l);                \        tostring (r);                \        return strcmp (l->u.s, r->u.s) rel 0;    \    }                        \    else                        \        return l->u.i rel r->u.i;        \} cmpf (less_than, <) cmpf (less_equal, <=) cmpf (equal, ==) cmpf (not_equal, !=) cmpf (greater_equal, >=) cmpf (greater_than, >)#undef cmpf/* The arithmetic operator handling functions.  */#define arithf(name, op)            \static                        \int name (l, r) VALUE *l; VALUE *r;        \{                        \  if (!toarith (l) || !toarith (r))        \    error_msg_and_die ("non-numeric argument");    \  return l->u.i op r->u.i;            \}#define arithdivf(name, op)            \static int name (l, r) VALUE *l; VALUE *r;        \{                        \  if (!toarith (l) || !toarith (r))        \    error_msg_and_die ( "non-numeric argument");    \  if (r->u.i == 0)                \    error_msg_and_die ( "division by zero");        \  return l->u.i op r->u.i;            \} arithf (plus, +) arithf (minus, -) arithf (multiply, *) arithdivf (divide, /) arithdivf (mod, %)#undef arithf#undef arithdivf/* Do the : operator.   SV is the VALUE for the lhs (the string),   PV is the VALUE for the rhs (the pattern).  */static VALUE *docolon (VALUE *sv, VALUE *pv){    VALUE *v;    const char *errmsg;    struct re_pattern_buffer re_buffer;    struct re_registers re_regs;    int len;    tostring (sv);    tostring (pv);    if (pv->u.s[0] == '^') {        fprintf (stderr, "\warning: unportable BRE: `%s': using `^' as the first character\n\of a basic regular expression is not portable; it is being ignored",        pv->u.s);    }    len = strlen (pv->u.s);    memset (&re_buffer, 0, sizeof (re_buffer));    memset (&re_regs, 0, sizeof (re_regs));    re_buffer.allocated = 2 * len;    re_buffer.buffer = (unsigned char *) xmalloc (re_buffer.allocated);    re_buffer.translate = 0;    re_syntax_options = RE_SYNTAX_POSIX_BASIC;    errmsg = re_compile_pattern (pv->u.s, len, &re_buffer);    if (errmsg) {        error_msg_and_die("%s", errmsg);    }    len = re_match (&re_buffer, sv->u.s, strlen (sv->u.s), 0, &re_regs);    if (len >= 0) {        /* Were \(...\) used? */        if (re_buffer.re_nsub > 0) { /* was (re_regs.start[1] >= 0) */            sv->u.s[re_regs.end[1]] = '\0';            v = str_value (sv->u.s + re_regs.start[1]);        }        else            v = int_value (len);    }    else {        /* Match failed -- return the right kind of null.  */        if (re_buffer.re_nsub > 0)            v = str_value ("");        else            v = int_value (0);    }    free (re_buffer.buffer);    return v;}/* Handle bare operands and ( expr ) syntax.  */static VALUE *eval7 (void){    VALUE *v;    if (!*args)        error_msg_and_die ( "syntax error");    if (nextarg ("(")) {        args++;        v = eval ();        if (!nextarg (")"))            error_msg_and_die ( "syntax error");            args++;            return v;        }    if (nextarg (")"))        error_msg_and_die ( "syntax error");    return str_value (*args++);}/* Handle match, substr, index, length, and quote keywords.  */static VALUE *eval6 (void){    VALUE *l, *r, *v, *i1, *i2;    if (nextarg ("quote")) {        args++;        if (!*args)            error_msg_and_die ( "syntax error");        return str_value (*args++);    }    else if (nextarg ("length")) {        args++;        r = eval6 ();        tostring (r);        v = int_value (strlen (r->u.s));        freev (r);        return v;    }    else if (nextarg ("match")) {        args++;        l = eval6 ();        r = eval6 ();        v = docolon (l, r);        freev (l);        freev (r);        return v;    }    else if (nextarg ("index")) {        args++;        l = eval6 ();        r = eval6 ();        tostring (l);        tostring (r);        v = int_value (strcspn (l->u.s, r->u.s) + 1);        if (v->u.i == (int) strlen (l->u.s) + 1)            v->u.i = 0;        freev (l);        freev (r);        return v;    }    else if (nextarg ("substr")) {        args++;        l = eval6 ();        i1 = eval6 ();        i2 = eval6 ();        tostring (l);        if (!toarith (i1) || !toarith (i2)            || i1->u.i > (int) strlen (l->u.s)            || i1->u.i <= 0 || i2->u.i <= 0)        v = str_value ("");        else {            v = xmalloc (sizeof(VALUE));            v->type = string;            v->u.s = strncpy ((char *) xmalloc (i2->u.i + 1),                l->u.s + i1->u.i - 1, i2->u.i);                v->u.s[i2->u.i] = 0;        }        freev (l);        freev (i1);        freev (i2);        return v;    }    else        return eval7 ();}/* Handle : operator (pattern matching).   Calls docolon to do the real work.  */static VALUE *eval5 (void){    VALUE *l, *r, *v;    l = eval6 ();    while (nextarg (":")) {        args++;        r = eval6 ();        v = docolon (l, r);        freev (l);        freev (r);        l = v;    }    return l;}/* Handle *, /, % operators.  */static VALUE *eval4 (void){    VALUE *l, *r;    int (*fxn) (), val;    l = eval5 ();    while (1) {        if (nextarg ("*"))            fxn = multiply;        else if (nextarg ("/"))            fxn = divide;        else if (nextarg ("%"))            fxn = mod;        else            return l;        args++;        r = eval5 ();        val = (*fxn) (l, r);        freev (l);        freev (r);        l = int_value (val);    }}/* Handle +, - operators.  */static VALUE *eval3 (void){    VALUE *l, *r;    int (*fxn) (), val;    l = eval4 ();    while (1) {        if (nextarg ("+"))            fxn = plus;        else if (nextarg ("-"))            fxn = minus;        else            return l;        args++;        r = eval4 ();        val = (*fxn) (l, r);        freev (l);        freev (r);        l = int_value (val);    }}/* Handle comparisons.  */static VALUE *eval2 (void){    VALUE *l, *r;    int (*fxn) (), val;    l = eval3 ();    while (1) {        if (nextarg ("<"))            fxn = less_than;        else if (nextarg ("<="))            fxn = less_equal;        else if (nextarg ("=") || nextarg ("=="))            fxn = equal;        else if (nextarg ("!="))            fxn = not_equal;        else if (nextarg (">="))            fxn = greater_equal;        else if (nextarg (">"))            fxn = greater_than;        else            return l;        args++;        r = eval3 ();        toarith (l);        toarith (r);        val = (*fxn) (l, r);        freev (l);        freev (r);        l = int_value (val);    }}/* Handle &.  */static VALUE *eval1 (void){    VALUE *l, *r;    l = eval2 ();    while (nextarg ("&")) {        args++;        r = eval2 ();        if (null (l) || null (r)) {            freev (l);            freev (r);            l = int_value (0);        }        else            freev (r);    }    return l;}/* Handle |.  */static VALUE *eval (void){    VALUE *l, *r;    l = eval1 ();    while (nextarg ("|")) {        args++;        r = eval1 ();        if (null (l)) {            freev (l);            l = r;        }        else            freev (r);    }    return l;} 

读书人网 >C++

热点推荐