diff options
author | Christian <c@ethdev.com> | 2014-10-16 20:08:54 +0800 |
---|---|---|
committer | Christian <c@ethdev.com> | 2014-10-16 20:08:54 +0800 |
commit | 8a506b505f4725e8a76bbad8399562099e4510c3 (patch) | |
tree | df14374ccbe42eef8ccb162b15c6742b4a662e9b /Scanner.cpp | |
parent | 4ece1ba1d327175aa7cad9a01ee35b0de2eb861b (diff) | |
download | dexon-solidity-8a506b505f4725e8a76bbad8399562099e4510c3.tar.gz dexon-solidity-8a506b505f4725e8a76bbad8399562099e4510c3.tar.zst dexon-solidity-8a506b505f4725e8a76bbad8399562099e4510c3.zip |
Corrected coding style.
Diffstat (limited to 'Scanner.cpp')
-rw-r--r-- | Scanner.cpp | 911 |
1 files changed, 444 insertions, 467 deletions
diff --git a/Scanner.cpp b/Scanner.cpp index 334da8e7..c2875c9c 100644 --- a/Scanner.cpp +++ b/Scanner.cpp @@ -45,35 +45,47 @@ #include <libsolidity/Scanner.h> -namespace dev { -namespace solidity { +namespace dev +{ +namespace solidity +{ -namespace { - bool IsDecimalDigit(char c) { - return '0' <= c && c <= '9'; - } - bool IsHexDigit(char c) { - return IsDecimalDigit(c) - || ('a' <= c && c <= 'f') - || ('A' <= c && c <= 'F'); - } - bool IsLineTerminator(char c) { return c == '\n'; } - bool IsWhiteSpace(char c) { - return c == ' ' || c == '\n' || c == '\t'; - } - bool IsIdentifierStart(char c) { - return c == '_' || c == '$' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); - } - bool IsIdentifierPart(char c) { - return IsIdentifierStart(c) || IsDecimalDigit(c); - } +namespace +{ +bool IsDecimalDigit(char c) +{ + return '0' <= c && c <= '9'; +} +bool IsHexDigit(char c) +{ + return IsDecimalDigit(c) + || ('a' <= c && c <= 'f') + || ('A' <= c && c <= 'F'); +} +bool IsLineTerminator(char c) +{ + return c == '\n'; +} +bool IsWhiteSpace(char c) +{ + return c == ' ' || c == '\n' || c == '\t'; +} +bool IsIdentifierStart(char c) +{ + return c == '_' || c == '$' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); +} +bool IsIdentifierPart(char c) +{ + return IsIdentifierStart(c) || IsDecimalDigit(c); +} - int HexValue(char c) { - if (c >= '0' && c <= '9') return c - '0'; - else if (c >= 'a' && c <= 'f') return c - 'a' + 10; - else if (c >= 'A' && c <= 'F') return c - 'A' + 10; - else return -1; - } +int HexValue(char c) +{ + if (c >= '0' && c <= '9') return c - '0'; + else if (c >= 'a' && c <= 'f') return c - 'a' + 10; + else if (c >= 'A' && c <= 'F') return c - 'A' + 10; + else return -1; +} } Scanner::Scanner(const CharStream& _source) @@ -84,7 +96,6 @@ Scanner::Scanner(const CharStream& _source) void Scanner::reset(const CharStream& _source) { m_source = _source; - m_char = m_source.get(); skipWhitespace(); scanToken(); @@ -95,18 +106,18 @@ void Scanner::reset(const CharStream& _source) bool Scanner::scanHexNumber(char& scanned_number, int expected_length) { BOOST_ASSERT(expected_length <= 4); // prevent overflow - char x = 0; - for (int i = 0; i < expected_length; i++) { + for (int i = 0; i < expected_length; i++) + { int d = HexValue(m_char); - if (d < 0) { + if (d < 0) + { rollback(i); return false; } x = x * 16 + d; advance(); } - scanned_number = x; return true; } @@ -128,16 +139,14 @@ Token::Value Scanner::next() bool Scanner::skipWhitespace() { const int start_position = getSourcePos(); - - while (true) { - if (IsLineTerminator(m_char)) { - m_hasLineTerminatorBeforeNext = true; - } else if (!IsWhiteSpace(m_char)) { - break; - } - advance(); + while (true) + { + if (IsLineTerminator(m_char)) + m_hasLineTerminatorBeforeNext = true; + else if (!IsWhiteSpace(m_char)) + break; + advance(); } - // Return whether or not we skipped any characters. return getSourcePos() != start_position; } @@ -145,24 +154,24 @@ bool Scanner::skipWhitespace() Token::Value Scanner::skipSingleLineComment() { - // The line terminator at the end of the line is not considered - // to be part of the single-line comment; it is recognized - // separately by the lexical grammar and becomes part of the - // stream of input elements for the syntactic grammar - while (advance() && !IsLineTerminator(m_char)) { }; - - return Token::WHITESPACE; + // The line terminator at the end of the line is not considered + // to be part of the single-line comment; it is recognized + // separately by the lexical grammar and becomes part of the + // stream of input elements for the syntactic grammar + while (advance() && !IsLineTerminator(m_char)) { }; + return Token::WHITESPACE; } Token::Value Scanner::skipMultiLineComment() { BOOST_ASSERT(m_char == '*'); advance(); - - while (!isSourcePastEndOfInput()) { + while (!isSourcePastEndOfInput()) + { char ch = m_char; advance(); - if (IsLineTerminator(ch)) { + if (IsLineTerminator(ch)) + { // Following ECMA-262, section 7.4, a comment containing // a newline will make the comment count as a line-terminator. m_hasMultilineCommentBeforeNext = true; @@ -170,274 +179,250 @@ Token::Value Scanner::skipMultiLineComment() // If we have reached the end of the multi-line comment, we // consume the '/' and insert a whitespace. This way all // multi-line comments are treated as whitespace. - if (ch == '*' && m_char == '/') { + if (ch == '*' && m_char == '/') + { m_char = ' '; return Token::WHITESPACE; } } - // Unterminated multi-line comment. return Token::ILLEGAL; } void Scanner::scanToken() { - m_next_token.literal.clear(); - Token::Value token; - do { - // Remember the position of the next token - m_next_token.location.start = getSourcePos(); - - switch (m_char) { - case '\n': - m_hasLineTerminatorBeforeNext = true; // fall-through - case ' ': - case '\t': - token = selectToken(Token::WHITESPACE); - break; - - case '"': case '\'': - token = scanString(); - break; - - case '<': - // < <= << <<= - advance(); - if (m_char == '=') { - token = selectToken(Token::LTE); - } else if (m_char == '<') { - token = selectToken('=', Token::ASSIGN_SHL, Token::SHL); - } else { - token = Token::LT; - } - break; - - case '>': - // > >= >> >>= >>> >>>= - advance(); - if (m_char == '=') { - token = selectToken(Token::GTE); - } else if (m_char == '>') { - // >> >>= >>> >>>= - advance(); - if (m_char == '=') { - token = selectToken(Token::ASSIGN_SAR); - } else if (m_char == '>') { - token = selectToken('=', Token::ASSIGN_SHR, Token::SHR); - } else { - token = Token::SAR; - } - } else { - token = Token::GT; - } - break; - - case '=': - // = == => - advance(); - if (m_char == '=') { - token = selectToken(Token::EQ); - } else if (m_char == '>') { - token = selectToken(Token::ARROW); - } else { - token = Token::ASSIGN; - } - break; - - case '!': - // ! != !== - advance(); - if (m_char == '=') { - token = selectToken(Token::NE); - } else { - token = Token::NOT; - } - break; - - case '+': - // + ++ += - advance(); - if (m_char == '+') { - token = selectToken(Token::INC); - } else if (m_char == '=') { - token = selectToken(Token::ASSIGN_ADD); - } else { - token = Token::ADD; - } - break; - - case '-': - // - -- -= - advance(); - if (m_char == '-') { - advance(); - token = Token::DEC; - } else if (m_char == '=') { - token = selectToken(Token::ASSIGN_SUB); - } else { - token = Token::SUB; - } - break; - - case '*': - // * *= - token = selectToken('=', Token::ASSIGN_MUL, Token::MUL); - break; - - case '%': - // % %= - token = selectToken('=', Token::ASSIGN_MOD, Token::MOD); - break; - - case '/': - // / // /* /= - advance(); - if (m_char == '/') { - token = skipSingleLineComment(); - } else if (m_char == '*') { - token = skipMultiLineComment(); - } else if (m_char == '=') { - token = selectToken(Token::ASSIGN_DIV); - } else { - token = Token::DIV; - } - break; - - case '&': - // & && &= - advance(); - if (m_char == '&') { - token = selectToken(Token::AND); - } else if (m_char == '=') { - token = selectToken(Token::ASSIGN_BIT_AND); - } else { - token = Token::BIT_AND; - } - break; - - case '|': - // | || |= - advance(); - if (m_char == '|') { - token = selectToken(Token::OR); - } else if (m_char == '=') { - token = selectToken(Token::ASSIGN_BIT_OR); - } else { - token = Token::BIT_OR; + m_next_token.literal.clear(); + Token::Value token; + do + { + // Remember the position of the next token + m_next_token.location.start = getSourcePos(); + switch (m_char) + { + case '\n': + m_hasLineTerminatorBeforeNext = true; // fall-through + case ' ': + case '\t': + token = selectToken(Token::WHITESPACE); + break; + case '"': + case '\'': + token = scanString(); + break; + case '<': + // < <= << <<= + advance(); + if (m_char == '=') + token = selectToken(Token::LTE); + else if (m_char == '<') + token = selectToken('=', Token::ASSIGN_SHL, Token::SHL); + else + token = Token::LT; + break; + case '>': + // > >= >> >>= >>> >>>= + advance(); + if (m_char == '=') + token = selectToken(Token::GTE); + else if (m_char == '>') + { + // >> >>= >>> >>>= + advance(); + if (m_char == '=') + token = selectToken(Token::ASSIGN_SAR); + else if (m_char == '>') + token = selectToken('=', Token::ASSIGN_SHR, Token::SHR); + else + token = Token::SAR; + } + else + token = Token::GT; + break; + case '=': + // = == => + advance(); + if (m_char == '=') + token = selectToken(Token::EQ); + else if (m_char == '>') + token = selectToken(Token::ARROW); + else + token = Token::ASSIGN; + break; + case '!': + // ! != + advance(); + if (m_char == '=') + token = selectToken(Token::NE); + else + token = Token::NOT; + break; + case '+': + // + ++ += + advance(); + if (m_char == '+') + token = selectToken(Token::INC); + else if (m_char == '=') + token = selectToken(Token::ASSIGN_ADD); + else + token = Token::ADD; + break; + case '-': + // - -- -= + advance(); + if (m_char == '-') + { + advance(); + token = Token::DEC; + } + else if (m_char == '=') + token = selectToken(Token::ASSIGN_SUB); + else + token = Token::SUB; + break; + case '*': + // * *= + token = selectToken('=', Token::ASSIGN_MUL, Token::MUL); + break; + case '%': + // % %= + token = selectToken('=', Token::ASSIGN_MOD, Token::MOD); + break; + case '/': + // / // /* /= + advance(); + if (m_char == '/') + token = skipSingleLineComment(); + else if (m_char == '*') + token = skipMultiLineComment(); + else if (m_char == '=') + token = selectToken(Token::ASSIGN_DIV); + else + token = Token::DIV; + break; + case '&': + // & && &= + advance(); + if (m_char == '&') + token = selectToken(Token::AND); + else if (m_char == '=') + token = selectToken(Token::ASSIGN_BIT_AND); + else + token = Token::BIT_AND; + break; + case '|': + // | || |= + advance(); + if (m_char == '|') + token = selectToken(Token::OR); + else if (m_char == '=') + token = selectToken(Token::ASSIGN_BIT_OR); + else + token = Token::BIT_OR; + break; + case '^': + // ^ ^= + token = selectToken('=', Token::ASSIGN_BIT_XOR, Token::BIT_XOR); + break; + case '.': + // . Number + advance(); + if (IsDecimalDigit(m_char)) + token = scanNumber(true); + else + token = Token::PERIOD; + break; + case ':': + token = selectToken(Token::COLON); + break; + case ';': + token = selectToken(Token::SEMICOLON); + break; + case ',': + token = selectToken(Token::COMMA); + break; + case '(': + token = selectToken(Token::LPAREN); + break; + case ')': + token = selectToken(Token::RPAREN); + break; + case '[': + token = selectToken(Token::LBRACK); + break; + case ']': + token = selectToken(Token::RBRACK); + break; + case '{': + token = selectToken(Token::LBRACE); + break; + case '}': + token = selectToken(Token::RBRACE); + break; + case '?': + token = selectToken(Token::CONDITIONAL); + break; + case '~': + token = selectToken(Token::BIT_NOT); + break; + default: + if (IsIdentifierStart(m_char)) + token = scanIdentifierOrKeyword(); + else if (IsDecimalDigit(m_char)) + token = scanNumber(false); + else if (skipWhitespace()) + token = Token::WHITESPACE; + else if (isSourcePastEndOfInput()) + token = Token::EOS; + else + token = selectToken(Token::ILLEGAL); + break; } - break; - - case '^': - // ^ ^= - token = selectToken('=', Token::ASSIGN_BIT_XOR, Token::BIT_XOR); - break; - - case '.': - // . Number - advance(); - if (IsDecimalDigit(m_char)) { - token = scanNumber(true); - } else { - token = Token::PERIOD; - } - break; - - case ':': - token = selectToken(Token::COLON); - break; - - case ';': - token = selectToken(Token::SEMICOLON); - break; - - case ',': - token = selectToken(Token::COMMA); - break; - - case '(': - token = selectToken(Token::LPAREN); - break; - - case ')': - token = selectToken(Token::RPAREN); - break; - - case '[': - token = selectToken(Token::LBRACK); - break; - - case ']': - token = selectToken(Token::RBRACK); - break; - - case '{': - token = selectToken(Token::LBRACE); - break; - - case '}': - token = selectToken(Token::RBRACE); - break; - - case '?': - token = selectToken(Token::CONDITIONAL); - break; - - case '~': - token = selectToken(Token::BIT_NOT); - break; - - default: - if (IsIdentifierStart(m_char)) { - token = scanIdentifierOrKeyword(); - } else if (IsDecimalDigit(m_char)) { - token = scanNumber(false); - } else if (skipWhitespace()) { - token = Token::WHITESPACE; - } else if (isSourcePastEndOfInput()) { - token = Token::EOS; - } else { - token = selectToken(Token::ILLEGAL); - } - break; + // Continue scanning for tokens as long as we're just skipping + // whitespace. } - - // Continue scanning for tokens as long as we're just skipping - // whitespace. - } while (token == Token::WHITESPACE); - - m_next_token.location.end = getSourcePos(); - m_next_token.token = token; + while (token == Token::WHITESPACE); + m_next_token.location.end = getSourcePos(); + m_next_token.token = token; } bool Scanner::scanEscape() { char c = m_char; advance(); - // Skip escaped newlines. if (IsLineTerminator(c)) return true; - - switch (c) { + switch (c) + { case '\'': // fall through case '"' : // fall through - case '\\': break; - case 'b' : c = '\b'; break; - case 'f' : c = '\f'; break; - case 'n' : c = '\n'; break; - case 'r' : c = '\r'; break; - case 't' : c = '\t'; break; - case 'u' : { + case '\\': + break; + case 'b' : + c = '\b'; + break; + case 'f' : + c = '\f'; + break; + case 'n' : + c = '\n'; + break; + case 'r' : + c = '\r'; + break; + case 't' : + c = '\t'; + break; + case 'u' : if (!scanHexNumber(c, 4)) return false; break; - } - case 'v' : c = '\v'; break; - case 'x' : { + case 'v' : + c = '\v'; + break; + case 'x' : if (!scanHexNumber(c, 2)) return false; break; } - } - // According to ECMA-262, section 7.8.4, characters not covered by the // above cases should be illegal, but they are commonly handled as // non-escaped characters by JS VMs. @@ -449,20 +434,21 @@ Token::Value Scanner::scanString() { const char quote = m_char; advance(); // consume quote - LiteralScope literal(this); - while (m_char != quote && !isSourcePastEndOfInput() && !IsLineTerminator(m_char)) { + while (m_char != quote && !isSourcePastEndOfInput() && !IsLineTerminator(m_char)) + { char c = m_char; advance(); - if (c == '\\') { - if (isSourcePastEndOfInput() || !scanEscape()) return Token::ILLEGAL; - } else { - addLiteralChar(c); + if (c == '\\') + { + if (isSourcePastEndOfInput() || !scanEscape()) + return Token::ILLEGAL; } + else + addLiteralChar(c); } if (m_char != quote) return Token::ILLEGAL; literal.Complete(); - advance(); // consume quote return Token::STRING_LITERAL; } @@ -477,71 +463,66 @@ void Scanner::scanDecimalDigits() Token::Value Scanner::scanNumber(bool _periodSeen) { - BOOST_ASSERT(IsDecimalDigit(m_char)); // the first digit of the number or the fraction - - enum { DECIMAL, HEX, OCTAL, IMPLICIT_OCTAL, BINARY } kind = DECIMAL; - - LiteralScope literal(this); - if (_periodSeen) { - // we have already seen a decimal point of the float - addLiteralChar('.'); - scanDecimalDigits(); // we know we have at least one digit - } else { - // if the first character is '0' we must check for octals and hex - if (m_char == '0') { - addLiteralCharAndAdvance(); - - // either 0, 0exxx, 0Exxx, 0.xxx, a hex number, a binary number or - // an octal number. - if (m_char == 'x' || m_char == 'X') { - // hex number - kind = HEX; - addLiteralCharAndAdvance(); - if (!IsHexDigit(m_char)) { - // we must have at least one hex digit after 'x'/'X' - return Token::ILLEGAL; + BOOST_ASSERT(IsDecimalDigit(m_char)); // the first digit of the number or the fraction + enum { DECIMAL, HEX, OCTAL, IMPLICIT_OCTAL, BINARY } kind = DECIMAL; + LiteralScope literal(this); + if (_periodSeen) + { + // we have already seen a decimal point of the float + addLiteralChar('.'); + scanDecimalDigits(); // we know we have at least one digit + } + else + { + // if the first character is '0' we must check for octals and hex + if (m_char == '0') + { + addLiteralCharAndAdvance(); + // either 0, 0exxx, 0Exxx, 0.xxx, a hex number, a binary number or + // an octal number. + if (m_char == 'x' || m_char == 'X') + { + // hex number + kind = HEX; + addLiteralCharAndAdvance(); + if (!IsHexDigit(m_char)) + return Token::ILLEGAL; // we must have at least one hex digit after 'x'/'X' + while (IsHexDigit(m_char)) + addLiteralCharAndAdvance(); + } } - while (IsHexDigit(m_char)) { - addLiteralCharAndAdvance(); + // Parse decimal digits and allow trailing fractional part. + if (kind == DECIMAL) + { + scanDecimalDigits(); // optional + if (m_char == '.') + { + addLiteralCharAndAdvance(); + scanDecimalDigits(); // optional + } } - } } - - // Parse decimal digits and allow trailing fractional part. - if (kind == DECIMAL) { - scanDecimalDigits(); // optional - if (m_char == '.') { + // scan exponent, if any + if (m_char == 'e' || m_char == 'E') + { + BOOST_ASSERT(kind != HEX); // 'e'/'E' must be scanned as part of the hex number + if (kind != DECIMAL) return Token::ILLEGAL; + // scan exponent addLiteralCharAndAdvance(); - scanDecimalDigits(); // optional - } + if (m_char == '+' || m_char == '-') + addLiteralCharAndAdvance(); + if (!IsDecimalDigit(m_char)) + return Token::ILLEGAL; // we must have at least one decimal digit after 'e'/'E' + scanDecimalDigits(); } - } - - // scan exponent, if any - if (m_char == 'e' || m_char == 'E') { - BOOST_ASSERT(kind != HEX); // 'e'/'E' must be scanned as part of the hex number - if (kind != DECIMAL) return Token::ILLEGAL; - // scan exponent - addLiteralCharAndAdvance(); - if (m_char == '+' || m_char == '-') - addLiteralCharAndAdvance(); - if (!IsDecimalDigit(m_char)) { - // we must have at least one decimal digit after 'e'/'E' - return Token::ILLEGAL; - } - scanDecimalDigits(); - } - - // The source character immediately following a numeric literal must - // not be an identifier start or a decimal digit; see ECMA-262 - // section 7.8.3, page 17 (note that we read only one decimal digit - // if the value is 0). - if (IsDecimalDigit(m_char) || IsIdentifierStart(m_char)) - return Token::ILLEGAL; - - literal.Complete(); - - return Token::NUMBER; + // The source character immediately following a numeric literal must + // not be an identifier start or a decimal digit; see ECMA-262 + // section 7.8.3, page 17 (note that we read only one decimal digit + // if the value is 0). + if (IsDecimalDigit(m_char) || IsIdentifierStart(m_char)) + return Token::ILLEGAL; + literal.Complete(); + return Token::NUMBER; } @@ -549,130 +530,126 @@ Token::Value Scanner::scanNumber(bool _periodSeen) // Keyword Matcher #define KEYWORDS(KEYWORD_GROUP, KEYWORD) \ - KEYWORD_GROUP('a') \ - KEYWORD("address", Token::ADDRESS) \ - KEYWORD_GROUP('b') \ - KEYWORD("break", Token::BREAK) \ - KEYWORD("bool", Token::BOOL) \ - KEYWORD_GROUP('c') \ - KEYWORD("case", Token::CASE) \ - KEYWORD("catch", Token::CATCH) \ - KEYWORD("const", Token::CONST) \ - KEYWORD("continue", Token::CONTINUE) \ - KEYWORD("contract", Token::CONTRACT) \ - KEYWORD_GROUP('d') \ - KEYWORD("debugger", Token::DEBUGGER) \ - KEYWORD("default", Token::DEFAULT) \ - KEYWORD("delete", Token::DELETE) \ - KEYWORD("do", Token::DO) \ - KEYWORD_GROUP('e') \ - KEYWORD("else", Token::ELSE) \ - KEYWORD("enum", Token::FUTURE_RESERVED_WORD) \ - KEYWORD_GROUP('f') \ - KEYWORD("false", Token::FALSE_LITERAL) \ - KEYWORD("finally", Token::FINALLY) \ - KEYWORD("for", Token::FOR) \ - KEYWORD("function", Token::FUNCTION) \ - KEYWORD_GROUP('h') \ - KEYWORD("hash", Token::HASH) \ - KEYWORD("hash32", Token::HASH32) \ - KEYWORD("hash64", Token::HASH64) \ - KEYWORD("hash128", Token::HASH128) \ - KEYWORD("hash256", Token::HASH256) \ - KEYWORD_GROUP('i') \ - KEYWORD("if", Token::IF) \ - KEYWORD("implements", Token::FUTURE_STRICT_RESERVED_WORD) \ - KEYWORD("in", Token::IN) \ - KEYWORD("instanceof", Token::INSTANCEOF) \ - KEYWORD("int", Token::INT) \ - KEYWORD("int32", Token::INT32) \ - KEYWORD("int64", Token::INT64) \ - KEYWORD("int128", Token::INT128) \ - KEYWORD("int256", Token::INT256) \ - KEYWORD("interface", Token::FUTURE_STRICT_RESERVED_WORD) \ - KEYWORD_GROUP('l') \ - KEYWORD_GROUP('m') \ - KEYWORD("mapping", Token::MAPPING) \ - KEYWORD_GROUP('n') \ - KEYWORD("new", Token::NEW) \ - KEYWORD("null", Token::NULL_LITERAL) \ - KEYWORD_GROUP('p') \ - KEYWORD("package", Token::FUTURE_STRICT_RESERVED_WORD) \ - KEYWORD("private", Token::PRIVATE) \ - KEYWORD("protected", Token::FUTURE_STRICT_RESERVED_WORD) \ - KEYWORD("public", Token::PUBLIC) \ - KEYWORD_GROUP('r') \ - KEYWORD("real", Token::REAL) \ - KEYWORD("return", Token::RETURN) \ - KEYWORD("returns", Token::RETURNS) \ - KEYWORD_GROUP('s') \ - KEYWORD("string", Token::STRING_TYPE) \ - KEYWORD("struct", Token::STRUCT) \ - KEYWORD("switch", Token::SWITCH) \ - KEYWORD_GROUP('t') \ - KEYWORD("text", Token::TEXT) \ - KEYWORD("this", Token::THIS) \ - KEYWORD("throw", Token::THROW) \ - KEYWORD("true", Token::TRUE_LITERAL) \ - KEYWORD("try", Token::TRY) \ - KEYWORD("typeof", Token::TYPEOF) \ - KEYWORD_GROUP('u') \ - KEYWORD("uint", Token::UINT) \ - KEYWORD("uint32", Token::UINT32) \ - KEYWORD("uint64", Token::UINT64) \ - KEYWORD("uint128", Token::UINT128) \ - KEYWORD("uint256", Token::UINT256) \ - KEYWORD("ureal", Token::UREAL) \ - KEYWORD_GROUP('v') \ - KEYWORD("var", Token::VAR) \ - KEYWORD("void", Token::VOID) \ - KEYWORD_GROUP('w') \ - KEYWORD("while", Token::WHILE) \ - KEYWORD("with", Token::WITH) + KEYWORD_GROUP('a') \ + KEYWORD("address", Token::ADDRESS) \ + KEYWORD_GROUP('b') \ + KEYWORD("break", Token::BREAK) \ + KEYWORD("bool", Token::BOOL) \ + KEYWORD_GROUP('c') \ + KEYWORD("case", Token::CASE) \ + KEYWORD("catch", Token::CATCH) \ + KEYWORD("const", Token::CONST) \ + KEYWORD("continue", Token::CONTINUE) \ + KEYWORD("contract", Token::CONTRACT) \ + KEYWORD_GROUP('d') \ + KEYWORD("debugger", Token::DEBUGGER) \ + KEYWORD("default", Token::DEFAULT) \ + KEYWORD("delete", Token::DELETE) \ + KEYWORD("do", Token::DO) \ + KEYWORD_GROUP('e') \ + KEYWORD("else", Token::ELSE) \ + KEYWORD("enum", Token::FUTURE_RESERVED_WORD) \ + KEYWORD_GROUP('f') \ + KEYWORD("false", Token::FALSE_LITERAL) \ + KEYWORD("finally", Token::FINALLY) \ + KEYWORD("for", Token::FOR) \ + KEYWORD("function", Token::FUNCTION) \ + KEYWORD_GROUP('h') \ + KEYWORD("hash", Token::HASH) \ + KEYWORD("hash32", Token::HASH32) \ + KEYWORD("hash64", Token::HASH64) \ + KEYWORD("hash128", Token::HASH128) \ + KEYWORD("hash256", Token::HASH256) \ + KEYWORD_GROUP('i') \ + KEYWORD("if", Token::IF) \ + KEYWORD("implements", Token::FUTURE_STRICT_RESERVED_WORD) \ + KEYWORD("in", Token::IN) \ + KEYWORD("instanceof", Token::INSTANCEOF) \ + KEYWORD("int", Token::INT) \ + KEYWORD("int32", Token::INT32) \ + KEYWORD("int64", Token::INT64) \ + KEYWORD("int128", Token::INT128) \ + KEYWORD("int256", Token::INT256) \ + KEYWORD("interface", Token::FUTURE_STRICT_RESERVED_WORD) \ + KEYWORD_GROUP('l') \ + KEYWORD_GROUP('m') \ + KEYWORD("mapping", Token::MAPPING) \ + KEYWORD_GROUP('n') \ + KEYWORD("new", Token::NEW) \ + KEYWORD("null", Token::NULL_LITERAL) \ + KEYWORD_GROUP('p') \ + KEYWORD("package", Token::FUTURE_STRICT_RESERVED_WORD) \ + KEYWORD("private", Token::PRIVATE) \ + KEYWORD("protected", Token::FUTURE_STRICT_RESERVED_WORD) \ + KEYWORD("public", Token::PUBLIC) \ + KEYWORD_GROUP('r') \ + KEYWORD("real", Token::REAL) \ + KEYWORD("return", Token::RETURN) \ + KEYWORD("returns", Token::RETURNS) \ + KEYWORD_GROUP('s') \ + KEYWORD("string", Token::STRING_TYPE) \ + KEYWORD("struct", Token::STRUCT) \ + KEYWORD("switch", Token::SWITCH) \ + KEYWORD_GROUP('t') \ + KEYWORD("text", Token::TEXT) \ + KEYWORD("this", Token::THIS) \ + KEYWORD("throw", Token::THROW) \ + KEYWORD("true", Token::TRUE_LITERAL) \ + KEYWORD("try", Token::TRY) \ + KEYWORD("typeof", Token::TYPEOF) \ + KEYWORD_GROUP('u') \ + KEYWORD("uint", Token::UINT) \ + KEYWORD("uint32", Token::UINT32) \ + KEYWORD("uint64", Token::UINT64) \ + KEYWORD("uint128", Token::UINT128) \ + KEYWORD("uint256", Token::UINT256) \ + KEYWORD("ureal", Token::UREAL) \ + KEYWORD_GROUP('v') \ + KEYWORD("var", Token::VAR) \ + KEYWORD("void", Token::VOID) \ + KEYWORD_GROUP('w') \ + KEYWORD("while", Token::WHILE) \ + KEYWORD("with", Token::WITH) static Token::Value KeywordOrIdentifierToken(const std::string& input) { - BOOST_ASSERT(!input.empty()); - const int kMinLength = 2; - const int kMaxLength = 10; - if (input.size() < kMinLength || input.size() > kMaxLength) { - return Token::IDENTIFIER; - } - switch (input[0]) { + BOOST_ASSERT(!input.empty()); + const int kMinLength = 2; + const int kMaxLength = 10; + if (input.size() < kMinLength || input.size() > kMaxLength) + return Token::IDENTIFIER; + switch (input[0]) + { default: #define KEYWORD_GROUP_CASE(ch) \ - break; \ - case ch: + break; \ +case ch: #define KEYWORD(keyword, token) \ { \ - /* 'keyword' is a char array, so sizeof(keyword) is */ \ - /* strlen(keyword) plus 1 for the NUL char. */ \ - const int keyword_length = sizeof(keyword) - 1; \ - BOOST_STATIC_ASSERT(keyword_length >= kMinLength); \ - BOOST_STATIC_ASSERT(keyword_length <= kMaxLength); \ - if (input == keyword) { \ - return token; \ - } \ + /* 'keyword' is a char array, so sizeof(keyword) is */ \ + /* strlen(keyword) plus 1 for the NUL char. */ \ + const int keyword_length = sizeof(keyword) - 1; \ + BOOST_STATIC_ASSERT(keyword_length >= kMinLength); \ + BOOST_STATIC_ASSERT(keyword_length <= kMaxLength); \ + if (input == keyword) { \ + return token; \ + } \ } - KEYWORDS(KEYWORD_GROUP_CASE, KEYWORD) - } - return Token::IDENTIFIER; + KEYWORDS(KEYWORD_GROUP_CASE, KEYWORD) + } + return Token::IDENTIFIER; } Token::Value Scanner::scanIdentifierOrKeyword() { BOOST_ASSERT(IsIdentifierStart(m_char)); LiteralScope literal(this); - addLiteralCharAndAdvance(); - // Scan the rest of the identifier characters. while (IsIdentifierPart(m_char)) addLiteralCharAndAdvance(); - literal.Complete(); - return KeywordOrIdentifierToken(m_next_token.literal); } @@ -697,17 +674,17 @@ std::tuple<int, int> CharStream::translatePositionToLineColumn(int _position) co using size_type = std::string::size_type; size_type searchPosition = std::min<size_type>(m_source.size(), _position); int lineNumber = std::count(m_source.begin(), m_source.begin() + searchPosition, '\n'); - size_type lineStart; - if (searchPosition == 0) { + if (searchPosition == 0) lineStart = 0; - } else { + else + { lineStart = m_source.rfind('\n', searchPosition - 1); lineStart = lineStart == std::string::npos ? 0 : lineStart + 1; } - return std::tuple<int, int>(lineNumber, searchPosition - lineStart); } -} } +} +} |