| Index: src/preparser.cc
|
| diff --git a/src/preparser.cc b/src/preparser.cc
|
| index a5de23ebeede10d2b59726f32d0294f6403555f1..a64a3592b00838441753a742480dc7914c123f9e 100644
|
| --- a/src/preparser.cc
|
| +++ b/src/preparser.cc
|
| @@ -55,6 +55,18 @@ int isfinite(double value);
|
| namespace v8 {
|
| namespace internal {
|
|
|
| +
|
| +void PreParserTraits::CheckStrictModeLValue(PreParserExpression expression,
|
| + bool* ok) {
|
| + if (expression.IsIdentifier() &&
|
| + expression.AsIdentifier().IsEvalOrArguments()) {
|
| + pre_parser_->ReportMessage("strict_eval_arguments",
|
| + Vector<const char*>::empty());
|
| + *ok = false;
|
| + }
|
| +}
|
| +
|
| +
|
| void PreParserTraits::ReportMessageAt(Scanner::Location location,
|
| const char* message,
|
| Vector<const char*> args) {
|
| @@ -91,16 +103,11 @@ PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) {
|
| } else if (scanner->current_token() == Token::YIELD) {
|
| return PreParserIdentifier::Yield();
|
| }
|
| - if (scanner->is_literal_ascii()) {
|
| - // Detect strict-mode poison words.
|
| - if (scanner->literal_length() == 4 &&
|
| - !strncmp(scanner->literal_ascii_string().start(), "eval", 4)) {
|
| - return PreParserIdentifier::Eval();
|
| - }
|
| - if (scanner->literal_length() == 9 &&
|
| - !strncmp(scanner->literal_ascii_string().start(), "arguments", 9)) {
|
| - return PreParserIdentifier::Arguments();
|
| - }
|
| + if (scanner->UnescapedLiteralMatches("eval", 4)) {
|
| + return PreParserIdentifier::Eval();
|
| + }
|
| + if (scanner->UnescapedLiteralMatches("arguments", 9)) {
|
| + return PreParserIdentifier::Arguments();
|
| }
|
| return PreParserIdentifier::Default();
|
| }
|
| @@ -108,43 +115,46 @@ PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) {
|
|
|
| PreParserExpression PreParserTraits::ExpressionFromString(
|
| int pos, Scanner* scanner, PreParserFactory* factory) {
|
| - const int kUseStrictLength = 10;
|
| - const char* kUseStrictChars = "use strict";
|
| pre_parser_->LogSymbol();
|
| - if (scanner->is_literal_ascii() &&
|
| - scanner->literal_length() == kUseStrictLength &&
|
| - !scanner->literal_contains_escapes() &&
|
| - !strncmp(scanner->literal_ascii_string().start(), kUseStrictChars,
|
| - kUseStrictLength)) {
|
| + if (scanner->UnescapedLiteralMatches("use strict", 10)) {
|
| return PreParserExpression::UseStrictStringLiteral();
|
| }
|
| return PreParserExpression::StringLiteral();
|
| }
|
|
|
|
|
| -PreParserExpression PreParserTraits::ParseObjectLiteral(bool* ok) {
|
| - return pre_parser_->ParseObjectLiteral(ok);
|
| +PreParserExpression PreParserTraits::ParseV8Intrinsic(bool* ok) {
|
| + return pre_parser_->ParseV8Intrinsic(ok);
|
| }
|
|
|
|
|
| -PreParserExpression PreParserTraits::ParseAssignmentExpression(bool accept_IN,
|
| - bool* ok) {
|
| - return pre_parser_->ParseAssignmentExpression(accept_IN, ok);
|
| +PreParserExpression PreParserTraits::ParseFunctionLiteral(
|
| + PreParserIdentifier name,
|
| + Scanner::Location function_name_location,
|
| + bool name_is_strict_reserved,
|
| + bool is_generator,
|
| + int function_token_position,
|
| + FunctionLiteral::FunctionType type,
|
| + bool* ok) {
|
| + return pre_parser_->ParseFunctionLiteral(
|
| + name, function_name_location, name_is_strict_reserved, is_generator,
|
| + function_token_position, type, ok);
|
| }
|
|
|
|
|
| -PreParserExpression PreParserTraits::ParseV8Intrinsic(bool* ok) {
|
| - return pre_parser_->ParseV8Intrinsic(ok);
|
| +PreParserExpression PreParserTraits::ParseConditionalExpression(bool accept_IN,
|
| + bool* ok) {
|
| + return pre_parser_->ParseConditionalExpression(accept_IN, ok);
|
| }
|
|
|
|
|
| PreParser::PreParseResult PreParser::PreParseLazyFunction(
|
| - LanguageMode mode, bool is_generator, ParserRecorder* log) {
|
| + StrictMode strict_mode, bool is_generator, ParserRecorder* log) {
|
| log_ = log;
|
| // Lazy functions always have trivial outer scopes (no with/catch scopes).
|
| PreParserScope top_scope(scope_, GLOBAL_SCOPE);
|
| FunctionState top_state(&function_state_, &scope_, &top_scope);
|
| - scope_->SetLanguageMode(mode);
|
| + scope_->SetStrictMode(strict_mode);
|
| PreParserScope function_scope(scope_, FUNCTION_SCOPE);
|
| FunctionState function_state(&function_state_, &scope_, &function_scope);
|
| function_state.set_is_generator(is_generator);
|
| @@ -157,7 +167,7 @@ PreParser::PreParseResult PreParser::PreParseLazyFunction(
|
| ReportUnexpectedToken(scanner()->current_token());
|
| } else {
|
| ASSERT_EQ(Token::RBRACE, scanner()->peek());
|
| - if (!scope_->is_classic_mode()) {
|
| + if (scope_->strict_mode() == STRICT) {
|
| int end_pos = scanner()->location().end_pos;
|
| CheckOctalLiteral(start_position, end_pos, &ok);
|
| }
|
| @@ -224,8 +234,7 @@ PreParser::SourceElements PreParser::ParseSourceElements(int end_token,
|
| Statement statement = ParseSourceElement(CHECK_OK);
|
| if (directive_prologue) {
|
| if (statement.IsUseStrictLiteral()) {
|
| - scope_->SetLanguageMode(allow_harmony_scoping() ?
|
| - EXTENDED_MODE : STRICT_MODE);
|
| + scope_->SetStrictMode(STRICT);
|
| } else if (!statement.IsStringLiteral()) {
|
| directive_prologue = false;
|
| }
|
| @@ -319,7 +328,7 @@ PreParser::Statement PreParser::ParseStatement(bool* ok) {
|
| Scanner::Location start_location = scanner()->peek_location();
|
| Statement statement = ParseFunctionDeclaration(CHECK_OK);
|
| Scanner::Location end_location = scanner()->location();
|
| - if (!scope_->is_classic_mode()) {
|
| + if (strict_mode() == STRICT) {
|
| PreParserTraits::ReportMessageAt(start_location.beg_pos,
|
| end_location.end_pos,
|
| "strict_function",
|
| @@ -347,7 +356,7 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
|
| // 'function' '*' Identifier '(' FormalParameterListopt ')'
|
| // '{' FunctionBody '}'
|
| Expect(Token::FUNCTION, CHECK_OK);
|
| -
|
| + int pos = position();
|
| bool is_generator = allow_generators() && Check(Token::MUL);
|
| bool is_strict_reserved = false;
|
| Identifier name = ParseIdentifierOrStrictReservedWord(
|
| @@ -356,6 +365,8 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
|
| scanner()->location(),
|
| is_strict_reserved,
|
| is_generator,
|
| + pos,
|
| + FunctionLiteral::DECLARATION,
|
| CHECK_OK);
|
| return Statement::FunctionDeclaration();
|
| }
|
| @@ -370,7 +381,7 @@ PreParser::Statement PreParser::ParseBlock(bool* ok) {
|
| //
|
| Expect(Token::LBRACE, CHECK_OK);
|
| while (peek() != Token::RBRACE) {
|
| - if (scope_->is_extended_mode()) {
|
| + if (FLAG_harmony_scoping && strict_mode() == STRICT) {
|
| ParseSourceElement(CHECK_OK);
|
| } else {
|
| ParseStatement(CHECK_OK);
|
| @@ -430,28 +441,24 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
|
| // * It is a Syntax Error if the code that matches this production is not
|
| // contained in extended code.
|
| //
|
| - // However disallowing const in classic mode will break compatibility with
|
| + // However disallowing const in sloppy mode will break compatibility with
|
| // existing pages. Therefore we keep allowing const with the old
|
| - // non-harmony semantics in classic mode.
|
| + // non-harmony semantics in sloppy mode.
|
| Consume(Token::CONST);
|
| - switch (scope_->language_mode()) {
|
| - case CLASSIC_MODE:
|
| - break;
|
| - case STRICT_MODE: {
|
| - Scanner::Location location = scanner()->peek_location();
|
| - ReportMessageAt(location, "strict_const");
|
| - *ok = false;
|
| - return Statement::Default();
|
| - }
|
| - case EXTENDED_MODE:
|
| - if (var_context != kSourceElement &&
|
| - var_context != kForStatement) {
|
| + if (strict_mode() == STRICT) {
|
| + if (FLAG_harmony_scoping) {
|
| + if (var_context != kSourceElement && var_context != kForStatement) {
|
| ReportMessageAt(scanner()->peek_location(), "unprotected_const");
|
| *ok = false;
|
| return Statement::Default();
|
| }
|
| require_initializer = true;
|
| - break;
|
| + } else {
|
| + Scanner::Location location = scanner()->peek_location();
|
| + ReportMessageAt(location, "strict_const");
|
| + *ok = false;
|
| + return Statement::Default();
|
| + }
|
| }
|
| } else if (peek() == Token::LET) {
|
| // ES6 Draft Rev4 section 12.2.1:
|
| @@ -460,7 +467,9 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
|
| //
|
| // * It is a Syntax Error if the code that matches this production is not
|
| // contained in extended code.
|
| - if (!scope_->is_extended_mode()) {
|
| + //
|
| + // TODO(rossberg): make 'let' a legal identifier in sloppy mode.
|
| + if (!FLAG_harmony_scoping || strict_mode() == SLOPPY) {
|
| ReportMessageAt(scanner()->peek_location(), "illegal_let");
|
| *ok = false;
|
| return Statement::Default();
|
| @@ -513,7 +522,7 @@ PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
|
| // Expression is a single identifier, and not, e.g., a parenthesized
|
| // identifier.
|
| ASSERT(!expr.AsIdentifier().IsFutureReserved());
|
| - ASSERT(scope_->is_classic_mode() ||
|
| + ASSERT(strict_mode() == SLOPPY ||
|
| (!expr.AsIdentifier().IsFutureStrictReserved() &&
|
| !expr.AsIdentifier().IsYield()));
|
| Consume(Token::COLON);
|
| @@ -611,7 +620,7 @@ PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
|
| // WithStatement ::
|
| // 'with' '(' Expression ')' Statement
|
| Expect(Token::WITH, CHECK_OK);
|
| - if (!scope_->is_classic_mode()) {
|
| + if (strict_mode() == STRICT) {
|
| ReportMessageAt(scanner()->location(), "strict_mode_with");
|
| *ok = false;
|
| return Statement::Default();
|
| @@ -830,60 +839,6 @@ PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
|
| #undef DUMMY
|
|
|
|
|
| -// Precedence = 2
|
| -PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
|
| - bool* ok) {
|
| - // AssignmentExpression ::
|
| - // ConditionalExpression
|
| - // YieldExpression
|
| - // LeftHandSideExpression AssignmentOperator AssignmentExpression
|
| -
|
| - if (function_state_->is_generator() && peek() == Token::YIELD) {
|
| - return ParseYieldExpression(ok);
|
| - }
|
| -
|
| - Scanner::Location before = scanner()->peek_location();
|
| - Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK);
|
| -
|
| - if (!Token::IsAssignmentOp(peek())) {
|
| - // Parsed conditional expression only (no assignment).
|
| - return expression;
|
| - }
|
| -
|
| - if (!scope_->is_classic_mode() &&
|
| - expression.IsIdentifier() &&
|
| - expression.AsIdentifier().IsEvalOrArguments()) {
|
| - Scanner::Location after = scanner()->location();
|
| - PreParserTraits::ReportMessageAt(before.beg_pos, after.end_pos,
|
| - "strict_eval_arguments", NULL);
|
| - *ok = false;
|
| - return Expression::Default();
|
| - }
|
| -
|
| - Token::Value op = Next(); // Get assignment operator.
|
| - ParseAssignmentExpression(accept_IN, CHECK_OK);
|
| -
|
| - if ((op == Token::ASSIGN) && expression.IsThisProperty()) {
|
| - function_state_->AddProperty();
|
| - }
|
| -
|
| - return Expression::Default();
|
| -}
|
| -
|
| -
|
| -// Precedence = 3
|
| -PreParser::Expression PreParser::ParseYieldExpression(bool* ok) {
|
| - // YieldExpression ::
|
| - // 'yield' '*'? AssignmentExpression
|
| - Consume(Token::YIELD);
|
| - Check(Token::MUL);
|
| -
|
| - ParseAssignmentExpression(false, CHECK_OK);
|
| -
|
| - return Expression::Default();
|
| -}
|
| -
|
| -
|
| // Precedence = 3
|
| PreParser::Expression PreParser::ParseConditionalExpression(bool accept_IN,
|
| bool* ok) {
|
| @@ -942,15 +897,9 @@ PreParser::Expression PreParser::ParseUnaryExpression(bool* ok) {
|
| return Expression::Default();
|
| } else if (Token::IsCountOp(op)) {
|
| op = Next();
|
| - Scanner::Location before = scanner()->peek_location();
|
| Expression expression = ParseUnaryExpression(CHECK_OK);
|
| - if (!scope_->is_classic_mode() &&
|
| - expression.IsIdentifier() &&
|
| - expression.AsIdentifier().IsEvalOrArguments()) {
|
| - Scanner::Location after = scanner()->location();
|
| - PreParserTraits::ReportMessageAt(before.beg_pos, after.end_pos,
|
| - "strict_eval_arguments", NULL);
|
| - *ok = false;
|
| + if (strict_mode() == STRICT) {
|
| + CheckStrictModeLValue(expression, CHECK_OK);
|
| }
|
| return Expression::Default();
|
| } else {
|
| @@ -963,18 +912,11 @@ PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) {
|
| // PostfixExpression ::
|
| // LeftHandSideExpression ('++' | '--')?
|
|
|
| - Scanner::Location before = scanner()->peek_location();
|
| Expression expression = ParseLeftHandSideExpression(CHECK_OK);
|
| if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
|
| Token::IsCountOp(peek())) {
|
| - if (!scope_->is_classic_mode() &&
|
| - expression.IsIdentifier() &&
|
| - expression.AsIdentifier().IsEvalOrArguments()) {
|
| - Scanner::Location after = scanner()->location();
|
| - PreParserTraits::ReportMessageAt(before.beg_pos, after.end_pos,
|
| - "strict_eval_arguments", NULL);
|
| - *ok = false;
|
| - return Expression::Default();
|
| + if (strict_mode() == STRICT) {
|
| + CheckStrictModeLValue(expression, CHECK_OK);
|
| }
|
| Next();
|
| return Expression::Default();
|
| @@ -1063,20 +1005,25 @@ PreParser::Expression PreParser::ParseMemberExpression(bool* ok) {
|
| Expression result = Expression::Default();
|
| if (peek() == Token::FUNCTION) {
|
| Consume(Token::FUNCTION);
|
| -
|
| + int function_token_position = position();
|
| bool is_generator = allow_generators() && Check(Token::MUL);
|
| Identifier name = Identifier::Default();
|
| bool is_strict_reserved_name = false;
|
| Scanner::Location function_name_location = Scanner::Location::invalid();
|
| + FunctionLiteral::FunctionType function_type =
|
| + FunctionLiteral::ANONYMOUS_EXPRESSION;
|
| if (peek_any_identifier()) {
|
| name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
|
| CHECK_OK);
|
| function_name_location = scanner()->location();
|
| + function_type = FunctionLiteral::NAMED_EXPRESSION;
|
| }
|
| result = ParseFunctionLiteral(name,
|
| function_name_location,
|
| is_strict_reserved_name,
|
| is_generator,
|
| + function_token_position,
|
| + function_type,
|
| CHECK_OK);
|
| } else {
|
| result = ParsePrimaryExpression(CHECK_OK);
|
| @@ -1122,116 +1069,13 @@ PreParser::Expression PreParser::ParseMemberExpressionContinuation(
|
| }
|
|
|
|
|
| -PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
|
| - // ObjectLiteral ::
|
| - // '{' (
|
| - // ((IdentifierName | String | Number) ':' AssignmentExpression)
|
| - // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
|
| - // )*[','] '}'
|
| -
|
| - ObjectLiteralChecker checker(this, scope_->language_mode());
|
| -
|
| - Expect(Token::LBRACE, CHECK_OK);
|
| - while (peek() != Token::RBRACE) {
|
| - Token::Value next = peek();
|
| - switch (next) {
|
| - case Token::IDENTIFIER:
|
| - case Token::FUTURE_RESERVED_WORD:
|
| - case Token::FUTURE_STRICT_RESERVED_WORD: {
|
| - bool is_getter = false;
|
| - bool is_setter = false;
|
| - ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
|
| - if ((is_getter || is_setter) && peek() != Token::COLON) {
|
| - Token::Value name = Next();
|
| - bool is_keyword = Token::IsKeyword(name);
|
| - if (name != Token::IDENTIFIER &&
|
| - name != Token::FUTURE_RESERVED_WORD &&
|
| - name != Token::FUTURE_STRICT_RESERVED_WORD &&
|
| - name != Token::NUMBER &&
|
| - name != Token::STRING &&
|
| - !is_keyword) {
|
| - *ok = false;
|
| - return Expression::Default();
|
| - }
|
| - if (!is_keyword) {
|
| - LogSymbol();
|
| - }
|
| - PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
|
| - checker.CheckProperty(name, type, CHECK_OK);
|
| - ParseFunctionLiteral(Identifier::Default(),
|
| - scanner()->location(),
|
| - false, // reserved words are allowed here
|
| - false, // not a generator
|
| - CHECK_OK);
|
| - if (peek() != Token::RBRACE) {
|
| - Expect(Token::COMMA, CHECK_OK);
|
| - }
|
| - continue; // restart the while
|
| - }
|
| - checker.CheckProperty(next, kValueProperty, CHECK_OK);
|
| - break;
|
| - }
|
| - case Token::STRING:
|
| - Consume(next);
|
| - checker.CheckProperty(next, kValueProperty, CHECK_OK);
|
| - LogSymbol();
|
| - break;
|
| - case Token::NUMBER:
|
| - Consume(next);
|
| - checker.CheckProperty(next, kValueProperty, CHECK_OK);
|
| - break;
|
| - default:
|
| - if (Token::IsKeyword(next)) {
|
| - Consume(next);
|
| - checker.CheckProperty(next, kValueProperty, CHECK_OK);
|
| - LogSymbol();
|
| - } else {
|
| - // Unexpected token.
|
| - *ok = false;
|
| - return Expression::Default();
|
| - }
|
| - }
|
| -
|
| - Expect(Token::COLON, CHECK_OK);
|
| - ParseAssignmentExpression(true, CHECK_OK);
|
| -
|
| - // TODO(1240767): Consider allowing trailing comma.
|
| - if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
|
| - }
|
| - Expect(Token::RBRACE, CHECK_OK);
|
| -
|
| - function_state_->NextMaterializedLiteralIndex();
|
| - return Expression::Default();
|
| -}
|
| -
|
| -
|
| -PreParser::Arguments PreParser::ParseArguments(bool* ok) {
|
| - // Arguments ::
|
| - // '(' (AssignmentExpression)*[','] ')'
|
| -
|
| - Expect(Token::LPAREN, ok);
|
| - if (!*ok) return -1;
|
| - bool done = (peek() == Token::RPAREN);
|
| - int argc = 0;
|
| - while (!done) {
|
| - ParseAssignmentExpression(true, ok);
|
| - if (!*ok) return -1;
|
| - argc++;
|
| - done = (peek() == Token::RPAREN);
|
| - if (!done) {
|
| - Expect(Token::COMMA, ok);
|
| - if (!*ok) return -1;
|
| - }
|
| - }
|
| - Expect(Token::RPAREN, ok);
|
| - return argc;
|
| -}
|
| -
|
| PreParser::Expression PreParser::ParseFunctionLiteral(
|
| Identifier function_name,
|
| Scanner::Location function_name_location,
|
| bool name_is_strict_reserved,
|
| bool is_generator,
|
| + int function_token_pos,
|
| + FunctionLiteral::FunctionType function_type,
|
| bool* ok) {
|
| // Function ::
|
| // '(' FormalParameterList? ')' '{' FunctionBody '}'
|
| @@ -1265,14 +1109,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
|
| reserved_error_loc = scanner()->location();
|
| }
|
|
|
| - int prev_value;
|
| - if (scanner()->is_literal_ascii()) {
|
| - prev_value =
|
| - duplicate_finder.AddAsciiSymbol(scanner()->literal_ascii_string(), 1);
|
| - } else {
|
| - prev_value =
|
| - duplicate_finder.AddUtf16Symbol(scanner()->literal_utf16_string(), 1);
|
| - }
|
| + int prev_value = scanner()->FindSymbol(&duplicate_finder, 1);
|
|
|
| if (!dupe_error_loc.IsValid() && prev_value != 0) {
|
| dupe_error_loc = scanner()->location();
|
| @@ -1302,7 +1139,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
|
|
|
| // Validate strict mode. We can do this only after parsing the function,
|
| // since the function can declare itself strict.
|
| - if (!scope_->is_classic_mode()) {
|
| + if (strict_mode() == STRICT) {
|
| if (function_name.IsEvalOrArguments()) {
|
| ReportMessageAt(function_name_location, "strict_eval_arguments");
|
| *ok = false;
|
| @@ -1340,9 +1177,10 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
|
|
|
| void PreParser::ParseLazyFunctionLiteralBody(bool* ok) {
|
| int body_start = position();
|
| - log_->PauseRecording();
|
| + bool is_logging = log_->ShouldLogSymbols();
|
| + if (is_logging) log_->PauseRecording();
|
| ParseSourceElements(Token::RBRACE, ok);
|
| - log_->ResumeRecording();
|
| + if (is_logging) log_->ResumeRecording();
|
| if (!*ok) return;
|
|
|
| // Position right after terminal '}'.
|
| @@ -1351,7 +1189,7 @@ void PreParser::ParseLazyFunctionLiteralBody(bool* ok) {
|
| log_->LogFunction(body_start, body_end,
|
| function_state_->materialized_literal_count(),
|
| function_state_->expected_property_count(),
|
| - scope_->language_mode());
|
| + strict_mode());
|
| }
|
|
|
|
|
| @@ -1374,11 +1212,8 @@ PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
|
|
|
|
|
| void PreParser::LogSymbol() {
|
| - int identifier_pos = position();
|
| - if (scanner()->is_literal_ascii()) {
|
| - log_->LogAsciiSymbol(identifier_pos, scanner()->literal_ascii_string());
|
| - } else {
|
| - log_->LogUtf16Symbol(identifier_pos, scanner()->literal_utf16_string());
|
| + if (log_->ShouldLogSymbols()) {
|
| + scanner()->LogSymbol(log_, position());
|
| }
|
| }
|
|
|
|
|