Browse Source

[4088fd] Changed the syntax to unquote integers

Francis Dupont 9 years ago
parent
commit
751b714cfa
6 changed files with 262 additions and 373 deletions
  1. 87 115
      src/lib/eval/lexer.cc
  2. 4 24
      src/lib/eval/lexer.ll
  3. 81 115
      src/lib/eval/parser.cc
  4. 49 76
      src/lib/eval/parser.h
  5. 21 20
      src/lib/eval/parser.yy
  6. 20 23
      src/lib/eval/tests/context_unittest.cc

+ 87 - 115
src/lib/eval/lexer.cc

@@ -469,8 +469,8 @@ static void yy_fatal_error (yyconst char msg[]  );
 	(yy_c_buf_p) = yy_cp;
 	(yy_c_buf_p) = yy_cp;
 
 
 /* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */
 /* %% [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,
 /* This struct is not used in this scanner,
    but its presence is necessary. */
    but its presence is necessary. */
 struct yy_trans_info
 struct yy_trans_info
@@ -478,13 +478,13 @@ struct yy_trans_info
 	flex_int32_t yy_verify;
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	flex_int32_t yy_nxt;
 	};
 	};
-static yyconst flex_int16_t yy_accept[48] =
+static yyconst flex_int16_t yy_accept[44] =
     {   0,
     {   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] =
 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
         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,    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,
     {   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,
     {   0,
         4,    5,    6,    7,    8,    9,   10,   11,   12,   13,
         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,
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    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. */
 /* 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,
-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 yy_state_type yy_last_accepting_state;
 static char *yy_last_accepting_cpos;
 static char *yy_last_accepting_cpos;
@@ -587,10 +581,10 @@ static char *yy_last_accepting_cpos;
 extern int yy_flex_debug;
 extern int yy_flex_debug;
 int yy_flex_debug = 1;
 int yy_flex_debug = 1;
 
 
-static yyconst flex_int16_t yy_rule_linenum[17] =
+static yyconst flex_int16_t yy_rule_linenum[16] =
     {   0,
     {   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
 /* 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
 // by moving it ahead by yyleng bytes. yyleng specifies the length of the
 // currently matched token.
 // currently matched token.
 #define YY_USER_ACTION  loc.columns(yyleng);
 #define YY_USER_ACTION  loc.columns(yyleng);
-#line 661 "lexer.cc"
+#line 655 "lexer.cc"
 
 
 #define INITIAL 0
 #define INITIAL 0
 
 
@@ -940,7 +934,7 @@ YY_DECL
     loc.step();
     loc.step();
 
 
 
 
-#line 944 "lexer.cc"
+#line 938 "lexer.cc"
 
 
 	while ( 1 )		/* loops until end-of-file is reached */
 	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 )
 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 				{
 				{
 				yy_current_state = (int) yy_def[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_c = yy_meta[(unsigned int) yy_c];
 				}
 				}
 			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
 			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
 			++yy_cp;
 			++yy_cp;
 			}
 			}
-		while ( yy_current_state != 47 );
+		while ( yy_current_state != 43 );
 		yy_cp = (yy_last_accepting_cpos);
 		yy_cp = (yy_last_accepting_cpos);
 		yy_current_state = (yy_last_accepting_state);
 		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 )
 			if ( yy_act == 0 )
 				fprintf( stderr, "--scanner backing up\n" );
 				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",
 				fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n",
 				         (long)yy_rule_linenum[yy_act], yytext );
 				         (long)yy_rule_linenum[yy_act], yytext );
-			else if ( yy_act == 17 )
+			else if ( yy_act == 16 )
 				fprintf( stderr, "--accepting default rule (\"%s\")\n",
 				fprintf( stderr, "--accepting default rule (\"%s\")\n",
 				         yytext );
 				         yytext );
-			else if ( yy_act == 18 )
+			else if ( yy_act == 17 )
 				fprintf( stderr, "--(end of buffer or a NUL)\n" );
 				fprintf( stderr, "--(end of buffer or a NUL)\n" );
 			else
 			else
 				fprintf( stderr, "--EOF (start condition %d)\n", YY_START );
 				fprintf( stderr, "--EOF (start condition %d)\n", YY_START );
@@ -1048,33 +1042,6 @@ case 3:
 YY_RULE_SETUP
 YY_RULE_SETUP
 #line 93 "lexer.ll"
 #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<void>(boost::lexical_cast<int>(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.
     // 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.
     // We need to get those quotes out of the way and just use its content, e.g.
     // for 'foo' we should get foo
     // for 'foo' we should get foo
@@ -1084,87 +1051,92 @@ YY_RULE_SETUP
     return isc::eval::EvalParser::make_STRING(tmp, loc);
     return isc::eval::EvalParser::make_STRING(tmp, loc);
 }
 }
 	YY_BREAK
 	YY_BREAK
-case 6:
+case 4:
 YY_RULE_SETUP
 YY_RULE_SETUP
-#line 124 "lexer.ll"
+#line 103 "lexer.ll"
 {
 {
     // A hex string has been matched. It contains the '0x' or '0X' header
     // A hex string has been matched. It contains the '0x' or '0X' header
     // followed by at least one hexadecimal digit.
     // followed by at least one hexadecimal digit.
     return isc::eval::EvalParser::make_HEXSTRING(yytext, loc);
     return isc::eval::EvalParser::make_HEXSTRING(yytext, loc);
 }
 }
 	YY_BREAK
 	YY_BREAK
-case 7:
+case 5:
 YY_RULE_SETUP
 YY_RULE_SETUP
-#line 130 "lexer.ll"
+#line 109 "lexer.ll"
 {
 {
     // An integer was found.
     // An integer was found.
     std::string tmp(yytext);
     std::string tmp(yytext);
 
 
-    int n;
     try {
     try {
-        n = boost::lexical_cast<int>(tmp);
+        static_cast<void>(boost::lexical_cast<int>(tmp));
     } catch (const boost::bad_lexical_cast &) {
     } catch (const boost::bad_lexical_cast &) {
         driver.error(loc, "Failed to convert " + tmp + " to an integer.");
         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
 	YY_BREAK
-case 8:
+case 6:
 YY_RULE_SETUP
 YY_RULE_SETUP
-#line 144 "lexer.ll"
+#line 123 "lexer.ll"
 return isc::eval::EvalParser::make_EQUAL(loc);
 return isc::eval::EvalParser::make_EQUAL(loc);
 	YY_BREAK
 	YY_BREAK
-case 9:
+case 7:
 YY_RULE_SETUP
 YY_RULE_SETUP
-#line 145 "lexer.ll"
+#line 124 "lexer.ll"
 return isc::eval::EvalParser::make_OPTION(loc);
 return isc::eval::EvalParser::make_OPTION(loc);
 	YY_BREAK
 	YY_BREAK
-case 10:
+case 8:
 YY_RULE_SETUP
 YY_RULE_SETUP
-#line 146 "lexer.ll"
+#line 125 "lexer.ll"
 return isc::eval::EvalParser::make_SUBSTRING(loc);
 return isc::eval::EvalParser::make_SUBSTRING(loc);
 	YY_BREAK
 	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
 YY_RULE_SETUP
-#line 147 "lexer.ll"
+#line 127 "lexer.ll"
 return isc::eval::EvalParser::make_LPAREN(loc);
 return isc::eval::EvalParser::make_LPAREN(loc);
 	YY_BREAK
 	YY_BREAK
-case 12:
+case 11:
 YY_RULE_SETUP
 YY_RULE_SETUP
-#line 148 "lexer.ll"
+#line 128 "lexer.ll"
 return isc::eval::EvalParser::make_RPAREN(loc);
 return isc::eval::EvalParser::make_RPAREN(loc);
 	YY_BREAK
 	YY_BREAK
-case 13:
+case 12:
 YY_RULE_SETUP
 YY_RULE_SETUP
-#line 149 "lexer.ll"
+#line 129 "lexer.ll"
 return isc::eval::EvalParser::make_LBRACKET(loc);
 return isc::eval::EvalParser::make_LBRACKET(loc);
 	YY_BREAK
 	YY_BREAK
-case 14:
+case 13:
 YY_RULE_SETUP
 YY_RULE_SETUP
-#line 150 "lexer.ll"
+#line 130 "lexer.ll"
 return isc::eval::EvalParser::make_RBRACKET(loc);
 return isc::eval::EvalParser::make_RBRACKET(loc);
 	YY_BREAK
 	YY_BREAK
-case 15:
+case 14:
 YY_RULE_SETUP
 YY_RULE_SETUP
-#line 151 "lexer.ll"
+#line 131 "lexer.ll"
 return isc::eval::EvalParser::make_COMA(loc);
 return isc::eval::EvalParser::make_COMA(loc);
 	YY_BREAK
 	YY_BREAK
-case 16:
+case 15:
 YY_RULE_SETUP
 YY_RULE_SETUP
-#line 153 "lexer.ll"
+#line 133 "lexer.ll"
 driver.error (loc, "Invalid character: " + std::string(yytext));
 driver.error (loc, "Invalid character: " + std::string(yytext));
 	YY_BREAK
 	YY_BREAK
 case YY_STATE_EOF(INITIAL):
 case YY_STATE_EOF(INITIAL):
-#line 154 "lexer.ll"
+#line 134 "lexer.ll"
 return isc::eval::EvalParser::make_END(loc);
 return isc::eval::EvalParser::make_END(loc);
 	YY_BREAK
 	YY_BREAK
-case 17:
+case 16:
 YY_RULE_SETUP
 YY_RULE_SETUP
-#line 155 "lexer.ll"
+#line 135 "lexer.ll"
 ECHO;
 ECHO;
 	YY_BREAK
 	YY_BREAK
-#line 1168 "lexer.cc"
+#line 1140 "lexer.cc"
 
 
 	case YY_END_OF_BUFFER:
 	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 )
 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 			{
 			{
 			yy_current_state = (int) yy_def[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_c = yy_meta[(unsigned int) yy_c];
 			}
 			}
 		yy_current_state = yy_nxt[yy_base[yy_current_state] + (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 )
 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 		{
 		{
 		yy_current_state = (int) yy_def[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_c = yy_meta[(unsigned int) yy_c];
 		}
 		}
 	yy_current_state = yy_nxt[yy_base[yy_current_state] + (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;
 		return yy_is_jam ? 0 : yy_current_state;
 }
 }
@@ -2252,7 +2224,7 @@ void yyfree (void * ptr )
 
 
 /* %ok-for-header */
 /* %ok-for-header */
 
 
-#line 155 "lexer.ll"
+#line 135 "lexer.ll"
 
 
 
 
 
 

+ 4 - 24
src/lib/eval/lexer.ll

@@ -90,27 +90,6 @@ blank [ \t]
     loc.step();
     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<void>(boost::lexical_cast<int>(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]*\' {
 \'[^\'\n]*\' {
     // A string has been matched. It contains the actual string and single quotes.
     // 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.
     // 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.
     // An integer was found.
     std::string tmp(yytext);
     std::string tmp(yytext);
 
 
-    int n;
     try {
     try {
-        n = boost::lexical_cast<int>(tmp);
+        static_cast<void>(boost::lexical_cast<int>(tmp));
     } catch (const boost::bad_lexical_cast &) {
     } catch (const boost::bad_lexical_cast &) {
         driver.error(loc, "Failed to convert " + tmp + " to an integer.");
         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);
 "=="        return isc::eval::EvalParser::make_EQUAL(loc);
 "option"    return isc::eval::EvalParser::make_OPTION(loc);
 "option"    return isc::eval::EvalParser::make_OPTION(loc);
 "substring" return isc::eval::EvalParser::make_SUBSTRING(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_LPAREN(loc);
 ")"         return isc::eval::EvalParser::make_RPAREN(loc);
 ")"         return isc::eval::EvalParser::make_RPAREN(loc);
 "["         return isc::eval::EvalParser::make_LBRACKET(loc);
 "["         return isc::eval::EvalParser::make_LBRACKET(loc);

+ 81 - 115
src/lib/eval/parser.cc

@@ -49,7 +49,7 @@
 
 
 #line 51 "parser.cc" // lalr1.cc:412
 #line 51 "parser.cc" // lalr1.cc:412
 // Unqualified %code blocks.
 // Unqualified %code blocks.
-#line 38 "parser.yy" // lalr1.cc:413
+#line 39 "parser.yy" // lalr1.cc:413
 
 
 # include "eval_context.h"
 # include "eval_context.h"
 
 
@@ -251,14 +251,10 @@ namespace isc { namespace eval {
   {
   {
       switch (that.type_get ())
       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 14: // "constant hexstring"
+      case 15: // TOKEN
         value.move< std::string > (that.value);
         value.move< std::string > (that.value);
         break;
         break;
 
 
@@ -277,14 +273,10 @@ namespace isc { namespace eval {
     state = that.state;
     state = that.state;
       switch (that.type_get ())
       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 14: // "constant hexstring"
+      case 15: // TOKEN
         value.copy< std::string > (that.value);
         value.copy< std::string > (that.value);
         break;
         break;
 
 
@@ -324,39 +316,32 @@ namespace isc { namespace eval {
         << yysym.location << ": ";
         << yysym.location << ": ";
     switch (yytype)
     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 > (); }
         { yyoutput << yysym.value.template as< std::string > (); }
-#line 332 "parser.cc" // lalr1.cc:636
+#line 324 "parser.cc" // lalr1.cc:636
         break;
         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 > (); }
         { 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;
         break;
 
 
       case 14: // "constant hexstring"
       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 > (); }
         { yyoutput << yysym.value.template as< std::string > (); }
-#line 353 "parser.cc" // lalr1.cc:636
+#line 338 "parser.cc" // lalr1.cc:636
         break;
         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;
         break;
 
 
 
 
@@ -556,14 +541,10 @@ namespace isc { namespace eval {
          when using variants.  */
          when using variants.  */
         switch (yyr1_[yyn])
         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 14: // "constant hexstring"
+      case 15: // TOKEN
         yylhs.value.build< std::string > ();
         yylhs.value.build< std::string > ();
         break;
         break;
 
 
@@ -585,104 +566,92 @@ namespace isc { namespace eval {
           switch (yyn)
           switch (yyn)
             {
             {
   case 3:
   case 3:
-#line 70 "parser.yy" // lalr1.cc:859
+#line 73 "parser.yy" // lalr1.cc:859
     {
     {
                     TokenPtr eq(new TokenEqual());
                     TokenPtr eq(new TokenEqual());
                     ctx.expression.push_back(eq);
                     ctx.expression.push_back(eq);
                 }
                 }
-#line 594 "parser.cc" // lalr1.cc:859
+#line 575 "parser.cc" // lalr1.cc:859
     break;
     break;
 
 
   case 4:
   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 > ()));
                       TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
                       ctx.expression.push_back(str);
                       ctx.expression.push_back(str);
                   }
                   }
-#line 603 "parser.cc" // lalr1.cc:859
+#line 584 "parser.cc" // lalr1.cc:859
     break;
     break;
 
 
   case 5:
   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 > ()));
                       TokenPtr hex(new TokenHexString(yystack_[0].value.as< std::string > ()));
                       ctx.expression.push_back(hex);
                       ctx.expression.push_back(hex);
                   }
                   }
-#line 630 "parser.cc" // lalr1.cc:859
+#line 593 "parser.cc" // lalr1.cc:859
     break;
     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<int>(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) {
                       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<uint16_t>(n)));
                       TokenPtr opt(new TokenOption(static_cast<uint16_t>(n)));
                       ctx.expression.push_back(opt);
                       ctx.expression.push_back(opt);
                   }
                   }
-#line 646 "parser.cc" // lalr1.cc:859
+#line 615 "parser.cc" // lalr1.cc:859
     break;
     break;
 
 
-  case 9:
-#line 109 "parser.yy" // lalr1.cc:859
+  case 7:
+#line 108 "parser.yy" // lalr1.cc:859
     {
     {
                       TokenPtr sub(new TokenSubstring());
                       TokenPtr sub(new TokenSubstring());
                       ctx.expression.push_back(sub);
                       ctx.expression.push_back(sub);
                   }
                   }
-#line 655 "parser.cc" // lalr1.cc:859
+#line 624 "parser.cc" // lalr1.cc:859
     break;
     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 > ()));
                      TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
                      ctx.expression.push_back(str);
                      ctx.expression.push_back(str);
                  }
                  }
-#line 664 "parser.cc" // lalr1.cc:859
+#line 633 "parser.cc" // lalr1.cc:859
     break;
     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 > ()));
                       TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
                       ctx.expression.push_back(str);
                       ctx.expression.push_back(str);
                   }
                   }
-#line 673 "parser.cc" // lalr1.cc:859
+#line 642 "parser.cc" // lalr1.cc:859
     break;
     break;
 
 
-  case 12:
-#line 128 "parser.yy" // lalr1.cc:859
+  case 11:
+#line 129 "parser.yy" // lalr1.cc:859
     {
     {
                      TokenPtr str(new TokenString("all"));
                      TokenPtr str(new TokenString("all"));
                      ctx.expression.push_back(str);
                      ctx.expression.push_back(str);
                  }
                  }
-#line 682 "parser.cc" // lalr1.cc:859
+#line 651 "parser.cc" // lalr1.cc:859
     break;
     break;
 
 
 
 
-#line 686 "parser.cc" // lalr1.cc:859
+#line 655 "parser.cc" // lalr1.cc:859
             default:
             default:
               break;
               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::yytable_ninf_ = -1;
 
 
   const signed char
   const signed char
   EvalParser::yypact_[] =
   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
   const unsigned char
   EvalParser::yydefact_[] =
   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
   const signed char
   EvalParser::yypgoto_[] =
   EvalParser::yypgoto_[] =
   {
   {
-     -10,   -10,   -10,    -9,   -10,   -10
+      -9,    -9,    -9,    -8,    -9,    -9
   };
   };
 
 
   const signed char
   const signed char
   EvalParser::yydefgoto_[] =
   EvalParser::yydefgoto_[] =
   {
   {
-      -1,     7,     8,     9,    20,    24
+      -1,     6,     7,     8,    19,    23
   };
   };
 
 
   const unsigned char
   const unsigned char
   EvalParser::yytable_[] =
   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
   const signed char
   EvalParser::yycheck_[] =
   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
   const unsigned char
   EvalParser::yystos_[] =
   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
   const unsigned char
   EvalParser::yyr1_[] =
   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
   const unsigned char
   EvalParser::yyr2_[] =
   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_[] =
   const EvalParser::yytname_[] =
   {
   {
   "\"end of file\"", "error", "$undefined", "\"==\"", "\"option\"",
   "\"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",
   "$accept", "expression", "bool_expr", "string_expr", "start_expr",
   "length_expr", YY_NULLPTR
   "length_expr", YY_NULLPTR
   };
   };
@@ -1026,8 +992,8 @@ namespace isc { namespace eval {
   const unsigned char
   const unsigned char
   EvalParser::yyrline_[] =
   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.
   // Print the state stack on the debug stream.
@@ -1062,8 +1028,8 @@ namespace isc { namespace eval {
 
 
 #line 21 "parser.yy" // lalr1.cc:1167
 #line 21 "parser.yy" // lalr1.cc:1167
 } } // isc::eval
 } } // 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
 void
 isc::eval::EvalParser::error(const location_type& loc,
 isc::eval::EvalParser::error(const location_type& loc,

+ 49 - 76
src/lib/eval/parser.h

@@ -45,11 +45,12 @@
 #include <string>
 #include <string>
 #include <eval/token.h>
 #include <eval/token.h>
 #include <eval/eval_context_decl.h>
 #include <eval/eval_context_decl.h>
+#include <boost/lexical_cast.hpp>
 
 
 using namespace isc::dhcp;
 using namespace isc::dhcp;
 using namespace isc::eval;
 using namespace isc::eval;
 
 
-#line 53 "parser.h" // lalr1.cc:392
+#line 54 "parser.h" // lalr1.cc:392
 
 
 # include <cassert>
 # include <cassert>
 # include <cstdlib> // std::abort
 # include <cstdlib> // std::abort
@@ -126,7 +127,7 @@ using namespace isc::eval;
 
 
 #line 21 "parser.yy" // lalr1.cc:392
 #line 21 "parser.yy" // lalr1.cc:392
 namespace isc { namespace eval {
 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.
     /// An auxiliary type to compute the largest semantic type.
     union union_type
     union union_type
     {
     {
-      // "integer"
-      char dummy1[sizeof(int)];
-
-      // "a number in a constant string"
-      // "the all constant string"
       // "constant string"
       // "constant string"
+      // "integer"
       // "constant hexstring"
       // "constant hexstring"
-      char dummy2[sizeof(std::string)];
+      // TOKEN
+      char dummy1[sizeof(std::string)];
 };
 };
 
 
     /// Symbol semantic values.
     /// Symbol semantic values.
@@ -327,16 +325,16 @@ namespace isc { namespace eval {
         TOKEN_EQUAL = 258,
         TOKEN_EQUAL = 258,
         TOKEN_OPTION = 259,
         TOKEN_OPTION = 259,
         TOKEN_SUBSTRING = 260,
         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_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 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);
   basic_symbol (typename Base::kind_type t, const std::string v, const location_type& l);
 
 
 
 
@@ -463,6 +459,10 @@ namespace isc { namespace eval {
 
 
     static inline
     static inline
     symbol_type
     symbol_type
+    make_ALL (const location_type& l);
+
+    static inline
+    symbol_type
     make_COMA (const location_type& l);
     make_COMA (const location_type& l);
 
 
     static inline
     static inline
@@ -483,15 +483,11 @@ namespace isc { namespace eval {
 
 
     static inline
     static inline
     symbol_type
     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
     static inline
     symbol_type
     symbol_type
-    make_STRING (const std::string& v, const location_type& l);
+    make_INTEGER (const std::string& v, const location_type& l);
 
 
     static inline
     static inline
     symbol_type
     symbol_type
@@ -499,7 +495,7 @@ namespace isc { namespace eval {
 
 
     static inline
     static inline
     symbol_type
     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.
     /// Build a parser object.
@@ -706,9 +702,9 @@ namespace isc { namespace eval {
     enum
     enum
     {
     {
       yyeof_ = 0,
       yyeof_ = 0,
-      yylast_ = 20,     ///< Last index in yytable_.
+      yylast_ = 19,     ///< Last index in yytable_.
       yynnts_ = 6,  ///< Number of nonterminal symbols.
       yynnts_ = 6,  ///< Number of nonterminal symbols.
-      yyfinal_ = 12, ///< Termination state number.
+      yyfinal_ = 11, ///< Termination state number.
       yyterror_ = 1,
       yyterror_ = 1,
       yyerrcode_ = 256,
       yyerrcode_ = 256,
       yyntokens_ = 16  ///< Number of tokens.
       yyntokens_ = 16  ///< Number of tokens.
@@ -790,14 +786,10 @@ namespace isc { namespace eval {
   {
   {
       switch (other.type_get ())
       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 14: // "constant hexstring"
+      case 15: // TOKEN
         value.copy< std::string > (other.value);
         value.copy< std::string > (other.value);
         break;
         break;
 
 
@@ -818,14 +810,10 @@ namespace isc { namespace eval {
     (void) v;
     (void) v;
       switch (this->type_get ())
       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 14: // "constant hexstring"
+      case 15: // TOKEN
         value.copy< std::string > (v);
         value.copy< std::string > (v);
         break;
         break;
 
 
@@ -845,13 +833,6 @@ namespace isc { namespace eval {
   {}
   {}
 
 
   template <typename Base>
   template <typename Base>
-  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 std::string 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)
     : Base (t)
     , value (v)
     , value (v)
@@ -884,14 +865,10 @@ namespace isc { namespace eval {
     // Type destructor.
     // Type destructor.
     switch (yytype)
     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 14: // "constant hexstring"
+      case 15: // TOKEN
         value.template destroy< std::string > ();
         value.template destroy< std::string > ();
         break;
         break;
 
 
@@ -918,14 +895,10 @@ namespace isc { namespace eval {
     super_type::move(s);
     super_type::move(s);
       switch (this->type_get ())
       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 14: // "constant hexstring"
+      case 15: // TOKEN
         value.move< std::string > (s.value);
         value.move< std::string > (s.value);
         break;
         break;
 
 
@@ -1015,6 +988,12 @@ namespace isc { namespace eval {
   }
   }
 
 
   EvalParser::symbol_type
   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)
   EvalParser::make_COMA (const location_type& l)
   {
   {
     return symbol_type (token::TOKEN_COMA, l);
     return symbol_type (token::TOKEN_COMA, l);
@@ -1045,21 +1024,15 @@ namespace isc { namespace eval {
   }
   }
 
 
   EvalParser::symbol_type
   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::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
   EvalParser::symbol_type
@@ -1069,15 +1042,15 @@ namespace isc { namespace eval {
   }
   }
 
 
   EvalParser::symbol_type
   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
 #line 21 "parser.yy" // lalr1.cc:392
 } } // isc::eval
 } } // isc::eval
-#line 1081 "parser.h" // lalr1.cc:392
+#line 1054 "parser.h" // lalr1.cc:392
 
 
 
 
 
 

+ 21 - 20
src/lib/eval/parser.yy

@@ -25,6 +25,7 @@
 #include <string>
 #include <string>
 #include <eval/token.h>
 #include <eval/token.h>
 #include <eval/eval_context_decl.h>
 #include <eval/eval_context_decl.h>
+#include <boost/lexical_cast.hpp>
 
 
 using namespace isc::dhcp;
 using namespace isc::dhcp;
 using namespace isc::eval;
 using namespace isc::eval;
@@ -44,17 +45,19 @@ using namespace isc::eval;
   EQUAL "=="
   EQUAL "=="
   OPTION "option"
   OPTION "option"
   SUBSTRING "substring"
   SUBSTRING "substring"
+  ALL "all"
   COMA ","
   COMA ","
   LPAREN  "("
   LPAREN  "("
   RPAREN  ")"
   RPAREN  ")"
   LBRACKET "["
   LBRACKET "["
   RBRACKET "]"
   RBRACKET "]"
 ;
 ;
-%token <std::string> NUMBER "a number in a constant string"
-%token <std::string> ALL "the all constant string"
+
 %token <std::string> STRING "constant string"
 %token <std::string> STRING "constant string"
+%token <std::string> INTEGER "integer"
 %token <std::string> HEXSTRING "constant hexstring"
 %token <std::string> HEXSTRING "constant hexstring"
-%token <int> INTEGER "integer"
+%token <std::string> TOKEN
+
 %printer { yyoutput << $$; } <*>;
 %printer { yyoutput << $$; } <*>;
 %%
 %%
 
 
@@ -78,16 +81,6 @@ string_expr : STRING
                       TokenPtr str(new TokenString($1));
                       TokenPtr str(new TokenString($1));
                       ctx.expression.push_back(str);
                       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
             | HEXSTRING
                   {
                   {
                       TokenPtr hex(new TokenHexString($1));
                       TokenPtr hex(new TokenHexString($1));
@@ -95,12 +88,18 @@ string_expr : STRING
                   }
                   }
             | OPTION "[" INTEGER "]"
             | OPTION "[" INTEGER "]"
                   {
                   {
-                      int n = $3;
+                      int n;
+                      try {
+                          n  = boost::lexical_cast<int>($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) {
                       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<uint16_t>(n)));
                       TokenPtr opt(new TokenOption(static_cast<uint16_t>(n)));
                       ctx.expression.push_back(opt);
                       ctx.expression.push_back(opt);
@@ -110,16 +109,18 @@ string_expr : STRING
                       TokenPtr sub(new TokenSubstring());
                       TokenPtr sub(new TokenSubstring());
                       ctx.expression.push_back(sub);
                       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));
                      TokenPtr str(new TokenString($1));
                      ctx.expression.push_back(str);
                      ctx.expression.push_back(str);
                  }
                  }
            ;
            ;
 
 
-length_expr : NUMBER
+length_expr : INTEGER
                   {
                   {
                       TokenPtr str(new TokenString($1));
                       TokenPtr str(new TokenString($1));
                       ctx.expression.push_back(str);
                       ctx.expression.push_back(str);

+ 20 - 23
src/lib/eval/tests/context_unittest.cc

@@ -137,14 +137,13 @@ TEST_F(EvalContextTest, string) {
     checkTokenString(tmp2, "bar");
     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;
     EvalContext eval;
 
 
     EXPECT_NO_THROW(parsed_ =
     EXPECT_NO_THROW(parsed_ =
-        eval.parseString("substring(option[123], '0', '2') == '42'"));
+        eval.parseString("substring(option[123], 0, 2) == '42'"));
     EXPECT_TRUE(parsed_);
     EXPECT_TRUE(parsed_);
 }
 }
 
 
@@ -210,7 +209,7 @@ TEST_F(EvalContextTest, substring) {
     EvalContext eval;
     EvalContext eval;
 
 
     EXPECT_NO_THROW(parsed_ =
     EXPECT_NO_THROW(parsed_ =
-        eval.parseString("substring('foobar','2','3') == 'oba'"));
+        eval.parseString("substring('foobar',2,all) == 'obar'"));
     EXPECT_TRUE(parsed_);
     EXPECT_TRUE(parsed_);
 
 
     ASSERT_EQ(6, eval.expression.size());
     ASSERT_EQ(6, eval.expression.size());
@@ -222,7 +221,7 @@ TEST_F(EvalContextTest, substring) {
 
 
     checkTokenString(tmp1, "foobar");
     checkTokenString(tmp1, "foobar");
     checkTokenString(tmp2, "2");
     checkTokenString(tmp2, "2");
-    checkTokenString(tmp3, "3");
+    checkTokenString(tmp3, "all");
     checkTokenSubstring(tmp4);
     checkTokenSubstring(tmp4);
 }
 }
 
 
@@ -256,9 +255,9 @@ TEST_F(EvalContextTest, scanParseErrors) {
                "<string>:1.8-27: Failed to convert 12345678901234567890 "
                "<string>:1.8-27: Failed to convert 12345678901234567890 "
                "to an integer.");
                "to an integer.");
     checkError("option[123] < 'foo'", "<string>:1.13: Invalid character: <");
     checkError("option[123] < 'foo'", "<string>:1.13: Invalid character: <");
-    checkError("substring('foo','12345678901234567890','1')",
-               "<string>:1.17-38: syntax error, unexpected constant string, "
-               "expecting a number in a constant string");
+    checkError("substring('foo',12345678901234567890,1)",
+               "<string>:1.17-36: Failed to convert 12345678901234567890 "
+               "to an integer.");
 }
 }
 
 
 // Tests some parser error cases
 // Tests some parser error cases
@@ -286,11 +285,13 @@ TEST_F(EvalContextTest, parseErrors) {
     checkError("substring('foobar') == 'f'",
     checkError("substring('foobar') == 'f'",
                "<string>:1.19: syntax error, "
                "<string>:1.19: syntax error, "
                "unexpected ), expecting \",\"");
                "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 integer, "
-               "expecting a number in a constant string");
+    checkError("substring('foobar',3) == 'bar'",
+               "<string>:1.21: syntax error, unexpected ), expecting \",\"");
+    checkError("substring('foobar','3',3) == 'bar'",
+               "<string>:1.20-22: syntax error, unexpected constant string, "
+               "expecting integer");
+    checkError("substring('foobar',1,a) == 'foo'",
+               "<string>:1.22: Invalid character: a");
 }
 }
 
 
 // Tests some type error cases (caught only by the strongly typed parser)
 // Tests some type error cases (caught only by the strongly typed parser)
@@ -298,16 +299,12 @@ TEST_F(EvalContextTest, typeErrors) {
     checkError("'foobar'",
     checkError("'foobar'",
                "<string>:1.9: syntax error, unexpected end of file, "
                "<string>:1.9: syntax error, unexpected end of file, "
                "expecting ==");
                "expecting ==");
-    checkError("substring('foobar','a','1') == 'foo'",
-               "<string>:1.20-22: syntax error, unexpected constant string, "
-               "expecting a number in a constant string");
-    checkError("substring('foobar','1','a') == 'foo'",
-               "<string>: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'",
+               "<string>:1.20-22: syntax error, unexpected all, "
+               "expecting integer");
+    checkError("substring('foobar',0x32,1) == 'foo'",
                "<string>:1.20-23: syntax error, unexpected constant "
                "<string>:1.20-23: syntax error, unexpected constant "
-               "hexstring, expecting a number in a constant string");
+               "hexstring, expecting integer");
 }
 }
 
 
 };
 };