From 070dc7605040e22484bb43673d75f5ec51a2865e Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Sun, 28 Sep 2014 18:27:47 -0700 Subject: [PATCH] Generate correct C literals for non-ascii characters --- spec/compiler/util/string_helpers_spec.cc | 27 +++++++++++++++++++++++ src/compiler/rules/character_range.cc | 23 +++---------------- src/compiler/util/string_helpers.cc | 9 ++++---- src/compiler/util/string_helpers.h | 2 +- 4 files changed, 35 insertions(+), 26 deletions(-) create mode 100644 spec/compiler/util/string_helpers_spec.cc diff --git a/spec/compiler/util/string_helpers_spec.cc b/spec/compiler/util/string_helpers_spec.cc new file mode 100644 index 00000000..56d57dec --- /dev/null +++ b/spec/compiler/util/string_helpers_spec.cc @@ -0,0 +1,27 @@ +#include "compiler/compiler_spec_helper.h" +#include "compiler/util/string_helpers.h" + +using namespace rules; +using util::escape_char; + +START_TEST + +describe("escape_char", []() { + it("returns ascii characters as strings", [&]() { + AssertThat(escape_char('x'), Equals("'x'")); + }); + + it("escapes special characters with backslashes", [&]() { + AssertThat(escape_char('\\'), Equals("'\\\\'")); + AssertThat(escape_char('\n'), Equals("'\\n'")); + AssertThat(escape_char('\t'), Equals("'\\t'")); + AssertThat(escape_char('\r'), Equals("'\\r'")); + AssertThat(escape_char('\''), Equals("'\\''")); + }); + + it("prints non-ascii characters as numbers", [&]() { + AssertThat(escape_char(256), Equals("256")); + }); +}); + +END_TEST diff --git a/src/compiler/rules/character_range.cc b/src/compiler/rules/character_range.cc index ecf32eea..fb99d0bb 100644 --- a/src/compiler/rules/character_range.cc +++ b/src/compiler/rules/character_range.cc @@ -1,4 +1,5 @@ #include "compiler/rules/character_range.h" +#include "compiler/util/string_helpers.h" #include #include @@ -27,29 +28,11 @@ bool CharacterRange::operator<(const CharacterRange &other) const { return false; } -string escape_character(uint32_t input) { - if (input >= 255) - return to_string(input); - - switch (input) { - case '\0': - return "\\0"; - case '\n': - return "\\n"; - case '\r': - return "\\r"; - case '\t': - return "\\t"; - default: - return string() + static_cast(input); - } -} - string CharacterRange::to_string() const { if (min == max) - return escape_character(min); + return util::escape_char(min); else - return string() + escape_character(min) + "-" + escape_character(max); + return string() + util::escape_char(min) + "-" + util::escape_char(max); } ostream &operator<<(ostream &stream, const CharacterRange &range) { diff --git a/src/compiler/util/string_helpers.cc b/src/compiler/util/string_helpers.cc index 0c6a487a..df1f00b4 100644 --- a/src/compiler/util/string_helpers.cc +++ b/src/compiler/util/string_helpers.cc @@ -7,6 +7,7 @@ namespace util { using std::string; using std::vector; using std::set; +using std::to_string; void str_replace(string *input, const string &search, const string &replace) { size_t pos = 0; @@ -26,7 +27,7 @@ string escape_string(string input) { return input; } -string escape_char(char character) { +string escape_char(uint32_t character) { switch (character) { case '"': return "'\\\"'"; @@ -42,11 +43,9 @@ string escape_char(char character) { return "'\\\\'"; default: if (character >= ' ' && character <= '~') { - return string("'") + character + "'"; + return string("'") + static_cast(character) + "'"; } else { - char buffer[5]; - snprintf(buffer, sizeof(buffer), "%d", static_cast(character)); - return string(buffer); + return to_string(character); } } } diff --git a/src/compiler/util/string_helpers.h b/src/compiler/util/string_helpers.h index 89d18d99..f9fed146 100644 --- a/src/compiler/util/string_helpers.h +++ b/src/compiler/util/string_helpers.h @@ -11,7 +11,7 @@ namespace util { void str_replace(std::string *input, const std::string &search, const std::string &replace); std::string escape_string(std::string input); -std::string escape_char(char character); +std::string escape_char(uint32_t character); } // namespace util } // namespace tree_sitter