From: Francis Dupont Date: Thu, 29 Apr 2021 08:30:08 +0000 (+0200) Subject: [#1824] Checkpoint: added ( string ) X-Git-Tag: Kea-1.9.8~164 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a8a00df956c09049f48315285404031ef2bff7bb;p=thirdparty%2Fkea.git [#1824] Checkpoint: added ( string ) --- diff --git a/src/lib/eval/eval.dox b/src/lib/eval/eval.dox index df1c93f4b7..b45b9a2d66 100644 --- a/src/lib/eval/eval.dox +++ b/src/lib/eval/eval.dox @@ -162,7 +162,7 @@ instantiated with the appropriate value and put onto the expression vector. concatenate two other tokens. - isc::dhcp::TokenIfElse -- represents the ifelse(cond, iftrue, ifelse) operator. - isc::dhcp::TokenToHexString -- represents the hexstring operator which - converts a binary value to its hexadecimal string representation. + converts a binary value to its hexadecimal string representation. - isc::dhcp::TokenNot -- the logical not operator. - isc::dhcp::TokenAnd -- the logical and (strict) operator. - isc::dhcp::TokenOr -- the logical or (strict) operator (strict means diff --git a/src/lib/eval/parser.yy b/src/lib/eval/parser.yy index 338cc1ee6b..c8314aa5f8 100644 --- a/src/lib/eval/parser.yy +++ b/src/lib/eval/parser.yy @@ -432,6 +432,7 @@ string_expr : STRING TokenPtr integer(new TokenInteger($1)); ctx.expression.push_back(integer); } + | "(" string_expr ")" ; integer_expr : INTEGER diff --git a/src/lib/eval/tests/context_unittest.cc b/src/lib/eval/tests/context_unittest.cc index 8b30b4aec9..4c6061856f 100644 --- a/src/lib/eval/tests/context_unittest.cc +++ b/src/lib/eval/tests/context_unittest.cc @@ -1347,6 +1347,7 @@ TEST_F(EvalContextTest, plus) { TEST_F(EvalContextTest, assocPlus) { EvalContext eval(Option::V4); + // Operator '+' is (left) associative EXPECT_NO_THROW(parsed_ = eval.parseString("'a' + 'b' + 'c' == 'abc'")); @@ -1365,6 +1366,28 @@ TEST_F(EvalContextTest, assocPlus) { checkTokenConcat(tmp5); } +// Test the parsing of plus expressions with enforced associativity +TEST_F(EvalContextTest, assocRightPlus) { + EvalContext eval(Option::V4); + + EXPECT_NO_THROW(parsed_ = + eval.parseString("'a' + ('b' + 'c') == 'abc'")); + + ASSERT_EQ(7, eval.expression.size()); + + TokenPtr tmp1 = eval.expression.at(0); + TokenPtr tmp2 = eval.expression.at(1); + TokenPtr tmp3 = eval.expression.at(2); + TokenPtr tmp4 = eval.expression.at(3); + TokenPtr tmp5 = eval.expression.at(4); + + checkTokenString(tmp1, "a"); + checkTokenString(tmp2, "b"); + checkTokenString(tmp3, "c"); + checkTokenConcat(tmp4); + checkTokenConcat(tmp5); +} + // Test the parsing of an ifelse expression TEST_F(EvalContextTest, ifElse) { EvalContext eval(Option::V4); @@ -1433,10 +1456,11 @@ TEST_F(EvalContextTest, scanParseErrors) { // This one is a little bid odd. This is a truncated address, so it's not // recognized as an address. Instead, the first token (10) is recognized as - // an integer. The only thing we can do with integers right now is test - // for equality, so the only possible next token is ==. There's a dot - // instead, so an error is reported. - checkError("10.0.1", ":1.3: syntax error, unexpected ., expecting =="); + // an integer. The only thing we can do with integers right now is to + // apply equality or concat operators, so the only possible next token + // are == and +. There's a dot instead, so an error is reported. + checkError("10.0.1", ":1.3: syntax error, unexpected ., " + "expecting == or +"); checkError("10.256.0.1", ":1.1-10: Failed to convert 10.256.0.1 to " @@ -1479,9 +1503,9 @@ TEST_F(EvalContextTest, scanParseErrors) { TEST_F(EvalContextTest, parseErrors) { checkError("'foo''bar'", ":1.6-10: syntax error, unexpected constant string, " - "expecting =="); + "expecting == or +"); checkError("'foo' (", - ":1.7: syntax error, unexpected (, expecting =="); + ":1.7: syntax error, unexpected (, expecting == or +"); checkError("== 'ab'", ":1.1-2: syntax error, unexpected =="); checkError("'foo' ==", ":1.9: syntax error, unexpected end of file"); @@ -1495,30 +1519,32 @@ TEST_F(EvalContextTest, parseErrors) { ":1.4: syntax error, unexpected end of file"); checkError("not 'foo'", ":1.10: syntax error, unexpected end of file, " - "expecting =="); + "expecting == or +"); checkError("not()", ":1.5: syntax error, unexpected )"); checkError("(not('foo' 'bar')", ":1.12-16: syntax error, unexpected constant string, " - "expecting =="); + "expecting ) or == or +"); checkError("and", ":1.1-3: syntax error, unexpected and"); checkError("'foo' and", - ":1.7-9: syntax error, unexpected and, expecting =="); + ":1.7-9: syntax error, unexpected and, " + "expecting == or +"); checkError("'foo' == 'bar' and", ":1.19: syntax error, unexpected end of file"); checkError("'foo' == 'bar' and ''", ":1.22: syntax error, unexpected end of file, " - "expecting =="); + "expecting == or +"); checkError("or", ":1.1-2: syntax error, unexpected or"); checkError("'foo' or", - ":1.7-8: syntax error, unexpected or, expecting =="); + ":1.7-8: syntax error, unexpected or, " + "expecting == or +"); checkError("'foo' == 'bar' or", ":1.18: syntax error, unexpected end of file"); checkError("'foo' == 'bar' or ''", ":1.21: syntax error, unexpected end of file, " - "expecting =="); + "expecting == or +"); checkError("option 'ab'", ":1.8-11: syntax error, unexpected " "constant string, expecting ["); @@ -1541,7 +1567,8 @@ TEST_F(EvalContextTest, parseErrors) { ":1.19-20: syntax error, unexpected ==, " "expecting end of file"); checkError("substring('foobar') == 'f'", - ":1.19: syntax error, unexpected ), expecting \",\""); + ":1.19: syntax error, unexpected ), " + "expecting \",\" or +"); checkError("substring('foobar',3) == 'bar'", ":1.21: syntax error, unexpected ), expecting \",\""); checkError("substring('foobar','3',3) == 'bar'", @@ -1557,26 +1584,28 @@ TEST_F(EvalContextTest, parseErrors) { checkError(long_text, ":1.65568: Invalid character: '"); checkError("concat('foobar') == 'f'", - ":1.16: syntax error, unexpected ), expecting \",\""); + ":1.16: syntax error, unexpected ), " + "expecting \",\" or +"); checkError("concat('foo','bar','') == 'foobar'", - ":1.19: syntax error, unexpected \",\", expecting )"); + ":1.19: syntax error, unexpected \",\", " + "expecting ) or +"); checkError("ifelse('foo'=='bar','foo')", - ":1.26: syntax error, unexpected ), expecting \",\""); + ":1.26: syntax error, unexpected ), " + "expecting \",\" or +"); checkError("ifelse('foo'=='bar','foo','bar','')", - ":1.32: syntax error, unexpected \",\", expecting )"); - checkError("+ 'a' = 'a'", - "to fill: pre plus"); - checkError("'a' + == 'a'", - "to fill: post plus"); + ":1.32: syntax error, unexpected \",\", " + "expecting ) or +"); + checkError("+ 'a' = 'a'", ":1.1: syntax error, unexpected +"); + checkError("'a' + == 'a'", ":1.7-8: syntax error, unexpected =="); checkError("'a' ++ 'b' == 'ab'", - "to fill double plus"); + ":1.6: syntax error, unexpected +"); } // Tests some type error cases TEST_F(EvalContextTest, typeErrors) { checkError("'foobar'", ":1.9: syntax error, unexpected end of file, " - "expecting =="); + "expecting == or +"); checkError("substring('foobar',all,1) == 'foo'", ":1.20-22: syntax error, unexpected all, " "expecting integer"); @@ -1595,19 +1624,23 @@ TEST_F(EvalContextTest, typeErrors) { "expecting end of file"); checkError("not 'true'", ":1.11: syntax error, unexpected end of file, " - "expecting =="); + "expecting == or +"); checkError("'true' and 'false'", - ":1.8-10: syntax error, unexpected and, expecting =="); + ":1.8-10: syntax error, unexpected and, " + "expecting == or +"); checkError("'true' or 'false'", - ":1.8-9: syntax error, unexpected or, expecting =="); + ":1.8-9: syntax error, unexpected or, " + "expecting == or +"); // Ifelse requires a boolean condition and string branches. checkError("ifelse('foobar','foo','bar')", - ":1.16: syntax error, unexpected \",\", expecting =="); + ":1.16: syntax error, unexpected \",\", " + "expecting == or +"); checkError("ifelse('foo'=='bar','foo'=='foo','bar')", ":1.26-27: syntax error, unexpected ==, " - "expecting \",\""); + "expecting \",\" or +"); checkError("ifelse('foo'=='bar','foo','bar'=='bar')", - ":1.32-33: syntax error, unexpected ==, expecting )"); + ":1.32-33: syntax error, unexpected ==, " + "expecting ) or +"); // Member uses quotes around the client class name. checkError("member(foo)", ":1.8: Invalid character: f");