Browse Source

[4088fd] Moved option code range check to the parser, freeing INTEGER tokens

Francis Dupont 9 years ago
parent
commit
6ae4da980b

+ 69 - 78
src/lib/eval/lexer.cc

@@ -478,14 +478,14 @@ struct yy_trans_info
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	};
-static yyconst flex_int16_t yy_accept[55] =
+static yyconst flex_int16_t yy_accept[56] =
     {   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
+       17,    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] =
@@ -528,58 +528,58 @@ static yyconst flex_int32_t yy_meta[32] =
         1
     } ;
 
-static yyconst flex_int16_t yy_base[57] =
+static yyconst flex_int16_t yy_base[58] =
     {   0,
-        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
+        0,    0,   86,   87,   83,   81,   28,   87,   87,   87,
+       24,   30,   32,   71,   87,   87,   56,   51,   56,   77,
+       75,   73,   87,   39,   42,   31,   46,    0,   87,   47,
+       57,   45,   87,   43,    0,   51,   44,   40,   66,   43,
+       36,   38,   87,   39,   35,   41,   87,   38,   40,   34,
+       46,   32,   87,   87,   87,   66,   47
     } ;
 
-static yyconst flex_int16_t yy_def[57] =
+static yyconst flex_int16_t yy_def[58] =
     {   0,
-       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
+       55,    1,   55,   55,   55,   55,   56,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   56,   55,   56,   56,   56,   55,   57,   55,   55,
+       55,   55,   55,   56,   57,   55,   55,   55,   56,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   55,   55,   55,    0,   55,   55
     } ;
 
-static yyconst flex_int16_t yy_nxt[117] =
+static yyconst flex_int16_t yy_nxt[119] =
     {   0,
-        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
+        4,    5,    6,    7,    8,    9,   10,   11,   12,   13,
+        4,   14,    4,    4,   15,   16,    4,    4,    4,    4,
+        4,    4,    4,    4,   17,    4,    4,   18,    4,   19,
+        4,   23,   27,   27,   23,   24,   25,   25,   27,   27,
+       27,   27,   23,   28,   26,   33,   23,   25,   25,   35,
+       25,   25,   54,   34,   27,   27,   53,   52,   51,   50,
+       49,   48,   47,   46,   45,   39,   22,   44,   22,   43,
+       42,   41,   40,   38,   37,   36,   23,   21,   20,   32,
+       31,   30,   29,   21,   20,   55,    3,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55
     } ;
 
-static yyconst flex_int16_t yy_chk[117] =
+static yyconst flex_int16_t yy_chk[119] =
     {   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,    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
+        1,    7,   11,   11,   26,    7,    7,    7,   12,   12,
+       13,   13,   24,   12,    7,   25,   34,   24,   24,   57,
+       25,   25,   52,   26,   27,   27,   51,   50,   49,   48,
+       46,   45,   44,   42,   41,   34,   56,   40,   56,   39,
+       38,   37,   36,   32,   31,   30,   22,   21,   20,   19,
+       18,   17,   14,    6,    5,    3,   55,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55
     } ;
 
 /* Table of booleans, true if rule could match eol. */
@@ -595,8 +595,8 @@ int yy_flex_debug = 1;
 
 static yyconst flex_int16_t yy_rule_linenum[18] =
     {   0,
-       83,   87,   93,  101,  107,  117,  123,  146,  147,  148,
-      149,  150,  151,  152,  153,  154,  156
+       83,   87,   93,  101,  107,  117,  123,  137,  138,  139,
+      140,  141,  142,  143,  144,  145,  147
     } ;
 
 /* The intent behind this definition is that it'll catch
@@ -975,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 >= 55 )
+				if ( yy_current_state >= 56 )
 					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 != 54 );
+		while ( yy_current_state != 55 );
 		yy_cp = (yy_last_accepting_cpos);
 		yy_current_state = (yy_last_accepting_state);
 
@@ -1096,88 +1096,79 @@ case 7:
 YY_RULE_SETUP
 #line 123 "lexer.ll"
 {
-    // A code (16 bit unsigned integer) was found.
+    // An integer was found.
     std::string tmp(yytext);
 
     int n;
     try {
         n = boost::lexical_cast<int>(tmp);
     } catch (const boost::bad_lexical_cast &) {
-        driver.error(loc, "Failed to convert specified option code to "
-                     "number in " + tmp + ".");
+        driver.error(loc, "Failed to convert " + tmp + " to an integer.");
     }
 
-    // 65535 is the maximum value of the option code in DHCPv6. We want the
-    // code to be the same for v4 and v6, so let's ignore for a moment that
-    // max. option code in DHCPv4 is 255.
-    if (n < 0 || n > 65535) {
-        driver.error(loc, "Option code has invalid value in " +
-                     std::string(yytext) + ". Allowed range: 0..65535");
-    }
-
-    return isc::eval::EvalParser::make_CODE(static_cast<uint16_t>(n), loc);
+    return isc::eval::EvalParser::make_INTEGER(n, loc);
 }
 	YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 146 "lexer.ll"
+#line 137 "lexer.ll"
 return isc::eval::EvalParser::make_EQUAL(loc);
 	YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 147 "lexer.ll"
+#line 138 "lexer.ll"
 return isc::eval::EvalParser::make_OPTION(loc);
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 148 "lexer.ll"
+#line 139 "lexer.ll"
 return isc::eval::EvalParser::make_SUBSTRING(loc);
 	YY_BREAK
 case 11:
 YY_RULE_SETUP
-#line 149 "lexer.ll"
+#line 140 "lexer.ll"
 return isc::eval::EvalParser::make_UNTYPED(loc);
 	YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 150 "lexer.ll"
+#line 141 "lexer.ll"
 return isc::eval::EvalParser::make_LPAREN(loc);
 	YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 151 "lexer.ll"
+#line 142 "lexer.ll"
 return isc::eval::EvalParser::make_RPAREN(loc);
 	YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 152 "lexer.ll"
+#line 143 "lexer.ll"
 return isc::eval::EvalParser::make_LBRACKET(loc);
 	YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 153 "lexer.ll"
+#line 144 "lexer.ll"
 return isc::eval::EvalParser::make_RBRACKET(loc);
 	YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 154 "lexer.ll"
+#line 145 "lexer.ll"
 return isc::eval::EvalParser::make_COMA(loc);
 	YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 156 "lexer.ll"
+#line 147 "lexer.ll"
 driver.error (loc, "Invalid character: " + std::string(yytext));
 	YY_BREAK
 case YY_STATE_EOF(INITIAL):
-#line 157 "lexer.ll"
+#line 148 "lexer.ll"
 return isc::eval::EvalParser::make_END(loc);
 	YY_BREAK
 case 18:
 YY_RULE_SETUP
-#line 158 "lexer.ll"
+#line 149 "lexer.ll"
 ECHO;
 	YY_BREAK
-#line 1181 "lexer.cc"
+#line 1172 "lexer.cc"
 
 	case YY_END_OF_BUFFER:
 		{
@@ -1490,7 +1481,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 >= 55 )
+			if ( yy_current_state >= 56 )
 				yy_c = yy_meta[(unsigned int) yy_c];
 			}
 		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1523,11 +1514,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 >= 55 )
+		if ( yy_current_state >= 56 )
 			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 == 54);
+	yy_is_jam = (yy_current_state == 55);
 
 		return yy_is_jam ? 0 : yy_current_state;
 }
@@ -2265,7 +2256,7 @@ void yyfree (void * ptr )
 
 /* %ok-for-header */
 
-#line 158 "lexer.ll"
+#line 149 "lexer.ll"
 
 
 

+ 5 - 14
src/lib/eval/lexer.ll

@@ -62,7 +62,7 @@ static isc::eval::location loc;
 
 /* These are not token expressions yet, just convenience expressions that
    can be used during actual token definitions. */
-int   [0-9]+
+int   \-?[0-9]+
 hex   [0-9a-fA-F]+
 blank [ \t]
 
@@ -90,7 +90,7 @@ blank [ \t]
     loc.step();
 }
 
-\'\-?{int}\' {
+\'{int}\' {
     // A string containing a number. Quotes should be removed, see below.
     std::string tmp(yytext+1);
     tmp.resize(tmp.size() - 1);
@@ -121,26 +121,17 @@ blank [ \t]
 }
 
 {int} {
-    // A code (16 bit unsigned integer) was found.
+    // An integer was found.
     std::string tmp(yytext);
 
     int n;
     try {
         n = boost::lexical_cast<int>(tmp);
     } catch (const boost::bad_lexical_cast &) {
-        driver.error(loc, "Failed to convert specified option code to "
-                     "number in " + tmp + ".");
+        driver.error(loc, "Failed to convert " + tmp + " to an integer.");
     }
 
-    // 65535 is the maximum value of the option code in DHCPv6. We want the
-    // code to be the same for v4 and v6, so let's ignore for a moment that
-    // max. option code in DHCPv4 is 255.
-    if (n < 0 || n > 65535) {
-        driver.error(loc, "Option code has invalid value in " +
-                     std::string(yytext) + ". Allowed range: 0..65535");
-    }
-
-    return isc::eval::EvalParser::make_CODE(static_cast<uint16_t>(n), loc);
+    return isc::eval::EvalParser::make_INTEGER(n, loc);
 }
 
 "=="        return isc::eval::EvalParser::make_EQUAL(loc);

+ 59 - 45
src/lib/eval/parser.cc

@@ -251,6 +251,10 @@ namespace isc { namespace eval {
   {
       switch (that.type_get ())
     {
+      case 16: // "integer"
+        value.move< int > (that.value);
+        break;
+
       case 12: // "a number in a constant string"
       case 13: // "the all constant string"
       case 14: // "constant string"
@@ -258,10 +262,6 @@ namespace isc { namespace eval {
         value.move< std::string > (that.value);
         break;
 
-      case 16: // "option code"
-        value.move< uint16_t > (that.value);
-        break;
-
       default:
         break;
     }
@@ -277,6 +277,10 @@ namespace isc { namespace eval {
     state = that.state;
       switch (that.type_get ())
     {
+      case 16: // "integer"
+        value.copy< int > (that.value);
+        break;
+
       case 12: // "a number in a constant string"
       case 13: // "the all constant string"
       case 14: // "constant string"
@@ -284,10 +288,6 @@ namespace isc { namespace eval {
         value.copy< std::string > (that.value);
         break;
 
-      case 16: // "option code"
-        value.copy< uint16_t > (that.value);
-        break;
-
       default:
         break;
     }
@@ -352,10 +352,10 @@ namespace isc { namespace eval {
 #line 353 "parser.cc" // lalr1.cc:636
         break;
 
-      case 16: // "option code"
+      case 16: // "integer"
 
 #line 59 "parser.yy" // lalr1.cc:636
-        { yyoutput << yysym.value.template as< uint16_t > (); }
+        { yyoutput << yysym.value.template as< int > (); }
 #line 360 "parser.cc" // lalr1.cc:636
         break;
 
@@ -556,6 +556,10 @@ namespace isc { namespace eval {
          when using variants.  */
         switch (yyr1_[yyn])
     {
+      case 16: // "integer"
+        yylhs.value.build< int > ();
+        break;
+
       case 12: // "a number in a constant string"
       case 13: // "the all constant string"
       case 14: // "constant string"
@@ -563,10 +567,6 @@ namespace isc { namespace eval {
         yylhs.value.build< std::string > ();
         break;
 
-      case 16: // "option code"
-        yylhs.value.build< uint16_t > ();
-        break;
-
       default:
         break;
     }
@@ -632,113 +632,127 @@ namespace isc { namespace eval {
   case 10:
 #line 97 "parser.yy" // lalr1.cc:859
     {
-    TokenPtr opt(new TokenOption(yystack_[1].value.as< uint16_t > ()));
+    int n = yystack_[1].value.as< int > ();
+    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());
+    }
+    TokenPtr opt(new TokenOption(static_cast<uint16_t>(n)));
     ctx.expression.push_back(opt);
   }
-#line 639 "parser.cc" // lalr1.cc:859
+#line 646 "parser.cc" // lalr1.cc:859
     break;
 
   case 11:
-#line 101 "parser.yy" // lalr1.cc:859
+#line 108 "parser.yy" // lalr1.cc:859
     {
     TokenPtr sub(new TokenSubstring());
     ctx.expression.push_back(sub);
   }
-#line 648 "parser.cc" // lalr1.cc:859
+#line 655 "parser.cc" // lalr1.cc:859
     break;
 
   case 12:
-#line 108 "parser.yy" // lalr1.cc:859
+#line 115 "parser.yy" // lalr1.cc:859
     {
     TokenPtr eq(new TokenEqual());
     ctx.expression.push_back(eq);
   }
-#line 657 "parser.cc" // lalr1.cc:859
+#line 664 "parser.cc" // lalr1.cc:859
     break;
 
   case 13:
-#line 115 "parser.yy" // lalr1.cc:859
+#line 122 "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
+#line 673 "parser.cc" // lalr1.cc:859
     break;
 
   case 14:
-#line 119 "parser.yy" // lalr1.cc:859
+#line 126 "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
+#line 682 "parser.cc" // lalr1.cc:859
     break;
 
   case 15:
-#line 123 "parser.yy" // lalr1.cc:859
+#line 130 "parser.yy" // lalr1.cc:859
     {
     TokenPtr str(new TokenString("all"));
     ctx.expression.push_back(str);
   }
-#line 684 "parser.cc" // lalr1.cc:859
+#line 691 "parser.cc" // lalr1.cc:859
     break;
 
   case 16:
-#line 127 "parser.yy" // lalr1.cc:859
+#line 134 "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
+#line 700 "parser.cc" // lalr1.cc:859
     break;
 
   case 17:
-#line 131 "parser.yy" // lalr1.cc:859
+#line 138 "parser.yy" // lalr1.cc:859
     {
-    TokenPtr opt(new TokenOption(yystack_[1].value.as< uint16_t > ()));
+    int n = yystack_[1].value.as< int > ();
+    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());
+    }
+    TokenPtr opt(new TokenOption(static_cast<uint16_t>(n)));
     ctx.expression.push_back(opt);
   }
-#line 702 "parser.cc" // lalr1.cc:859
+#line 716 "parser.cc" // lalr1.cc:859
     break;
 
   case 18:
-#line 135 "parser.yy" // lalr1.cc:859
+#line 149 "parser.yy" // lalr1.cc:859
     {
     TokenPtr sub(new TokenSubstring());
     ctx.expression.push_back(sub);
   }
-#line 711 "parser.cc" // lalr1.cc:859
+#line 725 "parser.cc" // lalr1.cc:859
     break;
 
   case 19:
-#line 142 "parser.yy" // lalr1.cc:859
+#line 156 "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
+#line 734 "parser.cc" // lalr1.cc:859
     break;
 
   case 20:
-#line 149 "parser.yy" // lalr1.cc:859
+#line 163 "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
+#line 743 "parser.cc" // lalr1.cc:859
     break;
 
   case 21:
-#line 153 "parser.yy" // lalr1.cc:859
+#line 167 "parser.yy" // lalr1.cc:859
     {
     TokenPtr str(new TokenString("all"));
     ctx.expression.push_back(str);
   }
-#line 738 "parser.cc" // lalr1.cc:859
+#line 752 "parser.cc" // lalr1.cc:859
     break;
 
 
-#line 742 "parser.cc" // lalr1.cc:859
+#line 756 "parser.cc" // lalr1.cc:859
             default:
               break;
             }
@@ -1086,7 +1100,7 @@ namespace isc { namespace eval {
   "\"substring\"", "\"untyped:\"", "\",\"", "\"(\"", "\")\"", "\"[\"",
   "\"]\"", "\"a number in a constant string\"",
   "\"the all constant string\"", "\"constant string\"",
-  "\"constant hexstring\"", "\"option code\"", "$accept", "expression",
+  "\"constant hexstring\"", "\"integer\"", "$accept", "expression",
   "untyped_expr", "token", "bool_expr", "string_expr", "start_expr",
   "length_expr", YY_NULLPTR
   };
@@ -1096,8 +1110,8 @@ namespace isc { namespace eval {
   EvalParser::yyrline_[] =
   {
        0,    68,    68,    69,    73,    77,    81,    85,    89,    93,
-      97,   101,   108,   115,   119,   123,   127,   131,   135,   142,
-     149,   153
+      97,   108,   115,   122,   126,   130,   134,   138,   149,   156,
+     163,   167
   };
 
   // Print the state stack on the debug stream.
@@ -1132,8 +1146,8 @@ namespace isc { namespace eval {
 
 #line 21 "parser.yy" // lalr1.cc:1167
 } } // isc::eval
-#line 1136 "parser.cc" // lalr1.cc:1167
-#line 159 "parser.yy" // lalr1.cc:1168
+#line 1150 "parser.cc" // lalr1.cc:1167
+#line 173 "parser.yy" // lalr1.cc:1168
 
 void
 isc::eval::EvalParser::error(const location_type& loc,

+ 28 - 28
src/lib/eval/parser.h

@@ -293,14 +293,14 @@ 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"
       // "constant hexstring"
-      char dummy1[sizeof(std::string)];
-
-      // "option code"
-      char dummy2[sizeof(uint16_t)];
+      char dummy2[sizeof(std::string)];
 };
 
     /// Symbol semantic values.
@@ -337,7 +337,7 @@ namespace isc { namespace eval {
         TOKEN_ALL = 268,
         TOKEN_STRING = 269,
         TOKEN_HEXSTRING = 270,
-        TOKEN_CODE = 271
+        TOKEN_INTEGER = 271
       };
     };
 
@@ -375,9 +375,9 @@ namespace isc { namespace eval {
 
   basic_symbol (typename Base::kind_type t, const location_type& l);
 
-  basic_symbol (typename Base::kind_type t, const std::string v, 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 uint16_t v, const location_type& l);
+  basic_symbol (typename Base::kind_type t, const std::string v, const location_type& l);
 
 
       /// Constructor for symbols with semantic value.
@@ -504,7 +504,7 @@ namespace isc { namespace eval {
 
     static inline
     symbol_type
-    make_CODE (const uint16_t& v, const location_type& l);
+    make_INTEGER (const int& v, const location_type& l);
 
 
     /// Build a parser object.
@@ -795,6 +795,10 @@ namespace isc { namespace eval {
   {
       switch (other.type_get ())
     {
+      case 16: // "integer"
+        value.copy< int > (other.value);
+        break;
+
       case 12: // "a number in a constant string"
       case 13: // "the all constant string"
       case 14: // "constant string"
@@ -802,10 +806,6 @@ namespace isc { namespace eval {
         value.copy< std::string > (other.value);
         break;
 
-      case 16: // "option code"
-        value.copy< uint16_t > (other.value);
-        break;
-
       default:
         break;
     }
@@ -823,6 +823,10 @@ namespace isc { namespace eval {
     (void) v;
       switch (this->type_get ())
     {
+      case 16: // "integer"
+        value.copy< int > (v);
+        break;
+
       case 12: // "a number in a constant string"
       case 13: // "the all constant string"
       case 14: // "constant string"
@@ -830,10 +834,6 @@ namespace isc { namespace eval {
         value.copy< std::string > (v);
         break;
 
-      case 16: // "option code"
-        value.copy< uint16_t > (v);
-        break;
-
       default:
         break;
     }
@@ -850,14 +850,14 @@ namespace isc { namespace eval {
   {}
 
   template <typename Base>
-  EvalParser::basic_symbol<Base>::basic_symbol (typename Base::kind_type t, const std::string v, const location_type& l)
+  EvalParser::basic_symbol<Base>::basic_symbol (typename Base::kind_type t, const int v, const location_type& l)
     : Base (t)
     , value (v)
     , location (l)
   {}
 
   template <typename Base>
-  EvalParser::basic_symbol<Base>::basic_symbol (typename Base::kind_type t, const uint16_t v, const location_type& l)
+  EvalParser::basic_symbol<Base>::basic_symbol (typename Base::kind_type t, const std::string v, const location_type& l)
     : Base (t)
     , value (v)
     , location (l)
@@ -889,6 +889,10 @@ namespace isc { namespace eval {
     // Type destructor.
     switch (yytype)
     {
+      case 16: // "integer"
+        value.template destroy< int > ();
+        break;
+
       case 12: // "a number in a constant string"
       case 13: // "the all constant string"
       case 14: // "constant string"
@@ -896,10 +900,6 @@ namespace isc { namespace eval {
         value.template destroy< std::string > ();
         break;
 
-      case 16: // "option code"
-        value.template destroy< uint16_t > ();
-        break;
-
       default:
         break;
     }
@@ -923,6 +923,10 @@ namespace isc { namespace eval {
     super_type::move(s);
       switch (this->type_get ())
     {
+      case 16: // "integer"
+        value.move< int > (s.value);
+        break;
+
       case 12: // "a number in a constant string"
       case 13: // "the all constant string"
       case 14: // "constant string"
@@ -930,10 +934,6 @@ namespace isc { namespace eval {
         value.move< std::string > (s.value);
         break;
 
-      case 16: // "option code"
-        value.move< uint16_t > (s.value);
-        break;
-
       default:
         break;
     }
@@ -1080,9 +1080,9 @@ namespace isc { namespace eval {
   }
 
   EvalParser::symbol_type
-  EvalParser::make_CODE (const uint16_t& v, const location_type& l)
+  EvalParser::make_INTEGER (const int& v, const location_type& l)
   {
-    return symbol_type (token::TOKEN_CODE, v, l);
+    return symbol_type (token::TOKEN_INTEGER, v, l);
   }
 
 

+ 19 - 5
src/lib/eval/parser.yy

@@ -55,7 +55,7 @@ using namespace isc::eval;
 %token <std::string> ALL "the all constant string"
 %token <std::string> STRING "constant string"
 %token <std::string> HEXSTRING "constant hexstring"
-%token <uint16_t> CODE "option code"
+%token <int> INTEGER "integer"
 %printer { yyoutput << $$; } <*>;
 %%
 
@@ -94,8 +94,15 @@ STRING {
     TokenPtr hex(new TokenHexString($1));
     ctx.expression.push_back(hex);
   }
-| OPTION "[" CODE "]" {
-    TokenPtr opt(new TokenOption($3));
+| OPTION "[" INTEGER "]" {
+    int n = $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());
+    }
+    TokenPtr opt(new TokenOption(static_cast<uint16_t>(n)));
     ctx.expression.push_back(opt);
   }
 | SUBSTRING "(" token "," token "," token ")" {
@@ -128,8 +135,15 @@ STRING {
     TokenPtr hex(new TokenHexString($1));
     ctx.expression.push_back(hex);
   }
-| OPTION "[" CODE "]" {
-    TokenPtr opt(new TokenOption($3));
+| OPTION "[" INTEGER "]" {
+    int n = $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());
+    }
+    TokenPtr opt(new TokenOption(static_cast<uint16_t>(n)));
     ctx.expression.push_back(opt);
   }
 | SUBSTRING "(" string_expr "," start_expr "," length_expr ")" {

+ 11 - 8
src/lib/eval/tests/context_unittest.cc

@@ -259,9 +259,6 @@ TEST_F(EvalContextTest, scanErrors) {
     checkError("'\n'", "<string>:1.1: Invalid character: '");
     checkError("0x123h", "<string>:1.6: Invalid character: h");
     checkError("=", "<string>:1.1: Invalid character: =");
-    checkError("option[65536]",
-               "<string>:1.8-12: Option code has invalid "
-               "value in 65536. Allowed range: 0..65535");
     checkError("subtring", "<string>:1.1: Invalid character: s");
     checkError("untype: 'abc'", "<string>:1.1: Invalid character: u");
     checkError("untyped 'abc'", "<string>:1.1: Invalid character: u");
@@ -274,10 +271,16 @@ TEST_F(EvalContextTest, scanParseErrors) {
     checkError("", "<string>:1.1: syntax error, unexpected end of file");
     checkError("untyped:",
                "<string>:1.9: syntax error, unexpected end of file");
-    checkError("0x", "<string>:1.1: syntax error, unexpected option code");
+    checkError("0x", "<string>:1.1: syntax error, unexpected integer");
     checkError("0abc",
-               "<string>:1.1: syntax error, unexpected option code");
+               "<string>:1.1: syntax error, unexpected integer");
     checkError("===", "<string>:1.1-2: syntax error, unexpected ==");
+    checkError("option[-1]",
+               "<string>:1.8-9: Option code has invalid "
+               "value in -1. Allowed range: 0..65535");
+    checkError("option[65536]",
+               "<string>:1.8-12: Option code has invalid "
+               "value in 65536. Allowed range: 0..65535");
     checkError("option[123] < 'foo'", "<string>:1.13: Invalid character: <");
 }
 
@@ -301,18 +304,18 @@ TEST_F(EvalContextTest, parseErrors) {
     checkError("option['ab'] == 'foo'",
                "<string>:1.8-11: syntax error, "
                "unexpected constant string, "
-               "expecting option code");
+               "expecting integer");
     checkError("option[0xa] == 'ab'",
                "<string>:1.8-10: syntax error, "
                "unexpected constant hexstring, "
-               "expecting option code");
+               "expecting integer");
     checkError("substring('foobar') == 'f'",
                "<string>:1.19: syntax error, "
                "unexpected ), expecting \",\"");
     checkError("substring('foobar','3') == 'bar'",
                "<string>:1.23: syntax error, unexpected ), expecting \",\"");
     checkError("substring('foobar',3,3) == 'bar'",
-               "<string>:1.20: syntax error, unexpected option code, "
+               "<string>:1.20: syntax error, unexpected integer, "
                "expecting a number in a constant string");
 }