From: Francis Dupont Date: Fri, 13 Nov 2015 15:53:23 +0000 (+0100) Subject: [4088fd] Changed the syntax to unquote integers X-Git-Tag: trac4201_base~5^2^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=751b714cfa98c91dd19a0f85b12dd9aab6f5b6ac;p=thirdparty%2Fkea.git [4088fd] Changed the syntax to unquote integers --- diff --git a/src/lib/eval/lexer.cc b/src/lib/eval/lexer.cc index ba342c19ad..cc3bbb1234 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 17 -#define YY_END_OF_BUFFER 18 +#define YY_NUM_RULES 16 +#define YY_END_OF_BUFFER 17 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -478,13 +478,13 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[48] = +static yyconst flex_int16_t yy_accept[44] = { 0, - 0, 0, 18, 16, 1, 2, 16, 11, 12, 15, - 16, 7, 7, 16, 13, 14, 16, 16, 1, 2, - 0, 5, 0, 0, 0, 7, 0, 8, 0, 0, - 3, 0, 6, 0, 0, 0, 0, 0, 4, 0, - 0, 9, 0, 0, 0, 10, 0 + 0, 0, 17, 15, 1, 2, 15, 10, 11, 14, + 15, 5, 5, 15, 12, 13, 15, 15, 15, 1, + 2, 0, 3, 5, 0, 6, 0, 0, 0, 4, + 9, 0, 0, 0, 0, 0, 0, 7, 0, 0, + 0, 8, 0 } ; static yyconst flex_int32_t yy_ec[256] = @@ -526,60 +526,54 @@ static yyconst flex_int32_t yy_meta[28] = 1, 1, 1, 1, 1, 1, 1 } ; -static yyconst flex_int16_t yy_base[50] = +static yyconst flex_int16_t yy_base[46] = { 0, - 0, 0, 75, 76, 72, 70, 24, 76, 76, 76, - 20, 26, 28, 61, 76, 76, 48, 43, 66, 62, - 60, 76, 37, 39, 38, 35, 0, 76, 37, 45, - 76, 46, 0, 42, 35, 55, 35, 30, 76, 34, - 30, 76, 34, 31, 33, 76, 76, 66, 28 + 0, 0, 62, 63, 59, 57, 55, 63, 63, 63, + 19, 21, 23, 47, 63, 63, 37, 33, 28, 52, + 50, 48, 63, 26, 0, 63, 31, 24, 32, 0, + 63, 29, 22, 24, 19, 23, 19, 63, 23, 20, + 22, 63, 63, 36, 35 } ; -static yyconst flex_int16_t yy_def[50] = +static yyconst flex_int16_t yy_def[46] = { 0, - 47, 1, 47, 47, 47, 47, 48, 47, 47, 47, - 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, - 48, 47, 48, 48, 48, 47, 49, 47, 47, 47, - 47, 48, 49, 47, 47, 48, 47, 47, 47, 47, - 47, 47, 47, 47, 47, 47, 0, 47, 47 + 43, 1, 43, 43, 43, 43, 44, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 44, 43, 43, 45, 43, 43, 43, 43, 45, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 0, 43, 43 } ; -static yyconst flex_int16_t yy_nxt[104] = +static yyconst flex_int16_t yy_nxt[91] = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 4, 4, 15, 16, 4, 4, 4, 4, 4, - 4, 17, 4, 4, 18, 4, 4, 22, 26, 26, - 33, 23, 24, 24, 26, 26, 26, 26, 27, 25, - 22, 22, 31, 26, 26, 24, 24, 24, 24, 22, - 46, 45, 44, 43, 42, 41, 40, 32, 39, 38, - 37, 35, 34, 22, 20, 36, 21, 19, 21, 30, - 29, 28, 20, 19, 47, 3, 47, 47, 47, 47, - 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, - 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, - - 47, 47, 47 + 14, 4, 4, 15, 16, 17, 4, 4, 4, 4, + 4, 18, 4, 4, 19, 4, 4, 24, 24, 24, + 24, 24, 24, 25, 24, 24, 22, 30, 22, 42, + 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, + 31, 23, 21, 20, 29, 28, 27, 26, 23, 21, + 20, 43, 3, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43 } ; -static yyconst flex_int16_t yy_chk[104] = +static yyconst flex_int16_t yy_chk[91] = { 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, 7, 11, 11, - 49, 7, 7, 7, 12, 12, 13, 13, 12, 7, - 23, 25, 24, 26, 26, 23, 23, 24, 24, 32, - 45, 44, 43, 41, 40, 38, 37, 25, 36, 35, - 34, 30, 29, 21, 20, 32, 48, 19, 48, 18, - 17, 14, 6, 5, 3, 47, 47, 47, 47, 47, - 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, - 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, - - 47, 47, 47 + 1, 1, 1, 1, 1, 1, 1, 11, 11, 12, + 12, 13, 13, 12, 24, 24, 44, 45, 44, 41, + 40, 39, 37, 36, 35, 34, 33, 32, 29, 28, + 27, 22, 21, 20, 19, 18, 17, 14, 7, 6, + 5, 3, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43 } ; /* Table of booleans, true if rule could match eol. */ -static yyconst flex_int32_t yy_rule_can_match_eol[18] = +static yyconst flex_int32_t yy_rule_can_match_eol[17] = { 0, -0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; +0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; @@ -587,10 +581,10 @@ static char *yy_last_accepting_cpos; extern int yy_flex_debug; int yy_flex_debug = 1; -static yyconst flex_int16_t yy_rule_linenum[17] = +static yyconst flex_int16_t yy_rule_linenum[16] = { 0, - 83, 87, 93, 108, 114, 124, 130, 144, 145, 146, - 147, 148, 149, 150, 151, 153 + 83, 87, 93, 103, 109, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 133 } ; /* The intent behind this definition is that it'll catch @@ -657,7 +651,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 661 "lexer.cc" +#line 655 "lexer.cc" #define INITIAL 0 @@ -940,7 +934,7 @@ YY_DECL loc.step(); -#line 944 "lexer.cc" +#line 938 "lexer.cc" while ( 1 ) /* loops until end-of-file is reached */ { @@ -969,13 +963,13 @@ 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 >= 48 ) + if ( yy_current_state >= 44 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_current_state != 47 ); + while ( yy_current_state != 43 ); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); @@ -1004,13 +998,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 < 17 ) + else if ( yy_act < 16 ) fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n", (long)yy_rule_linenum[yy_act], yytext ); - else if ( yy_act == 17 ) + else if ( yy_act == 16 ) fprintf( stderr, "--accepting default rule (\"%s\")\n", yytext ); - else if ( yy_act == 18 ) + else if ( yy_act == 17 ) fprintf( stderr, "--(end of buffer or a NUL)\n" ); else fprintf( stderr, "--EOF (start condition %d)\n", YY_START ); @@ -1047,33 +1041,6 @@ YY_RULE_SETUP case 3: YY_RULE_SETUP #line 93 "lexer.ll" -{ - // A string containing a number. Quotes should be removed, see below. - std::string tmp(yytext+1); - tmp.resize(tmp.size() - 1); - - try { - static_cast(boost::lexical_cast(tmp)); - } catch (const boost::bad_lexical_cast &) { - // In fact it is not a valid number - return isc::eval::EvalParser::make_STRING(tmp, loc); - } - - return isc::eval::EvalParser::make_NUMBER(tmp, loc); -} - YY_BREAK -case 4: -YY_RULE_SETUP -#line 108 "lexer.ll" -{ - // A string containing the "all" keyword. - - return isc::eval::EvalParser::make_ALL("all", loc); -} - YY_BREAK -case 5: -YY_RULE_SETUP -#line 114 "lexer.ll" { // A string has been matched. It contains the actual string and single quotes. // We need to get those quotes out of the way and just use its content, e.g. @@ -1084,87 +1051,92 @@ YY_RULE_SETUP return isc::eval::EvalParser::make_STRING(tmp, loc); } YY_BREAK -case 6: +case 4: YY_RULE_SETUP -#line 124 "lexer.ll" +#line 103 "lexer.ll" { // A hex string has been matched. It contains the '0x' or '0X' header // followed by at least one hexadecimal digit. return isc::eval::EvalParser::make_HEXSTRING(yytext, loc); } YY_BREAK -case 7: +case 5: YY_RULE_SETUP -#line 130 "lexer.ll" +#line 109 "lexer.ll" { // An integer was found. std::string tmp(yytext); - int n; try { - n = boost::lexical_cast(tmp); + static_cast(boost::lexical_cast(tmp)); } catch (const boost::bad_lexical_cast &) { driver.error(loc, "Failed to convert " + tmp + " to an integer."); } - return isc::eval::EvalParser::make_INTEGER(n, loc); + // The parser needs the string form as double conversion is no lossless + return isc::eval::EvalParser::make_INTEGER(tmp, loc); } YY_BREAK -case 8: +case 6: YY_RULE_SETUP -#line 144 "lexer.ll" +#line 123 "lexer.ll" return isc::eval::EvalParser::make_EQUAL(loc); YY_BREAK -case 9: +case 7: YY_RULE_SETUP -#line 145 "lexer.ll" +#line 124 "lexer.ll" return isc::eval::EvalParser::make_OPTION(loc); YY_BREAK -case 10: +case 8: YY_RULE_SETUP -#line 146 "lexer.ll" +#line 125 "lexer.ll" return isc::eval::EvalParser::make_SUBSTRING(loc); YY_BREAK -case 11: +case 9: +YY_RULE_SETUP +#line 126 "lexer.ll" +return isc::eval::EvalParser::make_ALL(loc); + YY_BREAK +case 10: YY_RULE_SETUP -#line 147 "lexer.ll" +#line 127 "lexer.ll" return isc::eval::EvalParser::make_LPAREN(loc); YY_BREAK -case 12: +case 11: YY_RULE_SETUP -#line 148 "lexer.ll" +#line 128 "lexer.ll" return isc::eval::EvalParser::make_RPAREN(loc); YY_BREAK -case 13: +case 12: YY_RULE_SETUP -#line 149 "lexer.ll" +#line 129 "lexer.ll" return isc::eval::EvalParser::make_LBRACKET(loc); YY_BREAK -case 14: +case 13: YY_RULE_SETUP -#line 150 "lexer.ll" +#line 130 "lexer.ll" return isc::eval::EvalParser::make_RBRACKET(loc); YY_BREAK -case 15: +case 14: YY_RULE_SETUP -#line 151 "lexer.ll" +#line 131 "lexer.ll" return isc::eval::EvalParser::make_COMA(loc); YY_BREAK -case 16: +case 15: YY_RULE_SETUP -#line 153 "lexer.ll" +#line 133 "lexer.ll" driver.error (loc, "Invalid character: " + std::string(yytext)); YY_BREAK case YY_STATE_EOF(INITIAL): -#line 154 "lexer.ll" +#line 134 "lexer.ll" return isc::eval::EvalParser::make_END(loc); YY_BREAK -case 17: +case 16: YY_RULE_SETUP -#line 155 "lexer.ll" +#line 135 "lexer.ll" ECHO; YY_BREAK -#line 1168 "lexer.cc" +#line 1140 "lexer.cc" case YY_END_OF_BUFFER: { @@ -1477,7 +1449,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 >= 48 ) + if ( yy_current_state >= 44 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1510,11 +1482,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 >= 48 ) + if ( yy_current_state >= 44 ) 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 == 47); + yy_is_jam = (yy_current_state == 43); return yy_is_jam ? 0 : yy_current_state; } @@ -2252,7 +2224,7 @@ void yyfree (void * ptr ) /* %ok-for-header */ -#line 155 "lexer.ll" +#line 135 "lexer.ll" diff --git a/src/lib/eval/lexer.ll b/src/lib/eval/lexer.ll index d36c81268b..ce20911a6a 100644 --- a/src/lib/eval/lexer.ll +++ b/src/lib/eval/lexer.ll @@ -90,27 +90,6 @@ blank [ \t] loc.step(); } -\'{int}\' { - // A string containing a number. Quotes should be removed, see below. - std::string tmp(yytext+1); - tmp.resize(tmp.size() - 1); - - try { - static_cast(boost::lexical_cast(tmp)); - } catch (const boost::bad_lexical_cast &) { - // In fact it is not a valid number - return isc::eval::EvalParser::make_STRING(tmp, loc); - } - - return isc::eval::EvalParser::make_NUMBER(tmp, loc); -} - -"'all'" { - // A string containing the "all" keyword. - - return isc::eval::EvalParser::make_ALL("all", loc); -} - \'[^\'\n]*\' { // A string has been matched. It contains the actual string and single quotes. // We need to get those quotes out of the way and just use its content, e.g. @@ -131,19 +110,20 @@ blank [ \t] // An integer was found. std::string tmp(yytext); - int n; try { - n = boost::lexical_cast(tmp); + static_cast(boost::lexical_cast(tmp)); } catch (const boost::bad_lexical_cast &) { driver.error(loc, "Failed to convert " + tmp + " to an integer."); } - return isc::eval::EvalParser::make_INTEGER(n, loc); + // The parser needs the string form as double conversion is no lossless + return isc::eval::EvalParser::make_INTEGER(tmp, loc); } "==" return isc::eval::EvalParser::make_EQUAL(loc); "option" return isc::eval::EvalParser::make_OPTION(loc); "substring" return isc::eval::EvalParser::make_SUBSTRING(loc); +"all" return isc::eval::EvalParser::make_ALL(loc); "(" return isc::eval::EvalParser::make_LPAREN(loc); ")" return isc::eval::EvalParser::make_RPAREN(loc); "[" return isc::eval::EvalParser::make_LBRACKET(loc); diff --git a/src/lib/eval/parser.cc b/src/lib/eval/parser.cc index a479c2ad20..c2c07d1230 100644 --- a/src/lib/eval/parser.cc +++ b/src/lib/eval/parser.cc @@ -49,7 +49,7 @@ #line 51 "parser.cc" // lalr1.cc:412 // Unqualified %code blocks. -#line 38 "parser.yy" // lalr1.cc:413 +#line 39 "parser.yy" // lalr1.cc:413 # include "eval_context.h" @@ -251,14 +251,10 @@ namespace isc { namespace eval { { switch (that.type_get ()) { - case 15: // "integer" - value.move< int > (that.value); - break; - - case 11: // "a number in a constant string" - case 12: // "the all constant string" - case 13: // "constant string" + case 12: // "constant string" + case 13: // "integer" case 14: // "constant hexstring" + case 15: // TOKEN value.move< std::string > (that.value); break; @@ -277,14 +273,10 @@ namespace isc { namespace eval { state = that.state; switch (that.type_get ()) { - case 15: // "integer" - value.copy< int > (that.value); - break; - - case 11: // "a number in a constant string" - case 12: // "the all constant string" - case 13: // "constant string" + case 12: // "constant string" + case 13: // "integer" case 14: // "constant hexstring" + case 15: // TOKEN value.copy< std::string > (that.value); break; @@ -324,39 +316,32 @@ namespace isc { namespace eval { << yysym.location << ": "; switch (yytype) { - case 11: // "a number in a constant string" + case 12: // "constant string" -#line 58 "parser.yy" // lalr1.cc:636 +#line 61 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } -#line 332 "parser.cc" // lalr1.cc:636 +#line 324 "parser.cc" // lalr1.cc:636 break; - case 12: // "the all constant string" + case 13: // "integer" -#line 58 "parser.yy" // lalr1.cc:636 +#line 61 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } -#line 339 "parser.cc" // lalr1.cc:636 - break; - - case 13: // "constant string" - -#line 58 "parser.yy" // lalr1.cc:636 - { yyoutput << yysym.value.template as< std::string > (); } -#line 346 "parser.cc" // lalr1.cc:636 +#line 331 "parser.cc" // lalr1.cc:636 break; case 14: // "constant hexstring" -#line 58 "parser.yy" // lalr1.cc:636 +#line 61 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } -#line 353 "parser.cc" // lalr1.cc:636 +#line 338 "parser.cc" // lalr1.cc:636 break; - case 15: // "integer" + case 15: // TOKEN -#line 58 "parser.yy" // lalr1.cc:636 - { yyoutput << yysym.value.template as< int > (); } -#line 360 "parser.cc" // lalr1.cc:636 +#line 61 "parser.yy" // lalr1.cc:636 + { yyoutput << yysym.value.template as< std::string > (); } +#line 345 "parser.cc" // lalr1.cc:636 break; @@ -556,14 +541,10 @@ namespace isc { namespace eval { when using variants. */ switch (yyr1_[yyn]) { - case 15: // "integer" - yylhs.value.build< int > (); - break; - - case 11: // "a number in a constant string" - case 12: // "the all constant string" - case 13: // "constant string" + case 12: // "constant string" + case 13: // "integer" case 14: // "constant hexstring" + case 15: // TOKEN yylhs.value.build< std::string > (); break; @@ -585,104 +566,92 @@ namespace isc { namespace eval { switch (yyn) { case 3: -#line 70 "parser.yy" // lalr1.cc:859 +#line 73 "parser.yy" // lalr1.cc:859 { TokenPtr eq(new TokenEqual()); ctx.expression.push_back(eq); } -#line 594 "parser.cc" // lalr1.cc:859 +#line 575 "parser.cc" // lalr1.cc:859 break; case 4: -#line 77 "parser.yy" // lalr1.cc:859 +#line 80 "parser.yy" // lalr1.cc:859 { TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); ctx.expression.push_back(str); } -#line 603 "parser.cc" // lalr1.cc:859 +#line 584 "parser.cc" // lalr1.cc:859 break; case 5: -#line 82 "parser.yy" // lalr1.cc:859 - { - TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); - ctx.expression.push_back(str); - } -#line 612 "parser.cc" // lalr1.cc:859 - break; - - case 6: -#line 87 "parser.yy" // lalr1.cc:859 - { - TokenPtr str(new TokenString("all")); - ctx.expression.push_back(str); - } -#line 621 "parser.cc" // lalr1.cc:859 - break; - - case 7: -#line 92 "parser.yy" // lalr1.cc:859 +#line 85 "parser.yy" // lalr1.cc:859 { TokenPtr hex(new TokenHexString(yystack_[0].value.as< std::string > ())); ctx.expression.push_back(hex); } -#line 630 "parser.cc" // lalr1.cc:859 +#line 593 "parser.cc" // lalr1.cc:859 break; - case 8: -#line 97 "parser.yy" // lalr1.cc:859 + case 6: +#line 90 "parser.yy" // lalr1.cc:859 { - int n = yystack_[1].value.as< int > (); + int n; + try { + n = boost::lexical_cast(yystack_[1].value.as< std::string > ()); + } catch (const boost::bad_lexical_cast &) { + // This can't happen... + ctx.error(yystack_[1].location, + "Option code has invalid value in " + yystack_[1].value.as< std::string > ()); + } if (n < 0 || n > 65535) { - std::ostringstream oss; - oss << "Option code has invalid value in " << n - << ". Allowed range: 0..65535"; - ctx.error(yystack_[1].location, oss.str()); + ctx.error(yystack_[1].location, + "Option code has invalid value in " + + yystack_[1].value.as< std::string > () + ". Allowed range: 0..65535"); } TokenPtr opt(new TokenOption(static_cast(n))); ctx.expression.push_back(opt); } -#line 646 "parser.cc" // lalr1.cc:859 +#line 615 "parser.cc" // lalr1.cc:859 break; - case 9: -#line 109 "parser.yy" // lalr1.cc:859 + case 7: +#line 108 "parser.yy" // lalr1.cc:859 { TokenPtr sub(new TokenSubstring()); ctx.expression.push_back(sub); } -#line 655 "parser.cc" // lalr1.cc:859 +#line 624 "parser.cc" // lalr1.cc:859 break; - case 10: -#line 116 "parser.yy" // lalr1.cc:859 + case 9: +#line 117 "parser.yy" // lalr1.cc:859 { TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); ctx.expression.push_back(str); } -#line 664 "parser.cc" // lalr1.cc:859 +#line 633 "parser.cc" // lalr1.cc:859 break; - case 11: -#line 123 "parser.yy" // lalr1.cc:859 + case 10: +#line 124 "parser.yy" // lalr1.cc:859 { TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); ctx.expression.push_back(str); } -#line 673 "parser.cc" // lalr1.cc:859 +#line 642 "parser.cc" // lalr1.cc:859 break; - case 12: -#line 128 "parser.yy" // lalr1.cc:859 + case 11: +#line 129 "parser.yy" // lalr1.cc:859 { TokenPtr str(new TokenString("all")); ctx.expression.push_back(str); } -#line 682 "parser.cc" // lalr1.cc:859 +#line 651 "parser.cc" // lalr1.cc:859 break; -#line 686 "parser.cc" // lalr1.cc:859 +#line 655 "parser.cc" // lalr1.cc:859 default: break; } @@ -937,74 +906,72 @@ namespace isc { namespace eval { } - const signed char EvalParser::yypact_ninf_ = -10; + const signed char EvalParser::yypact_ninf_ = -9; const signed char EvalParser::yytable_ninf_ = -1; const signed char EvalParser::yypact_[] = { - -4, 2, 5, -10, -10, -10, -10, 3, -10, 10, - -1, -4, -10, -4, 6, 9, -10, -10, 7, -10, - 11, -6, -10, -10, 12, -10 + -4, -7, -2, -9, -9, -9, 7, -9, 6, 0, + -4, -9, -4, 3, 8, -9, -9, 4, -9, 9, + -1, -9, -9, 10, -9 }; const unsigned char EvalParser::yydefact_[] = { - 0, 0, 0, 5, 6, 4, 7, 0, 2, 0, - 0, 0, 1, 0, 0, 0, 3, 8, 0, 10, - 0, 0, 11, 12, 0, 9 + 0, 0, 0, 4, 5, 8, 0, 2, 0, 0, + 0, 1, 0, 0, 0, 3, 6, 0, 9, 0, + 0, 11, 10, 0, 7 }; const signed char EvalParser::yypgoto_[] = { - -10, -10, -10, -9, -10, -10 + -9, -9, -9, -8, -9, -9 }; const signed char EvalParser::yydefgoto_[] = { - -1, 7, 8, 9, 20, 24 + -1, 6, 7, 8, 19, 23 }; const unsigned char EvalParser::yytable_[] = { - 1, 2, 15, 12, 16, 22, 23, 3, 4, 5, - 6, 10, 11, 13, 14, 18, 17, 21, 19, 0, - 25 + 1, 2, 14, 9, 15, 21, 10, 11, 3, 12, + 4, 5, 22, 13, 16, 17, 20, 18, 0, 24 }; const signed char EvalParser::yycheck_[] = { - 4, 5, 11, 0, 13, 11, 12, 11, 12, 13, - 14, 9, 7, 3, 15, 6, 10, 6, 11, -1, - 8 + 4, 5, 10, 10, 12, 6, 8, 0, 12, 3, + 14, 15, 13, 13, 11, 7, 7, 13, -1, 9 }; const unsigned char EvalParser::yystos_[] = { - 0, 4, 5, 11, 12, 13, 14, 17, 18, 19, - 9, 7, 0, 3, 15, 19, 19, 10, 6, 11, - 20, 6, 11, 12, 21, 8 + 0, 4, 5, 12, 14, 15, 17, 18, 19, 10, + 8, 0, 3, 13, 19, 19, 11, 7, 13, 20, + 7, 6, 13, 21, 9 }; const unsigned char EvalParser::yyr1_[] = { - 0, 16, 17, 18, 19, 19, 19, 19, 19, 19, - 20, 21, 21 + 0, 16, 17, 18, 19, 19, 19, 19, 19, 20, + 21, 21 }; const unsigned char EvalParser::yyr2_[] = { - 0, 2, 1, 3, 1, 1, 1, 1, 4, 8, - 1, 1, 1 + 0, 2, 1, 3, 1, 1, 4, 8, 1, 1, + 1, 1 }; @@ -1015,9 +982,8 @@ namespace isc { namespace eval { const EvalParser::yytname_[] = { "\"end of file\"", "error", "$undefined", "\"==\"", "\"option\"", - "\"substring\"", "\",\"", "\"(\"", "\")\"", "\"[\"", "\"]\"", - "\"a number in a constant string\"", "\"the all constant string\"", - "\"constant string\"", "\"constant hexstring\"", "\"integer\"", + "\"substring\"", "\"all\"", "\",\"", "\"(\"", "\")\"", "\"[\"", "\"]\"", + "\"constant string\"", "\"integer\"", "\"constant hexstring\"", "TOKEN", "$accept", "expression", "bool_expr", "string_expr", "start_expr", "length_expr", YY_NULLPTR }; @@ -1026,8 +992,8 @@ namespace isc { namespace eval { const unsigned char EvalParser::yyrline_[] = { - 0, 66, 66, 69, 76, 81, 86, 91, 96, 108, - 115, 122, 127 + 0, 69, 69, 72, 79, 84, 89, 107, 112, 116, + 123, 128 }; // Print the state stack on the debug stream. @@ -1062,8 +1028,8 @@ namespace isc { namespace eval { #line 21 "parser.yy" // lalr1.cc:1167 } } // isc::eval -#line 1066 "parser.cc" // lalr1.cc:1167 -#line 134 "parser.yy" // lalr1.cc:1168 +#line 1032 "parser.cc" // lalr1.cc:1167 +#line 135 "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 e1049e1b36..dfceb2d386 100644 --- a/src/lib/eval/parser.h +++ b/src/lib/eval/parser.h @@ -45,11 +45,12 @@ #include #include #include +#include using namespace isc::dhcp; using namespace isc::eval; -#line 53 "parser.h" // lalr1.cc:392 +#line 54 "parser.h" // lalr1.cc:392 # include # include // std::abort @@ -126,7 +127,7 @@ using namespace isc::eval; #line 21 "parser.yy" // lalr1.cc:392 namespace isc { namespace eval { -#line 130 "parser.h" // lalr1.cc:392 +#line 131 "parser.h" // lalr1.cc:392 @@ -293,14 +294,11 @@ namespace isc { namespace eval { /// An auxiliary type to compute the largest semantic type. union union_type { - // "integer" - char dummy1[sizeof(int)]; - - // "a number in a constant string" - // "the all constant string" // "constant string" + // "integer" // "constant hexstring" - char dummy2[sizeof(std::string)]; + // TOKEN + char dummy1[sizeof(std::string)]; }; /// Symbol semantic values. @@ -327,16 +325,16 @@ namespace isc { namespace eval { TOKEN_EQUAL = 258, TOKEN_OPTION = 259, TOKEN_SUBSTRING = 260, - TOKEN_COMA = 261, - TOKEN_LPAREN = 262, - TOKEN_RPAREN = 263, - TOKEN_LBRACKET = 264, - TOKEN_RBRACKET = 265, - TOKEN_NUMBER = 266, - TOKEN_ALL = 267, - TOKEN_STRING = 268, + TOKEN_ALL = 261, + TOKEN_COMA = 262, + TOKEN_LPAREN = 263, + TOKEN_RPAREN = 264, + TOKEN_LBRACKET = 265, + TOKEN_RBRACKET = 266, + TOKEN_STRING = 267, + TOKEN_INTEGER = 268, TOKEN_HEXSTRING = 269, - TOKEN_INTEGER = 270 + TOKEN_TOKEN = 270 }; }; @@ -374,8 +372,6 @@ namespace isc { namespace eval { basic_symbol (typename Base::kind_type t, const location_type& l); - basic_symbol (typename Base::kind_type t, const int v, const location_type& l); - basic_symbol (typename Base::kind_type t, const std::string v, const location_type& l); @@ -461,6 +457,10 @@ namespace isc { namespace eval { symbol_type make_SUBSTRING (const location_type& l); + static inline + symbol_type + make_ALL (const location_type& l); + static inline symbol_type make_COMA (const location_type& l); @@ -483,15 +483,11 @@ namespace isc { namespace eval { static inline symbol_type - make_NUMBER (const std::string& v, const location_type& l); - - static inline - symbol_type - make_ALL (const std::string& v, const location_type& l); + make_STRING (const std::string& v, const location_type& l); static inline symbol_type - make_STRING (const std::string& v, const location_type& l); + make_INTEGER (const std::string& v, const location_type& l); static inline symbol_type @@ -499,7 +495,7 @@ namespace isc { namespace eval { static inline symbol_type - make_INTEGER (const int& v, const location_type& l); + make_TOKEN (const std::string& v, const location_type& l); /// Build a parser object. @@ -706,9 +702,9 @@ namespace isc { namespace eval { enum { yyeof_ = 0, - yylast_ = 20, ///< Last index in yytable_. + yylast_ = 19, ///< Last index in yytable_. yynnts_ = 6, ///< Number of nonterminal symbols. - yyfinal_ = 12, ///< Termination state number. + yyfinal_ = 11, ///< Termination state number. yyterror_ = 1, yyerrcode_ = 256, yyntokens_ = 16 ///< Number of tokens. @@ -790,14 +786,10 @@ namespace isc { namespace eval { { switch (other.type_get ()) { - case 15: // "integer" - value.copy< int > (other.value); - break; - - case 11: // "a number in a constant string" - case 12: // "the all constant string" - case 13: // "constant string" + case 12: // "constant string" + case 13: // "integer" case 14: // "constant hexstring" + case 15: // TOKEN value.copy< std::string > (other.value); break; @@ -818,14 +810,10 @@ namespace isc { namespace eval { (void) v; switch (this->type_get ()) { - case 15: // "integer" - value.copy< int > (v); - break; - - case 11: // "a number in a constant string" - case 12: // "the all constant string" - case 13: // "constant string" + case 12: // "constant string" + case 13: // "integer" case 14: // "constant hexstring" + case 15: // TOKEN value.copy< std::string > (v); break; @@ -844,13 +832,6 @@ namespace isc { namespace eval { , location (l) {} - template - EvalParser::basic_symbol::basic_symbol (typename Base::kind_type t, const int v, const location_type& l) - : Base (t) - , value (v) - , location (l) - {} - template EvalParser::basic_symbol::basic_symbol (typename Base::kind_type t, const std::string v, const location_type& l) : Base (t) @@ -884,14 +865,10 @@ namespace isc { namespace eval { // Type destructor. switch (yytype) { - case 15: // "integer" - value.template destroy< int > (); - break; - - case 11: // "a number in a constant string" - case 12: // "the all constant string" - case 13: // "constant string" + case 12: // "constant string" + case 13: // "integer" case 14: // "constant hexstring" + case 15: // TOKEN value.template destroy< std::string > (); break; @@ -918,14 +895,10 @@ namespace isc { namespace eval { super_type::move(s); switch (this->type_get ()) { - case 15: // "integer" - value.move< int > (s.value); - break; - - case 11: // "a number in a constant string" - case 12: // "the all constant string" - case 13: // "constant string" + case 12: // "constant string" + case 13: // "integer" case 14: // "constant hexstring" + case 15: // TOKEN value.move< std::string > (s.value); break; @@ -1014,6 +987,12 @@ namespace isc { namespace eval { return symbol_type (token::TOKEN_SUBSTRING, l); } + EvalParser::symbol_type + EvalParser::make_ALL (const location_type& l) + { + return symbol_type (token::TOKEN_ALL, l); + } + EvalParser::symbol_type EvalParser::make_COMA (const location_type& l) { @@ -1045,21 +1024,15 @@ namespace isc { namespace eval { } EvalParser::symbol_type - EvalParser::make_NUMBER (const std::string& v, const location_type& l) - { - return symbol_type (token::TOKEN_NUMBER, v, l); - } - - EvalParser::symbol_type - EvalParser::make_ALL (const std::string& v, const location_type& l) + EvalParser::make_STRING (const std::string& v, const location_type& l) { - return symbol_type (token::TOKEN_ALL, v, l); + return symbol_type (token::TOKEN_STRING, v, l); } EvalParser::symbol_type - EvalParser::make_STRING (const std::string& v, const location_type& l) + EvalParser::make_INTEGER (const std::string& v, const location_type& l) { - return symbol_type (token::TOKEN_STRING, v, l); + return symbol_type (token::TOKEN_INTEGER, v, l); } EvalParser::symbol_type @@ -1069,15 +1042,15 @@ namespace isc { namespace eval { } EvalParser::symbol_type - EvalParser::make_INTEGER (const int& v, const location_type& l) + EvalParser::make_TOKEN (const std::string& v, const location_type& l) { - return symbol_type (token::TOKEN_INTEGER, v, l); + return symbol_type (token::TOKEN_TOKEN, v, l); } #line 21 "parser.yy" // lalr1.cc:392 } } // isc::eval -#line 1081 "parser.h" // lalr1.cc:392 +#line 1054 "parser.h" // lalr1.cc:392 diff --git a/src/lib/eval/parser.yy b/src/lib/eval/parser.yy index c6e0386672..b4a3237c96 100644 --- a/src/lib/eval/parser.yy +++ b/src/lib/eval/parser.yy @@ -25,6 +25,7 @@ #include #include #include +#include using namespace isc::dhcp; using namespace isc::eval; @@ -44,17 +45,19 @@ using namespace isc::eval; EQUAL "==" OPTION "option" SUBSTRING "substring" + ALL "all" COMA "," LPAREN "(" RPAREN ")" LBRACKET "[" RBRACKET "]" ; -%token NUMBER "a number in a constant string" -%token ALL "the all constant string" + %token STRING "constant string" +%token INTEGER "integer" %token HEXSTRING "constant hexstring" -%token INTEGER "integer" +%token TOKEN + %printer { yyoutput << $$; } <*>; %% @@ -78,16 +81,6 @@ string_expr : STRING TokenPtr str(new TokenString($1)); ctx.expression.push_back(str); } - | NUMBER - { - TokenPtr str(new TokenString($1)); - ctx.expression.push_back(str); - } - | ALL - { - TokenPtr str(new TokenString("all")); - ctx.expression.push_back(str); - } | HEXSTRING { TokenPtr hex(new TokenHexString($1)); @@ -95,12 +88,18 @@ string_expr : STRING } | OPTION "[" INTEGER "]" { - int n = $3; + int n; + try { + n = boost::lexical_cast($3); + } catch (const boost::bad_lexical_cast &) { + // This can't happen... + ctx.error(@3, + "Option code has invalid value in " + $3); + } if (n < 0 || n > 65535) { - std::ostringstream oss; - oss << "Option code has invalid value in " << n - << ". Allowed range: 0..65535"; - ctx.error(@3, oss.str()); + ctx.error(@3, + "Option code has invalid value in " + + $3 + ". Allowed range: 0..65535"); } TokenPtr opt(new TokenOption(static_cast(n))); ctx.expression.push_back(opt); @@ -110,16 +109,18 @@ string_expr : STRING TokenPtr sub(new TokenSubstring()); ctx.expression.push_back(sub); } + | TOKEN + // Temporary unused token to avoid explict but long errors ; -start_expr : NUMBER +start_expr : INTEGER { TokenPtr str(new TokenString($1)); ctx.expression.push_back(str); } ; -length_expr : NUMBER +length_expr : INTEGER { TokenPtr str(new TokenString($1)); ctx.expression.push_back(str); diff --git a/src/lib/eval/tests/context_unittest.cc b/src/lib/eval/tests/context_unittest.cc index cd2c9a6629..ddeb032621 100644 --- a/src/lib/eval/tests/context_unittest.cc +++ b/src/lib/eval/tests/context_unittest.cc @@ -137,14 +137,13 @@ TEST_F(EvalContextTest, string) { checkTokenString(tmp2, "bar"); } -// Test the parsing of a basic expression with a constant string holding -// a number. -TEST_F(EvalContextTest, number) { +// Test the parsing of a basic expression using integers +TEST_F(EvalContextTest, integer) { EvalContext eval; EXPECT_NO_THROW(parsed_ = - eval.parseString("substring(option[123], '0', '2') == '42'")); + eval.parseString("substring(option[123], 0, 2) == '42'")); EXPECT_TRUE(parsed_); } @@ -210,7 +209,7 @@ TEST_F(EvalContextTest, substring) { EvalContext eval; EXPECT_NO_THROW(parsed_ = - eval.parseString("substring('foobar','2','3') == 'oba'")); + eval.parseString("substring('foobar',2,all) == 'obar'")); EXPECT_TRUE(parsed_); ASSERT_EQ(6, eval.expression.size()); @@ -222,7 +221,7 @@ TEST_F(EvalContextTest, substring) { checkTokenString(tmp1, "foobar"); checkTokenString(tmp2, "2"); - checkTokenString(tmp3, "3"); + checkTokenString(tmp3, "all"); checkTokenSubstring(tmp4); } @@ -256,9 +255,9 @@ TEST_F(EvalContextTest, scanParseErrors) { ":1.8-27: Failed to convert 12345678901234567890 " "to an integer."); checkError("option[123] < 'foo'", ":1.13: Invalid character: <"); - checkError("substring('foo','12345678901234567890','1')", - ":1.17-38: syntax error, unexpected constant string, " - "expecting a number in a constant string"); + checkError("substring('foo',12345678901234567890,1)", + ":1.17-36: Failed to convert 12345678901234567890 " + "to an integer."); } // Tests some parser error cases @@ -286,11 +285,13 @@ TEST_F(EvalContextTest, parseErrors) { checkError("substring('foobar') == 'f'", ":1.19: syntax error, " "unexpected ), expecting \",\""); - checkError("substring('foobar','3') == 'bar'", - ":1.23: syntax error, unexpected ), expecting \",\""); - checkError("substring('foobar',3,3) == 'bar'", - ":1.20: syntax error, unexpected integer, " - "expecting a number in a constant string"); + checkError("substring('foobar',3) == 'bar'", + ":1.21: syntax error, unexpected ), expecting \",\""); + checkError("substring('foobar','3',3) == 'bar'", + ":1.20-22: syntax error, unexpected constant string, " + "expecting integer"); + checkError("substring('foobar',1,a) == 'foo'", + ":1.22: Invalid character: a"); } // Tests some type error cases (caught only by the strongly typed parser) @@ -298,16 +299,12 @@ TEST_F(EvalContextTest, typeErrors) { checkError("'foobar'", ":1.9: syntax error, unexpected end of file, " "expecting =="); - checkError("substring('foobar','a','1') == 'foo'", - ":1.20-22: syntax error, unexpected constant string, " - "expecting a number in a constant string"); - checkError("substring('foobar','1','a') == 'foo'", - ":1.24-26: syntax error, unexpected constant string, " - "expecting a number in a constant string or the all constant " - "string"); - checkError("substring('foobar',0x32,'1') == 'foo'", + checkError("substring('foobar',all,1) == 'foo'", + ":1.20-22: syntax error, unexpected all, " + "expecting integer"); + checkError("substring('foobar',0x32,1) == 'foo'", ":1.20-23: syntax error, unexpected constant " - "hexstring, expecting a number in a constant string"); + "hexstring, expecting integer"); } };