Browse Source

[4231] Added and & or operators

Francis Dupont 9 years ago
parent
commit
d0ee0b0811

+ 122 - 98
src/lib/eval/lexer.cc

@@ -469,8 +469,8 @@ static void yy_fatal_error (yyconst char msg[]  );
 	(yy_c_buf_p) = yy_cp;
 
 /* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */
-#define YY_NUM_RULES 22
-#define YY_END_OF_BUFFER 23
+#define YY_NUM_RULES 24
+#define YY_END_OF_BUFFER 25
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -478,31 +478,31 @@ struct yy_trans_info
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	};
-static yyconst flex_int16_t yy_acclist[105] =
+static yyconst flex_int16_t yy_acclist[110] =
     {   0,
-       23,   21,   22,    1,   21,   22,    2,   22,   21,   22,
-       16,   21,   22,   17,   21,   22,   20,   21,   22,   21,
-       22,   15,   21,   22,    5,   21,   22,    5,   21,   22,
-       21,   22,   21,   22,16390,   18,   21,   22,   19,   21,
-       22,   21,   22,16390,   21,   22,16390,   21,   22,16390,
-       21,   22,16390,   21,   22,16390,   21,   22,16390,   21,
-       22,16390,    1,    2,    3,    5,    7,16390, 8198,16390,
-    16390,16390,16390,16390,16390,16390,    4,   13,16390,16390,
-       10,16390,   14,16390,16390,16390,16390,16390,16390,16390,
-        9,16390,16390,16390,16390,   11,16390,    8,16390,16390,
-
-    16390,16390,   12,16390
+       25,   23,   24,    1,   23,   24,    2,   24,   23,   24,
+       18,   23,   24,   19,   23,   24,   22,   23,   24,   23,
+       24,   17,   23,   24,    5,   23,   24,    5,   23,   24,
+       23,   24,   23,   24,16390,   20,   23,   24,   21,   23,
+       24,   23,   24,16390,   23,   24,16390,   23,   24,16390,
+       23,   24,16390,   23,   24,16390,   23,   24,16390,   23,
+       24,16390,    1,    2,    3,    5,    7,16390, 8198,16390,
+    16390,16390,16390,16390,16390,   16,16390,16390,16390,    4,
+       13,16390,   15,16390,16390,   10,16390,   14,16390,16390,
+    16390,16390,16390,16390,16390,    9,16390,16390,16390,16390,
+
+       11,16390,    8,16390,16390,16390,16390,   12,16390
     } ;
 
-static yyconst flex_int16_t yy_accept[67] =
+static yyconst flex_int16_t yy_accept[70] =
     {   0,
         1,    1,    1,    2,    4,    7,    9,   11,   14,   17,
        20,   22,   25,   28,   31,   33,   36,   39,   42,   45,
        48,   51,   54,   57,   60,   63,   64,   65,   65,   66,
        67,   67,   68,   68,   68,   69,   70,   71,   72,   73,
-       74,   75,   76,   77,   78,   80,   81,   83,   85,   86,
-       87,   88,   89,   90,   91,   93,   94,   95,   96,   98,
-      100,  101,  102,  103,  105,  105
+       74,   75,   76,   78,   79,   80,   81,   83,   85,   86,
+       88,   90,   91,   92,   93,   94,   95,   96,   98,   99,
+      100,  101,  103,  105,  106,  107,  108,  110,  110
     } ;
 
 static yyconst flex_int32_t yy_ec[256] =
@@ -516,10 +516,10 @@ static yyconst flex_int32_t yy_ec[256] =
        12,    1,    1,    1,   13,   13,   13,   13,   13,   13,
        14,   14,   14,   14,   14,   14,   14,   14,   14,   14,
        14,   14,   14,   14,   14,   14,   14,   15,   14,   14,
-       16,    1,   17,    1,   18,    1,   19,   20,   13,   13,
+       16,    1,   17,    1,   18,    1,   19,   20,   13,   21,
 
-       21,   13,   22,   23,   24,   14,   14,   25,   14,   26,
-       27,   28,   14,   29,   30,   31,   32,   14,   14,   33,
+       22,   13,   23,   24,   25,   14,   14,   26,   14,   27,
+       28,   29,   14,   30,   31,   32,   33,   14,   14,   34,
        14,   14,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -537,94 +537,108 @@ static yyconst flex_int32_t yy_ec[256] =
         1,    1,    1,    1,    1
     } ;
 
-static yyconst flex_int32_t yy_meta[34] =
+static yyconst flex_int32_t yy_meta[35] =
     {   0,
         1,    2,    3,    1,    1,    1,    1,    2,    1,    4,
         4,    1,    4,    2,    2,    1,    2,    2,    4,    4,
-        4,    2,    2,    2,    2,    2,    2,    2,    2,    2,
-        2,    2,    2
+        4,    4,    2,    2,    2,    2,    2,    2,    2,    2,
+        2,    2,    2,    2
     } ;
 
-static yyconst flex_int16_t yy_base[69] =
+static yyconst flex_int16_t yy_base[72] =
     {   0,
-        0,    0,  135,  136,  132,  130,  128,  136,  136,  136,
-       24,  136,   26,   28,  119,   58,  136,  136,   75,   15,
-       21,   18,   19,   24,   29,  128,  126,  124,  136,   41,
-        0,  136,   55,   62,  102,  136,  101,   38,   48,   43,
-       55,   64,   57,    0,  100,   66,   99,   98,   45,   69,
-       70,   72,   28,   73,   97,   77,   80,   42,   96,   95,
-       84,   85,   63,   94,  136,  111,  114,  110
+        0,    0,   95,  184,   83,   73,   70,  184,  184,  184,
+       25,  184,   27,   29,   48,   41,  184,  184,   60,   19,
+       25,   28,   40,   38,   53,   55,   47,   44,  184,   62,
+        0,  184,   79,   81,   62,  184,   64,   73,   76,   78,
+       83,   87,   66,   91,   94,    0,   96,   98,  100,  103,
+      106,  109,  111,  113,  117,  120,  124,  126,  128,  131,
+      134,  136,  139,  142,  144,  149,  147,  184,  176,  179,
+       37
     } ;
 
-static yyconst flex_int16_t yy_def[69] =
+static yyconst flex_int16_t yy_def[72] =
     {   0,
-       65,    1,   65,   65,   65,   65,   66,   65,   65,   65,
-       65,   65,   65,   65,   65,   67,   65,   65,   67,   19,
-       19,   19,   19,   19,   19,   65,   65,   66,   65,   65,
-       68,   65,   65,   19,   19,   65,   19,   19,   19,   19,
-       19,   19,   19,   68,   19,   19,   19,   19,   19,   19,
+       68,    1,   68,   68,   68,   68,   69,   68,   68,   68,
+       68,   68,   68,   68,   68,   70,   68,   68,   70,   19,
+       19,   19,   19,   19,   19,   68,   68,   69,   68,   68,
+       71,   68,   68,   19,   19,   68,   19,   19,   19,   19,
+       19,   19,   19,   19,   19,   71,   19,   19,   19,   19,
        19,   19,   19,   19,   19,   19,   19,   19,   19,   19,
-       19,   19,   19,   19,    0,   65,   65,   65
+       19,   19,   19,   19,   19,   19,   19,    0,   68,   68,
+       68
     } ;
 
-static yyconst flex_int16_t yy_nxt[170] =
+static yyconst flex_int16_t yy_nxt[219] =
     {   0,
         4,    5,    6,    7,    8,    9,   10,   11,   12,   13,
        14,   15,   16,   16,   16,   17,   18,    4,   19,   16,
-       20,   16,   21,   16,   16,   22,   23,   16,   16,   24,
-       25,   16,   16,   30,   30,   30,   30,   30,   30,   35,
-       31,   39,   35,   35,   40,   35,   41,   38,   35,   43,
-       30,   30,   35,   35,   57,   42,   33,   33,   31,   33,
-       33,   46,   35,   65,   65,   34,   35,   35,   53,   35,
-       61,   36,   35,   48,   36,   34,   33,   33,   65,   35,
-       47,   35,   34,   50,   64,   49,   35,   35,   35,   51,
-       35,   36,   34,   35,   35,   52,   35,   35,   54,   37,
-
-       55,   35,   56,   58,   35,   60,   59,   62,   35,   35,
-       63,   28,   28,   44,   28,   35,   35,   35,   35,   35,
-       35,   35,   35,   35,   35,   45,   35,   29,   27,   26,
-       32,   29,   27,   26,   65,    3,   65,   65,   65,   65,
-       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-       65,   65,   65,   65,   65,   65,   65,   65,   65
+       16,   20,   16,   21,   16,   16,   22,   23,   16,   16,
+       24,   25,   16,   16,   30,   30,   30,   30,   30,   30,
+       46,   31,   33,   33,   35,   35,   40,   29,   34,   27,
+       35,   35,   39,   35,   35,   41,   26,   36,   34,   32,
+       31,   33,   33,   35,   35,   35,   35,   34,   42,   43,
+       44,   30,   30,   29,   45,   27,   36,   34,   35,   35,
+       33,   33,   68,   68,   26,   37,   38,   35,   35,   47,
+       35,   35,   35,   48,   68,   36,   68,   68,   35,   35,
+
+       49,   35,   35,   35,   35,   68,   35,   35,   35,   35,
+       53,   50,   35,   35,   51,   68,   35,   35,   52,   35,
+       35,   35,   35,   35,   35,   35,   35,   54,   35,   35,
+       55,   35,   35,   56,   35,   35,   35,   35,   35,   35,
+       68,   57,   35,   35,   58,   35,   35,   60,   59,   35,
+       35,   35,   35,   35,   35,   61,   35,   63,   62,   35,
+       35,   35,   35,   64,   35,   35,   65,   35,   35,   35,
+       66,   67,   35,   35,   35,   35,   28,   28,   68,   28,
+       35,   35,   35,    3,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68
     } ;
 
-static yyconst flex_int16_t yy_chk[170] =
+static yyconst flex_int16_t yy_chk[219] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,   11,   11,   13,   13,   14,   14,   20,
-       13,   21,   22,   23,   22,   21,   23,   20,   24,   25,
-       30,   30,   53,   25,   53,   24,   33,   33,   13,   16,
-       16,   38,   38,   34,   34,   16,   58,   40,   49,   49,
-       58,   33,   39,   40,   16,   16,   19,   19,   34,   41,
-       39,   43,   19,   42,   63,   41,   34,   63,   42,   43,
-       46,   19,   19,   50,   51,   46,   52,   54,   50,   19,
-
-       51,   56,   52,   54,   57,   57,   56,   61,   61,   62,
-       62,   66,   66,   68,   66,   67,   67,   67,   64,   60,
-       59,   55,   48,   47,   45,   37,   35,   28,   27,   26,
-       15,    7,    6,    5,    3,   65,   65,   65,   65,   65,
-       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-       65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
-       65,   65,   65,   65,   65,   65,   65,   65,   65
+        1,    1,    1,    1,   11,   11,   13,   13,   14,   14,
+       71,   13,   16,   16,   20,   20,   21,   28,   16,   27,
+       21,   21,   20,   22,   22,   22,   26,   16,   16,   15,
+       13,   19,   19,   24,   24,   23,   23,   19,   23,   23,
+       24,   30,   30,    7,   25,    6,   19,   19,   25,   25,
+       33,   33,   34,   34,    5,   19,   19,   35,   35,   37,
+       37,   43,   43,   38,    3,   33,    0,   34,   38,   38,
+
+       39,   39,   39,   40,   40,    0,   34,   34,   41,   41,
+       44,   40,   42,   42,   41,    0,   44,   44,   42,   45,
+       45,   47,   47,   48,   48,   49,   49,   45,   50,   50,
+       49,   51,   51,   52,   52,   52,   53,   53,   54,   54,
+        0,   53,   55,   55,   54,   56,   56,   56,   55,   57,
+       57,   58,   58,   59,   59,   57,   60,   60,   59,   61,
+       61,   62,   62,   61,   63,   63,   64,   64,   64,   65,
+       65,   66,   67,   67,   66,   66,   69,   69,    0,   69,
+       70,   70,   70,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+
+       68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+       68,   68,   68,   68,   68,   68,   68,   68
     } ;
 
 /* Table of booleans, true if rule could match eol. */
-static yyconst flex_int32_t yy_rule_can_match_eol[23] =
+static yyconst flex_int32_t yy_rule_can_match_eol[25] =
     {   0,
 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0,     };
+    0, 0, 0, 0, 0,     };
 
 extern int yy_flex_debug;
 int yy_flex_debug = 1;
 
-static yyconst flex_int16_t yy_rule_linenum[22] =
+static yyconst flex_int16_t yy_rule_linenum[24] =
     {   0,
        86,   90,   96,  106,  112,  126,  133,  134,  135,  136,
       137,  138,  139,  140,  141,  142,  143,  144,  145,  146,
-      148
+      147,  148,  150
     } ;
 
 static yy_state_type *yy_state_buf=0, *yy_state_ptr=0;
@@ -709,7 +723,7 @@ static isc::eval::location loc;
 // by moving it ahead by yyleng bytes. yyleng specifies the length of the
 // currently matched token.
 #define YY_USER_ACTION  loc.columns(yyleng);
-#line 713 "lexer.cc"
+#line 727 "lexer.cc"
 
 #define INITIAL 0
 
@@ -998,7 +1012,7 @@ YY_DECL
     loc.step();
 
 
-#line 1002 "lexer.cc"
+#line 1016 "lexer.cc"
 
 	while ( 1 )		/* loops until end-of-file is reached */
 		{
@@ -1026,14 +1040,14 @@ yy_match:
 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 				{
 				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 66 )
+				if ( yy_current_state >= 69 )
 					yy_c = yy_meta[(unsigned int) yy_c];
 				}
 			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
 			*(yy_state_ptr)++ = yy_current_state;
 			++yy_cp;
 			}
-		while ( yy_current_state != 65 );
+		while ( yy_current_state != 68 );
 
 yy_find_action:
 /* %% [10.0] code to find the action number goes here */
@@ -1096,13 +1110,13 @@ do_action:	/* This label is used only to access EOF actions. */
 			{
 			if ( yy_act == 0 )
 				fprintf( stderr, "--scanner backing up\n" );
-			else if ( yy_act < 22 )
+			else if ( yy_act < 24 )
 				fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n",
 				         (long)yy_rule_linenum[yy_act], yytext );
-			else if ( yy_act == 22 )
+			else if ( yy_act == 24 )
 				fprintf( stderr, "--accepting default rule (\"%s\")\n",
 				         yytext );
-			else if ( yy_act == 23 )
+			else if ( yy_act == 25 )
 				fprintf( stderr, "--(end of buffer or a NUL)\n" );
 			else
 				fprintf( stderr, "--EOF (start condition %d)\n", YY_START );
@@ -1222,48 +1236,58 @@ return isc::eval::EvalParser::make_NOT(loc);
 case 15:
 YY_RULE_SETUP
 #line 141 "lexer.ll"
-return isc::eval::EvalParser::make_DOT(loc);
+return isc::eval::EvalParser::make_AND(loc);
 	YY_BREAK
 case 16:
 YY_RULE_SETUP
 #line 142 "lexer.ll"
-return isc::eval::EvalParser::make_LPAREN(loc);
+return isc::eval::EvalParser::make_OR(loc);
 	YY_BREAK
 case 17:
 YY_RULE_SETUP
 #line 143 "lexer.ll"
-return isc::eval::EvalParser::make_RPAREN(loc);
+return isc::eval::EvalParser::make_DOT(loc);
 	YY_BREAK
 case 18:
 YY_RULE_SETUP
 #line 144 "lexer.ll"
-return isc::eval::EvalParser::make_LBRACKET(loc);
+return isc::eval::EvalParser::make_LPAREN(loc);
 	YY_BREAK
 case 19:
 YY_RULE_SETUP
 #line 145 "lexer.ll"
-return isc::eval::EvalParser::make_RBRACKET(loc);
+return isc::eval::EvalParser::make_RPAREN(loc);
 	YY_BREAK
 case 20:
 YY_RULE_SETUP
 #line 146 "lexer.ll"
-return isc::eval::EvalParser::make_COMA(loc);
+return isc::eval::EvalParser::make_LBRACKET(loc);
 	YY_BREAK
 case 21:
 YY_RULE_SETUP
+#line 147 "lexer.ll"
+return isc::eval::EvalParser::make_RBRACKET(loc);
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
 #line 148 "lexer.ll"
+return isc::eval::EvalParser::make_COMA(loc);
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 150 "lexer.ll"
 driver.error (loc, "Invalid character: " + std::string(yytext));
 	YY_BREAK
 case YY_STATE_EOF(INITIAL):
-#line 149 "lexer.ll"
+#line 151 "lexer.ll"
 return isc::eval::EvalParser::make_END(loc);
 	YY_BREAK
-case 22:
+case 24:
 YY_RULE_SETUP
-#line 150 "lexer.ll"
+#line 152 "lexer.ll"
 ECHO;
 	YY_BREAK
-#line 1267 "lexer.cc"
+#line 1291 "lexer.cc"
 
 	case YY_END_OF_BUFFER:
 		{
@@ -1544,7 +1568,7 @@ static int yy_get_next_buffer (void)
 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 			{
 			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 66 )
+			if ( yy_current_state >= 69 )
 				yy_c = yy_meta[(unsigned int) yy_c];
 			}
 		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1572,11 +1596,11 @@ static int yy_get_next_buffer (void)
 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 		{
 		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 66 )
+		if ( yy_current_state >= 69 )
 			yy_c = yy_meta[(unsigned int) yy_c];
 		}
 	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-	yy_is_jam = (yy_current_state == 65);
+	yy_is_jam = (yy_current_state == 68);
 	if ( ! yy_is_jam )
 		*(yy_state_ptr)++ = yy_current_state;
 
@@ -2324,7 +2348,7 @@ void yyfree (void * ptr )
 
 /* %ok-for-header */
 
-#line 150 "lexer.ll"
+#line 152 "lexer.ll"
 
 
 

+ 2 - 0
src/lib/eval/lexer.ll

@@ -138,6 +138,8 @@ blank [ \t]
 "substring" return isc::eval::EvalParser::make_SUBSTRING(loc);
 "all"       return isc::eval::EvalParser::make_ALL(loc);
 "not"       return isc::eval::EvalParser::make_NOT(loc);
+"and"       return isc::eval::EvalParser::make_AND(loc);
+"or"        return isc::eval::EvalParser::make_OR(loc);
 "."         return isc::eval::EvalParser::make_DOT(loc);
 "("         return isc::eval::EvalParser::make_LPAREN(loc);
 ")"         return isc::eval::EvalParser::make_RPAREN(loc);

+ 1 - 1
src/lib/eval/location.hh

@@ -1,4 +1,4 @@
-// Generated 20151207
+// Generated 20151209
 // A Bison parser, made by GNU Bison 3.0.4.
 
 // Locations for Bison parsers in C++

+ 135 - 114
src/lib/eval/parser.cc

@@ -251,19 +251,19 @@ namespace isc { namespace eval {
   {
       switch (that.type_get ())
     {
-      case 27: // option_repr_type
+      case 29: // option_repr_type
         value.move< TokenOption::RepresentationType > (that.value);
         break;
 
-      case 17: // "constant string"
-      case 18: // "integer"
-      case 19: // "constant hexstring"
-      case 20: // "option name"
-      case 21: // TOKEN
+      case 19: // "constant string"
+      case 20: // "integer"
+      case 21: // "constant hexstring"
+      case 22: // "option name"
+      case 23: // TOKEN
         value.move< std::string > (that.value);
         break;
 
-      case 26: // option_code
+      case 28: // option_code
         value.move< uint16_t > (that.value);
         break;
 
@@ -282,19 +282,19 @@ namespace isc { namespace eval {
     state = that.state;
       switch (that.type_get ())
     {
-      case 27: // option_repr_type
+      case 29: // option_repr_type
         value.copy< TokenOption::RepresentationType > (that.value);
         break;
 
-      case 17: // "constant string"
-      case 18: // "integer"
-      case 19: // "constant hexstring"
-      case 20: // "option name"
-      case 21: // TOKEN
+      case 19: // "constant string"
+      case 20: // "integer"
+      case 21: // "constant hexstring"
+      case 22: // "option name"
+      case 23: // TOKEN
         value.copy< std::string > (that.value);
         break;
 
-      case 26: // option_code
+      case 28: // option_code
         value.copy< uint16_t > (that.value);
         break;
 
@@ -334,51 +334,51 @@ namespace isc { namespace eval {
         << yysym.location << ": ";
     switch (yytype)
     {
-            case 17: // "constant string"
+            case 19: // "constant string"
 
-#line 72 "parser.yy" // lalr1.cc:636
+#line 78 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< std::string > (); }
 #line 342 "parser.cc" // lalr1.cc:636
         break;
 
-      case 18: // "integer"
+      case 20: // "integer"
 
-#line 72 "parser.yy" // lalr1.cc:636
+#line 78 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< std::string > (); }
 #line 349 "parser.cc" // lalr1.cc:636
         break;
 
-      case 19: // "constant hexstring"
+      case 21: // "constant hexstring"
 
-#line 72 "parser.yy" // lalr1.cc:636
+#line 78 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< std::string > (); }
 #line 356 "parser.cc" // lalr1.cc:636
         break;
 
-      case 20: // "option name"
+      case 22: // "option name"
 
-#line 72 "parser.yy" // lalr1.cc:636
+#line 78 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< std::string > (); }
 #line 363 "parser.cc" // lalr1.cc:636
         break;
 
-      case 21: // TOKEN
+      case 23: // TOKEN
 
-#line 72 "parser.yy" // lalr1.cc:636
+#line 78 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< std::string > (); }
 #line 370 "parser.cc" // lalr1.cc:636
         break;
 
-      case 26: // option_code
+      case 28: // option_code
 
-#line 72 "parser.yy" // lalr1.cc:636
+#line 78 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< uint16_t > (); }
 #line 377 "parser.cc" // lalr1.cc:636
         break;
 
-      case 27: // option_repr_type
+      case 29: // option_repr_type
 
-#line 72 "parser.yy" // lalr1.cc:636
+#line 78 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< TokenOption::RepresentationType > (); }
 #line 384 "parser.cc" // lalr1.cc:636
         break;
@@ -580,19 +580,19 @@ namespace isc { namespace eval {
          when using variants.  */
         switch (yyr1_[yyn])
     {
-      case 27: // option_repr_type
+      case 29: // option_repr_type
         yylhs.value.build< TokenOption::RepresentationType > ();
         break;
 
-      case 17: // "constant string"
-      case 18: // "integer"
-      case 19: // "constant hexstring"
-      case 20: // "option name"
-      case 21: // TOKEN
+      case 19: // "constant string"
+      case 20: // "integer"
+      case 21: // "constant hexstring"
+      case 22: // "option name"
+      case 23: // TOKEN
         yylhs.value.build< std::string > ();
         break;
 
-      case 26: // option_code
+      case 28: // option_code
         yylhs.value.build< uint16_t > ();
         break;
 
@@ -614,7 +614,7 @@ namespace isc { namespace eval {
           switch (yyn)
             {
   case 4:
-#line 86 "parser.yy" // lalr1.cc:859
+#line 92 "parser.yy" // lalr1.cc:859
     {
                     TokenPtr neg(new TokenNot());
                     ctx.expression.push_back(neg);
@@ -623,120 +623,138 @@ namespace isc { namespace eval {
     break;
 
   case 5:
-#line 91 "parser.yy" // lalr1.cc:859
+#line 97 "parser.yy" // lalr1.cc:859
     {
-                    TokenPtr eq(new TokenEqual());
-                    ctx.expression.push_back(eq);
+                    TokenPtr neg(new TokenAnd());
+                    ctx.expression.push_back(neg);
                 }
 #line 632 "parser.cc" // lalr1.cc:859
     break;
 
   case 6:
-#line 96 "parser.yy" // lalr1.cc:859
+#line 102 "parser.yy" // lalr1.cc:859
     {
-                    TokenPtr opt(new TokenOption(yystack_[3].value.as< uint16_t > (), TokenOption::EXISTS));
-                    ctx.expression.push_back(opt);
+                    TokenPtr neg(new TokenOr());
+                    ctx.expression.push_back(neg);
                 }
 #line 641 "parser.cc" // lalr1.cc:859
     break;
 
   case 7:
-#line 103 "parser.yy" // lalr1.cc:859
+#line 107 "parser.yy" // lalr1.cc:859
+    {
+                    TokenPtr eq(new TokenEqual());
+                    ctx.expression.push_back(eq);
+                }
+#line 650 "parser.cc" // lalr1.cc:859
+    break;
+
+  case 8:
+#line 112 "parser.yy" // lalr1.cc:859
+    {
+                    TokenPtr opt(new TokenOption(yystack_[3].value.as< uint16_t > (), TokenOption::EXISTS));
+                    ctx.expression.push_back(opt);
+                }
+#line 659 "parser.cc" // lalr1.cc:859
+    break;
+
+  case 9:
+#line 119 "parser.yy" // lalr1.cc:859
     {
                       TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
                       ctx.expression.push_back(str);
                   }
-#line 650 "parser.cc" // lalr1.cc:859
+#line 668 "parser.cc" // lalr1.cc:859
     break;
 
-  case 8:
-#line 108 "parser.yy" // lalr1.cc:859
+  case 10:
+#line 124 "parser.yy" // lalr1.cc:859
     {
                       TokenPtr hex(new TokenHexString(yystack_[0].value.as< std::string > ()));
                       ctx.expression.push_back(hex);
                   }
-#line 659 "parser.cc" // lalr1.cc:859
+#line 677 "parser.cc" // lalr1.cc:859
     break;
 
-  case 9:
-#line 113 "parser.yy" // lalr1.cc:859
+  case 11:
+#line 129 "parser.yy" // lalr1.cc:859
     {
                       TokenPtr opt(new TokenOption(yystack_[3].value.as< uint16_t > (), yystack_[0].value.as< TokenOption::RepresentationType > ()));
                       ctx.expression.push_back(opt);
                   }
-#line 668 "parser.cc" // lalr1.cc:859
+#line 686 "parser.cc" // lalr1.cc:859
     break;
 
-  case 10:
-#line 118 "parser.yy" // lalr1.cc:859
+  case 12:
+#line 134 "parser.yy" // lalr1.cc:859
     {
                       TokenPtr sub(new TokenSubstring());
                       ctx.expression.push_back(sub);
                   }
-#line 677 "parser.cc" // lalr1.cc:859
+#line 695 "parser.cc" // lalr1.cc:859
     break;
 
-  case 12:
-#line 127 "parser.yy" // lalr1.cc:859
+  case 14:
+#line 143 "parser.yy" // lalr1.cc:859
     {
                      yylhs.value.as< uint16_t > () = ctx.convertOptionCode(yystack_[0].value.as< std::string > (), yystack_[0].location);
                  }
-#line 685 "parser.cc" // lalr1.cc:859
+#line 703 "parser.cc" // lalr1.cc:859
     break;
 
-  case 13:
-#line 131 "parser.yy" // lalr1.cc:859
+  case 15:
+#line 147 "parser.yy" // lalr1.cc:859
     {
                      yylhs.value.as< uint16_t > () = ctx.convertOptionName(yystack_[0].value.as< std::string > (), yystack_[0].location);
                  }
-#line 693 "parser.cc" // lalr1.cc:859
+#line 711 "parser.cc" // lalr1.cc:859
     break;
 
-  case 14:
-#line 137 "parser.yy" // lalr1.cc:859
+  case 16:
+#line 153 "parser.yy" // lalr1.cc:859
     {
                           yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::TEXTUAL;
                       }
-#line 701 "parser.cc" // lalr1.cc:859
+#line 719 "parser.cc" // lalr1.cc:859
     break;
 
-  case 15:
-#line 141 "parser.yy" // lalr1.cc:859
+  case 17:
+#line 157 "parser.yy" // lalr1.cc:859
     {
                           yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::HEXADECIMAL;
                       }
-#line 709 "parser.cc" // lalr1.cc:859
+#line 727 "parser.cc" // lalr1.cc:859
     break;
 
-  case 16:
-#line 147 "parser.yy" // lalr1.cc:859
+  case 18:
+#line 163 "parser.yy" // lalr1.cc:859
     {
                      TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
                      ctx.expression.push_back(str);
                  }
-#line 718 "parser.cc" // lalr1.cc:859
+#line 736 "parser.cc" // lalr1.cc:859
     break;
 
-  case 17:
-#line 154 "parser.yy" // lalr1.cc:859
+  case 19:
+#line 170 "parser.yy" // lalr1.cc:859
     {
                       TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
                       ctx.expression.push_back(str);
                   }
-#line 727 "parser.cc" // lalr1.cc:859
+#line 745 "parser.cc" // lalr1.cc:859
     break;
 
-  case 18:
-#line 159 "parser.yy" // lalr1.cc:859
+  case 20:
+#line 175 "parser.yy" // lalr1.cc:859
     {
                      TokenPtr str(new TokenString("all"));
                      ctx.expression.push_back(str);
                  }
-#line 736 "parser.cc" // lalr1.cc:859
+#line 754 "parser.cc" // lalr1.cc:859
     break;
 
 
-#line 740 "parser.cc" // lalr1.cc:859
+#line 758 "parser.cc" // lalr1.cc:859
             default:
               break;
             }
@@ -998,77 +1016,79 @@ namespace isc { namespace eval {
   const signed char
   EvalParser::yypact_[] =
   {
-      -4,    -7,    15,    -4,    -4,   -14,   -14,   -14,    12,   -14,
-      11,   -13,    -1,   -14,    16,   -14,    -1,   -14,   -14,    13,
-      18,    19,   -14,   -14,    21,   -13,    20,    14,    24,   -14,
-      22,   -14,   -14,   -14,   -14,    25,     1,    17,   -14,   -14,
-      27,   -14
+      -4,    -9,    -5,    -4,    -4,   -14,   -14,   -14,    35,    20,
+      18,   -13,    -1,   -14,    -2,   -14,    -4,    -4,    -1,   -14,
+     -14,    19,    22,    26,   -14,   -14,    29,   -14,    25,   -13,
+      23,    21,    27,   -14,    28,   -14,   -14,   -14,   -14,    31,
+       4,    24,   -14,   -14,    30,   -14
   };
 
   const unsigned char
   EvalParser::yydefact_[] =
   {
-       0,     0,     0,     0,     0,     7,     8,    11,     0,     2,
-       0,     0,     0,     4,     0,     1,     0,    12,    13,     0,
-       0,     0,     3,     5,     0,     0,     0,     0,     0,    16,
-       0,    14,    15,     6,     9,     0,     0,     0,    18,    17,
-       0,    10
+       0,     0,     0,     0,     0,     9,    10,    13,     0,     2,
+       0,     0,     0,     4,     0,     1,     0,     0,     0,    14,
+      15,     0,     0,     0,     3,     5,     6,     7,     0,     0,
+       0,     0,     0,    18,     0,    16,    17,     8,    11,     0,
+       0,     0,    20,    19,     0,    12
   };
 
   const signed char
   EvalParser::yypgoto_[] =
   {
-     -14,   -14,    23,    -6,    10,   -14,   -14,   -14
+     -14,   -14,     9,    11,    12,   -14,   -14,   -14
   };
 
   const signed char
   EvalParser::yydefgoto_[] =
   {
-      -1,     8,     9,    10,    19,    34,    30,    40
+      -1,     8,     9,    10,    21,    38,    34,    44
   };
 
   const unsigned char
   EvalParser::yytable_[] =
   {
-       1,     2,     3,    20,     2,    17,    21,    18,    11,     4,
-      23,    38,    15,     5,    16,     6,     5,     7,     6,    39,
-       7,    31,    32,    33,    31,    32,    13,    14,    12,    24,
-      22,    26,    27,    25,    36,    28,    37,     0,    29,     0,
-      35,    41
+       1,     2,     3,    22,     2,    16,    17,    19,    11,    20,
+      12,     4,    13,    14,    24,     5,    42,     6,     5,     7,
+       6,    18,     7,    23,    43,    25,    26,    16,    17,    27,
+      35,    36,    37,    35,    36,    15,    16,    28,    31,    29,
+      30,    32,    40,    33,    41,    39,    45
   };
 
-  const signed char
+  const unsigned char
   EvalParser::yycheck_[] =
   {
-       4,     5,     6,     4,     5,    18,    12,    20,    15,    13,
-      16,    10,     0,    17,     3,    19,    17,    21,    19,    18,
-      21,     7,     8,     9,     7,     8,     3,     4,    13,    16,
-      14,    12,    11,    15,    12,    25,    11,    -1,    18,    -1,
-      16,    14
+       4,     5,     6,     4,     5,     7,     8,    20,    17,    22,
+      15,    15,     3,     4,    16,    19,    12,    21,    19,    23,
+      21,     3,    23,    12,    20,    16,    17,     7,     8,    18,
+       9,    10,    11,     9,    10,     0,     7,    18,    13,    17,
+      14,    29,    14,    20,    13,    18,    16
   };
 
   const unsigned char
   EvalParser::yystos_[] =
   {
-       0,     4,     5,     6,    13,    17,    19,    21,    23,    24,
-      25,    15,    13,    24,    24,     0,     3,    18,    20,    26,
-       4,    25,    14,    25,    16,    15,    12,    11,    26,    18,
-      28,     7,     8,     9,    27,    16,    12,    11,    10,    18,
-      29,    14
+       0,     4,     5,     6,    15,    19,    21,    23,    25,    26,
+      27,    17,    15,    26,    26,     0,     7,     8,     3,    20,
+      22,    28,     4,    27,    16,    26,    26,    27,    18,    17,
+      14,    13,    28,    20,    30,     9,    10,    11,    29,    18,
+      14,    13,    12,    20,    31,    16
   };
 
   const unsigned char
   EvalParser::yyr1_[] =
   {
-       0,    22,    23,    24,    24,    24,    24,    25,    25,    25,
-      25,    25,    26,    26,    27,    27,    28,    29,    29
+       0,    24,    25,    26,    26,    26,    26,    26,    26,    27,
+      27,    27,    27,    27,    28,    28,    29,    29,    30,    31,
+      31
   };
 
   const unsigned char
   EvalParser::yyr2_[] =
   {
-       0,     2,     1,     3,     2,     3,     6,     1,     1,     6,
-       8,     1,     1,     1,     1,     1,     1,     1,     1
+       0,     2,     1,     3,     2,     3,     3,     3,     6,     1,
+       1,     6,     8,     1,     1,     1,     1,     1,     1,     1,
+       1
   };
 
 
@@ -1079,9 +1099,9 @@ namespace isc { namespace eval {
   const EvalParser::yytname_[] =
   {
   "\"end of file\"", "error", "$undefined", "\"==\"", "\"option\"",
-  "\"substring\"", "\"not\"", "\"text\"", "\"hex\"", "\"exists\"",
-  "\"all\"", "\".\"", "\",\"", "\"(\"", "\")\"", "\"[\"", "\"]\"",
-  "\"constant string\"", "\"integer\"", "\"constant hexstring\"",
+  "\"substring\"", "\"not\"", "\"and\"", "\"or\"", "\"text\"", "\"hex\"",
+  "\"exists\"", "\"all\"", "\".\"", "\",\"", "\"(\"", "\")\"", "\"[\"",
+  "\"]\"", "\"constant string\"", "\"integer\"", "\"constant hexstring\"",
   "\"option name\"", "TOKEN", "$accept", "expression", "bool_expr",
   "string_expr", "option_code", "option_repr_type", "start_expr",
   "length_expr", YY_NULLPTR
@@ -1091,8 +1111,9 @@ namespace isc { namespace eval {
   const unsigned char
   EvalParser::yyrline_[] =
   {
-       0,    81,    81,    84,    85,    90,    95,   102,   107,   112,
-     117,   122,   126,   130,   136,   140,   146,   153,   158
+       0,    87,    87,    90,    91,    96,   101,   106,   111,   118,
+     123,   128,   133,   138,   142,   146,   152,   156,   162,   169,
+     174
   };
 
   // Print the state stack on the debug stream.
@@ -1127,8 +1148,8 @@ namespace isc { namespace eval {
 
 #line 21 "parser.yy" // lalr1.cc:1167
 } } // isc::eval
-#line 1131 "parser.cc" // lalr1.cc:1167
-#line 165 "parser.yy" // lalr1.cc:1168
+#line 1152 "parser.cc" // lalr1.cc:1167
+#line 181 "parser.yy" // lalr1.cc:1168
 
 void
 isc::eval::EvalParser::error(const location_type& loc,

+ 72 - 50
src/lib/eval/parser.h

@@ -334,21 +334,23 @@ namespace isc { namespace eval {
         TOKEN_OPTION = 259,
         TOKEN_SUBSTRING = 260,
         TOKEN_NOT = 261,
-        TOKEN_TEXT = 262,
-        TOKEN_HEX = 263,
-        TOKEN_EXISTS = 264,
-        TOKEN_ALL = 265,
-        TOKEN_DOT = 266,
-        TOKEN_COMA = 267,
-        TOKEN_LPAREN = 268,
-        TOKEN_RPAREN = 269,
-        TOKEN_LBRACKET = 270,
-        TOKEN_RBRACKET = 271,
-        TOKEN_STRING = 272,
-        TOKEN_INTEGER = 273,
-        TOKEN_HEXSTRING = 274,
-        TOKEN_OPTION_NAME = 275,
-        TOKEN_TOKEN = 276
+        TOKEN_AND = 262,
+        TOKEN_OR = 263,
+        TOKEN_TEXT = 264,
+        TOKEN_HEX = 265,
+        TOKEN_EXISTS = 266,
+        TOKEN_ALL = 267,
+        TOKEN_DOT = 268,
+        TOKEN_COMA = 269,
+        TOKEN_LPAREN = 270,
+        TOKEN_RPAREN = 271,
+        TOKEN_LBRACKET = 272,
+        TOKEN_RBRACKET = 273,
+        TOKEN_STRING = 274,
+        TOKEN_INTEGER = 275,
+        TOKEN_HEXSTRING = 276,
+        TOKEN_OPTION_NAME = 277,
+        TOKEN_TOKEN = 278
       };
     };
 
@@ -481,6 +483,14 @@ namespace isc { namespace eval {
 
     static inline
     symbol_type
+    make_AND (const location_type& l);
+
+    static inline
+    symbol_type
+    make_OR (const location_type& l);
+
+    static inline
+    symbol_type
     make_TEXT (const location_type& l);
 
     static inline
@@ -624,7 +634,7 @@ namespace isc { namespace eval {
   // number is the opposite.  If YYTABLE_NINF, syntax error.
   static const unsigned char yytable_[];
 
-  static const signed char yycheck_[];
+  static const unsigned char yycheck_[];
 
   // YYSTOS[STATE-NUM] -- The (internal number of the) accessing
   // symbol of state STATE-NUM.
@@ -744,12 +754,12 @@ namespace isc { namespace eval {
     enum
     {
       yyeof_ = 0,
-      yylast_ = 41,     ///< Last index in yytable_.
+      yylast_ = 46,     ///< Last index in yytable_.
       yynnts_ = 8,  ///< Number of nonterminal symbols.
       yyfinal_ = 15, ///< Termination state number.
       yyterror_ = 1,
       yyerrcode_ = 256,
-      yyntokens_ = 22  ///< Number of tokens.
+      yyntokens_ = 24  ///< Number of tokens.
     };
 
 
@@ -793,9 +803,9 @@ namespace isc { namespace eval {
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16,    17,    18,    19,    20,    21
+      15,    16,    17,    18,    19,    20,    21,    22,    23
     };
-    const unsigned int user_token_number_max_ = 276;
+    const unsigned int user_token_number_max_ = 278;
     const token_number_type undef_token_ = 2;
 
     if (static_cast<int>(t) <= yyeof_)
@@ -828,19 +838,19 @@ namespace isc { namespace eval {
   {
       switch (other.type_get ())
     {
-      case 27: // option_repr_type
+      case 29: // option_repr_type
         value.copy< TokenOption::RepresentationType > (other.value);
         break;
 
-      case 17: // "constant string"
-      case 18: // "integer"
-      case 19: // "constant hexstring"
-      case 20: // "option name"
-      case 21: // TOKEN
+      case 19: // "constant string"
+      case 20: // "integer"
+      case 21: // "constant hexstring"
+      case 22: // "option name"
+      case 23: // TOKEN
         value.copy< std::string > (other.value);
         break;
 
-      case 26: // option_code
+      case 28: // option_code
         value.copy< uint16_t > (other.value);
         break;
 
@@ -861,19 +871,19 @@ namespace isc { namespace eval {
     (void) v;
       switch (this->type_get ())
     {
-      case 27: // option_repr_type
+      case 29: // option_repr_type
         value.copy< TokenOption::RepresentationType > (v);
         break;
 
-      case 17: // "constant string"
-      case 18: // "integer"
-      case 19: // "constant hexstring"
-      case 20: // "option name"
-      case 21: // TOKEN
+      case 19: // "constant string"
+      case 20: // "integer"
+      case 21: // "constant hexstring"
+      case 22: // "option name"
+      case 23: // TOKEN
         value.copy< std::string > (v);
         break;
 
-      case 26: // option_code
+      case 28: // option_code
         value.copy< uint16_t > (v);
         break;
 
@@ -939,19 +949,19 @@ namespace isc { namespace eval {
     // Type destructor.
     switch (yytype)
     {
-      case 27: // option_repr_type
+      case 29: // option_repr_type
         value.template destroy< TokenOption::RepresentationType > ();
         break;
 
-      case 17: // "constant string"
-      case 18: // "integer"
-      case 19: // "constant hexstring"
-      case 20: // "option name"
-      case 21: // TOKEN
+      case 19: // "constant string"
+      case 20: // "integer"
+      case 21: // "constant hexstring"
+      case 22: // "option name"
+      case 23: // TOKEN
         value.template destroy< std::string > ();
         break;
 
-      case 26: // option_code
+      case 28: // option_code
         value.template destroy< uint16_t > ();
         break;
 
@@ -978,19 +988,19 @@ namespace isc { namespace eval {
     super_type::move(s);
       switch (this->type_get ())
     {
-      case 27: // option_repr_type
+      case 29: // option_repr_type
         value.move< TokenOption::RepresentationType > (s.value);
         break;
 
-      case 17: // "constant string"
-      case 18: // "integer"
-      case 19: // "constant hexstring"
-      case 20: // "option name"
-      case 21: // TOKEN
+      case 19: // "constant string"
+      case 20: // "integer"
+      case 21: // "constant hexstring"
+      case 22: // "option name"
+      case 23: // TOKEN
         value.move< std::string > (s.value);
         break;
 
-      case 26: // option_code
+      case 28: // option_code
         value.move< uint16_t > (s.value);
         break;
 
@@ -1051,7 +1061,7 @@ namespace isc { namespace eval {
     {
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
-     275,   276
+     275,   276,   277,   278
     };
     return static_cast<token_type> (yytoken_number_[type]);
   }
@@ -1087,6 +1097,18 @@ namespace isc { namespace eval {
   }
 
   EvalParser::symbol_type
+  EvalParser::make_AND (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_AND, l);
+  }
+
+  EvalParser::symbol_type
+  EvalParser::make_OR (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_OR, l);
+  }
+
+  EvalParser::symbol_type
   EvalParser::make_TEXT (const location_type& l)
   {
     return symbol_type (token::TOKEN_TEXT, l);
@@ -1179,7 +1201,7 @@ namespace isc { namespace eval {
 
 #line 21 "parser.yy" // lalr1.cc:392
 } } // isc::eval
-#line 1183 "parser.h" // lalr1.cc:392
+#line 1205 "parser.h" // lalr1.cc:392
 
 
 

+ 17 - 1
src/lib/eval/parser.yy

@@ -48,6 +48,8 @@ using namespace isc::eval;
   OPTION "option"
   SUBSTRING "substring"
   NOT "not"
+  AND "and"
+  OR "or"
   TEXT "text"
   HEX "hex"
   EXISTS "exists"
@@ -69,6 +71,10 @@ using namespace isc::eval;
 %type <uint16_t> option_code
 %type <TokenOption::RepresentationType> option_repr_type
 
+%left OR
+%left AND
+%precedence NOT
+
 %printer { yyoutput << $$; } <*>;
 
 %%
@@ -87,6 +93,16 @@ bool_expr : "(" bool_expr ")"
                     TokenPtr neg(new TokenNot());
                     ctx.expression.push_back(neg);
                 }
+          | bool_expr AND bool_expr
+                {
+                    TokenPtr neg(new TokenAnd());
+                    ctx.expression.push_back(neg);
+                }
+          | bool_expr OR bool_expr
+                {
+                    TokenPtr neg(new TokenOr());
+                    ctx.expression.push_back(neg);
+                }
           | string_expr EQUAL string_expr
                 {
                     TokenPtr eq(new TokenEqual());
@@ -120,7 +136,7 @@ string_expr : STRING
                       ctx.expression.push_back(sub);
                   }
             | TOKEN
-                // Temporary unused token to avoid explict but long errors
+                // Temporary unused token to avoid explicit but long errors
             ;
 
 option_code : INTEGER

+ 1 - 1
src/lib/eval/position.hh

@@ -1,4 +1,4 @@
-// Generated 20151207
+// Generated 20151209
 // A Bison parser, made by GNU Bison 3.0.4.
 
 // Positions for Bison parsers in C++

+ 1 - 1
src/lib/eval/stack.hh

@@ -1,4 +1,4 @@
-// Generated 20151207
+// Generated 20151209
 // A Bison parser, made by GNU Bison 3.0.4.
 
 // Stack handling for Bison parsers in C++

+ 36 - 7
src/lib/eval/tests/context_unittest.cc

@@ -348,9 +348,19 @@ TEST_F(EvalContextTest, parseErrors) {
     checkError("'foo''bar'",
                "<string>:1.6-10: syntax error, unexpected constant string, "
                "expecting ==");
+    checkError("'foo' (",
+               "<string>:1.7: syntax error, unexpected (, expecting ==");
     checkError("== 'ab'", "<string>:1.1-2: syntax error, unexpected ==");
     checkError("'foo' ==",
                "<string>:1.9: syntax error, unexpected end of file");
+    checkError("('foo' == 'bar'",
+               "<string>:1.16: syntax error, unexpected end of file, "
+               "expecting and or or or )");
+    checkError("('foo' == 'bar') ''",
+               "<string>:1.18-19: syntax error, unexpected constant string, "
+               "expecting end of file");
+    checkError("not",
+               "<string>:1.4: syntax error, unexpected end of file");
     checkError("not 'foo'",
                "<string>:1.10: syntax error, unexpected end of file, "
                "expecting ==");
@@ -359,12 +369,24 @@ TEST_F(EvalContextTest, parseErrors) {
     checkError("(not('foo' 'bar')",
                "<string>:1.12-16: syntax error, unexpected constant string, "
                "expecting ==");
-    checkError("('foo' == 'bar'",
-               "<string>:1.16: syntax error, unexpected end of file, "
-               "expecting )");
-    checkError("('foo' == 'bar') ''",
-               "<string>:1.18-19: syntax error, unexpected constant string, "
-               "expecting end of file");
+    checkError("and",
+               "<string>:1.1-3: syntax error, unexpected and");
+    checkError("'foo' and",
+               "<string>:1.7-9: syntax error, unexpected and, expecting ==");
+    checkError("'foo' == 'bar' and",
+               "<string>:1.19: syntax error, unexpected end of file");
+    checkError("'foo' == 'bar' and ''",
+               "<string>:1.22: syntax error, unexpected end of file, "
+               "expecting ==");
+    checkError("or",
+               "<string>:1.1-2: syntax error, unexpected or");
+    checkError("'foo' or",
+               "<string>:1.7-8: syntax error, unexpected or, expecting ==");
+    checkError("'foo' == 'bar' or",
+               "<string>:1.18: syntax error, unexpected end of file");
+    checkError("'foo' == 'bar' or ''",
+               "<string>:1.21: syntax error, unexpected end of file, "
+               "expecting ==");
     checkError("option 'ab'",
                "<string>:1.8-11: syntax error, unexpected "
                "constant string, expecting [");
@@ -398,7 +420,7 @@ TEST_F(EvalContextTest, parseErrors) {
                "<string>:1.22: Invalid character: a");
 }
 
-// Tests some type error cases (caught only by the strongly typed parser)
+// Tests some type error cases
 TEST_F(EvalContextTest, typeErrors) {
     checkError("'foobar'",
                "<string>:1.9: syntax error, unexpected end of file, "
@@ -412,6 +434,13 @@ TEST_F(EvalContextTest, typeErrors) {
     checkError("('foo' == 'bar') == 'false'",
                "<string>:1.18-19: syntax error, unexpected ==, "
                "expecting end of file");
+    checkError("not 'true'",
+               "<string>:1.11: syntax error, unexpected end of file, "
+               "expecting ==");
+    checkError("'true' and 'false'",
+               "<string>:1.8-10: syntax error, unexpected and, expecting ==");
+    checkError("'true' or 'false'",
+               "<string>:1.8-9: syntax error, unexpected or, expecting ==");
 }
 
 };

+ 132 - 0
src/lib/eval/tests/token_unittest.cc

@@ -484,6 +484,138 @@ TEST_F(TokenTest, optionNot) {
     EXPECT_EQ("true", values_.top());
 }
 
+// This test checks if a token representing an and is able to
+// conjugate two values (with incorrectly built stack).
+TEST_F(TokenTest, optionAndInvalid) {
+
+    ASSERT_NO_THROW(t_.reset(new TokenAnd()));
+
+    // CASE 1: There's not enough values on the stack. and is an operator that
+    // takes two parameters. There are 0 on the stack.
+    EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
+
+    // CASE 2: One value is still not enough.
+    values_.push("foo");
+    EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
+
+    // CASE 3: The two values must be logical
+    values_.push("true");
+    EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
+
+    // Swap the 2 values
+    values_.push("true");
+    values_.push("foo");
+    EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
+}
+
+// This test checks if a token representing an and operator is able to
+// conjugate false with another logical
+TEST_F(TokenTest, optionAndFalse) {
+
+    ASSERT_NO_THROW(t_.reset(new TokenAnd()));
+
+    values_.push("true");
+    values_.push("false");
+    EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
+
+    // After evaluation there should be a single "false" value
+    ASSERT_EQ(1, values_.size());
+    EXPECT_EQ("false", values_.top());
+
+    // After true and false, checks false and true
+    values_.push("true");
+    EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
+    ASSERT_EQ(1, values_.size());
+    EXPECT_EQ("false", values_.top());
+
+    // And false and false
+    values_.push("false");
+    EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
+    ASSERT_EQ(1, values_.size());
+    EXPECT_EQ("false", values_.top());
+}
+
+// This test checks if a token representing an and is able to
+// conjugate two true values.
+TEST_F(TokenTest, optionAndTrue) {
+
+    ASSERT_NO_THROW(t_.reset(new TokenAnd()));
+
+    values_.push("true");
+    values_.push("true");
+    EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
+
+    // After evaluation there should be a single "true" value
+    ASSERT_EQ(1, values_.size());
+    EXPECT_EQ("true", values_.top());
+}
+
+// This test checks if a token representing an or is able to
+// combinate two values (with incorrectly built stack).
+TEST_F(TokenTest, optionOrInvalid) {
+
+    ASSERT_NO_THROW(t_.reset(new TokenOr()));
+
+    // CASE 1: There's not enough values on the stack. or is an operator that
+    // takes two parameters. There are 0 on the stack.
+    EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
+
+    // CASE 2: One value is still not enough.
+    values_.push("foo");
+    EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack);
+
+    // CASE 3: The two values must be logical
+    values_.push("true");
+    EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
+
+    // Swap the 2 values
+    values_.push("true");
+    values_.push("foo");
+    EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
+}
+
+// This test checks if a token representing an or is able to
+// conjugate two false values.
+TEST_F(TokenTest, optionOrFalse) {
+
+    ASSERT_NO_THROW(t_.reset(new TokenOr()));
+
+    values_.push("false");
+    values_.push("false");
+    EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
+
+    // After evaluation there should be a single "false" value
+    ASSERT_EQ(1, values_.size());
+    EXPECT_EQ("false", values_.top());
+}
+
+// This test checks if a token representing an == operator is able to
+// conjugate true with another logical
+TEST_F(TokenTest, optionOrTrue) {
+
+    ASSERT_NO_THROW(t_.reset(new TokenOr()));
+
+    values_.push("false");
+    values_.push("true");
+    EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
+
+    // After evaluation there should be a single "true" value
+    ASSERT_EQ(1, values_.size());
+    EXPECT_EQ("true", values_.top());
+
+    // After false or true, checks true or false
+    values_.push("false");
+    EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
+    ASSERT_EQ(1, values_.size());
+    EXPECT_EQ("true", values_.top());
+
+    // And true or true
+    values_.push("true");
+    EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
+    ASSERT_EQ(1, values_.size());
+    EXPECT_EQ("true", values_.top());
+}
+
 };
 
 // This test checks if an a token representing a substring request

+ 71 - 0
src/lib/eval/token.cc

@@ -200,3 +200,74 @@ TokenNot::evaluate(const Pkt& /*pkt*/, ValueStack& values) {
                   << "Got '" << op << "'.");
     }
 }
+
+void
+TokenAnd::evaluate(const Pkt& /*pkt*/, ValueStack& values) {
+
+    if (values.size() < 2) {
+        isc_throw(EvalBadStack, "Incorrect stack order. Expected at least "
+                  "2 values for and operator, got " << values.size());
+    }
+
+    string op1 = values.top();
+    values.pop();
+    string op2 = values.top();
+    values.pop(); // Dammit, std::stack interface is awkward.
+
+    if (op1 == "true") {
+        if (op2 == "true") {
+            values.push("true");
+        } else if (op2 == "false") {
+            values.push("false");
+        } else {
+            isc_throw(EvalTypeError, "Expected logical values at "
+                      << "top of stack. Got 'true' and '" << op2 << "'");
+        }
+    } else if (op1 == "false") {
+        if ((op2 == "true") || (op2 == "false")) {
+            values.push("false");
+        } else {
+            isc_throw(EvalTypeError, "Expected logical values at "
+                      << "top of stack. Got 'false' and '" << op2 << "'");
+        }
+    } else {
+        isc_throw(EvalTypeError, "Expected logical values at top of stack. "
+                  << "Got '" << op1 << "' and '" << op2 << "'");
+    }
+}
+
+void
+TokenOr::evaluate(const Pkt& /*pkt*/, ValueStack& values) {
+
+    if (values.size() < 2) {
+        isc_throw(EvalBadStack, "Incorrect stack order. Expected at least "
+                  "2 values for or operator, got " << values.size());
+    }
+
+    string op1 = values.top();
+    values.pop();
+    string op2 = values.top();
+    values.pop(); // Dammit, std::stack interface is awkward.
+
+    if (op1 == "true") {
+        if ((op2 == "true") || (op2 == "false")) {
+            values.push("true");
+        } else {
+            isc_throw(EvalTypeError, "Expected logical values at "
+                      << "top of stack. Got 'true' and '" << op2 << "'");
+        }
+    } else if (op1 == "false") {
+        if (op2 == "true") {
+            values.push("true");
+        } else if (op2 == "false") {
+            values.push("false");
+        } else {
+            isc_throw(EvalTypeError, "Expected logical values at "
+                      << "top of stack. Got 'false' and '" << op2 << "'");
+        }
+    } else {
+        isc_throw(EvalTypeError, "Expected logical values at top of stack. "
+                  << "Got '" << op1 << "' and '" << op2 << "'");
+    }
+}
+

+ 50 - 0
src/lib/eval/token.h

@@ -304,6 +304,56 @@ public:
     void evaluate(const Pkt& pkt, ValueStack& values);
 };
 
+/// @brief Token that represents logical and operator
+///
+/// For example "option[10].exists and option[11].exists"
+class TokenAnd : public Token {
+public:
+    /// @brief Constructor (does nothing)
+    TokenAnd() {}
+
+    /// @brief Logical and.
+    ///
+    /// Evaluation does not use packet information, but rather consumes the last
+    /// two parameters. It returns "true" if and only if both are "true".
+    /// It requires at least two logical (i.e., "true" or "false') values
+    /// present on stack.
+    ///
+    /// @throw EvalBadStack if there are less than 2 values on stack
+    /// @throw EvalTypeError if one of the 2 values on stack is not
+    ///        "true" or "false"
+    ///
+    /// @param pkt (unused)
+    /// @param values - stack of values (2 arguments will be popped, 1 result
+    ///        will be pushed)
+    void evaluate(const Pkt& pkt, ValueStack& values);
+};
+
+/// @brief Token that represents logical or operator
+///
+/// For example "option[10].exists or option[11].exists"
+class TokenOr : public Token {
+public:
+    /// @brief Constructor (does nothing)
+    TokenOr() {}
+
+    /// @brief Logical or.
+    ///
+    /// Evaluation does not use packet information, but rather consumes the last
+    /// two parameters. It returns "false" if and only if both are "false".
+    /// It requires at least two logical (i.e., "true" or "false') values
+    /// present on stack.
+    ///
+    /// @throw EvalBadStack if there are less than 2 values on stack
+    /// @throw EvalTypeError if one of the 2 values on stack is not
+    ///        "true" or "false"
+    ///
+    /// @param pkt (unused)
+    /// @param values - stack of values (2 arguments will be popped, 1 result
+    ///        will be pushed)
+    void evaluate(const Pkt& pkt, ValueStack& values);
+};
+
 }; // end of isc::dhcp namespace
 }; // end of isc namespace