mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Introduce hex literals (#832)
* Introduce hex keyword token * Support hex literals * Include tests for hex literals * Document hex literals
This commit is contained in:
parent
970260bf0f
commit
ec3298535e
@ -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.
|
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
|
.. index:: enum
|
||||||
|
|
||||||
.. _enums:
|
.. _enums:
|
||||||
|
@ -591,7 +591,23 @@ void Scanner::scanToken()
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (isIdentifierStart(m_char))
|
if (isIdentifierStart(m_char))
|
||||||
|
{
|
||||||
tie(token, m, n) = scanIdentifierOrKeyword();
|
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))
|
else if (isDecimalDigit(m_char))
|
||||||
token = scanNumber();
|
token = scanNumber();
|
||||||
else if (skipWhitespace())
|
else if (skipWhitespace())
|
||||||
@ -684,6 +700,25 @@ Token::Value Scanner::scanString()
|
|||||||
return Token::StringLiteral;
|
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()
|
void Scanner::scanDecimalDigits()
|
||||||
{
|
{
|
||||||
while (isDecimalDigit(m_char))
|
while (isDecimalDigit(m_char))
|
||||||
|
@ -203,6 +203,7 @@ private:
|
|||||||
std::tuple<Token::Value, unsigned, unsigned> scanIdentifierOrKeyword();
|
std::tuple<Token::Value, unsigned, unsigned> scanIdentifierOrKeyword();
|
||||||
|
|
||||||
Token::Value scanString();
|
Token::Value scanString();
|
||||||
|
Token::Value scanHexString();
|
||||||
Token::Value scanSingleLineDocComment();
|
Token::Value scanSingleLineDocComment();
|
||||||
Token::Value scanMultiLineDocComment();
|
Token::Value scanMultiLineDocComment();
|
||||||
/// Scans a slash '/' and depending on the characters returns the appropriate token
|
/// Scans a slash '/' and depending on the characters returns the appropriate token
|
||||||
|
@ -155,6 +155,7 @@ namespace solidity
|
|||||||
K(External, "external", 0) \
|
K(External, "external", 0) \
|
||||||
K(For, "for", 0) \
|
K(For, "for", 0) \
|
||||||
K(Function, "function", 0) \
|
K(Function, "function", 0) \
|
||||||
|
K(Hex, "hex", 0) \
|
||||||
K(If, "if", 0) \
|
K(If, "if", 0) \
|
||||||
K(Indexed, "indexed", 0) \
|
K(Indexed, "indexed", 0) \
|
||||||
K(Internal, "internal", 0) \
|
K(Internal, "internal", 0) \
|
||||||
|
@ -324,6 +324,42 @@ BOOST_AUTO_TEST_CASE(invalid_short_unicode_string_escape)
|
|||||||
BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal);
|
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()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user