diff --git a/ets2panda/ir/expressions/objectExpression.cpp b/ets2panda/ir/expressions/objectExpression.cpp index eb1cb44b0fd1327526678af65ee0bc0e6780335f..f51b45af75b322f8f157b146f83b9c059f2a3131 100644 --- a/ets2panda/ir/expressions/objectExpression.cpp +++ b/ets2panda/ir/expressions/objectExpression.cpp @@ -68,6 +68,20 @@ ObjectExpression *ObjectExpression::Clone(ArenaAllocator *const allocator, AstNo throw Error(ErrorType::GENERIC, "", CLONE_ALLOCATION_ERROR); } +static std::pair ValidateProperty(Property *prop, bool &foundProto) +{ + ValidationInfo info = prop->ValidateExpression(); + if (prop->Kind() == PropertyKind::PROTO) { + if (foundProto) { + return {{"Duplicate __proto__ fields are not allowed in object literals", prop->Key()->Start()}, true}; + } + + foundProto = true; + } + + return {info, false}; +} + ValidationInfo ObjectExpression::ValidateExpression() { if (optional_) { @@ -93,16 +107,11 @@ ValidationInfo ObjectExpression::ValidateExpression() } case AstNodeType::PROPERTY: { auto *prop = it->AsProperty(); - info = prop->ValidateExpression(); - - if (prop->Kind() == PropertyKind::PROTO) { - if (foundProto) { - return {"Duplicate __proto__ fields are not allowed in object literals", prop->Key()->Start()}; - } - - foundProto = true; + bool ret = false; + std::tie(info, ret) = ValidateProperty(prop, foundProto); + if (ret) { + return info; } - break; } default: { diff --git a/ets2panda/lexer/lexer.cpp b/ets2panda/lexer/lexer.cpp index 85c612f062472c8f361b1dc07df4b816f2b025c9..5ccd3fee190d88d4123c0008e5b5ad34eb89a7f9 100644 --- a/ets2panda/lexer/lexer.cpp +++ b/ets2panda/lexer/lexer.cpp @@ -320,44 +320,7 @@ void Lexer::ScanNumber(bool allowBigInt) } } - switch (Iterator().Peek()) { - case LEX_CHAR_LOWERCASE_E: - case LEX_CHAR_UPPERCASE_E: { - allowBigInt = false; - - if (!parseExponent) { - break; - } - - flags |= NumberFlags::EXPONENT; - - Iterator().Forward(1); - - switch (Iterator().Peek()) { - case LEX_CHAR_UNDERSCORE: { - break; - } - case LEX_CHAR_PLUS: - case LEX_CHAR_MINUS: { - Iterator().Forward(1); - break; - } - default: { - exponentSignPos = Iterator().Index() - GetToken().Start().index; - break; - } - } - - if (!IsDecimalDigit(Iterator().Peek())) { - ThrowError("Invalid numeric literal"); - } - ScanDecimalNumbers(); - break; - } - default: { - break; - } - } + std::tie(exponentSignPos, allowBigInt, flags) = ScanCharLex(allowBigInt, parseExponent, flags); CheckNumberLiteralEnd(); @@ -393,6 +356,57 @@ void Lexer::ScanNumber(bool allowBigInt) ConvertNumber(utf8, flags); } +std::tuple Lexer::ScanCharLex(bool allowBigInt, bool parseExponent, NumberFlags flags) +{ + size_t exponentSignPos = std::numeric_limits::max(); + switch (Iterator().Peek()) { + case LEX_CHAR_LOWERCASE_E: + case LEX_CHAR_UPPERCASE_E: { + allowBigInt = false; + + if (!parseExponent) { + break; + } + + flags |= NumberFlags::EXPONENT; + + Iterator().Forward(1); + + exponentSignPos = ScanSignOfNumber(); + + if (!IsDecimalDigit(Iterator().Peek())) { + ThrowError("Invalid numeric literal"); + } + ScanDecimalNumbers(); + break; + } + default: { + break; + } + } + return {exponentSignPos, allowBigInt, flags}; +} + +size_t Lexer::ScanSignOfNumber() +{ + size_t exponentSignPos = std::numeric_limits::max(); + switch (Iterator().Peek()) { + case LEX_CHAR_UNDERSCORE: { + break; + } + case LEX_CHAR_PLUS: + case LEX_CHAR_MINUS: { + Iterator().Forward(1); + break; + } + default: { + exponentSignPos = Iterator().Index() - GetToken().Start().index; + break; + } + } + return exponentSignPos; +} + void Lexer::PushTemplateContext(TemplateLiteralParserContext *ctx) { tlCtx_ = ctx; diff --git a/ets2panda/lexer/lexer.h b/ets2panda/lexer/lexer.h index 35de361dcd025c06a67bb71f7f252f8e27caa6ba..d4e92a064192f708ee19d3b0a8c7d0526c340ceb 100644 --- a/ets2panda/lexer/lexer.h +++ b/ets2panda/lexer/lexer.h @@ -16,6 +16,7 @@ #ifndef ES2PANDA_PARSER_CORE_LEXER_H #define ES2PANDA_PARSER_CORE_LEXER_H +#include #include "lexer/regexp/regexp.h" #include "lexer/token/letters.h" #include "lexer/token/token.h" @@ -283,6 +284,8 @@ protected: template void ScanNumberRadix(bool allowNumericSeparator = true); void ScanNumber(bool allowBigInt = true); + std::tuple ScanCharLex(bool allowBigInt, bool parseExponent, NumberFlags flags); + size_t ScanSignOfNumber(); template void ScanTooLargeNumber(RadixType number); virtual void ConvertNumber(const std::string &utf8, NumberFlags flags); diff --git a/ets2panda/lexer/regexp/regexp.cpp b/ets2panda/lexer/regexp/regexp.cpp index efa0b645ff03567d08d6745a10eb47884c7248f7..acb8bfa9d6ab79300d9dd0f3f93f256292b572eb 100644 --- a/ets2panda/lexer/regexp/regexp.cpp +++ b/ets2panda/lexer/regexp/regexp.cpp @@ -141,43 +141,9 @@ void RegExpParser::ParseAlternative() return; } case LEX_CHAR_LEFT_PAREN: { - Next(); - - if (Peek() != LEX_CHAR_QUESTION) { - ParseCapturingGroup(); - break; - } - - Next(); // eat '?' - - char32_t cp = Next(); - if (cp == LEX_CHAR_COLON) { - ParseNonCapturingGroup(); - break; - } - - if (cp == LEX_CHAR_EQUALS || cp == LEX_CHAR_EXCLAMATION) { - ParseAssertion(); - - if (Unicode()) { - return; - } - - break; - } - - if (cp != LEX_CHAR_LESS_THAN) { - ThrowError("Invalid group"); - } - - cp = Peek(); - if (cp == LEX_CHAR_EQUALS || cp == LEX_CHAR_EXCLAMATION) { - Next(); - ParseAssertion(); + if (ParseAlternativeCharLeftParen()) { return; } - - ParseNamedCapturingGroup(); break; } case LEX_CHAR_LEFT_SQUARE: { @@ -205,6 +171,44 @@ void RegExpParser::ParseAlternative() ParseQuantifier(); } +bool RegExpParser::ParseAlternativeCharLeftParen() +{ + Next(); + + if (Peek() != LEX_CHAR_QUESTION) { + ParseCapturingGroup(); + return false; + } + + Next(); // eat '?' + + char32_t cp = Next(); + if (cp == LEX_CHAR_COLON) { + ParseNonCapturingGroup(); + return false; + } + + if (cp == LEX_CHAR_EQUALS || cp == LEX_CHAR_EXCLAMATION) { + ParseAssertion(); + + return Unicode(); + } + + if (cp != LEX_CHAR_LESS_THAN) { + ThrowError("Invalid group"); + } + + cp = Peek(); + if (cp == LEX_CHAR_EQUALS || cp == LEX_CHAR_EXCLAMATION) { + Next(); + ParseAssertion(); + return true; + } + + ParseNamedCapturingGroup(); + return false; +} + void RegExpParser::ParseAlternatives() { while (true) { @@ -461,6 +465,11 @@ void RegExpParser::ParseAtomEscape() Next(); + ParseAtomEscapeSwitch(cp); +} + +void RegExpParser::ParseAtomEscapeSwitch(char32_t cp) +{ switch (cp) { case LEX_CHAR_LOWERCASE_X: { ParseHexEscape(); diff --git a/ets2panda/lexer/regexp/regexp.h b/ets2panda/lexer/regexp/regexp.h index ca02c1ca94e49abf0f247179ec41da23581e66c5..d9f0e5198cbbb34d5781b65600a7b8d4aec53035 100644 --- a/ets2panda/lexer/regexp/regexp.h +++ b/ets2panda/lexer/regexp/regexp.h @@ -62,6 +62,7 @@ private: void ParseDisjunction(); void ParseAlternatives(); void ParseAlternative(); + bool ParseAlternativeCharLeftParen(); void ParseNonCapturingGroup(); void ParseNamedCapturingGroup(); @@ -71,6 +72,7 @@ private: char32_t ParseClassAtom(); void ParseCharacterClass(); void ParseAtomEscape(); + void ParseAtomEscapeSwitch(char32_t cp); uint32_t ParseControlEscape(); uint32_t ParseDecimalEscape(); diff --git a/ets2panda/test/unit/node_creator.h b/ets2panda/test/unit/node_creator.h index ed0653acd4d937a2f74f39d9651f462f75d21ce0..fc31c63b4ad9a94d0298645d0806d05dd7e94bb8 100644 --- a/ets2panda/test/unit/node_creator.h +++ b/ets2panda/test/unit/node_creator.h @@ -13,6 +13,9 @@ * limitations under the License. */ +#ifndef ETS2PANDA_TEST_UNIT_NODE_CREATOR_H +#define ETS2PANDA_TEST_UNIT_NODE_CREATOR_H + #include "ir/astNode.h" #include "ir/statements/variableDeclarator.h" #include "ir/statements/variableDeclaration.h" @@ -85,3 +88,4 @@ private: ArenaAllocator *const alloc_; }; } // namespace ark::es2panda::gtests +#endif // ETS2PANDA_TEST_UNIT_NODE_CREATOR_H