diff options
-rw-r--r-- | evaluator.c | 125 |
1 files changed, 98 insertions, 27 deletions
diff --git a/evaluator.c b/evaluator.c index 6a99041..f3d72d7 100644 --- a/evaluator.c +++ b/evaluator.c @@ -118,12 +118,18 @@ typedef enum { O_COL, /* colon in a?b:c */ O_OR, /* logical OR */ O_AND, /* logical AND */ - O_EQ, /* equal */ - O_NE, /* not equal */ - O_LT, /* less than */ - O_LE, /* less or equal */ - O_GT, /* greater than */ - O_GE, /* greater or equal */ + O_NEQ, /* numeric equal */ + O_NNE, /* numeric not equal */ + O_NLT, /* numeric less than */ + O_NLE, /* numeric less or equal */ + O_NGT, /* numeric greater than */ + O_NGE, /* numeric greater or equal */ + O_SEQ, /* string equal */ + O_SNE, /* string not equal */ + O_SLT, /* string less than */ + O_SLE, /* string less or equal */ + O_SGT, /* string greater than */ + O_SGE, /* string greater or equal */ O_ADD, /* addition */ O_SUB, /* subtraction */ O_SGN, /* sign '-' */ @@ -167,17 +173,17 @@ typedef struct _NODE { -/* operators */ +/* non-alphanumeric operators */ /* IMPORTANT! list must be sorted by length! */ -static PATTERN Pattern[] = { +static PATTERN Pattern1[] = { {";", 1, O_LST}, /* expression lists */ {"=", 1, O_SET}, /* variable assignements */ {"?", 1, O_CND}, /* conditional a?b:c */ {":", 1, O_COL}, /* colon a?b:c */ {"|", 1, O_OR}, /* logical OR */ {"&", 1, O_AND}, /* logical AND */ - {"<", 1, O_LT}, /* less than */ - {">", 1, O_GT}, /* greater than */ + {"<", 1, O_NLT}, /* numeric less than */ + {">", 1, O_NGT}, /* numeric greater than */ {"+", 1, O_ADD}, /* addition */ {"-", 1, O_SUB}, /* subtraction or sign */ {".", 1, O_CAT}, /* string concatenation */ @@ -189,10 +195,21 @@ static PATTERN Pattern[] = { {"(", 1, O_BRO}, /* open brace */ {",", 1, O_COM}, /* comma (argument seperator) */ {")", 1, O_BRC}, /* closing brace */ - {"==", 2, O_EQ}, /* equal */ - {"!=", 2, O_NE}, /* not equal */ - {"<=", 2, O_LE}, /* less or equal */ - {">=", 2, O_GE} /* greater or equal */ + {"==", 2, O_NEQ}, /* numeric equal */ + {"!=", 2, O_NNE}, /* numeric not equal */ + {"<=", 2, O_NLE}, /* numeric less or equal */ + {">=", 2, O_NGE} /* numeric greater or equal */ +}; + +/* alphanumeric operators */ +/* IMPORTANT! list must be sorted by length! */ +static PATTERN Pattern2[] = { + {"eq", 2, O_SEQ}, /* string equal */ + {"ne", 2, O_SNE}, /* string not equal */ + {"lt", 2, O_SLT}, /* string less than */ + {"le", 2, O_SLE}, /* string less or equal */ + {"gt", 2, O_SGT}, /* string greater than */ + {"ge", 2, O_SGE} /* string greater or equal */ }; @@ -545,6 +562,7 @@ static void Parse(void) /* names */ if (is_alpha(*ExprPtr)) { + int i; char *start = ExprPtr; while (is_alnum(*ExprPtr)) ExprPtr++; @@ -555,6 +573,16 @@ static void Parse(void) } Word = strndup(start, ExprPtr - start); Token = T_NAME; + + /* check for alphanumeric operators */ + for (i = sizeof(Pattern2) / sizeof(Pattern2[0]) - 1; i >= 0; i--) { + if (strcmp(Word, Pattern2[i].pattern) == 0) { + Token = T_OPERATOR; + Operator = Pattern2[i].op; + break; + } + } + } /* numbers */ @@ -582,15 +610,15 @@ static void Parse(void) ExprPtr++; } - /* operators */ + /* non-alpha operators */ else { int i; - for (i = sizeof(Pattern) / sizeof(Pattern[0]) - 1; i >= 0; i--) { - int len = Pattern[i].len; - if (strncmp(ExprPtr, Pattern[i].pattern, Pattern[i].len) == 0) { + for (i = sizeof(Pattern1) / sizeof(Pattern1[0]) - 1; i >= 0; i--) { + int len = Pattern1[i].len; + if (strncmp(ExprPtr, Pattern1[i].pattern, Pattern1[i].len) == 0) { Word = strndup(ExprPtr, len); Token = T_OPERATOR; - Operator = Pattern[i].op; + Operator = Pattern1[i].op; ExprPtr += len; break; } @@ -842,7 +870,8 @@ static NODE *Level07(void) Root = Level08(); - while (Token == T_OPERATOR && (Operator == O_GT || Operator == O_GE || Operator == O_LT || Operator == O_LE)) { + while (Token == T_OPERATOR && (Operator == O_NGT || Operator == O_NGE || Operator == O_NLT || Operator == O_NLE || + Operator == O_SGT || Operator == O_SGE || Operator == O_SLT || Operator == O_SLE)) { Root = NewNode(Root); Parse(); LinkNode(Root, Level08()); @@ -859,7 +888,7 @@ static NODE *Level06(void) Root = Level07(); - while (Token == T_OPERATOR && (Operator == O_EQ || Operator == O_NE)) { + while (Token == T_OPERATOR && (Operator == O_NEQ || Operator == O_NNE || Operator == O_SEQ || Operator == O_SNE)) { Root = NewNode(Root); Parse(); LinkNode(Root, Level07()); @@ -1066,48 +1095,90 @@ static int EvalTree(NODE * Root) } break; - case O_EQ: /* numeric equal */ + case O_NEQ: /* numeric equal */ type = R_NUMBER; EvalTree(Root->Child[0]); EvalTree(Root->Child[1]); number = (R2N(Root->Child[0]->Result) == R2N(Root->Child[1]->Result)); break; - case O_NE: /* numeric not equal */ + case O_NNE: /* numeric not equal */ type = R_NUMBER; EvalTree(Root->Child[0]); EvalTree(Root->Child[1]); number = (R2N(Root->Child[0]->Result) != R2N(Root->Child[1]->Result)); break; - case O_LT: /* numeric less than */ + case O_NLT: /* numeric less than */ type = R_NUMBER; EvalTree(Root->Child[0]); EvalTree(Root->Child[1]); number = (R2N(Root->Child[0]->Result) < R2N(Root->Child[1]->Result)); break; - case O_LE: /* numeric less equal */ + case O_NLE: /* numeric less equal */ type = R_NUMBER; EvalTree(Root->Child[0]); EvalTree(Root->Child[1]); number = (R2N(Root->Child[0]->Result) <= R2N(Root->Child[1]->Result)); break; - case O_GT: /* numeric greater than */ + case O_NGT: /* numeric greater than */ type = R_NUMBER; EvalTree(Root->Child[0]); EvalTree(Root->Child[1]); number = (R2N(Root->Child[0]->Result) > R2N(Root->Child[1]->Result)); break; - case O_GE: /* numeric greater equal */ + case O_NGE: /* numeric greater equal */ type = R_NUMBER; EvalTree(Root->Child[0]); EvalTree(Root->Child[1]); number = (R2N(Root->Child[0]->Result) >= R2N(Root->Child[1]->Result)); break; + case O_SEQ: /* string equal */ + type = R_NUMBER; + EvalTree(Root->Child[0]); + EvalTree(Root->Child[1]); + number = (strcmp(R2S(Root->Child[0]->Result), R2S(Root->Child[1]->Result)) == 0); + break; + + case O_SNE: /* string not equal */ + type = R_NUMBER; + EvalTree(Root->Child[0]); + EvalTree(Root->Child[1]); + number = (strcmp(R2S(Root->Child[0]->Result), R2S(Root->Child[1]->Result)) != 0); + break; + + case O_SLT: /* string less than */ + type = R_NUMBER; + EvalTree(Root->Child[0]); + EvalTree(Root->Child[1]); + number = (strcmp(R2S(Root->Child[0]->Result), R2S(Root->Child[1]->Result)) < 0); + break; + + case O_SLE: /* string less equal */ + type = R_NUMBER; + EvalTree(Root->Child[0]); + EvalTree(Root->Child[1]); + number = (strcmp(R2S(Root->Child[0]->Result), R2S(Root->Child[1]->Result)) <= 0); + break; + + case O_SGT: /* string greater than */ + type = R_NUMBER; + EvalTree(Root->Child[0]); + EvalTree(Root->Child[1]); + number = (strcmp(R2S(Root->Child[0]->Result), R2S(Root->Child[1]->Result)) > 0); + break; + + case O_SGE: /* string greater equal */ + type = R_NUMBER; + EvalTree(Root->Child[0]); + EvalTree(Root->Child[1]); + number = (strcmp(R2S(Root->Child[0]->Result), R2S(Root->Child[1]->Result)) >= 0); + break; + case O_ADD: /* addition */ type = R_NUMBER; EvalTree(Root->Child[0]); |