diff --git a/src/lib/eval/lexer.cc b/src/lib/eval/lexer.cc index 245922c83b..ed5f9f46e8 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 20 -#define YY_END_OF_BUFFER 21 +#define YY_NUM_RULES 21 +#define YY_END_OF_BUFFER 22 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -478,27 +478,29 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_acclist[90] = +static yyconst flex_int16_t yy_acclist[96] = { 0, - 21, 19, 20, 1, 19, 20, 2, 20, 19, 20, - 14, 19, 20, 15, 19, 20, 18, 19, 20, 19, - 20, 13, 19, 20, 5, 19, 20, 5, 19, 20, - 19, 20, 19, 20,16390, 16, 19, 20, 17, 19, - 20, 19, 20,16390, 19, 20,16390, 19, 20,16390, - 19, 20,16390, 19, 20,16390, 1, 2, 3, 5, - 7,16390, 8198,16390,16390,16390,16390,16390, 4, 12, - 16390, 10,16390,16390,16390,16390,16390,16390, 9,16390, - 16390,16390, 8,16390,16390,16390,16390, 11,16390 + 22, 20, 21, 1, 20, 21, 2, 21, 20, 21, + 15, 20, 21, 16, 20, 21, 19, 20, 21, 20, + 21, 14, 20, 21, 5, 20, 21, 5, 20, 21, + 20, 21, 20, 21,16390, 17, 20, 21, 18, 20, + 21, 20, 21,16390, 20, 21,16390, 20, 21,16390, + 20, 21,16390, 20, 21,16390, 20, 21,16390, 1, + 2, 3, 5, 7,16390, 8198,16390,16390,16390,16390, + 16390,16390, 4, 13,16390, 10,16390, 12,16390,16390, + 16390,16390,16390,16390, 9,16390,16390,16390, 8,16390, + 16390,16390,16390, 11,16390 + } ; -static yyconst flex_int16_t yy_accept[58] = +static yyconst flex_int16_t yy_accept[61] = { 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, 58, 59, 59, 60, 61, 61, - 62, 62, 62, 63, 64, 65, 66, 67, 68, 69, - 70, 72, 74, 75, 76, 77, 78, 79, 81, 82, - 83, 85, 86, 87, 88, 90, 90 + 48, 51, 54, 57, 60, 61, 62, 62, 63, 64, + 64, 65, 65, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 76, 78, 80, 81, 82, 83, 84, + 85, 87, 88, 89, 91, 92, 93, 94, 96, 96 } ; static yyconst flex_int32_t yy_ec[256] = @@ -541,81 +543,83 @@ static yyconst flex_int32_t yy_meta[34] = 2, 2, 2 } ; -static yyconst flex_int16_t yy_base[60] = +static yyconst flex_int16_t yy_base[63] = { 0, - 0, 0, 119, 120, 116, 114, 112, 120, 120, 120, - 24, 120, 26, 28, 103, 58, 120, 120, 75, 19, - 17, 18, 26, 112, 110, 108, 120, 38, 0, 120, - 50, 54, 86, 120, 85, 21, 33, 43, 37, 0, - 80, 76, 48, 44, 55, 57, 56, 66, 63, 65, - 60, 71, 72, 77, 40, 120, 102, 105, 51 + 0, 0, 124, 125, 121, 119, 117, 125, 125, 125, + 24, 125, 26, 28, 108, 58, 125, 125, 75, 19, + 18, 21, 22, 27, 117, 115, 113, 125, 40, 0, + 125, 53, 55, 91, 125, 86, 38, 37, 42, 44, + 49, 0, 82, 81, 74, 60, 56, 63, 62, 65, + 54, 72, 66, 40, 77, 78, 83, 28, 125, 108, + 111, 38 } ; -static yyconst flex_int16_t yy_def[60] = +static yyconst flex_int16_t yy_def[63] = { 0, - 56, 1, 56, 56, 56, 56, 57, 56, 56, 56, - 56, 56, 56, 56, 56, 58, 56, 56, 58, 19, - 19, 19, 19, 56, 56, 57, 56, 56, 59, 56, - 56, 19, 19, 56, 19, 19, 19, 19, 19, 59, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 0, 56, 56, 56 + 59, 1, 59, 59, 59, 59, 60, 59, 59, 59, + 59, 59, 59, 59, 59, 61, 59, 59, 61, 19, + 19, 19, 19, 19, 59, 59, 60, 59, 59, 62, + 59, 59, 19, 19, 59, 19, 19, 19, 19, 19, + 19, 62, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 0, 59, + 59, 59 } ; -static yyconst flex_int16_t yy_nxt[154] = +static yyconst flex_int16_t yy_nxt[159] = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16, 16, 17, 18, 4, 19, 16, - 16, 16, 20, 16, 16, 16, 21, 16, 16, 22, - 23, 16, 16, 28, 28, 28, 28, 28, 28, 36, - 29, 33, 33, 33, 37, 33, 39, 28, 28, 38, - 33, 31, 31, 42, 40, 56, 56, 33, 29, 31, - 31, 33, 44, 43, 33, 32, 34, 33, 33, 45, - 56, 46, 33, 47, 34, 32, 31, 31, 33, 33, - 33, 33, 32, 49, 33, 48, 50, 33, 51, 33, - 33, 34, 32, 52, 53, 33, 33, 54, 55, 35, + 16, 16, 20, 16, 16, 21, 22, 16, 16, 23, + 24, 16, 16, 29, 29, 29, 29, 29, 29, 37, + 30, 42, 34, 34, 38, 34, 34, 41, 39, 29, + 29, 34, 34, 40, 32, 32, 59, 59, 30, 32, + 32, 34, 34, 47, 34, 33, 34, 45, 34, 35, + 44, 59, 46, 34, 35, 33, 32, 32, 34, 34, + 34, 48, 33, 49, 34, 50, 34, 34, 52, 34, + 34, 35, 33, 51, 55, 53, 34, 54, 34, 36, - 33, 33, 26, 26, 33, 26, 33, 33, 33, 41, - 33, 27, 25, 24, 30, 27, 25, 24, 56, 3, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56 + 56, 34, 34, 57, 58, 34, 34, 34, 27, 27, + 43, 27, 34, 34, 34, 34, 28, 26, 25, 31, + 28, 26, 25, 59, 3, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59 } ; -static yyconst flex_int16_t yy_chk[154] = +static yyconst flex_int16_t yy_chk[159] = { 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, 20, 21, 36, 23, 28, 28, 22, - 23, 31, 31, 36, 59, 32, 32, 37, 13, 16, - 16, 39, 38, 37, 55, 16, 31, 38, 44, 39, - 32, 43, 43, 44, 16, 16, 19, 19, 32, 45, - 47, 46, 19, 46, 51, 45, 47, 49, 49, 50, - 48, 19, 19, 50, 52, 52, 53, 53, 54, 19, + 13, 62, 21, 20, 21, 22, 23, 24, 22, 29, + 29, 24, 58, 23, 32, 32, 33, 33, 13, 16, + 16, 38, 37, 40, 54, 16, 39, 38, 40, 32, + 37, 33, 39, 41, 16, 16, 19, 19, 51, 33, + 47, 41, 19, 46, 46, 47, 49, 48, 49, 50, + 53, 19, 19, 48, 53, 50, 52, 52, 45, 19, - 42, 54, 57, 57, 41, 57, 58, 58, 58, 35, - 33, 26, 25, 24, 15, 7, 6, 5, 3, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56 + 55, 55, 56, 56, 57, 44, 43, 57, 60, 60, + 36, 60, 61, 61, 61, 34, 27, 26, 25, 15, + 7, 6, 5, 3, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59 } ; /* Table of booleans, true if rule could match eol. */ -static yyconst flex_int32_t yy_rule_can_match_eol[21] = +static yyconst flex_int32_t yy_rule_can_match_eol[22] = { 0, 0, 1, 0, 0, 0, 1, 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[20] = +static yyconst flex_int16_t yy_rule_linenum[21] = { 0, 86, 90, 96, 106, 112, 126, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 146 + 137, 138, 139, 140, 141, 142, 143, 144, 145, 147 } ; static yy_state_type *yy_state_buf=0, *yy_state_ptr=0; @@ -700,7 +704,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 704 "lexer.cc" +#line 708 "lexer.cc" #define INITIAL 0 @@ -989,7 +993,7 @@ YY_DECL loc.step(); -#line 993 "lexer.cc" +#line 997 "lexer.cc" while ( 1 ) /* loops until end-of-file is reached */ { @@ -1017,14 +1021,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 >= 57 ) + if ( yy_current_state >= 60 ) 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 != 56 ); + while ( yy_current_state != 59 ); yy_find_action: /* %% [10.0] code to find the action number goes here */ @@ -1087,13 +1091,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 < 20 ) + else if ( yy_act < 21 ) fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n", (long)yy_rule_linenum[yy_act], yytext ); - else if ( yy_act == 20 ) + else if ( yy_act == 21 ) fprintf( stderr, "--accepting default rule (\"%s\")\n", yytext ); - else if ( yy_act == 21 ) + else if ( yy_act == 22 ) fprintf( stderr, "--(end of buffer or a NUL)\n" ); else fprintf( stderr, "--EOF (start condition %d)\n", YY_START ); @@ -1198,53 +1202,58 @@ return isc::eval::EvalParser::make_SUBSTRING(loc); case 12: YY_RULE_SETUP #line 138 "lexer.ll" -return isc::eval::EvalParser::make_ALL(loc); +return isc::eval::EvalParser::make_NOT(loc); YY_BREAK case 13: YY_RULE_SETUP #line 139 "lexer.ll" -return isc::eval::EvalParser::make_DOT(loc); +return isc::eval::EvalParser::make_ALL(loc); YY_BREAK case 14: YY_RULE_SETUP #line 140 "lexer.ll" -return isc::eval::EvalParser::make_LPAREN(loc); +return isc::eval::EvalParser::make_DOT(loc); YY_BREAK case 15: YY_RULE_SETUP #line 141 "lexer.ll" -return isc::eval::EvalParser::make_RPAREN(loc); +return isc::eval::EvalParser::make_LPAREN(loc); YY_BREAK case 16: YY_RULE_SETUP #line 142 "lexer.ll" -return isc::eval::EvalParser::make_LBRACKET(loc); +return isc::eval::EvalParser::make_RPAREN(loc); YY_BREAK case 17: YY_RULE_SETUP #line 143 "lexer.ll" -return isc::eval::EvalParser::make_RBRACKET(loc); +return isc::eval::EvalParser::make_LBRACKET(loc); YY_BREAK case 18: YY_RULE_SETUP #line 144 "lexer.ll" -return isc::eval::EvalParser::make_COMA(loc); +return isc::eval::EvalParser::make_RBRACKET(loc); YY_BREAK case 19: YY_RULE_SETUP -#line 146 "lexer.ll" -driver.error (loc, "Invalid character: " + std::string(yytext)); - YY_BREAK -case YY_STATE_EOF(INITIAL): -#line 147 "lexer.ll" -return isc::eval::EvalParser::make_END(loc); +#line 145 "lexer.ll" +return isc::eval::EvalParser::make_COMA(loc); YY_BREAK case 20: YY_RULE_SETUP +#line 147 "lexer.ll" +driver.error (loc, "Invalid character: " + std::string(yytext)); + YY_BREAK +case YY_STATE_EOF(INITIAL): #line 148 "lexer.ll" +return isc::eval::EvalParser::make_END(loc); + YY_BREAK +case 21: +YY_RULE_SETUP +#line 149 "lexer.ll" ECHO; YY_BREAK -#line 1248 "lexer.cc" +#line 1257 "lexer.cc" case YY_END_OF_BUFFER: { @@ -1525,7 +1534,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 >= 57 ) + if ( yy_current_state >= 60 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1553,11 +1562,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 >= 57 ) + if ( yy_current_state >= 60 ) 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 == 56); + yy_is_jam = (yy_current_state == 59); if ( ! yy_is_jam ) *(yy_state_ptr)++ = yy_current_state; @@ -2305,7 +2314,7 @@ void yyfree (void * ptr ) /* %ok-for-header */ -#line 148 "lexer.ll" +#line 149 "lexer.ll" diff --git a/src/lib/eval/lexer.ll b/src/lib/eval/lexer.ll index 61207ef2e0..a77e7593df 100644 --- a/src/lib/eval/lexer.ll +++ b/src/lib/eval/lexer.ll @@ -135,6 +135,7 @@ blank [ \t] "text" return isc::eval::EvalParser::make_TEXT(loc); "hex" return isc::eval::EvalParser::make_HEX(loc); "substring" return isc::eval::EvalParser::make_SUBSTRING(loc); +"not" return isc::eval::EvalParser::make_NOT(loc); "all" return isc::eval::EvalParser::make_ALL(loc); "." return isc::eval::EvalParser::make_DOT(loc); "(" return isc::eval::EvalParser::make_LPAREN(loc); diff --git a/src/lib/eval/parser.cc b/src/lib/eval/parser.cc index ff2cdc1d6f..d743ac5672 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 25: // option_repr_type + case 26: // option_repr_type value.move< TokenOption::RepresentationType > (that.value); break; - case 15: // "constant string" - case 16: // "integer" - case 17: // "constant hexstring" - case 18: // "option name" - case 19: // TOKEN + case 16: // "constant string" + case 17: // "integer" + case 18: // "constant hexstring" + case 19: // "option name" + case 20: // TOKEN value.move< std::string > (that.value); break; - case 24: // option_code + case 25: // 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 25: // option_repr_type + case 26: // option_repr_type value.copy< TokenOption::RepresentationType > (that.value); break; - case 15: // "constant string" - case 16: // "integer" - case 17: // "constant hexstring" - case 18: // "option name" - case 19: // TOKEN + case 16: // "constant string" + case 17: // "integer" + case 18: // "constant hexstring" + case 19: // "option name" + case 20: // TOKEN value.copy< std::string > (that.value); break; - case 24: // option_code + case 25: // option_code value.copy< uint16_t > (that.value); break; @@ -334,51 +334,51 @@ namespace isc { namespace eval { << yysym.location << ": "; switch (yytype) { - case 15: // "constant string" + case 16: // "constant string" -#line 70 "parser.yy" // lalr1.cc:636 +#line 71 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } #line 342 "parser.cc" // lalr1.cc:636 break; - case 16: // "integer" + case 17: // "integer" -#line 70 "parser.yy" // lalr1.cc:636 +#line 71 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } #line 349 "parser.cc" // lalr1.cc:636 break; - case 17: // "constant hexstring" + case 18: // "constant hexstring" -#line 70 "parser.yy" // lalr1.cc:636 +#line 71 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } #line 356 "parser.cc" // lalr1.cc:636 break; - case 18: // "option name" + case 19: // "option name" -#line 70 "parser.yy" // lalr1.cc:636 +#line 71 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } #line 363 "parser.cc" // lalr1.cc:636 break; - case 19: // TOKEN + case 20: // TOKEN -#line 70 "parser.yy" // lalr1.cc:636 +#line 71 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } #line 370 "parser.cc" // lalr1.cc:636 break; - case 24: // option_code + case 25: // option_code -#line 70 "parser.yy" // lalr1.cc:636 +#line 71 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< uint16_t > (); } #line 377 "parser.cc" // lalr1.cc:636 break; - case 25: // option_repr_type + case 26: // option_repr_type -#line 70 "parser.yy" // lalr1.cc:636 +#line 71 "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 25: // option_repr_type + case 26: // option_repr_type yylhs.value.build< TokenOption::RepresentationType > (); break; - case 15: // "constant string" - case 16: // "integer" - case 17: // "constant hexstring" - case 18: // "option name" - case 19: // TOKEN + case 16: // "constant string" + case 17: // "integer" + case 18: // "constant hexstring" + case 19: // "option name" + case 20: // TOKEN yylhs.value.build< std::string > (); break; - case 24: // option_code + case 25: // option_code yylhs.value.build< uint16_t > (); break; @@ -614,111 +614,120 @@ namespace isc { namespace eval { switch (yyn) { case 4: -#line 84 "parser.yy" // lalr1.cc:859 +#line 85 "parser.yy" // lalr1.cc:859 { - TokenPtr eq(new TokenEqual()); - ctx.expression.push_back(eq); + TokenPtr neg(new TokenNot()); + ctx.expression.push_back(neg); } #line 623 "parser.cc" // lalr1.cc:859 break; case 5: -#line 91 "parser.yy" // lalr1.cc:859 +#line 90 "parser.yy" // lalr1.cc:859 { - TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); - ctx.expression.push_back(str); - } + TokenPtr eq(new TokenEqual()); + ctx.expression.push_back(eq); + } #line 632 "parser.cc" // lalr1.cc:859 break; case 6: -#line 96 "parser.yy" // lalr1.cc:859 +#line 97 "parser.yy" // lalr1.cc:859 { - TokenPtr hex(new TokenHexString(yystack_[0].value.as< std::string > ())); - ctx.expression.push_back(hex); + TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); + ctx.expression.push_back(str); } #line 641 "parser.cc" // lalr1.cc:859 break; case 7: -#line 101 "parser.yy" // lalr1.cc:859 +#line 102 "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); + TokenPtr hex(new TokenHexString(yystack_[0].value.as< std::string > ())); + ctx.expression.push_back(hex); } #line 650 "parser.cc" // lalr1.cc:859 break; case 8: -#line 106 "parser.yy" // lalr1.cc:859 +#line 107 "parser.yy" // lalr1.cc:859 { - TokenPtr sub(new TokenSubstring()); - ctx.expression.push_back(sub); + TokenPtr opt(new TokenOption(yystack_[3].value.as< uint16_t > (), yystack_[0].value.as< TokenOption::RepresentationType > ())); + ctx.expression.push_back(opt); } #line 659 "parser.cc" // lalr1.cc:859 break; - case 10: -#line 115 "parser.yy" // lalr1.cc:859 + case 9: +#line 112 "parser.yy" // lalr1.cc:859 { - yylhs.value.as< uint16_t > () = ctx.convertOptionCode(yystack_[0].value.as< std::string > (), yystack_[0].location); - } -#line 667 "parser.cc" // lalr1.cc:859 + TokenPtr sub(new TokenSubstring()); + ctx.expression.push_back(sub); + } +#line 668 "parser.cc" // lalr1.cc:859 break; case 11: -#line 119 "parser.yy" // lalr1.cc:859 +#line 121 "parser.yy" // lalr1.cc:859 { - yylhs.value.as< uint16_t > () = ctx.convertOptionName(yystack_[0].value.as< std::string > (), yystack_[0].location); + yylhs.value.as< uint16_t > () = ctx.convertOptionCode(yystack_[0].value.as< std::string > (), yystack_[0].location); } -#line 675 "parser.cc" // lalr1.cc:859 +#line 676 "parser.cc" // lalr1.cc:859 break; case 12: #line 125 "parser.yy" // lalr1.cc:859 { - yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::TEXTUAL; - } -#line 683 "parser.cc" // lalr1.cc:859 + yylhs.value.as< uint16_t > () = ctx.convertOptionName(yystack_[0].value.as< std::string > (), yystack_[0].location); + } +#line 684 "parser.cc" // lalr1.cc:859 break; case 13: -#line 129 "parser.yy" // lalr1.cc:859 +#line 131 "parser.yy" // lalr1.cc:859 { - yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::HEXADECIMAL; + yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::TEXTUAL; } -#line 691 "parser.cc" // lalr1.cc:859 +#line 692 "parser.cc" // lalr1.cc:859 break; case 14: #line 135 "parser.yy" // lalr1.cc:859 { - TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); - ctx.expression.push_back(str); - } + yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::HEXADECIMAL; + } #line 700 "parser.cc" // lalr1.cc:859 break; case 15: -#line 142 "parser.yy" // lalr1.cc:859 +#line 141 "parser.yy" // lalr1.cc:859 { - TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); - ctx.expression.push_back(str); - } + TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); + ctx.expression.push_back(str); + } #line 709 "parser.cc" // lalr1.cc:859 break; case 16: -#line 147 "parser.yy" // lalr1.cc:859 +#line 148 "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 + break; + + case 17: +#line 153 "parser.yy" // lalr1.cc:859 { TokenPtr str(new TokenString("all")); ctx.expression.push_back(str); } -#line 718 "parser.cc" // lalr1.cc:859 +#line 727 "parser.cc" // lalr1.cc:859 break; -#line 722 "parser.cc" // lalr1.cc:859 +#line 731 "parser.cc" // lalr1.cc:859 default: break; } @@ -973,79 +982,79 @@ namespace isc { namespace eval { } - const signed char EvalParser::yypact_ninf_ = -9; + const signed char EvalParser::yypact_ninf_ = -10; const signed char EvalParser::yytable_ninf_ = -1; const signed char EvalParser::yypact_[] = { - -4, -8, -3, -4, -9, -9, -9, 12, -9, 19, - 1, -1, 11, -9, -1, -9, -9, 10, 15, -9, - -9, 17, 13, 14, -9, 18, -9, -9, -9, -6, - -9, -9, 20, -9 + -4, -1, 3, -4, -4, -10, -10, -10, 18, -10, + 17, -8, 1, -10, 13, -10, 1, -10, -10, 12, + 19, -10, -10, 22, 11, 16, -10, 20, -10, -10, + -10, -7, -10, -10, 23, -10 }; const unsigned char EvalParser::yydefact_[] = { - 0, 0, 0, 0, 5, 6, 9, 0, 2, 0, - 0, 0, 0, 1, 0, 10, 11, 0, 0, 3, - 4, 0, 0, 0, 14, 0, 12, 13, 7, 0, - 16, 15, 0, 8 + 0, 0, 0, 0, 0, 6, 7, 10, 0, 2, + 0, 0, 0, 4, 0, 1, 0, 11, 12, 0, + 0, 3, 5, 0, 0, 0, 15, 0, 13, 14, + 8, 0, 17, 16, 0, 9 }; const signed char EvalParser::yypgoto_[] = { - -9, -9, 24, -5, -9, -9, -9, -9 + -10, -10, 21, -9, -10, -10, -10, -10 }; const signed char EvalParser::yydefgoto_[] = { - -1, 7, 8, 9, 17, 28, 25, 32 + -1, 8, 9, 10, 19, 30, 27, 34 }; const unsigned char EvalParser::yytable_[] = { - 1, 2, 30, 1, 2, 10, 18, 3, 11, 20, - 31, 4, 13, 5, 4, 6, 5, 15, 6, 16, - 26, 27, 14, 19, 21, 22, 23, 12, 29, 24, - 0, 0, 33 + 1, 2, 32, 20, 3, 1, 2, 22, 4, 17, + 33, 18, 5, 11, 6, 12, 7, 5, 15, 6, + 16, 7, 28, 29, 13, 14, 21, 23, 26, 0, + 24, 31, 25, 0, 0, 0, 35 }; const signed char EvalParser::yycheck_[] = { - 4, 5, 8, 4, 5, 13, 11, 11, 11, 14, - 16, 15, 0, 17, 15, 19, 17, 16, 19, 18, - 6, 7, 3, 12, 14, 10, 9, 3, 10, 16, - -1, -1, 12 + 4, 5, 9, 12, 8, 4, 5, 16, 12, 17, + 17, 19, 16, 14, 18, 12, 20, 16, 0, 18, + 3, 20, 6, 7, 3, 4, 13, 15, 17, -1, + 11, 11, 10, -1, -1, -1, 13 }; const unsigned char EvalParser::yystos_[] = { - 0, 4, 5, 11, 15, 17, 19, 21, 22, 23, - 13, 11, 22, 0, 3, 16, 18, 24, 23, 12, - 23, 14, 10, 9, 16, 26, 6, 7, 25, 10, - 8, 16, 27, 12 + 0, 4, 5, 8, 12, 16, 18, 20, 22, 23, + 24, 14, 12, 23, 23, 0, 3, 17, 19, 25, + 24, 13, 24, 15, 11, 10, 17, 27, 6, 7, + 26, 11, 9, 17, 28, 13 }; const unsigned char EvalParser::yyr1_[] = { - 0, 20, 21, 22, 22, 23, 23, 23, 23, 23, - 24, 24, 25, 25, 26, 27, 27 + 0, 21, 22, 23, 23, 23, 24, 24, 24, 24, + 24, 25, 25, 26, 26, 27, 28, 28 }; const unsigned char EvalParser::yyr2_[] = { - 0, 2, 1, 3, 3, 1, 1, 6, 8, 1, - 1, 1, 1, 1, 1, 1, 1 + 0, 2, 1, 3, 2, 3, 1, 1, 6, 8, + 1, 1, 1, 1, 1, 1, 1, 1 }; @@ -1056,10 +1065,10 @@ namespace isc { namespace eval { const EvalParser::yytname_[] = { "\"end of file\"", "error", "$undefined", "\"==\"", "\"option\"", - "\"substring\"", "\"text\"", "\"hex\"", "\"all\"", "\".\"", "\",\"", - "\"(\"", "\")\"", "\"[\"", "\"]\"", "\"constant string\"", "\"integer\"", - "\"constant hexstring\"", "\"option name\"", "TOKEN", "$accept", - "expression", "bool_expr", "string_expr", "option_code", + "\"substring\"", "\"text\"", "\"hex\"", "\"not\"", "\"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 }; @@ -1067,8 +1076,8 @@ namespace isc { namespace eval { const unsigned char EvalParser::yyrline_[] = { - 0, 79, 79, 82, 83, 90, 95, 100, 105, 110, - 114, 118, 124, 128, 134, 141, 146 + 0, 80, 80, 83, 84, 89, 96, 101, 106, 111, + 116, 120, 124, 130, 134, 140, 147, 152 }; // Print the state stack on the debug stream. @@ -1103,8 +1112,8 @@ namespace isc { namespace eval { #line 21 "parser.yy" // lalr1.cc:1167 } } // isc::eval -#line 1107 "parser.cc" // lalr1.cc:1167 -#line 153 "parser.yy" // lalr1.cc:1168 +#line 1116 "parser.cc" // lalr1.cc:1167 +#line 159 "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 b5a1d9d0cc..3aa107e905 100644 --- a/src/lib/eval/parser.h +++ b/src/lib/eval/parser.h @@ -335,18 +335,19 @@ namespace isc { namespace eval { TOKEN_SUBSTRING = 260, TOKEN_TEXT = 261, TOKEN_HEX = 262, - TOKEN_ALL = 263, - TOKEN_DOT = 264, - TOKEN_COMA = 265, - TOKEN_LPAREN = 266, - TOKEN_RPAREN = 267, - TOKEN_LBRACKET = 268, - TOKEN_RBRACKET = 269, - TOKEN_STRING = 270, - TOKEN_INTEGER = 271, - TOKEN_HEXSTRING = 272, - TOKEN_OPTION_NAME = 273, - TOKEN_TOKEN = 274 + TOKEN_NOT = 263, + TOKEN_ALL = 264, + TOKEN_DOT = 265, + TOKEN_COMA = 266, + TOKEN_LPAREN = 267, + TOKEN_RPAREN = 268, + TOKEN_LBRACKET = 269, + TOKEN_RBRACKET = 270, + TOKEN_STRING = 271, + TOKEN_INTEGER = 272, + TOKEN_HEXSTRING = 273, + TOKEN_OPTION_NAME = 274, + TOKEN_TOKEN = 275 }; }; @@ -481,6 +482,10 @@ namespace isc { namespace eval { symbol_type make_HEX (const location_type& l); + static inline + symbol_type + make_NOT (const location_type& l); + static inline symbol_type make_ALL (const location_type& l); @@ -734,12 +739,12 @@ namespace isc { namespace eval { enum { yyeof_ = 0, - yylast_ = 32, ///< Last index in yytable_. + yylast_ = 36, ///< Last index in yytable_. yynnts_ = 8, ///< Number of nonterminal symbols. - yyfinal_ = 13, ///< Termination state number. + yyfinal_ = 15, ///< Termination state number. yyterror_ = 1, yyerrcode_ = 256, - yyntokens_ = 20 ///< Number of tokens. + yyntokens_ = 21 ///< Number of tokens. }; @@ -783,9 +788,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 + 15, 16, 17, 18, 19, 20 }; - const unsigned int user_token_number_max_ = 274; + const unsigned int user_token_number_max_ = 275; const token_number_type undef_token_ = 2; if (static_cast(t) <= yyeof_) @@ -818,19 +823,19 @@ namespace isc { namespace eval { { switch (other.type_get ()) { - case 25: // option_repr_type + case 26: // option_repr_type value.copy< TokenOption::RepresentationType > (other.value); break; - case 15: // "constant string" - case 16: // "integer" - case 17: // "constant hexstring" - case 18: // "option name" - case 19: // TOKEN + case 16: // "constant string" + case 17: // "integer" + case 18: // "constant hexstring" + case 19: // "option name" + case 20: // TOKEN value.copy< std::string > (other.value); break; - case 24: // option_code + case 25: // option_code value.copy< uint16_t > (other.value); break; @@ -851,19 +856,19 @@ namespace isc { namespace eval { (void) v; switch (this->type_get ()) { - case 25: // option_repr_type + case 26: // option_repr_type value.copy< TokenOption::RepresentationType > (v); break; - case 15: // "constant string" - case 16: // "integer" - case 17: // "constant hexstring" - case 18: // "option name" - case 19: // TOKEN + case 16: // "constant string" + case 17: // "integer" + case 18: // "constant hexstring" + case 19: // "option name" + case 20: // TOKEN value.copy< std::string > (v); break; - case 24: // option_code + case 25: // option_code value.copy< uint16_t > (v); break; @@ -929,19 +934,19 @@ namespace isc { namespace eval { // Type destructor. switch (yytype) { - case 25: // option_repr_type + case 26: // option_repr_type value.template destroy< TokenOption::RepresentationType > (); break; - case 15: // "constant string" - case 16: // "integer" - case 17: // "constant hexstring" - case 18: // "option name" - case 19: // TOKEN + case 16: // "constant string" + case 17: // "integer" + case 18: // "constant hexstring" + case 19: // "option name" + case 20: // TOKEN value.template destroy< std::string > (); break; - case 24: // option_code + case 25: // option_code value.template destroy< uint16_t > (); break; @@ -968,19 +973,19 @@ namespace isc { namespace eval { super_type::move(s); switch (this->type_get ()) { - case 25: // option_repr_type + case 26: // option_repr_type value.move< TokenOption::RepresentationType > (s.value); break; - case 15: // "constant string" - case 16: // "integer" - case 17: // "constant hexstring" - case 18: // "option name" - case 19: // TOKEN + case 16: // "constant string" + case 17: // "integer" + case 18: // "constant hexstring" + case 19: // "option name" + case 20: // TOKEN value.move< std::string > (s.value); break; - case 24: // option_code + case 25: // option_code value.move< uint16_t > (s.value); break; @@ -1040,7 +1045,8 @@ namespace isc { namespace eval { yytoken_number_[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274 + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275 }; return static_cast (yytoken_number_[type]); } @@ -1081,6 +1087,12 @@ namespace isc { namespace eval { return symbol_type (token::TOKEN_HEX, l); } + EvalParser::symbol_type + EvalParser::make_NOT (const location_type& l) + { + return symbol_type (token::TOKEN_NOT, l); + } + EvalParser::symbol_type EvalParser::make_ALL (const location_type& l) { @@ -1156,7 +1168,7 @@ namespace isc { namespace eval { #line 21 "parser.yy" // lalr1.cc:392 } } // isc::eval -#line 1160 "parser.h" // lalr1.cc:392 +#line 1172 "parser.h" // lalr1.cc:392 diff --git a/src/lib/eval/parser.yy b/src/lib/eval/parser.yy index 961889929e..9087ab3a6c 100644 --- a/src/lib/eval/parser.yy +++ b/src/lib/eval/parser.yy @@ -49,6 +49,7 @@ using namespace isc::eval; SUBSTRING "substring" TEXT "text" HEX "hex" + NOT "not" ALL "all" DOT "." COMA "," @@ -80,6 +81,11 @@ expression : bool_expr ; bool_expr : "(" bool_expr ")" + | NOT bool_expr + { + TokenPtr neg(new TokenNot()); + ctx.expression.push_back(neg); + } | string_expr EQUAL string_expr { TokenPtr eq(new TokenEqual()); diff --git a/src/lib/eval/tests/context_unittest.cc b/src/lib/eval/tests/context_unittest.cc index 030cacbff6..eed1043b02 100644 --- a/src/lib/eval/tests/context_unittest.cc +++ b/src/lib/eval/tests/context_unittest.cc @@ -341,6 +341,14 @@ TEST_F(EvalContextTest, parseErrors) { checkError("== 'ab'", ":1.1-2: syntax error, unexpected =="); checkError("'foo' ==", ":1.9: syntax error, unexpected end of file"); + checkError("not 'foo'", + ":1.10: syntax error, unexpected end of file, " + "expecting =="); + checkError("not()", + ":1.5: syntax error, unexpected )"); + 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 )"); diff --git a/src/lib/eval/tests/token_unittest.cc b/src/lib/eval/tests/token_unittest.cc index e93d558f88..307b0034a9 100644 --- a/src/lib/eval/tests/token_unittest.cc +++ b/src/lib/eval/tests/token_unittest.cc @@ -407,6 +407,39 @@ TEST_F(TokenTest, optionEqualTrue) { EXPECT_EQ("true", values_.top()); } +// This test checks if a token representing a not is able to +// negate a boolean value (with incorrectly built stack). +TEST_F(TokenTest, optionNotInvalid) { + + ASSERT_NO_THROW(t_.reset(new TokenNot())); + + // CASE 1: The stack is empty. + EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack); + + // CASE 2: The top value is not a boolean + values_.push("foo"); + EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError); +} + +// This test checks if a token representing a not operator is able to +// negate a boolean value. +TEST_F(TokenTest, optionNot) { + + ASSERT_NO_THROW(t_.reset(new TokenNot())); + + values_.push("true"); + EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_)); + + // After evaluation there should be the negation of the value. + ASSERT_EQ(1, values_.size()); + EXPECT_EQ("false", values_.top()); + + // Double negation is identity. + 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 59df54ce22..ea693276b7 100644 --- a/src/lib/eval/token.cc +++ b/src/lib/eval/token.cc @@ -176,3 +176,23 @@ TokenSubstring::evaluate(const Pkt& /*pkt*/, ValueStack& values) { // and finally get the substring values.push(string_str.substr(start_pos, length)); } + +void +TokenNot::evaluate(const Pkt& /*pkt*/, ValueStack& values) { + + if (values.size() == 0) { + isc_throw(EvalBadStack, "Incorrect empty stack."); + } + + string op = values.top(); + values.pop(); + + if (op == "true") { + values.push("false"); + } else if (op == "false") { + values.push("true"); + } else { + isc_throw(EvalTypeError, "Expected a logical value at top of stack. " + << "Got '" << op << "'."); + } +} diff --git a/src/lib/eval/token.h b/src/lib/eval/token.h index a476948adc..ca45078bb7 100644 --- a/src/lib/eval/token.h +++ b/src/lib/eval/token.h @@ -277,6 +277,31 @@ public: void evaluate(const Pkt& pkt, ValueStack& values); }; +/// @brief Token that represents logical negation operator +/// +/// For example in the expression "not(option[vendor-class].text == 'MSF')" +/// this token represents the leading "not" +class TokenNot : public Token { +public: + /// @brief Constructor (does nothing) + TokenNot() {} + + /// @brief Logical negation. + /// + /// Evaluation does not use packet information, but rather consumes the last + /// result. It does a simple string comparison and sets the value to + /// either "true" or "false". It requires at least one value to be + /// present on stack and to be either "true" or "false". + /// + /// @throw EvalBadStack if there are less than 1 value on stack + /// @throw EvalTypeError if the top value on the stack is not either + /// "true" or "false" + /// + /// @param pkt (unused) + /// @param values - stack of values (logical top value negated) + void evaluate(const Pkt& pkt, ValueStack& values); +}; + }; // end of isc::dhcp namespace }; // end of isc namespace