aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/types.rst9
-rw-r--r--libsolidity/parsing/Scanner.cpp35
-rw-r--r--libsolidity/parsing/Scanner.h1
-rw-r--r--libsolidity/parsing/Token.h1
-rw-r--r--test/libsolidity/SolidityScanner.cpp36
5 files changed, 82 insertions, 0 deletions
diff --git a/docs/types.rst b/docs/types.rst
index 12a35aaf..31f6b53d 100644
--- a/docs/types.rst
+++ b/docs/types.rst
@@ -218,6 +218,15 @@ String literals are written with either double or single-quotes (``"foo"`` or ``
String literals support escape characters, such as ``\n``, ``\xNN`` and ``\uNNNN``. ``\xNN`` takes a hex value and inserts the appropriate byte, while ``\uNNNN`` takes a Unicode codepoint and inserts an UTF-8 sequence.
+.. index:: literal, bytes
+
+Hexadecimal Literals
+--------------------
+
+Hexademical Literals are prefixed with the keyword ``hex`` and are enclosed in double or single-quotes (``hex"001122FF"``). Their content must be a hexadecimal string and their value will be the binary representation of those values.
+
+Hexademical Literals behave like String Literals and have the same convertibility restrictions.
+
.. index:: enum
.. _enums:
diff --git a/libsolidity/parsing/Scanner.cpp b/libsolidity/parsing/Scanner.cpp
index d730210a..603f3e42 100644
--- a/libsolidity/parsing/Scanner.cpp
+++ b/libsolidity/parsing/Scanner.cpp
@@ -591,7 +591,23 @@ void Scanner::scanToken()
break;
default:
if (isIdentifierStart(m_char))
+ {
tie(token, m, n) = scanIdentifierOrKeyword();
+
+ // Special case for hexademical literals
+ if (token == Token::Hex)
+ {
+ // reset
+ m = 0;
+ n = 0;
+
+ // Special quoted hex string must follow
+ if (m_char == '"' || m_char == '\'')
+ token = scanHexString();
+ else
+ token = Token::Illegal;
+ }
+ }
else if (isDecimalDigit(m_char))
token = scanNumber();
else if (skipWhitespace())
@@ -684,6 +700,25 @@ Token::Value Scanner::scanString()
return Token::StringLiteral;
}
+Token::Value Scanner::scanHexString()
+{
+ char const quote = m_char;
+ advance(); // consume quote
+ LiteralScope literal(this, LITERAL_TYPE_STRING);
+ while (m_char != quote && !isSourcePastEndOfInput() && !isLineTerminator(m_char))
+ {
+ char c = m_char;
+ if (!scanHexByte(c))
+ return Token::Illegal;
+ addLiteralChar(c);
+ }
+ if (m_char != quote)
+ return Token::Illegal;
+ literal.complete();
+ advance(); // consume quote
+ return Token::StringLiteral;
+}
+
void Scanner::scanDecimalDigits()
{
while (isDecimalDigit(m_char))
diff --git a/libsolidity/parsing/Scanner.h b/libsolidity/parsing/Scanner.h
index 708adf8f..36cba112 100644
--- a/libsolidity/parsing/Scanner.h
+++ b/libsolidity/parsing/Scanner.h
@@ -203,6 +203,7 @@ private:
std::tuple<Token::Value, unsigned, unsigned> scanIdentifierOrKeyword();
Token::Value scanString();
+ Token::Value scanHexString();
Token::Value scanSingleLineDocComment();
Token::Value scanMultiLineDocComment();
/// Scans a slash '/' and depending on the characters returns the appropriate token
diff --git a/libsolidity/parsing/Token.h b/libsolidity/parsing/Token.h
index f4de74c7..007baef4 100644
--- a/libsolidity/parsing/Token.h
+++ b/libsolidity/parsing/Token.h
@@ -155,6 +155,7 @@ namespace solidity
K(External, "external", 0) \
K(For, "for", 0) \
K(Function, "function", 0) \
+ K(Hex, "hex", 0) \
K(If, "if", 0) \
K(Indexed, "indexed", 0) \
K(Internal, "internal", 0) \
diff --git a/test/libsolidity/SolidityScanner.cpp b/test/libsolidity/SolidityScanner.cpp
index 624614d2..31b75f25 100644
--- a/test/libsolidity/SolidityScanner.cpp
+++ b/test/libsolidity/SolidityScanner.cpp
@@ -324,6 +324,42 @@ BOOST_AUTO_TEST_CASE(invalid_short_unicode_string_escape)
BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal);
}
+BOOST_AUTO_TEST_CASE(valid_hex_literal)
+{
+ Scanner scanner(CharStream("{ hex\"00112233FF\""));
+ BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
+ BOOST_CHECK_EQUAL(scanner.next(), Token::StringLiteral);
+ BOOST_CHECK_EQUAL(scanner.currentLiteral(), std::string("\x00\x11\x22\x33\xFF", 5));
+}
+
+BOOST_AUTO_TEST_CASE(invalid_short_hex_literal)
+{
+ Scanner scanner(CharStream("{ hex\"00112233F\""));
+ BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
+ BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal);
+}
+
+BOOST_AUTO_TEST_CASE(invalid_hex_literal_with_space)
+{
+ Scanner scanner(CharStream("{ hex\"00112233FF \""));
+ BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
+ BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal);
+}
+
+BOOST_AUTO_TEST_CASE(invalid_hex_literal_with_wrong_quotes)
+{
+ Scanner scanner(CharStream("{ hex\"00112233FF'"));
+ BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
+ BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal);
+}
+
+BOOST_AUTO_TEST_CASE(invalid_hex_literal_nonhex_string)
+{
+ Scanner scanner(CharStream("{ hex\"hello\""));
+ BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
+ BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal);
+}
+
BOOST_AUTO_TEST_SUITE_END()