diff --git a/rcl/include/rcl/lexer.h b/rcl/include/rcl/lexer.h
index 032bf8c..3b66c13 100644
--- a/rcl/include/rcl/lexer.h
+++ b/rcl/include/rcl/lexer.h
@@ -86,6 +86,7 @@ typedef enum rcl_lexeme_t
* This function analyzes a string to see if it starts with a valid lexeme.
* If the string does not begin with a valid lexeme then lexeme will be RCL_LEXEME_NONE, and the
* length will be set to include the character that made it impossible.
+ * It will never be longer than the length of the string.
* If the first character is '\0' then lexeme will be RCL_LEXEME_EOF.
*
*
diff --git a/rcl/src/rcl/lexer.c b/rcl/src/rcl/lexer.c
index 6307d52..7aace4f 100644
--- a/rcl/src/rcl/lexer.c
+++ b/rcl/src/rcl/lexer.c
@@ -650,10 +650,11 @@ rcl_lexer_analyze(
movement = state->else_movement;
}
- // Move the lexer to another character in the string
if (0u == movement) {
- // Go forwards 1 char
- ++(*length);
+ if ('\0' != current_char) {
+ // Go forwards 1 char as long as the end hasn't been reached
+ ++(*length);
+ }
} else {
// Go backwards N chars
if (movement - 1u > *length) {
diff --git a/rcl/src/rcl/lexer_lookahead.c b/rcl/src/rcl/lexer_lookahead.c
index a5b2589..0dedb8e 100644
--- a/rcl/src/rcl/lexer_lookahead.c
+++ b/rcl/src/rcl/lexer_lookahead.c
@@ -141,6 +141,12 @@ rcl_lexer_lookahead2_peek2(
}
RCL_CHECK_ARGUMENT_FOR_NULL(next_type2, RCL_RET_INVALID_ARGUMENT);
+ if (RCL_LEXEME_NONE == *next_type1 || RCL_LEXEME_EOF == *next_type1) {
+ // No need to peek further
+ *next_type2 = *next_type1;
+ return ret;
+ }
+
size_t length;
if (buffer->impl->text_idx >= buffer->impl->end[1]) {
diff --git a/rcl/test/rcl/test_lexer.cpp b/rcl/test/rcl/test_lexer.cpp
index ee2dc1f..d231a68 100644
--- a/rcl/test/rcl/test_lexer.cpp
+++ b/rcl/test/rcl/test_lexer.cpp
@@ -45,7 +45,8 @@ public:
rcl_ret_t ret = rcl_lexer_analyze(text, &actual_lexeme, &length); \
ASSERT_EQ(RCL_RET_OK, ret); \
EXPECT_EQ(expected_lexeme, actual_lexeme); \
- std::string actual_text(text, length); \
+ std::string actual_text(text, 0u, length); \
+ EXPECT_EQ(length, actual_text.size()); \
EXPECT_STREQ(expected_text, actual_text.c_str()); \
} while (false)
diff --git a/rcl/test/rcl/test_lexer_lookahead.cpp b/rcl/test/rcl/test_lexer_lookahead.cpp
index 0fe8ff0..e3781cd 100644
--- a/rcl/test/rcl/test_lexer_lookahead.cpp
+++ b/rcl/test/rcl/test_lexer_lookahead.cpp
@@ -118,6 +118,51 @@ TEST_F(CLASSNAME(TestLexerLookaheadFixture, RMW_IMPLEMENTATION), test_peek2)
EXPECT_EQ(RCL_LEXEME_FORWARD_SLASH, lexeme2);
}
+TEST_F(CLASSNAME(TestLexerLookaheadFixture, RMW_IMPLEMENTATION), test_peek2_no_lexeme)
+{
+ rcl_ret_t ret;
+ rcl_lexer_lookahead2_t buffer;
+ SCOPE_LOOKAHEAD2(buffer, "~foo");
+
+ rcl_lexeme_t lexeme1 = RCL_LEXEME_NONE;
+ rcl_lexeme_t lexeme2 = RCL_LEXEME_NONE;
+
+ ret = rcl_lexer_lookahead2_peek2(&buffer, &lexeme1, &lexeme2);
+ EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
+ EXPECT_EQ(RCL_LEXEME_NONE, lexeme1);
+ EXPECT_EQ(RCL_LEXEME_NONE, lexeme2);
+}
+
+TEST_F(CLASSNAME(TestLexerLookaheadFixture, RMW_IMPLEMENTATION), test_peek2_no_lexeme_eof)
+{
+ rcl_ret_t ret;
+ rcl_lexer_lookahead2_t buffer;
+ SCOPE_LOOKAHEAD2(buffer, "~");
+
+ rcl_lexeme_t lexeme1 = RCL_LEXEME_NONE;
+ rcl_lexeme_t lexeme2 = RCL_LEXEME_NONE;
+
+ ret = rcl_lexer_lookahead2_peek2(&buffer, &lexeme1, &lexeme2);
+ EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
+ EXPECT_EQ(RCL_LEXEME_NONE, lexeme1);
+ EXPECT_EQ(RCL_LEXEME_NONE, lexeme2);
+}
+
+TEST_F(CLASSNAME(TestLexerLookaheadFixture, RMW_IMPLEMENTATION), test_peek2_eof)
+{
+ rcl_ret_t ret;
+ rcl_lexer_lookahead2_t buffer;
+ SCOPE_LOOKAHEAD2(buffer, "");
+
+ rcl_lexeme_t lexeme1 = RCL_LEXEME_NONE;
+ rcl_lexeme_t lexeme2 = RCL_LEXEME_NONE;
+
+ ret = rcl_lexer_lookahead2_peek2(&buffer, &lexeme1, &lexeme2);
+ EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
+ EXPECT_EQ(RCL_LEXEME_EOF, lexeme1);
+ EXPECT_EQ(RCL_LEXEME_EOF, lexeme2);
+}
+
TEST_F(CLASSNAME(TestLexerLookaheadFixture, RMW_IMPLEMENTATION), test_eof)
{
rcl_ret_t ret;