From: Francis Dupont Date: Fri, 6 Nov 2015 12:38:09 +0000 (+0100) Subject: [4088fd] Split the syntax into untyped/typed X-Git-Tag: trac4088fd_typed X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2760bbdf573ce824133352251e42392076686ec7;p=thirdparty%2Fkea.git [4088fd] Split the syntax into untyped/typed --- diff --git a/src/lib/eval/lexer.cc b/src/lib/eval/lexer.cc index fdc3e69cdd..92573d9260 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 15 -#define YY_END_OF_BUFFER 16 +#define YY_NUM_RULES 18 +#define YY_END_OF_BUFFER 19 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -478,12 +478,14 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[40] = +static yyconst flex_int16_t yy_accept[55] = { 0, - 0, 0, 16, 14, 1, 2, 14, 9, 10, 13, - 5, 5, 14, 11, 12, 14, 14, 1, 2, 0, - 3, 5, 0, 6, 0, 0, 4, 0, 0, 0, - 0, 0, 0, 7, 0, 0, 0, 8, 0 + 0, 0, 19, 17, 1, 2, 17, 12, 13, 16, + 7, 7, 17, 14, 15, 17, 17, 17, 1, 2, + 0, 5, 0, 0, 0, 7, 0, 8, 0, 0, + 0, 3, 0, 6, 0, 0, 0, 0, 0, 0, + 0, 4, 0, 0, 0, 9, 0, 0, 0, 0, + 0, 11, 10, 0 } ; static yyconst flex_int32_t yy_ec[256] = @@ -492,16 +494,16 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 4, 5, - 6, 1, 1, 7, 1, 1, 1, 8, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, - 10, 1, 1, 1, 11, 11, 11, 11, 11, 11, + 6, 1, 1, 7, 8, 1, 1, 9, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 11, 1, 1, + 12, 1, 1, 1, 13, 13, 13, 13, 13, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 12, 1, 1, - 13, 1, 14, 1, 1, 1, 11, 15, 11, 11, + 1, 1, 1, 1, 1, 1, 1, 14, 1, 1, + 15, 1, 16, 1, 1, 1, 17, 18, 13, 19, - 11, 11, 16, 1, 17, 1, 1, 1, 1, 18, - 19, 20, 1, 21, 22, 23, 24, 1, 1, 12, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 20, 13, 21, 1, 22, 1, 1, 23, 1, 24, + 25, 26, 1, 27, 28, 29, 30, 1, 1, 14, + 31, 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, 1, 1, 1, 1, 1, 1, @@ -518,59 +520,72 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 1, 1, 1 } ; -static yyconst flex_int32_t yy_meta[25] = +static yyconst flex_int32_t yy_meta[32] = { 0, - 1, 1, 2, 1, 1, 1, 1, 3, 3, 1, - 3, 1, 1, 1, 3, 1, 1, 1, 1, 1, - 1, 1, 1, 1 + 1, 1, 2, 1, 1, 1, 1, 1, 3, 3, + 1, 1, 3, 1, 1, 1, 3, 3, 3, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1 } ; -static yyconst flex_int16_t yy_base[42] = +static yyconst flex_int16_t yy_base[57] = { 0, - 0, 0, 55, 56, 52, 50, 48, 56, 56, 56, - 17, 19, 41, 56, 56, 30, 25, 46, 44, 42, - 56, 22, 0, 56, 22, 29, 0, 26, 20, 22, - 17, 21, 17, 56, 20, 18, 19, 56, 56, 31, - 30 + 0, 0, 84, 85, 81, 79, 28, 85, 85, 85, + 25, 31, 69, 85, 85, 54, 49, 54, 75, 73, + 71, 85, 38, 40, 29, 44, 0, 85, 45, 55, + 43, 85, 39, 0, 49, 42, 38, 64, 42, 37, + 38, 85, 37, 33, 39, 85, 36, 38, 32, 44, + 30, 85, 85, 85, 62, 43 } ; -static yyconst flex_int16_t yy_def[42] = +static yyconst flex_int16_t yy_def[57] = { 0, - 39, 1, 39, 39, 39, 39, 40, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 40, - 39, 39, 41, 39, 39, 39, 41, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 0, 39, - 39 + 54, 1, 54, 54, 54, 54, 55, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 55, 54, 55, 55, 55, 54, 56, 54, 54, 54, + 54, 54, 55, 56, 54, 54, 54, 55, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 0, 54, 54 } ; -static yyconst flex_int16_t yy_nxt[81] = +static yyconst flex_int16_t yy_nxt[117] = { 0, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 4, 4, 14, 15, 4, 4, 4, 4, 16, 4, - 4, 17, 4, 4, 22, 22, 22, 22, 23, 22, - 22, 20, 27, 20, 38, 37, 36, 35, 34, 33, - 32, 31, 30, 29, 28, 21, 19, 18, 26, 25, - 24, 21, 19, 18, 39, 3, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39 + 4, 5, 6, 7, 8, 9, 10, 4, 11, 12, + 4, 13, 4, 4, 14, 15, 4, 4, 4, 4, + 4, 4, 4, 4, 16, 4, 4, 17, 4, 18, + 4, 22, 22, 26, 26, 23, 24, 24, 27, 26, + 26, 22, 22, 32, 25, 34, 24, 24, 24, 24, + 53, 33, 26, 26, 52, 51, 50, 49, 48, 47, + 46, 38, 21, 45, 21, 44, 43, 42, 41, 40, + 39, 37, 36, 35, 22, 20, 19, 31, 30, 29, + 28, 20, 19, 54, 3, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54 } ; -static yyconst flex_int16_t yy_chk[81] = +static yyconst flex_int16_t yy_chk[117] = { 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, 11, 11, 12, 12, 11, 22, - 22, 40, 41, 40, 37, 36, 35, 33, 32, 31, - 30, 29, 28, 26, 25, 20, 19, 18, 17, 16, - 13, 7, 6, 5, 3, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 7, 25, 11, 11, 7, 7, 7, 11, 12, + 12, 23, 33, 24, 7, 56, 23, 23, 24, 24, + 51, 25, 26, 26, 50, 49, 48, 47, 45, 44, + 43, 33, 55, 41, 55, 40, 39, 38, 37, 36, + 35, 31, 30, 29, 21, 20, 19, 18, 17, 16, + 13, 6, 5, 3, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54 } ; /* Table of booleans, true if rule could match eol. */ -static yyconst flex_int32_t yy_rule_can_match_eol[16] = +static yyconst flex_int32_t yy_rule_can_match_eol[19] = { 0, -0, 1, 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, 0, 0, }; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; @@ -578,10 +593,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[15] = +static yyconst flex_int16_t yy_rule_linenum[18] = { 0, - 83, 87, 93, 103, 109, 132, 133, 134, 135, 136, - 137, 138, 139, 141 + 83, 87, 93, 101, 107, 117, 123, 146, 147, 148, + 149, 150, 151, 152, 153, 154, 156 } ; /* The intent behind this definition is that it'll catch @@ -648,7 +663,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 652 "lexer.cc" +#line 667 "lexer.cc" #define INITIAL 0 @@ -931,7 +946,7 @@ YY_DECL loc.step(); -#line 935 "lexer.cc" +#line 950 "lexer.cc" while ( 1 ) /* loops until end-of-file is reached */ { @@ -960,13 +975,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 >= 40 ) + if ( yy_current_state >= 55 ) 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 != 39 ); + while ( yy_current_state != 54 ); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); @@ -995,13 +1010,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 < 15 ) + else if ( yy_act < 18 ) fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n", (long)yy_rule_linenum[yy_act], yytext ); - else if ( yy_act == 15 ) + else if ( yy_act == 18 ) fprintf( stderr, "--accepting default rule (\"%s\")\n", yytext ); - else if ( yy_act == 16 ) + else if ( yy_act == 19 ) fprintf( stderr, "--(end of buffer or a NUL)\n" ); else fprintf( stderr, "--EOF (start condition %d)\n", YY_START ); @@ -1038,6 +1053,26 @@ 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); + + return isc::eval::EvalParser::make_NUMBER(tmp, loc); +} + YY_BREAK +case 4: +YY_RULE_SETUP +#line 101 "lexer.ll" +{ + // A string containing the "all" keyword. + + return isc::eval::EvalParser::make_ALL("all", loc); +} + YY_BREAK +case 5: +YY_RULE_SETUP +#line 107 "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. @@ -1048,18 +1083,18 @@ YY_RULE_SETUP return isc::eval::EvalParser::make_STRING(tmp, loc); } YY_BREAK -case 4: +case 6: YY_RULE_SETUP -#line 103 "lexer.ll" +#line 117 "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 5: +case 7: YY_RULE_SETUP -#line 109 "lexer.ll" +#line 123 "lexer.ll" { // A code (16 bit unsigned integer) was found. std::string tmp(yytext); @@ -1083,61 +1118,66 @@ YY_RULE_SETUP return isc::eval::EvalParser::make_CODE(static_cast(n), loc); } YY_BREAK -case 6: +case 8: YY_RULE_SETUP -#line 132 "lexer.ll" +#line 146 "lexer.ll" return isc::eval::EvalParser::make_EQUAL(loc); YY_BREAK -case 7: +case 9: YY_RULE_SETUP -#line 133 "lexer.ll" +#line 147 "lexer.ll" return isc::eval::EvalParser::make_OPTION(loc); YY_BREAK -case 8: +case 10: YY_RULE_SETUP -#line 134 "lexer.ll" +#line 148 "lexer.ll" return isc::eval::EvalParser::make_SUBSTRING(loc); YY_BREAK -case 9: +case 11: +YY_RULE_SETUP +#line 149 "lexer.ll" +return isc::eval::EvalParser::make_UNTYPED(loc); + YY_BREAK +case 12: YY_RULE_SETUP -#line 135 "lexer.ll" +#line 150 "lexer.ll" return isc::eval::EvalParser::make_LPAREN(loc); YY_BREAK -case 10: +case 13: YY_RULE_SETUP -#line 136 "lexer.ll" +#line 151 "lexer.ll" return isc::eval::EvalParser::make_RPAREN(loc); YY_BREAK -case 11: +case 14: YY_RULE_SETUP -#line 137 "lexer.ll" +#line 152 "lexer.ll" return isc::eval::EvalParser::make_LBRACKET(loc); YY_BREAK -case 12: +case 15: YY_RULE_SETUP -#line 138 "lexer.ll" +#line 153 "lexer.ll" return isc::eval::EvalParser::make_RBRACKET(loc); YY_BREAK -case 13: +case 16: YY_RULE_SETUP -#line 139 "lexer.ll" +#line 154 "lexer.ll" return isc::eval::EvalParser::make_COMA(loc); YY_BREAK -case 14: +case 17: YY_RULE_SETUP -#line 141 "lexer.ll" +#line 156 "lexer.ll" driver.error (loc, "Invalid character: " + std::string(yytext)); YY_BREAK case YY_STATE_EOF(INITIAL): -#line 142 "lexer.ll" +#line 157 "lexer.ll" return isc::eval::EvalParser::make_END(loc); YY_BREAK -case 15: +case 18: YY_RULE_SETUP -#line 143 "lexer.ll" +#line 158 "lexer.ll" ECHO; YY_BREAK -#line 1141 "lexer.cc" +#line 1181 "lexer.cc" case YY_END_OF_BUFFER: { @@ -1450,7 +1490,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 >= 40 ) + if ( yy_current_state >= 55 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1483,11 +1523,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 >= 40 ) + if ( yy_current_state >= 55 ) 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 == 39); + yy_is_jam = (yy_current_state == 54); return yy_is_jam ? 0 : yy_current_state; } @@ -2225,7 +2265,7 @@ void yyfree (void * ptr ) /* %ok-for-header */ -#line 143 "lexer.ll" +#line 158 "lexer.ll" diff --git a/src/lib/eval/lexer.ll b/src/lib/eval/lexer.ll index 7903b3bbf5..6a581adf29 100644 --- a/src/lib/eval/lexer.ll +++ b/src/lib/eval/lexer.ll @@ -90,6 +90,20 @@ 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); + + 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. @@ -132,6 +146,7 @@ blank [ \t] "==" return isc::eval::EvalParser::make_EQUAL(loc); "option" return isc::eval::EvalParser::make_OPTION(loc); "substring" return isc::eval::EvalParser::make_SUBSTRING(loc); +"untyped:" return isc::eval::EvalParser::make_UNTYPED(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 c971e90812..cac8768118 100644 --- a/src/lib/eval/parser.cc +++ b/src/lib/eval/parser.cc @@ -251,12 +251,14 @@ namespace isc { namespace eval { { switch (that.type_get ()) { - case 11: // "constant string" - case 12: // "constant hexstring" + case 12: // "a number in a constant string" + case 13: // "the all constant string" + case 14: // "constant string" + case 15: // "constant hexstring" value.move< std::string > (that.value); break; - case 13: // "option code" + case 16: // "option code" value.move< uint16_t > (that.value); break; @@ -275,12 +277,14 @@ namespace isc { namespace eval { state = that.state; switch (that.type_get ()) { - case 11: // "constant string" - case 12: // "constant hexstring" + case 12: // "a number in a constant string" + case 13: // "the all constant string" + case 14: // "constant string" + case 15: // "constant hexstring" value.copy< std::string > (that.value); break; - case 13: // "option code" + case 16: // "option code" value.copy< uint16_t > (that.value); break; @@ -320,25 +324,39 @@ namespace isc { namespace eval { << yysym.location << ": "; switch (yytype) { - case 11: // "constant string" + case 12: // "a number in a constant string" -#line 56 "parser.yy" // lalr1.cc:636 +#line 59 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } -#line 328 "parser.cc" // lalr1.cc:636 +#line 332 "parser.cc" // lalr1.cc:636 break; - case 12: // "constant hexstring" + case 13: // "the all constant string" -#line 56 "parser.yy" // lalr1.cc:636 +#line 59 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } -#line 335 "parser.cc" // lalr1.cc:636 +#line 339 "parser.cc" // lalr1.cc:636 break; - case 13: // "option code" + case 14: // "constant string" -#line 56 "parser.yy" // lalr1.cc:636 +#line 59 "parser.yy" // lalr1.cc:636 + { yyoutput << yysym.value.template as< std::string > (); } +#line 346 "parser.cc" // lalr1.cc:636 + break; + + case 15: // "constant hexstring" + +#line 59 "parser.yy" // lalr1.cc:636 + { yyoutput << yysym.value.template as< std::string > (); } +#line 353 "parser.cc" // lalr1.cc:636 + break; + + case 16: // "option code" + +#line 59 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< uint16_t > (); } -#line 342 "parser.cc" // lalr1.cc:636 +#line 360 "parser.cc" // lalr1.cc:636 break; @@ -538,12 +556,14 @@ namespace isc { namespace eval { when using variants. */ switch (yyr1_[yyn]) { - case 11: // "constant string" - case 12: // "constant hexstring" + case 12: // "a number in a constant string" + case 13: // "the all constant string" + case 14: // "constant string" + case 15: // "constant hexstring" yylhs.value.build< std::string > (); break; - case 13: // "option code" + case 16: // "option code" yylhs.value.build< uint16_t > (); break; @@ -564,53 +584,161 @@ namespace isc { namespace eval { { switch (yyn) { - case 2: -#line 65 "parser.yy" // lalr1.cc:859 + case 4: +#line 73 "parser.yy" // lalr1.cc:859 { TokenPtr eq(new TokenEqual()); ctx.expression.push_back(eq); } -#line 574 "parser.cc" // lalr1.cc:859 +#line 594 "parser.cc" // lalr1.cc:859 break; - case 4: -#line 73 "parser.yy" // lalr1.cc:859 + case 6: +#line 81 "parser.yy" // lalr1.cc:859 { TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); ctx.expression.push_back(str); } -#line 583 "parser.cc" // lalr1.cc:859 +#line 603 "parser.cc" // lalr1.cc:859 break; - case 5: -#line 77 "parser.yy" // lalr1.cc:859 + case 7: +#line 85 "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 8: +#line 89 "parser.yy" // lalr1.cc:859 + { + TokenPtr str(new TokenString("all")); + ctx.expression.push_back(str); + } +#line 621 "parser.cc" // lalr1.cc:859 + break; + + case 9: +#line 93 "parser.yy" // lalr1.cc:859 { TokenPtr hex(new TokenHexString(yystack_[0].value.as< std::string > ())); ctx.expression.push_back(hex); } -#line 592 "parser.cc" // lalr1.cc:859 +#line 630 "parser.cc" // lalr1.cc:859 break; - case 6: -#line 81 "parser.yy" // lalr1.cc:859 + case 10: +#line 97 "parser.yy" // lalr1.cc:859 { TokenPtr opt(new TokenOption(yystack_[1].value.as< uint16_t > ())); ctx.expression.push_back(opt); } -#line 601 "parser.cc" // lalr1.cc:859 +#line 639 "parser.cc" // lalr1.cc:859 break; - case 7: -#line 85 "parser.yy" // lalr1.cc:859 + case 11: +#line 101 "parser.yy" // lalr1.cc:859 { TokenPtr sub(new TokenSubstring()); ctx.expression.push_back(sub); } -#line 610 "parser.cc" // lalr1.cc:859 +#line 648 "parser.cc" // lalr1.cc:859 + break; + + case 12: +#line 108 "parser.yy" // lalr1.cc:859 + { + TokenPtr eq(new TokenEqual()); + ctx.expression.push_back(eq); + } +#line 657 "parser.cc" // lalr1.cc:859 + break; + + case 13: +#line 115 "parser.yy" // lalr1.cc:859 + { + TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); + ctx.expression.push_back(str); + } +#line 666 "parser.cc" // lalr1.cc:859 + break; + + case 14: +#line 119 "parser.yy" // lalr1.cc:859 + { + TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); + ctx.expression.push_back(str); + } +#line 675 "parser.cc" // lalr1.cc:859 + break; + + case 15: +#line 123 "parser.yy" // lalr1.cc:859 + { + TokenPtr str(new TokenString("all")); + ctx.expression.push_back(str); + } +#line 684 "parser.cc" // lalr1.cc:859 + break; + + case 16: +#line 127 "parser.yy" // lalr1.cc:859 + { + TokenPtr hex(new TokenHexString(yystack_[0].value.as< std::string > ())); + ctx.expression.push_back(hex); + } +#line 693 "parser.cc" // lalr1.cc:859 + break; + + case 17: +#line 131 "parser.yy" // lalr1.cc:859 + { + TokenPtr opt(new TokenOption(yystack_[1].value.as< uint16_t > ())); + ctx.expression.push_back(opt); + } +#line 702 "parser.cc" // lalr1.cc:859 + break; + + case 18: +#line 135 "parser.yy" // lalr1.cc:859 + { + TokenPtr sub(new TokenSubstring()); + ctx.expression.push_back(sub); + } +#line 711 "parser.cc" // lalr1.cc:859 + break; + + case 19: +#line 142 "parser.yy" // lalr1.cc:859 + { + TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); + ctx.expression.push_back(str); + } +#line 720 "parser.cc" // lalr1.cc:859 + break; + + case 20: +#line 149 "parser.yy" // lalr1.cc:859 + { + TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); + ctx.expression.push_back(str); + } +#line 729 "parser.cc" // lalr1.cc:859 + break; + + case 21: +#line 153 "parser.yy" // lalr1.cc:859 + { + TokenPtr str(new TokenString("all")); + ctx.expression.push_back(str); + } +#line 738 "parser.cc" // lalr1.cc:859 break; -#line 614 "parser.cc" // lalr1.cc:859 +#line 742 "parser.cc" // lalr1.cc:859 default: break; } @@ -865,67 +993,86 @@ namespace isc { namespace eval { } - const signed char EvalParser::yypact_ninf_ = -9; + const signed char EvalParser::yypact_ninf_ = -27; const signed char EvalParser::yytable_ninf_ = -1; const signed char EvalParser::yypact_[] = { - -1, -4, -6, -9, -9, 6, 5, 0, -1, -9, - -1, 2, 8, -9, -9, -1, 9, -1, 10, -9 + 0, -3, 1, 14, -27, -27, -27, -27, 8, -27, + 13, 5, 18, 15, 16, -27, -27, -27, -27, -27, + 31, -27, 18, 24, 29, 21, 14, 14, -27, -27, + 26, 28, 33, -27, -27, 34, -27, 14, -10, 35, + -27, -27, 36, 14, -27, 37, -27 }; const unsigned char EvalParser::yydefact_[] = { - 0, 0, 0, 4, 5, 0, 3, 0, 0, 1, - 0, 0, 0, 2, 6, 0, 0, 0, 0, 7 + 0, 0, 0, 0, 14, 15, 13, 16, 0, 3, + 0, 0, 0, 0, 0, 7, 8, 6, 9, 2, + 5, 1, 0, 0, 0, 0, 0, 0, 12, 17, + 0, 0, 0, 4, 19, 0, 10, 0, 0, 0, + 20, 21, 0, 0, 18, 0, 11 }; const signed char EvalParser::yypgoto_[] = { - -9, -9, -8 + -27, -27, -27, -26, -27, -2, -27, -27 }; const signed char EvalParser::yydefgoto_[] = { - -1, 5, 6 + -1, 8, 19, 20, 9, 10, 35, 42 }; const unsigned char EvalParser::yytable_[] = { - 12, 8, 13, 1, 2, 7, 9, 16, 10, 18, - 3, 4, 14, 11, 15, 17, 0, 0, 19 + 32, 33, 40, 41, 1, 2, 3, 11, 21, 12, + 24, 39, 4, 5, 6, 7, 22, 45, 13, 14, + 28, 23, 1, 2, 26, 25, 15, 16, 17, 18, + 4, 5, 6, 7, 27, 29, 30, 31, 34, 36, + 37, 38, 43, 0, 0, 44, 46 }; const signed char EvalParser::yycheck_[] = { - 8, 7, 10, 4, 5, 9, 0, 15, 3, 17, - 11, 12, 10, 13, 6, 6, -1, -1, 8 + 26, 27, 12, 13, 4, 5, 6, 10, 0, 8, + 12, 37, 12, 13, 14, 15, 3, 43, 4, 5, + 22, 16, 4, 5, 8, 10, 12, 13, 14, 15, + 12, 13, 14, 15, 3, 11, 7, 16, 12, 11, + 7, 7, 7, -1, -1, 9, 9 }; const unsigned char EvalParser::yystos_[] = { - 0, 4, 5, 11, 12, 15, 16, 9, 7, 0, - 3, 13, 16, 16, 10, 6, 16, 6, 16, 8 + 0, 4, 5, 6, 12, 13, 14, 15, 18, 21, + 22, 10, 8, 4, 5, 12, 13, 14, 15, 19, + 20, 0, 3, 16, 22, 10, 8, 3, 22, 11, + 7, 16, 20, 20, 12, 23, 11, 7, 7, 20, + 12, 13, 24, 7, 9, 20, 9 }; const unsigned char EvalParser::yyr1_[] = { - 0, 14, 15, 15, 16, 16, 16, 16 + 0, 17, 18, 18, 19, 19, 20, 20, 20, 20, + 20, 20, 21, 22, 22, 22, 22, 22, 22, 23, + 24, 24 }; const unsigned char EvalParser::yyr2_[] = { - 0, 2, 3, 1, 1, 1, 4, 8 + 0, 2, 2, 1, 3, 1, 1, 1, 1, 1, + 4, 8, 3, 1, 1, 1, 1, 4, 8, 1, + 1, 1 }; @@ -936,16 +1083,21 @@ namespace isc { namespace eval { const EvalParser::yytname_[] = { "\"end of file\"", "error", "$undefined", "\"==\"", "\"option\"", - "\"substring\"", "\",\"", "\"(\"", "\")\"", "\"[\"", "\"]\"", - "\"constant string\"", "\"constant hexstring\"", "\"option code\"", - "$accept", "expression", "token", YY_NULLPTR + "\"substring\"", "\"untyped:\"", "\",\"", "\"(\"", "\")\"", "\"[\"", + "\"]\"", "\"a number in a constant string\"", + "\"the all constant string\"", "\"constant string\"", + "\"constant hexstring\"", "\"option code\"", "$accept", "expression", + "untyped_expr", "token", "bool_expr", "string_expr", "start_expr", + "length_expr", YY_NULLPTR }; #if YYDEBUG const unsigned char EvalParser::yyrline_[] = { - 0, 65, 65, 69, 73, 77, 81, 85 + 0, 68, 68, 69, 73, 77, 81, 85, 89, 93, + 97, 101, 108, 115, 119, 123, 127, 131, 135, 142, + 149, 153 }; // Print the state stack on the debug stream. @@ -980,8 +1132,8 @@ namespace isc { namespace eval { #line 21 "parser.yy" // lalr1.cc:1167 } } // isc::eval -#line 984 "parser.cc" // lalr1.cc:1167 -#line 91 "parser.yy" // lalr1.cc:1168 +#line 1136 "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 01ec9e26bf..ec2b500803 100644 --- a/src/lib/eval/parser.h +++ b/src/lib/eval/parser.h @@ -293,6 +293,8 @@ namespace isc { namespace eval { /// An auxiliary type to compute the largest semantic type. union union_type { + // "a number in a constant string" + // "the all constant string" // "constant string" // "constant hexstring" char dummy1[sizeof(std::string)]; @@ -325,14 +327,17 @@ 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_STRING = 266, - TOKEN_HEXSTRING = 267, - TOKEN_CODE = 268 + TOKEN_UNTYPED = 261, + TOKEN_COMA = 262, + TOKEN_LPAREN = 263, + TOKEN_RPAREN = 264, + TOKEN_LBRACKET = 265, + TOKEN_RBRACKET = 266, + TOKEN_NUMBER = 267, + TOKEN_ALL = 268, + TOKEN_STRING = 269, + TOKEN_HEXSTRING = 270, + TOKEN_CODE = 271 }; }; @@ -457,6 +462,10 @@ namespace isc { namespace eval { symbol_type make_SUBSTRING (const location_type& l); + static inline + symbol_type + make_UNTYPED (const location_type& l); + static inline symbol_type make_COMA (const location_type& l); @@ -477,6 +486,14 @@ namespace isc { namespace eval { symbol_type make_RBRACKET (const location_type& l); + 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); + static inline symbol_type make_STRING (const std::string& v, const location_type& l); @@ -694,12 +711,12 @@ namespace isc { namespace eval { enum { yyeof_ = 0, - yylast_ = 18, ///< Last index in yytable_. - yynnts_ = 3, ///< Number of nonterminal symbols. - yyfinal_ = 9, ///< Termination state number. + yylast_ = 46, ///< Last index in yytable_. + yynnts_ = 8, ///< Number of nonterminal symbols. + yyfinal_ = 21, ///< Termination state number. yyterror_ = 1, yyerrcode_ = 256, - yyntokens_ = 14 ///< Number of tokens. + yyntokens_ = 17 ///< Number of tokens. }; @@ -742,9 +759,10 @@ namespace isc { namespace eval { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 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 + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16 }; - const unsigned int user_token_number_max_ = 268; + const unsigned int user_token_number_max_ = 271; const token_number_type undef_token_ = 2; if (static_cast(t) <= yyeof_) @@ -777,12 +795,14 @@ namespace isc { namespace eval { { switch (other.type_get ()) { - case 11: // "constant string" - case 12: // "constant hexstring" + case 12: // "a number in a constant string" + case 13: // "the all constant string" + case 14: // "constant string" + case 15: // "constant hexstring" value.copy< std::string > (other.value); break; - case 13: // "option code" + case 16: // "option code" value.copy< uint16_t > (other.value); break; @@ -803,12 +823,14 @@ namespace isc { namespace eval { (void) v; switch (this->type_get ()) { - case 11: // "constant string" - case 12: // "constant hexstring" + case 12: // "a number in a constant string" + case 13: // "the all constant string" + case 14: // "constant string" + case 15: // "constant hexstring" value.copy< std::string > (v); break; - case 13: // "option code" + case 16: // "option code" value.copy< uint16_t > (v); break; @@ -867,12 +889,14 @@ namespace isc { namespace eval { // Type destructor. switch (yytype) { - case 11: // "constant string" - case 12: // "constant hexstring" + case 12: // "a number in a constant string" + case 13: // "the all constant string" + case 14: // "constant string" + case 15: // "constant hexstring" value.template destroy< std::string > (); break; - case 13: // "option code" + case 16: // "option code" value.template destroy< uint16_t > (); break; @@ -899,12 +923,14 @@ namespace isc { namespace eval { super_type::move(s); switch (this->type_get ()) { - case 11: // "constant string" - case 12: // "constant hexstring" + case 12: // "a number in a constant string" + case 13: // "the all constant string" + case 14: // "constant string" + case 15: // "constant hexstring" value.move< std::string > (s.value); break; - case 13: // "option code" + case 16: // "option code" value.move< uint16_t > (s.value); break; @@ -964,7 +990,7 @@ namespace isc { namespace eval { yytoken_number_[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268 + 265, 266, 267, 268, 269, 270, 271 }; return static_cast (yytoken_number_[type]); } @@ -993,6 +1019,12 @@ namespace isc { namespace eval { return symbol_type (token::TOKEN_SUBSTRING, l); } + EvalParser::symbol_type + EvalParser::make_UNTYPED (const location_type& l) + { + return symbol_type (token::TOKEN_UNTYPED, l); + } + EvalParser::symbol_type EvalParser::make_COMA (const location_type& l) { @@ -1023,6 +1055,18 @@ namespace isc { namespace eval { return symbol_type (token::TOKEN_RBRACKET, l); } + 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) + { + return symbol_type (token::TOKEN_ALL, v, l); + } + EvalParser::symbol_type EvalParser::make_STRING (const std::string& v, const location_type& l) { @@ -1044,7 +1088,7 @@ namespace isc { namespace eval { #line 21 "parser.yy" // lalr1.cc:392 } } // isc::eval -#line 1048 "parser.h" // lalr1.cc:392 +#line 1092 "parser.h" // lalr1.cc:392 diff --git a/src/lib/eval/parser.yy b/src/lib/eval/parser.yy index 1a388c4930..ecc1d48433 100644 --- a/src/lib/eval/parser.yy +++ b/src/lib/eval/parser.yy @@ -44,12 +44,15 @@ using namespace isc::eval; EQUAL "==" OPTION "option" SUBSTRING "substring" + UNTYPED "untyped:" COMA "," LPAREN "(" RPAREN ")" LBRACKET "[" RBRACKET "]" ; +%token NUMBER "a number in a constant string" +%token ALL "the all constant string" %token STRING "constant string" %token HEXSTRING "constant hexstring" %token CODE "option code" @@ -62,6 +65,11 @@ using namespace isc::eval; // Expression can either be a single token or a (something == something) expression expression: +UNTYPED untyped_expr +| bool_expr +; + +untyped_expr: token EQUAL token { TokenPtr eq(new TokenEqual()); ctx.expression.push_back(eq); @@ -74,6 +82,14 @@ 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)); ctx.expression.push_back(hex); @@ -88,6 +104,58 @@ STRING { } ; +bool_expr: +string_expr EQUAL string_expr { + TokenPtr eq(new TokenEqual()); + ctx.expression.push_back(eq); + } +; + +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)); + ctx.expression.push_back(hex); + } +| OPTION "[" CODE "]" { + TokenPtr opt(new TokenOption($3)); + ctx.expression.push_back(opt); + } +| SUBSTRING "(" string_expr "," start_expr "," length_expr ")" { + TokenPtr sub(new TokenSubstring()); + ctx.expression.push_back(sub); + } +; + +start_expr: +NUMBER { + TokenPtr str(new TokenString($1)); + ctx.expression.push_back(str); + } +; + +length_expr: +NUMBER { + TokenPtr str(new TokenString($1)); + ctx.expression.push_back(str); + } +| ALL { + TokenPtr str(new TokenString("all")); + ctx.expression.push_back(str); + } +; + %% void isc::eval::EvalParser::error(const location_type& loc, diff --git a/src/lib/eval/tests/context_unittest.cc b/src/lib/eval/tests/context_unittest.cc index c7440b8cbc..0c94bf290c 100644 --- a/src/lib/eval/tests/context_unittest.cc +++ b/src/lib/eval/tests/context_unittest.cc @@ -109,6 +109,29 @@ public: } } + /// @brief checks if the given expression raises the expected message + /// when it is parsed by the strongly typed parser but is accepted + /// by the untyped one. + void checkTyped(const string& expr, const string& msg) { + EvalContext eval; + parsed_ = false; + EXPECT_NO_THROW(parsed_ = eval.parseString("untyped:" + expr)); + EXPECT_TRUE(parsed_); + parsed_ = false; + try { + parsed_ = eval.parseString(expr); + FAIL() << "Expected EvalParseError but nothing was raised"; + } + catch (const EvalParseError& ex) { + EXPECT_EQ(msg, ex.what()); + EXPECT_FALSE(parsed_); + } + catch (...) { + FAIL() << "Expected EvalParseError but something else was raised"; + } + } + + bool parsed_; ///< Parsing status }; @@ -125,7 +148,7 @@ TEST_F(EvalContextTest, basic) { TEST_F(EvalContextTest, string) { EvalContext eval; - EXPECT_NO_THROW(parsed_ = eval.parseString("'foo'")); + EXPECT_NO_THROW(parsed_ = eval.parseString("untyped: 'foo'")); EXPECT_TRUE(parsed_); ASSERT_EQ(1, eval.expression.size()); @@ -139,7 +162,7 @@ TEST_F(EvalContextTest, string) { TEST_F(EvalContextTest, hexstring) { EvalContext eval; - EXPECT_NO_THROW(parsed_ = eval.parseString("0x666f6f")); + EXPECT_NO_THROW(parsed_ = eval.parseString("untyped: 0x666f6f")); EXPECT_TRUE(parsed_); ASSERT_EQ(1, eval.expression.size()); @@ -171,7 +194,7 @@ TEST_F(EvalContextTest, equal) { TEST_F(EvalContextTest, option) { EvalContext eval; - EXPECT_NO_THROW(parsed_ = eval.parseString("option[123]")); + EXPECT_NO_THROW(parsed_ = eval.parseString("untyped: option[123]")); EXPECT_TRUE(parsed_); ASSERT_EQ(1, eval.expression.size()); checkTokenOption(eval.expression.at(0), 123); @@ -181,7 +204,8 @@ TEST_F(EvalContextTest, option) { TEST_F(EvalContextTest, substring) { EvalContext eval; - EXPECT_NO_THROW(parsed_ = eval.parseString("substring('foobar','2','3')")); + EXPECT_NO_THROW(parsed_ = + eval.parseString("untyped: substring('foobar','2','3')")); EXPECT_TRUE(parsed_); ASSERT_EQ(4, eval.expression.size()); @@ -204,54 +228,75 @@ TEST_F(EvalContextTest, scanErrors) { checkError("'\n'", ":1.1: Invalid character: '"); checkError("0x123h", ":1.6: Invalid character: h"); checkError("=", ":1.1: Invalid character: ="); - checkError("option[65536]", ":1.8-12: Option code has invalid " - "value in 65536. Allowed range: 0..65535"); + checkError("option[65536]", + ":1.8-12: Option code has invalid " + "value in 65536. Allowed range: 0..65535"); checkError("subtring", ":1.1: Invalid character: s"); + checkError("untype: 'abc'", ":1.1: Invalid character: u"); + checkError("untyped 'abc'", ":1.1: Invalid character: u"); checkError("foo", ":1.1: Invalid character: f"); checkError(" bar", ":1.2: Invalid character: b"); } // Tests some scanner/parser error cases TEST_F(EvalContextTest, scanParseErrors) { - checkError("", ":1.1: syntax error, unexpected end of file, " - "expecting option or substring or constant string or " - "constant hexstring"); - checkError("0x", ":1.1: syntax error, unexpected option code, " - "expecting option or substring or constant string or " - "constant hexstring"); - checkError("===", ":1.1-2: syntax error, unexpected ==, " - "expecting option or substring or constant string " - "or constant hexstring"); + checkError("", ":1.1: syntax error, unexpected end of file"); + checkError("untyped:", + ":1.9: syntax error, unexpected end of file"); + checkError("0x", ":1.1: syntax error, unexpected option code"); + checkError("===", ":1.1-2: syntax error, unexpected =="); } // Tests some parser error cases TEST_F(EvalContextTest, parseErrors) { - checkError("'foo''bar'", ":1.6-10: syntax error, unexpected " - "constant string, expecting end of file"); - checkError("== 'ab'", ":1.1-2: syntax error, unexpected ==, " - "expecting option or substring or constant string " - "or constant hexstring"); - checkError("'foo' ==", ":1.9: syntax error, unexpected end " - "of file, expecting option or substring or " - "constant string or constant hexstring"); - checkError("option 'ab'", ":1.8-11: syntax error, unexpected " - "constant string, expecting ["); - checkError("option(10) == 'ab'", ":1.7: syntax error, " - "unexpected (, expecting ["); - checkError("option['ab'] == 'foo'", ":1.8-11: syntax error, " - "unexpected constant string, " - "expecting option code"); - checkError("option[0xa] == 'ab'", ":1.8-10: syntax error, " - "unexpected constant hexstring, " - "expecting option code"); - checkError("substring('foobar') == 'f'", ":1.19: syntax error, " - "unexpected ), expecting \",\""); + checkError("untyped:'foo''bar'", + ":1.14-18: syntax error, unexpected " + "constant string, expecting end of file"); + checkError("'foo''bar'", + ":1.6-10: syntax error, unexpected constant string, " + "expecting =="); + checkError("== 'ab'", ":1.1-2: syntax error, unexpected =="); + checkError("'foo' ==", + ":1.9: syntax error, unexpected end of file"); + checkError("option 'ab'", + ":1.8-11: syntax error, unexpected " + "constant string, expecting ["); + checkError("option(10) == 'ab'", + ":1.7: syntax error, " + "unexpected (, expecting ["); + checkError("option['ab'] == 'foo'", + ":1.8-11: syntax error, " + "unexpected constant string, " + "expecting option code"); + checkError("option[0xa] == 'ab'", + ":1.8-10: syntax error, " + "unexpected constant hexstring, " + "expecting option code"); + 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 option code, " - "expecting option or substring or constant string or " - "constant hexstring"); + "expecting a number in a constant string"); +} + +// Tests some type error cases (caught only by the strongly typed parser) +TEST_F(EvalContextTest, typeErrors) { + checkTyped("'foobar'", + ":1.9: syntax error, unexpected end of file, " + "expecting =="); + checkTyped("substring('foobar','a','1') == 'foo'", + ":1.20-22: syntax error, unexpected constant string, " + "expecting a number in a constant string"); + checkTyped("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"); + checkTyped("substring('foobar',0x32,'1') == 'foo'", + ":1.20-23: syntax error, unexpected constant " + "hexstring, expecting a number in a constant string"); } };