void
EvalContext::scanFileBegin()
{
+ loc.initialize(&file_);
yy_flex_debug = trace_scanning_;
if (file_.empty () || file_ == "-") {
yyin = stdin;
void
EvalContext::scanStringBegin()
{
- YY_BUFFER_STATE buffer;
+ loc.initialize(&file_);
yy_flex_debug = trace_scanning_;
+ YY_BUFFER_STATE buffer;
buffer = yy_scan_bytes(string_.c_str(),string_.size());
if (!buffer) {
error("cannot scan string");
void
EvalContext::scanFileBegin()
{
+ loc.initialize(&file_);
yy_flex_debug = trace_scanning_;
if (file_.empty () || file_ == "-") {
yyin = stdin;
void
EvalContext::scanStringBegin()
{
- YY_BUFFER_STATE buffer;
+ loc.initialize(&file_);
yy_flex_debug = trace_scanning_;
+ YY_BUFFER_STATE buffer;
buffer = yy_scan_bytes(string_.c_str(), string_.size());
if (!buffer) {
error("cannot scan string");
#line 51 "parser.cc" // lalr1.cc:412
// Unqualified %code blocks.
-#line 43 "parser.yy" // lalr1.cc:413
+#line 38 "parser.yy" // lalr1.cc:413
# include "eval_context.h"
{
case 11: // "constant string"
-#line 61 "parser.yy" // lalr1.cc:636
+#line 56 "parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< std::string > (); }
#line 328 "parser.cc" // lalr1.cc:636
break;
case 12: // "constant hexstring"
-#line 61 "parser.yy" // lalr1.cc:636
+#line 56 "parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< std::string > (); }
#line 335 "parser.cc" // lalr1.cc:636
break;
case 13: // "option code"
-#line 61 "parser.yy" // lalr1.cc:636
+#line 56 "parser.yy" // lalr1.cc:636
{ yyoutput << yysym.value.template as< uint16_t > (); }
#line 342 "parser.cc" // lalr1.cc:636
break;
YYCDEBUG << "Starting parse" << std::endl;
- // User initialization code.
- #line 36 "parser.yy" // lalr1.cc:745
-{
- // Initialize the initial location.
- yyla.location.begin.filename = yyla.location.end.filename = &ctx.file_;
-}
-
-#line 461 "parser.cc" // lalr1.cc:745
-
/* Initialize the stack. The initial state will be set in
yynewstate, since the latter expects the semantical and the
location values to have been already stored, initialize these
switch (yyn)
{
case 2:
-#line 70 "parser.yy" // lalr1.cc:859
+#line 65 "parser.yy" // lalr1.cc:859
{
TokenPtr eq(new TokenEqual());
ctx.expression.push_back(eq);
}
-#line 583 "parser.cc" // lalr1.cc:859
+#line 574 "parser.cc" // lalr1.cc:859
break;
case 4:
-#line 78 "parser.yy" // lalr1.cc:859
+#line 73 "parser.yy" // lalr1.cc:859
{
TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
ctx.expression.push_back(str);
}
-#line 592 "parser.cc" // lalr1.cc:859
+#line 583 "parser.cc" // lalr1.cc:859
break;
case 5:
-#line 82 "parser.yy" // lalr1.cc:859
+#line 77 "parser.yy" // lalr1.cc:859
{
TokenPtr hex(new TokenHexString(yystack_[0].value.as< std::string > ()));
ctx.expression.push_back(hex);
}
-#line 601 "parser.cc" // lalr1.cc:859
+#line 592 "parser.cc" // lalr1.cc:859
break;
case 6:
-#line 86 "parser.yy" // lalr1.cc:859
+#line 81 "parser.yy" // lalr1.cc:859
{
TokenPtr opt(new TokenOption(yystack_[1].value.as< uint16_t > ()));
ctx.expression.push_back(opt);
}
-#line 610 "parser.cc" // lalr1.cc:859
+#line 601 "parser.cc" // lalr1.cc:859
break;
case 7:
-#line 90 "parser.yy" // lalr1.cc:859
+#line 85 "parser.yy" // lalr1.cc:859
{
TokenPtr sub(new TokenSubstring());
ctx.expression.push_back(sub);
}
-#line 619 "parser.cc" // lalr1.cc:859
+#line 610 "parser.cc" // lalr1.cc:859
break;
-#line 623 "parser.cc" // lalr1.cc:859
+#line 614 "parser.cc" // lalr1.cc:859
default:
break;
}
const unsigned char
EvalParser::yyrline_[] =
{
- 0, 70, 70, 74, 78, 82, 86, 90
+ 0, 65, 65, 69, 73, 77, 81, 85
};
// Print the state stack on the debug stream.
#line 21 "parser.yy" // lalr1.cc:1167
} } // isc::eval
-#line 993 "parser.cc" // lalr1.cc:1167
-#line 96 "parser.yy" // lalr1.cc:1168
+#line 984 "parser.cc" // lalr1.cc:1167
+#line 91 "parser.yy" // lalr1.cc:1168
void
isc::eval::EvalParser::error(const location_type& loc,
// The parsing context.
%param { EvalContext& ctx }
%locations
-%initial-action
-{
- // Initialize the initial location.
- @$.begin.filename = @$.end.filename = &ctx.file_;
-};
%define parse.trace
%define parse.error verbose
%code
namespace {
+/// @brief Test class for testing EvalContext aka class test parsing
class EvalContextTest : public ::testing::Test {
public:
+ /// @brief checks if the given token is a string with the expected value
void checkTokenString(const TokenPtr& token, const std::string& expected) {
ASSERT_TRUE(token);
boost::shared_ptr<TokenString> str =
EXPECT_EQ(expected, values.top());
}
+ /// @brief checks if the given token is a hex string with the expected value
void checkTokenHexString(const TokenPtr& token,
const std::string& expected) {
ASSERT_TRUE(token);
EXPECT_EQ(expected, values.top());
}
+ /// @brief checks if the given token is an equal operator
void checkTokenEq(const TokenPtr& token) {
ASSERT_TRUE(token);
boost::shared_ptr<TokenEqual> eq =
EXPECT_TRUE(eq);
}
- void checkTokenOption(const TokenPtr& token, uint16_t expected_option) {
+ /// @brief checks if the given token is an option with the expected code
+ void checkTokenOption(const TokenPtr& token, uint16_t expected_code) {
ASSERT_TRUE(token);
boost::shared_ptr<TokenOption> opt =
boost::dynamic_pointer_cast<TokenOption>(token);
ASSERT_TRUE(opt);
- EXPECT_EQ(expected_option, opt->getCode());
+ EXPECT_EQ(expected_code, opt->getCode());
}
+ /// @brief checks if the given token is a substring operator
void checkTokenSubstring(const TokenPtr& token) {
ASSERT_TRUE(token);
boost::shared_ptr<TokenSubstring> sub =
EXPECT_TRUE(sub);
}
+ /// @brief checks if the given expression raises the expected message
+ /// when it is parsed.
+ void checkError(const string& expr, const string& msg) {
+ EvalContext eval;
+ 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
};
+// Test the parsing of a basic expression
TEST_F(EvalContextTest, basic) {
EvalContext tmp;
EXPECT_TRUE(parsed_);
}
+// Test the parsing of a string terminal
TEST_F(EvalContextTest, string) {
EvalContext eval;
checkTokenString(tmp, "foo");
}
+// Test the parsing of a hexstring terminal
TEST_F(EvalContextTest, hexstring) {
EvalContext eval;
checkTokenHexString(tmp, "foo");
}
+// Test the parsing of an equal expression
TEST_F(EvalContextTest, equal) {
EvalContext eval;
checkTokenEq(tmp3);
}
+// Test the parsing of an option terminal
TEST_F(EvalContextTest, option) {
EvalContext eval;
checkTokenOption(eval.expression.at(0), 123);
}
+// Test the parsing of a substring expression
TEST_F(EvalContextTest, substring) {
EvalContext eval;
checkTokenSubstring(tmp4);
}
+// Test some scanner error cases
+TEST_F(EvalContextTest, scanErrors) {
+ checkError("'", "<string>:1.1: Invalid character: '");
+ checkError("'\''", "<string>:1.3: Invalid character: '");
+ 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("foo", "<string>:1.1: Invalid character: f");
+ checkError(" bar", "<string>:1.2: Invalid character: b");
+}
+
+// Tests some scanner/parser error cases
+TEST_F(EvalContextTest, scanParseErrors) {
+ checkError("", "<string>:1.1: syntax error, unexpected end of file, "
+ "expecting option or substring or constant string or "
+ "constant hexstring");
+ checkError("0x", "<string>:1.1: syntax error, unexpected option code, "
+ "expecting option or substring or constant string or "
+ "constant hexstring");
+ checkError("===", "<string>:1.1-2: syntax error, unexpected ==, "
+ "expecting option or substring or constant string "
+ "or constant hexstring");
+}
+
};