From cbbe1593bb0893654bd71e611ca610df03bac768 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Mon, 20 Jul 2026 12:26:29 +0200 Subject: Add newlines a tabs to supported string characters --- boot/driver.cc | 25 ++++++++++++++++++++++++- boot/lexer.ll | 22 +++++++++++++++++----- include/elna/boot/driver.h | 7 +++++++ 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/boot/driver.cc b/boot/driver.cc index 374bcc9..24a11fa 100644 --- a/boot/driver.cc +++ b/boot/driver.cc @@ -66,6 +66,29 @@ namespace elna::boot } } + void normalize_newlines(std::string& string) + { + std::string result; + auto length = string.size(); + + for (std::size_t i = 0; i < length; ++i) + { + if (string[i] == '\r') + { + if (i + 1 < length && string[i + 1] == '\n') + { + ++i; // Skip \n in \r\n pairs. + } + result.push_back('\n'); + } + else + { + result.push_back(string[i]); + } + } + string = std::move(result); + } + std::optional escape_string(const char *escape) { std::string result; @@ -73,7 +96,7 @@ namespace elna::boot while (*current_position != '\0') { - if (*current_position == '\\' && *(current_position + 1) == 'x') + if (*current_position == '\\' && (*(current_position + 1) == 'x' || *(current_position + 1) == 'X')) { current_position += 2; diff --git a/boot/lexer.ll b/boot/lexer.ll index faae3d7..e84af85 100644 --- a/boot/lexer.ll +++ b/boot/lexer.ll @@ -17,7 +17,19 @@ along with GCC; see the file COPYING3. If not see %{ #define YY_NO_UNISTD_H -#define YY_USER_ACTION this->location.columns(yyleng); +#define YY_USER_ACTION do { \ + for (int i = 0; i < yyleng; i++) \ + { \ + if (yytext[i] == '\n') \ + { \ + this->location.lines(1); \ + } \ + else \ + { \ + this->location.columns(1); \ + } \ + } \ +} while (0); #include #include "parser.hh" @@ -47,7 +59,6 @@ BIGIT [01] [^*\n]+ ; /* Eat comment in chunks. */ \* ; /* Eat the lone star. */ \n+ { - this->location.lines(yyleng); this->location.step(); } } @@ -56,7 +67,6 @@ BIGIT [01] this->location.step(); } \n+ { - this->location.lines(yyleng); } if { return yy::parser::make_IF(this->location); @@ -220,20 +230,22 @@ of { return yy::parser::make_FLOAT(result, this->location); } } -'[[:print:]]+' { +'([[:print:]]{-}['\\]|[[:blank:]]|\n|\r|\\.|\\\n)+' { std::optional result = escape_string(yytext); if (!result.has_value() || result.value().size() != 1) { REJECT; } + normalize_newlines(result.value()); return yy::parser::make_CHARACTER(result.value(), this->location); } -\"[[:print:]]*\" { +\"([[:print:]]{-}[\"\\]|[[:blank:]]|\n|\r|\\.|\\\n)*\" { std::optional result = escape_string(yytext); if (!result.has_value()) { REJECT; } + normalize_newlines(result.value()); return yy::parser::make_STRING(result.value(), this->location); } \( { diff --git a/include/elna/boot/driver.h b/include/elna/boot/driver.h index ef5be81..34a8c99 100644 --- a/include/elna/boot/driver.h +++ b/include/elna/boot/driver.h @@ -46,5 +46,12 @@ namespace elna::boot constexpr char escape_invalid_char = '\xff'; char escape_char(char escape); + /** + * Replaces both \r\n sequences and lone \r characters with \n. + * Modifies the original input. + * + * \param string Text to normalize. + */ + void normalize_newlines(std::string& string); std::optional escape_string(const char *escape); } -- cgit v1.2.3