EQUAL "=="
OPTION "option"
SUBSTRING "substring"
+ DOTTEXT ".text"
+ DOTHEX ".hex"
ALL "all"
COMA ","
LPAREN "("
%token <std::string> TOKEN
%printer { yyoutput << $$; } <*>;
+
+%code
+{
+namespace {
+
+/* Convert option code specified as string to an 16 bit unsigned
+ representation. If the option code is not within the range of
+ 0..65535 an error is reported. */
+uint16_t
+convert_option_code(const std::string& option_code,
+ const isc::eval::EvalParser::location_type& loc,
+ EvalContext& ctx) {
+ int n = 0;
+ try {
+ n = boost::lexical_cast<int>(option_code);
+ } catch (const boost::bad_lexical_cast &) {
+ // This can't happen...
+ ctx.error(loc, "Option code has invalid value in " + option_code);
+ }
+ if (n < 0 || n > 65535) {
+ ctx.error(loc, "Option code has invalid value in "
+ + option_code + ". Allowed range: 0..65535");
+ }
+ return (static_cast<uint16_t>(n));
+}
+}
+
+}
+
%%
// The whole grammar starts with an expression.
TokenPtr hex(new TokenHexString($1));
ctx.expression.push_back(hex);
}
- | OPTION "[" INTEGER "]"
+ | OPTION "[" INTEGER "]" DOTTEXT
{
- int n = 0;
- 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) {
- ctx.error(@3,
- "Option code has invalid value in "
- + $3 + ". Allowed range: 0..65535");
- }
- TokenPtr opt(new TokenOption(static_cast<uint16_t>(n)));
+ uint16_t numeric_code = convert_option_code($3, @3, ctx);
+ TokenPtr opt(new TokenOption(numeric_code));
ctx.expression.push_back(opt);
}
| SUBSTRING "(" string_expr "," start_expr "," length_expr ")"
EvalContext tmp;
- EXPECT_NO_THROW(parsed_ = tmp.parseString("option[123] == 'MSFT'"));
+ try {
+ tmp.parseString("option[123].text == 'MSFT'");
+ } catch (const std::exception& ex) {
+ std::cout << ex.what() << std::endl;
+ }
+ EXPECT_NO_THROW(parsed_ = tmp.parseString("option[123].text == 'MSFT'"));
EXPECT_TRUE(parsed_);
}
EvalContext eval;
EXPECT_NO_THROW(parsed_ =
- eval.parseString("substring(option[123], 0, 2) == '42'"));
+ eval.parseString("substring(option[123].text, 0, 2) == '42'"));
EXPECT_TRUE(parsed_);
}
TEST_F(EvalContextTest, option) {
EvalContext eval;
- EXPECT_NO_THROW(parsed_ = eval.parseString("option[123] == 'foo'"));
+ EXPECT_NO_THROW(parsed_ = eval.parseString("option[123].text == 'foo'"));
EXPECT_TRUE(parsed_);
ASSERT_EQ(3, eval.expression.size());
checkTokenOption(eval.expression.at(0), 123);
checkError("0abc",
"<string>:1.1: syntax error, unexpected integer");
checkError("===", "<string>:1.1-2: syntax error, unexpected ==");
- checkError("option[-1]",
+ checkError("option[-1].text",
"<string>:1.8-9: Option code has invalid "
"value in -1. Allowed range: 0..65535");
- checkError("option[65536]",
+ checkError("option[65536].text",
"<string>:1.8-12: Option code has invalid "
"value in 65536. Allowed range: 0..65535");
checkError("option[12345678901234567890]",
"<string>:1.8-27: Failed to convert 12345678901234567890 "
"to an integer.");
- checkError("option[123] < 'foo'", "<string>:1.13: Invalid character: <");
+ checkError("option[123].text < 'foo'", "<string>:1.18: Invalid character: <");
checkError("substring('foo',12345678901234567890,1)",
"<string>:1.17-36: Failed to convert 12345678901234567890 "
"to an integer.");
checkError("option(10) == 'ab'",
"<string>:1.7: syntax error, "
"unexpected (, expecting [");
- checkError("option['ab'] == 'foo'",
+ checkError("option['ab'].text == 'foo'",
"<string>:1.8-11: syntax error, "
"unexpected constant string, "
"expecting integer");
- checkError("option[0xa] == 'ab'",
+ checkError("option[0xa].text == 'ab'",
"<string>:1.8-10: syntax error, "
"unexpected constant hexstring, "
"expecting integer");