From: Francis Dupont Date: Wed, 9 Dec 2015 15:00:46 +0000 (+0100) Subject: [4231] Added and & or operators X-Git-Tag: trac4232_base~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d0ee0b0811cee581a322450a3af7bce4e377ae5d;p=thirdparty%2Fkea.git [4231] Added and & or operators --- diff --git a/src/lib/eval/lexer.cc b/src/lib/eval/lexer.cc index 109d8c241b..99843f2814 100644 --- a/src/lib/eval/lexer.cc +++ b/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" diff --git a/src/lib/eval/lexer.ll b/src/lib/eval/lexer.ll index 1112b58c31..ff458cc0c6 100644 --- a/src/lib/eval/lexer.ll +++ b/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); diff --git a/src/lib/eval/location.hh b/src/lib/eval/location.hh index 3f828a7ee5..2f28d52763 100644 --- a/src/lib/eval/location.hh +++ b/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++ diff --git a/src/lib/eval/parser.cc b/src/lib/eval/parser.cc index 304b2cc48e..9bbef776dc 100644 --- a/src/lib/eval/parser.cc +++ b/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, diff --git a/src/lib/eval/parser.h b/src/lib/eval/parser.h index 1d2bd0a10c..9f76e82eae 100644 --- a/src/lib/eval/parser.h +++ b/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 }; }; @@ -479,6 +481,14 @@ namespace isc { namespace eval { symbol_type make_NOT (const location_type& l); + 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); @@ -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(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 (yytoken_number_[type]); } @@ -1086,6 +1096,18 @@ namespace isc { namespace eval { return symbol_type (token::TOKEN_NOT, l); } + 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) { @@ -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 diff --git a/src/lib/eval/parser.yy b/src/lib/eval/parser.yy index fda62bab5e..7ddedfe1a2 100644 --- a/src/lib/eval/parser.yy +++ b/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 option_code %type 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 diff --git a/src/lib/eval/position.hh b/src/lib/eval/position.hh index 28ec48963a..d314a8426c 100644 --- a/src/lib/eval/position.hh +++ b/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++ diff --git a/src/lib/eval/stack.hh b/src/lib/eval/stack.hh index 39dfd940f5..14b0aeb4dd 100644 --- a/src/lib/eval/stack.hh +++ b/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++ diff --git a/src/lib/eval/tests/context_unittest.cc b/src/lib/eval/tests/context_unittest.cc index bded550b07..fbb5e3f508 100644 --- a/src/lib/eval/tests/context_unittest.cc +++ b/src/lib/eval/tests/context_unittest.cc @@ -348,9 +348,19 @@ TEST_F(EvalContextTest, parseErrors) { checkError("'foo''bar'", ":1.6-10: syntax error, unexpected constant string, " "expecting =="); + checkError("'foo' (", + ":1.7: syntax error, unexpected (, expecting =="); checkError("== 'ab'", ":1.1-2: syntax error, unexpected =="); checkError("'foo' ==", ":1.9: syntax error, unexpected end of file"); + checkError("('foo' == 'bar'", + ":1.16: syntax error, unexpected end of file, " + "expecting and or or or )"); + checkError("('foo' == 'bar') ''", + ":1.18-19: syntax error, unexpected constant string, " + "expecting end of file"); + checkError("not", + ":1.4: syntax error, unexpected end of file"); checkError("not 'foo'", ":1.10: syntax error, unexpected end of file, " "expecting =="); @@ -359,12 +369,24 @@ TEST_F(EvalContextTest, parseErrors) { checkError("(not('foo' 'bar')", ":1.12-16: syntax error, unexpected constant string, " "expecting =="); - checkError("('foo' == 'bar'", - ":1.16: syntax error, unexpected end of file, " - "expecting )"); - checkError("('foo' == 'bar') ''", - ":1.18-19: syntax error, unexpected constant string, " - "expecting end of file"); + checkError("and", + ":1.1-3: syntax error, unexpected and"); + checkError("'foo' and", + ":1.7-9: syntax error, unexpected and, expecting =="); + checkError("'foo' == 'bar' and", + ":1.19: syntax error, unexpected end of file"); + checkError("'foo' == 'bar' and ''", + ":1.22: syntax error, unexpected end of file, " + "expecting =="); + checkError("or", + ":1.1-2: syntax error, unexpected or"); + checkError("'foo' or", + ":1.7-8: syntax error, unexpected or, expecting =="); + checkError("'foo' == 'bar' or", + ":1.18: syntax error, unexpected end of file"); + checkError("'foo' == 'bar' or ''", + ":1.21: syntax error, unexpected end of file, " + "expecting =="); checkError("option 'ab'", ":1.8-11: syntax error, unexpected " "constant string, expecting ["); @@ -398,7 +420,7 @@ TEST_F(EvalContextTest, parseErrors) { ":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'", ":1.9: syntax error, unexpected end of file, " @@ -412,6 +434,13 @@ TEST_F(EvalContextTest, typeErrors) { checkError("('foo' == 'bar') == 'false'", ":1.18-19: syntax error, unexpected ==, " "expecting end of file"); + checkError("not 'true'", + ":1.11: syntax error, unexpected end of file, " + "expecting =="); + checkError("'true' and 'false'", + ":1.8-10: syntax error, unexpected and, expecting =="); + checkError("'true' or 'false'", + ":1.8-9: syntax error, unexpected or, expecting =="); } }; diff --git a/src/lib/eval/tests/token_unittest.cc b/src/lib/eval/tests/token_unittest.cc index 3652a97ea8..0fcf98f3fc 100644 --- a/src/lib/eval/tests/token_unittest.cc +++ b/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 diff --git a/src/lib/eval/token.cc b/src/lib/eval/token.cc index f528c50d71..289caa03d6 100644 --- a/src/lib/eval/token.cc +++ b/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 << "'"); + } +} + diff --git a/src/lib/eval/token.h b/src/lib/eval/token.h index e06ad43b6f..eacf51f905 100644 --- a/src/lib/eval/token.h +++ b/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