Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  parser.py   Sprache: Python

 
# -*- coding: utf-8 -*-
# Copyright JS Foundation and other contributors, https://js.foundation/
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#   * Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
#   * Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

from __future__ import absolute_import, unicode_literals

from .objects import Object
from .compat import basestring, unicode
from .utils import format
from .error_handler import ErrorHandler
from .messages import Messages
from .scanner import RawToken, Scanner, SourceLocation, Position, RegExp
from .token import Token, TokenName
from .syntax import Syntax
from . import nodes as Node


class Value(object):
    def __init__(self, value):
        self.value = value


class Params(object):
    def __init__(self, simple=None, message=None, stricted=None, firstRestricted=None, inFor=None, paramSet=None, params=None, get=None):
        self.simple = simple
        self.message = message
        self.stricted = stricted
        self.firstRestricted = firstRestricted
        self.inFor = inFor
        self.paramSet = paramSet
        self.params = params
        self.get = get


class Config(Object):
    def __init__(self, range=False, loc=False, source=None, tokens=False, comment=False, tolerant=False, **options):
        self.range = range
        self.loc = loc
        self.source = source
        self.tokens = tokens
        self.comment = comment
        self.tolerant = tolerant
        for k, v in options.items():
            setattr(self, k, v)


class Context(object):
    def __init__(self, isModule=False, allowAwait=False, allowIn=True, allowStrictDirective=True, allowYield=True, firstCoverInitializedNameError=None, isAssignmentTarget=False, isBindingElement=False, inFunctionBody=False, inIteration=False, inSwitch=FalselabelSet=None, strict=False):
        self.isModule = isModule
        self.allowAwait = allowAwait
        self.allowIn = allowIn
        self.allowStrictDirective = allowStrictDirective
        self.allowYield = allowYield
        self.firstCoverInitializedNameError = firstCoverInitializedNameError
        self.isAssignmentTarget = isAssignmentTarget
        self.isBindingElement = isBindingElement
        self.inFunctionBody = inFunctionBody
        self.inIteration = inIteration
        self.inSwitch = inSwitch
        self.labelSet = {} if labelSet is None else labelSet
        self.strict = strict


class Marker(object):
    def __init__(self, index=None, line=None, column=None):
        self.index = index
        self.line = line
        self.column = column


class TokenEntry(Object):
    def __init__(self, type=None, value=None, regex=None, range=None, loc=None):
        self.type = type
        self.value = value
        self.regex = regex
        self.range = range
        self.loc = loc


class Parser(object):
    def __init__(self, code, options={}, delegate=None):
        self.config = Config(**options)

        self.delegate = delegate

        self.errorHandler = ErrorHandler()
        self.errorHandler.tolerant = self.config.tolerant
        self.scanner = Scanner(code, self.errorHandler)
        self.scanner.trackComment = self.config.comment

        self.operatorPrecedence = {
            '||': 1,
            '&&': 2,
            '|': 3,
            '^': 4,
            '&': 5,
            '==': 6,
            '!=': 6,
            '===': 6,
            '!==': 6,
            '<': 7,
            '>': 7,
            '<=': 7,
            '>=': 7,
            'instanceof': 7,
            'in': 7,
            '<<': 8,
            '>>': 8,
            '>>>': 8,
            '+': 9,
            '-': 9,
            '*': 11,
            '/': 11,
            '%': 11,
        }

        self.lookahead = RawToken(
            type=Token.EOF,
            value='',
            lineNumber=self.scanner.lineNumber,
            lineStart=0,
            start=0,
            end=0
        )
        self.hasLineTerminator = False

        self.context = Context(
            isModule=False,
            allowAwait=False,
            allowIn=True,
            allowStrictDirective=True,
            allowYield=True,
            firstCoverInitializedNameError=None,
            isAssignmentTarget=False,
            isBindingElement=False,
            inFunctionBody=False,
            inIteration=False,
            inSwitch=False,
            labelSet={},
            strict=False
        )
        self.tokens = []

        self.startMarker = Marker(
            index=0,
            line=self.scanner.lineNumber,
            column=0
        )
        self.lastMarker = Marker(
            index=0,
            line=self.scanner.lineNumber,
            column=0
        )
        self.nextToken()
        self.lastMarker = Marker(
            index=self.scanner.index,
            line=self.scanner.lineNumber,
            column=self.scanner.index - self.scanner.lineStart
        )

    def throwError(self, messageFormat, *args):
        msg = format(messageFormat, *args)
        index = self.lastMarker.index
        line = self.lastMarker.line
        column = self.lastMarker.column + 1
        raise self.errorHandler.createError(index, line, column, msg)

    def tolerateError(self, messageFormat, *args):
        msg = format(messageFormat, *args)
        index = self.lastMarker.index
        line = self.scanner.lineNumber
        column = self.lastMarker.column + 1
        self.errorHandler.tolerateError(index, line, column, msg)

    # Throw an exception because of the token.

    def unexpectedTokenError(self, token=None, message=None):
        msg = message or Messages.UnexpectedToken
        if token:
            if not message:
                typ = token.type
                if typ is Token.EOF:
                    msg = Messages.UnexpectedEOS
                elif typ is Token.Identifier:
                    msg = Messages.UnexpectedIdentifier
                elif typ is Token.NumericLiteral:
                    msg = Messages.UnexpectedNumber
                elif typ is Token.StringLiteral:
                    msg = Messages.UnexpectedString
                elif typ is Token.Template:
                    msg = Messages.UnexpectedTemplate
                elif typ is Token.Keyword:
                    if self.scanner.isFutureReservedWord(token.value):
                        msg = Messages.UnexpectedReserved
                    elif self.context.strict and self.scanner.isStrictModeReservedWord(token.value):
                        msg = Messages.StrictReservedWord
                else:
                    msg = Messages.UnexpectedToken
            value = token.value
        else:
            value = 'ILLEGAL'

        msg = msg.replace('%0', unicode(value), 1)

        if token and isinstance(token.lineNumber, int):
            index = token.start
            line = token.lineNumber
            lastMarkerLineStart = self.lastMarker.index - self.lastMarker.column
            column = token.start - lastMarkerLineStart + 1
            return self.errorHandler.createError(index, line, column, msg)
        else:
            index = self.lastMarker.index
            line = self.lastMarker.line
            column = self.lastMarker.column + 1
            return self.errorHandler.createError(index, line, column, msg)

    def throwUnexpectedToken(self, token=None, message=None):
        raise self.unexpectedTokenError(token, message)

    def tolerateUnexpectedToken(self, token=None, message=None):
        self.errorHandler.tolerate(self.unexpectedTokenError(token, message))

    def collectComments(self):
        if not self.config.comment:
            self.scanner.scanComments()
        else:
            comments = self.scanner.scanComments()
            if comments:
                for e in comments:
                    if e.multiLine:
                        node = Node.BlockComment(self.scanner.source[e.slice[0]:e.slice[1]])
                    else:
                        node = Node.LineComment(self.scanner.source[e.slice[0]:e.slice[1]])
                    if self.config.range:
                        node.range = e.range
                    if self.config.loc:
                        node.loc = e.loc
                    if self.delegate:
                        metadata = SourceLocation(
                            start=Position(
                                line=e.loc.start.line,
                                column=e.loc.start.column,
                                offset=e.range[0],
                            ),
                            end=Position(
                                line=e.loc.end.line,
                                column=e.loc.end.column,
                                offset=e.range[1],
                            )
                        )
                        new_node = self.delegate(node, metadata)
                        if new_node is not None:
                            node = new_node

    # From internal representation to an external structure

    def getTokenRaw(self, token):
        return self.scanner.source[token.start:token.end]

    def convertToken(self, token):
        t = TokenEntry(
            type=TokenName[token.type],
            value=self.getTokenRaw(token),
        )
        if self.config.range:
            t.range = [token.start, token.end]
        if self.config.loc:
            t.loc = SourceLocation(
                start=Position(
                    line=self.startMarker.line,
                    column=self.startMarker.column,
                ),
                end=Position(
                    line=self.scanner.lineNumber,
                    column=self.scanner.index - self.scanner.lineStart,
                ),
            )
        if token.type is Token.RegularExpression:
            t.regex = RegExp(
                pattern=token.pattern,
                flags=token.flags,
            )

        return t

    def nextToken(self):
        token = self.lookahead

        self.lastMarker.index = self.scanner.index
        self.lastMarker.line = self.scanner.lineNumber
        self.lastMarker.column = self.scanner.index - self.scanner.lineStart

        self.collectComments()

        if self.scanner.index != self.startMarker.index:
            self.startMarker.index = self.scanner.index
            self.startMarker.line = self.scanner.lineNumber
            self.startMarker.column = self.scanner.index - self.scanner.lineStart

        next = self.scanner.lex()
        self.hasLineTerminator = token.lineNumber != next.lineNumber

        if next and self.context.strict and next.type is Token.Identifier:
            if self.scanner.isStrictModeReservedWord(next.value):
                next.type = Token.Keyword
        self.lookahead = next

        if self.config.tokens and next.type is not Token.EOF:
            self.tokens.append(self.convertToken(next))

        return token

    def nextRegexToken(self):
        self.collectComments()

        token = self.scanner.scanRegExp()
        if self.config.tokens:
            # Pop the previous token, '/' or '/='
            # self is added from the lookahead token.
            self.tokens.pop()

            self.tokens.append(self.convertToken(token))

        # Prime the next lookahead.
        self.lookahead = token
        self.nextToken()

        return token

    def createNode(self):
        return Marker(
            index=self.startMarker.index,
            line=self.startMarker.line,
            column=self.startMarker.column,
        )

    def startNode(self, token, lastLineStart=0):
        column = token.start - token.lineStart
        line = token.lineNumber
        if column < 0:
            column += lastLineStart
            line -= 1

        return Marker(
            index=token.start,
            line=line,
            column=column,
        )

    def finalize(self, marker, node):
        if self.config.range:
            node.range = [marker.index, self.lastMarker.index]

        if self.config.loc:
            node.loc = SourceLocation(
                start=Position(
                    line=marker.line,
                    column=marker.column,
                ),
                end=Position(
                    line=self.lastMarker.line,
                    column=self.lastMarker.column,
                ),
            )
            if self.config.source:
                node.loc.source = self.config.source

        if self.delegate:
            metadata = SourceLocation(
                start=Position(
                    line=marker.line,
                    column=marker.column,
                    offset=marker.index,
                ),
                end=Position(
                    line=self.lastMarker.line,
                    column=self.lastMarker.column,
                    offset=self.lastMarker.index,
                )
            )
            new_node = self.delegate(node, metadata)
            if new_node is not None:
                node = new_node

        return node

    # Expect the next token to match the specified punctuator.
    # If not, an exception will be thrown.

    def expect(self, value):
        token = self.nextToken()
        if token.type is not Token.Punctuator or token.value != value:
            self.throwUnexpectedToken(token)

    # Quietly expect a comma when in tolerant mode, otherwise delegates to expect().

    def expectCommaSeparator(self):
        if self.config.tolerant:
            token = self.lookahead
            if token.type is Token.Punctuator and token.value == ',':
                self.nextToken()
            elif token.type is Token.Punctuator and token.value == ';':
                self.nextToken()
                self.tolerateUnexpectedToken(token)
            else:
                self.tolerateUnexpectedToken(token, Messages.UnexpectedToken)
        else:
            self.expect(',')

    # Expect the next token to match the specified keyword.
    # If not, an exception will be thrown.

    def expectKeyword(self, keyword):
        token = self.nextToken()
        if token.type is not Token.Keyword or token.value != keyword:
            self.throwUnexpectedToken(token)

    # Return true if the next token matches the specified punctuator.

    def match(self, *value):
        return self.lookahead.type is Token.Punctuator and self.lookahead.value in value

    # Return true if the next token matches the specified keyword

    def matchKeyword(self, *keyword):
        return self.lookahead.type is Token.Keyword and self.lookahead.value in keyword

    # Return true if the next token matches the specified contextual keyword
    # (where an identifier is sometimes a keyword depending on the context)

    def matchContextualKeyword(self, *keyword):
        return self.lookahead.type is Token.Identifier and self.lookahead.value in keyword

    # Return true if the next token is an assignment operator

    def matchAssign(self):
        if self.lookahead.type is not Token.Punctuator:
            return False

        op = self.lookahead.value
        return op in ('=''*=''**=''/=''%=''+=''-=''<<=''>>=''>>>=''&=''^=''|=')

    # Cover grammar support.
    #
    # When an assignment expression position starts with an left parenthesis, the determination of the type
    # of the syntax is to be deferred arbitrarily long until the end of the parentheses pair (plus a lookahead)
    # or the first comma. This situation also defers the determination of all the expressions nested in the pair.
    #
    # There are three productions that can be parsed in a parentheses pair that needs to be determined
    # after the outermost pair is closed. They are:
    #
    #   1. AssignmentExpression
    #   2. BindingElements
    #   3. AssignmentTargets
    #
    # In order to avoid exponential backtracking, we use two flags to denote if the production can be
    # binding element or assignment target.
    #
    # The three productions have the relationship:
    #
    #   BindingElements ⊆ AssignmentTargets ⊆ AssignmentExpression
    #
    # with a single exception that CoverInitializedName when used directly in an Expression, generates
    # an early error. Therefore, we need the third state, firstCoverInitializedNameError, to track the
    # first usage of CoverInitializedName and report it when we reached the end of the parentheses pair.
    #
    # isolateCoverGrammar function runs the given parser function with a new cover grammar context, and it does not
    # effect the current flags. This means the production the parser parses is only used as an expression. Therefore
    # the CoverInitializedName check is conducted.
    #
    # inheritCoverGrammar function runs the given parse function with a new cover grammar context, and it propagates
    # the flags outside of the parser. This means the production the parser parses is used as a part of a potential
    # pattern. The CoverInitializedName check is deferred.

    def isolateCoverGrammar(self, parseFunction):
        previousIsBindingElement = self.context.isBindingElement
        previousIsAssignmentTarget = self.context.isAssignmentTarget
        previousFirstCoverInitializedNameError = self.context.firstCoverInitializedNameError

        self.context.isBindingElement = True
        self.context.isAssignmentTarget = True
        self.context.firstCoverInitializedNameError = None

        result = parseFunction()
        if self.context.firstCoverInitializedNameError is not None:
            self.throwUnexpectedToken(self.context.firstCoverInitializedNameError)

        self.context.isBindingElement = previousIsBindingElement
        self.context.isAssignmentTarget = previousIsAssignmentTarget
        self.context.firstCoverInitializedNameError = previousFirstCoverInitializedNameError

        return result

    def inheritCoverGrammar(self, parseFunction):
        previousIsBindingElement = self.context.isBindingElement
        previousIsAssignmentTarget = self.context.isAssignmentTarget
        previousFirstCoverInitializedNameError = self.context.firstCoverInitializedNameError

        self.context.isBindingElement = True
        self.context.isAssignmentTarget = True
        self.context.firstCoverInitializedNameError = None

        result = parseFunction()

        self.context.isBindingElement = self.context.isBindingElement and previousIsBindingElement
        self.context.isAssignmentTarget = self.context.isAssignmentTarget and previousIsAssignmentTarget
        self.context.firstCoverInitializedNameError = previousFirstCoverInitializedNameError or self.context.firstCoverInitializedNameError

        return result

    def consumeSemicolon(self):
        if self.match(';'):
            self.nextToken()
        elif not self.hasLineTerminator:
            if self.lookahead.type is not Token.EOF and not self.match('}'):
                self.throwUnexpectedToken(self.lookahead)
            self.lastMarker.index = self.startMarker.index
            self.lastMarker.line = self.startMarker.line
            self.lastMarker.column = self.startMarker.column

    https://tc39.github.io/ecma262/#sec-primary-expression

    def parsePrimaryExpression(self):
        node = self.createNode()

        typ = self.lookahead.type
        if typ is Token.Identifier:
            if (self.context.isModule or self.context.allowAwait) and self.lookahead.value == 'await':
                self.tolerateUnexpectedToken(self.lookahead)
            expr = self.parseFunctionExpression() if self.matchAsyncFunction() else self.finalize(node, Node.Identifier(self.nextToken().value))

        elif typ in (
            Token.NumericLiteral,
            Token.StringLiteral,
        ):
            if self.context.strict and self.lookahead.octal:
                self.tolerateUnexpectedToken(self.lookahead, Messages.StrictOctalLiteral)
            self.context.isAssignmentTarget = False
            self.context.isBindingElement = False
            token = self.nextToken()
            raw = self.getTokenRaw(token)
            expr = self.finalize(node, Node.Literal(token.value, raw))

        elif typ is Token.BooleanLiteral:
            self.context.isAssignmentTarget = False
            self.context.isBindingElement = False
            token = self.nextToken()
            raw = self.getTokenRaw(token)
            expr = self.finalize(node, Node.Literal(token.value == 'true', raw))

        elif typ is Token.NullLiteral:
            self.context.isAssignmentTarget = False
            self.context.isBindingElement = False
            token = self.nextToken()
            raw = self.getTokenRaw(token)
            expr = self.finalize(node, Node.Literal(None, raw))

        elif typ is Token.Template:
            expr = self.parseTemplateLiteral()

        elif typ is Token.Punctuator:
            value = self.lookahead.value
            if value == '(':
                self.context.isBindingElement = False
                expr = self.inheritCoverGrammar(self.parseGroupExpression)
            elif value == '[':
                expr = self.inheritCoverGrammar(self.parseArrayInitializer)
            elif value == '{':
                expr = self.inheritCoverGrammar(self.parseObjectInitializer)
            elif value in ('/''/='):
                self.context.isAssignmentTarget = False
                self.context.isBindingElement = False
                self.scanner.index = self.startMarker.index
                token = self.nextRegexToken()
                raw = self.getTokenRaw(token)
                expr = self.finalize(node, Node.RegexLiteral(token.regex, raw, token.pattern, token.flags))
            else:
                expr = self.throwUnexpectedToken(self.nextToken())

        elif typ is Token.Keyword:
            if not self.context.strict and self.context.allowYield and self.matchKeyword('yield'):
                expr = self.parseIdentifierName()
            elif not self.context.strict and self.matchKeyword('let'):
                expr = self.finalize(node, Node.Identifier(self.nextToken().value))
            else:
                self.context.isAssignmentTarget = False
                self.context.isBindingElement = False
                if self.matchKeyword('function'):
                    expr = self.parseFunctionExpression()
                elif self.matchKeyword('this'):
                    self.nextToken()
                    expr = self.finalize(node, Node.ThisExpression())
                elif self.matchKeyword('class'):
                    expr = self.parseClassExpression()
                elif self.matchImportCall():
                    expr = self.parseImportCall()
                else:
                    expr = self.throwUnexpectedToken(self.nextToken())

        else:
            expr = self.throwUnexpectedToken(self.nextToken())

        return expr

    https://tc39.github.io/ecma262/#sec-array-initializer

    def parseSpreadElement(self):
        node = self.createNode()
        self.expect('...')
        arg = self.inheritCoverGrammar(self.parseAssignmentExpression)
        return self.finalize(node, Node.SpreadElement(arg))

    def parseArrayInitializer(self):
        node = self.createNode()
        elements = []

        self.expect('[')
        while not self.match(']'):
            if self.match(','):
                self.nextToken()
                elements.append(None)
            elif self.match('...'):
                element = self.parseSpreadElement()
                if not self.match(']'):
                    self.context.isAssignmentTarget = False
                    self.context.isBindingElement = False
                    self.expect(',')
                elements.append(element)
            else:
                elements.append(self.inheritCoverGrammar(self.parseAssignmentExpression))
                if not self.match(']'):
                    self.expect(',')
        self.expect(']')

        return self.finalize(node, Node.ArrayExpression(elements))

    https://tc39.github.io/ecma262/#sec-object-initializer

    def parsePropertyMethod(self, params):
        self.context.isAssignmentTarget = False
        self.context.isBindingElement = False

        previousStrict = self.context.strict
        previousAllowStrictDirective = self.context.allowStrictDirective
        self.context.allowStrictDirective = params.simple
        body = self.isolateCoverGrammar(self.parseFunctionSourceElements)
        if self.context.strict and params.firstRestricted:
            self.tolerateUnexpectedToken(params.firstRestricted, params.message)
        if self.context.strict and params.stricted:
            self.tolerateUnexpectedToken(params.stricted, params.message)
        self.context.strict = previousStrict
        self.context.allowStrictDirective = previousAllowStrictDirective

        return body

    def parsePropertyMethodFunction(self):
        isGenerator = False
        node = self.createNode()

        previousAllowYield = self.context.allowYield
        self.context.allowYield = True
        params = self.parseFormalParameters()
        method = self.parsePropertyMethod(params)
        self.context.allowYield = previousAllowYield

        return self.finalize(node, Node.FunctionExpression(None, params.params, method, isGenerator))

    def parsePropertyMethodAsyncFunction(self):
        node = self.createNode()

        previousAllowYield = self.context.allowYield
        previousAwait = self.context.allowAwait
        self.context.allowYield = False
        self.context.allowAwait = True
        params = self.parseFormalParameters()
        method = self.parsePropertyMethod(params)
        self.context.allowYield = previousAllowYield
        self.context.allowAwait = previousAwait

        return self.finalize(node, Node.AsyncFunctionExpression(None, params.params, method))

    def parseObjectPropertyKey(self):
        node = self.createNode()
        token = self.nextToken()

        typ = token.type
        if typ in (
            Token.StringLiteral,
            Token.NumericLiteral,
        ):
            if self.context.strict and token.octal:
                self.tolerateUnexpectedToken(token, Messages.StrictOctalLiteral)
            raw = self.getTokenRaw(token)
            key = self.finalize(node, Node.Literal(token.value, raw))

        elif typ in (
            Token.Identifier,
            Token.BooleanLiteral,
            Token.NullLiteral,
            Token.Keyword,
        ):
            key = self.finalize(node, Node.Identifier(token.value))

        elif typ is Token.Punctuator:
            if token.value == '[':
                key = self.isolateCoverGrammar(self.parseAssignmentExpression)
                self.expect(']')
            else:
                key = self.throwUnexpectedToken(token)

        else:
            key = self.throwUnexpectedToken(token)

        return key

    def isPropertyKey(self, key, value):
        return (
            (key.type is Syntax.Identifier and key.name == value) or
            (key.type is Syntax.Literal and key.value == value)
        )

    def parseObjectProperty(self, hasProto):
        node = self.createNode()
        token = self.lookahead

        key = None
        value = None

        computed = False
        method = False
        shorthand = False
        isAsync = False

        if token.type is Token.Identifier:
            id = token.value
            self.nextToken()
            computed = self.match('[')
            isAsync = not self.hasLineTerminator and (id == 'async'and not (self.match(':''(''*'','))
            key = self.parseObjectPropertyKey() if isAsync else self.finalize(node, Node.Identifier(id))
        elif self.match('*'):
            self.nextToken()
        else:
            computed = self.match('[')
            key = self.parseObjectPropertyKey()

        lookaheadPropertyKey = self.qualifiedPropertyName(self.lookahead)
        if token.type is Token.Identifier and not isAsync and token.value == 'get' and lookaheadPropertyKey:
            kind = 'get'
            computed = self.match('[')
            key = self.parseObjectPropertyKey()
            self.context.allowYield = False
            value = self.parseGetterMethod()

        elif token.type is Token.Identifier and not isAsync and token.value == 'set' and lookaheadPropertyKey:
            kind = 'set'
            computed = self.match('[')
            key = self.parseObjectPropertyKey()
            value = self.parseSetterMethod()

        elif token.type is Token.Punctuator and token.value == '*' and lookaheadPropertyKey:
            kind = 'init'
            computed = self.match('[')
            key = self.parseObjectPropertyKey()
            value = self.parseGeneratorMethod()
            method = True

        else:
            if not key:
                self.throwUnexpectedToken(self.lookahead)

            kind = 'init'
            if self.match(':'and not isAsync:
                if not computed and self.isPropertyKey(key, '__proto__'):
                    if hasProto.value:
                        self.tolerateError(Messages.DuplicateProtoProperty)
                    hasProto.value = True
                self.nextToken()
                value = self.inheritCoverGrammar(self.parseAssignmentExpression)

            elif self.match('('):
                value = self.parsePropertyMethodAsyncFunction() if isAsync else self.parsePropertyMethodFunction()
                method = True

            elif token.type is Token.Identifier:
                id = self.finalize(node, Node.Identifier(token.value))
                if self.match('='):
                    self.context.firstCoverInitializedNameError = self.lookahead
                    self.nextToken()
                    shorthand = True
                    init = self.isolateCoverGrammar(self.parseAssignmentExpression)
                    value = self.finalize(node, Node.AssignmentPattern(id, init))
                else:
                    shorthand = True
                    value = id
            else:
                self.throwUnexpectedToken(self.nextToken())

        return self.finalize(node, Node.Property(kind, key, computed, value, method, shorthand))

    def parseObjectInitializer(self):
        node = self.createNode()

        self.expect('{')
        properties = []
        hasProto = Value(False)
        while not self.match('}'):
            properties.append(self.parseSpreadElement() if self.match('...'else self.parseObjectProperty(hasProto))
            if not self.match('}'):
                self.expectCommaSeparator()
        self.expect('}')

        return self.finalize(node, Node.ObjectExpression(properties))

    https://tc39.github.io/ecma262/#sec-template-literals

    def parseTemplateHead(self):
        assert self.lookahead.head, 'Template literal must start with a template head'

        node = self.createNode()
        token = self.nextToken()
        raw = token.value
        cooked = token.cooked

        return self.finalize(node, Node.TemplateElement(raw, cooked, token.tail))

    def parseTemplateElement(self):
        if self.lookahead.type is not Token.Template:
            self.throwUnexpectedToken()

        node = self.createNode()
        token = self.nextToken()
        raw = token.value
        cooked = token.cooked

        return self.finalize(node, Node.TemplateElement(raw, cooked, token.tail))

    def parseTemplateLiteral(self):
        node = self.createNode()

        expressions = []
        quasis = []

        quasi = self.parseTemplateHead()
        quasis.append(quasi)
        while not quasi.tail:
            expressions.append(self.parseExpression())
            quasi = self.parseTemplateElement()
            quasis.append(quasi)

        return self.finalize(node, Node.TemplateLiteral(quasis, expressions))

    https://tc39.github.io/ecma262/#sec-grouping-operator

    def reinterpretExpressionAsPattern(self, expr):
        typ = expr.type
        if typ in (
            Syntax.Identifier,
            Syntax.MemberExpression,
            Syntax.RestElement,
            Syntax.AssignmentPattern,
        ):
            pass
        elif typ is Syntax.SpreadElement:
            expr.type = Syntax.RestElement
            self.reinterpretExpressionAsPattern(expr.argument)
        elif typ is Syntax.ArrayExpression:
            expr.type = Syntax.ArrayPattern
            for elem in expr.elements:
                if elem is not None:
                    self.reinterpretExpressionAsPattern(elem)
        elif typ is Syntax.ObjectExpression:
            expr.type = Syntax.ObjectPattern
            for prop in expr.properties:
                self.reinterpretExpressionAsPattern(prop if prop.type is Syntax.SpreadElement else prop.value)
        elif typ is Syntax.AssignmentExpression:
            expr.type = Syntax.AssignmentPattern
            del expr.operator
            self.reinterpretExpressionAsPattern(expr.left)
        else:
            # Allow other node type for tolerant parsing.
            pass

    def parseGroupExpression(self):
        self.expect('(')
        if self.match(')'):
            self.nextToken()
            if not self.match('=>'):
                self.expect('=>')
            expr = Node.ArrowParameterPlaceHolder([])
        else:
            startToken = self.lookahead
            params = []
            if self.match('...'):
                expr = self.parseRestElement(params)
                self.expect(')')
                if not self.match('=>'):
                    self.expect('=>')
                expr = Node.ArrowParameterPlaceHolder([expr])
            else:
                arrow = False
                self.context.isBindingElement = True
                expr = self.inheritCoverGrammar(self.parseAssignmentExpression)

                if self.match(','):
                    expressions = []

                    self.context.isAssignmentTarget = False
                    expressions.append(expr)
                    while self.lookahead.type is not Token.EOF:
                        if not self.match(','):
                            break
                        self.nextToken()
                        if self.match(')'):
                            self.nextToken()
                            for expression in expressions:
                                self.reinterpretExpressionAsPattern(expression)
                            arrow = True
                            expr = Node.ArrowParameterPlaceHolder(expressions)
                        elif self.match('...'):
                            if not self.context.isBindingElement:
                                self.throwUnexpectedToken(self.lookahead)
                            expressions.append(self.parseRestElement(params))
                            self.expect(')')
                            if not self.match('=>'):
                                self.expect('=>')
                            self.context.isBindingElement = False
                            for expression in expressions:
                                self.reinterpretExpressionAsPattern(expression)
                            arrow = True
                            expr = Node.ArrowParameterPlaceHolder(expressions)
                        else:
                            expressions.append(self.inheritCoverGrammar(self.parseAssignmentExpression))
                        if arrow:
                            break
                    if not arrow:
                        expr = self.finalize(self.startNode(startToken), Node.SequenceExpression(expressions))

                if not arrow:
                    self.expect(')')
                    if self.match('=>'):
                        if expr.type is Syntax.Identifier and expr.name == 'yield':
                            arrow = True
                            expr = Node.ArrowParameterPlaceHolder([expr])
                        if not arrow:
                            if not self.context.isBindingElement:
                                self.throwUnexpectedToken(self.lookahead)

                            if expr.type is Syntax.SequenceExpression:
                                for expression in expr.expressions:
                                    self.reinterpretExpressionAsPattern(expression)
                            else:
                                self.reinterpretExpressionAsPattern(expr)

                            if expr.type is Syntax.SequenceExpression:
                                parameters = expr.expressions
                            else:
                                parameters = [expr]
                            expr = Node.ArrowParameterPlaceHolder(parameters)
                    self.context.isBindingElement = False

        return expr

    https://tc39.github.io/ecma262/#sec-left-hand-side-expressions

    def parseArguments(self):
        self.expect('(')
        args = []
        if not self.match(')'):
            while True:
                if self.match('...'):
                    expr = self.parseSpreadElement()
                else:
                    expr = self.isolateCoverGrammar(self.parseAssignmentExpression)
                args.append(expr)
                if self.match(')'):
                    break
                self.expectCommaSeparator()
                if self.match(')'):
                    break
        self.expect(')')

        return args

    def isIdentifierName(self, token):
        return (
            token.type is Token.Identifier or
            token.type is Token.Keyword or
            token.type is Token.BooleanLiteral or
            token.type is Token.NullLiteral
        )

    def parseIdentifierName(self):
        node = self.createNode()
        token = self.nextToken()
        if not self.isIdentifierName(token):
            self.throwUnexpectedToken(token)
        return self.finalize(node, Node.Identifier(token.value))

    def parseNewExpression(self):
        node = self.createNode()

        id = self.parseIdentifierName()
        assert id.name == 'new''New expression must start with `new`'

        if self.match('.'):
            self.nextToken()
            if self.lookahead.type is Token.Identifier and self.context.inFunctionBody and self.lookahead.value == 'target':
                property = self.parseIdentifierName()
                expr = Node.MetaProperty(id, property)
            else:
                self.throwUnexpectedToken(self.lookahead)
        elif self.matchKeyword('import'):
            self.throwUnexpectedToken(self.lookahead)
        else:
            callee = self.isolateCoverGrammar(self.parseLeftHandSideExpression)
            args = self.parseArguments() if self.match('('else []
            expr = Node.NewExpression(callee, args)
            self.context.isAssignmentTarget = False
            self.context.isBindingElement = False

        return self.finalize(node, expr)

    def parseAsyncArgument(self):
        arg = self.parseAssignmentExpression()
        self.context.firstCoverInitializedNameError = None
        return arg

    def parseAsyncArguments(self):
        self.expect('(')
        args = []
        if not self.match(')'):
            while True:
                if self.match('...'):
                    expr = self.parseSpreadElement()
                else:
                    expr = self.isolateCoverGrammar(self.parseAsyncArgument)
                args.append(expr)
                if self.match(')'):
                    break
                self.expectCommaSeparator()
                if self.match(')'):
                    break
        self.expect(')')

        return args

    def matchImportCall(self):
        match = self.matchKeyword('import')
        if match:
            state = self.scanner.saveState()
            self.scanner.scanComments()
            next = self.scanner.lex()
            self.scanner.restoreState(state)
            match = (next.type is Token.Punctuator) and (next.value == '(')

        return match

    def parseImportCall(self):
        node = self.createNode()
        self.expectKeyword('import')
        return self.finalize(node, Node.Import())

    def parseLeftHandSideExpressionAllowCall(self):
        startToken = self.lookahead
        maybeAsync = self.matchContextualKeyword('async')

        previousAllowIn = self.context.allowIn
        self.context.allowIn = True

        if self.matchKeyword('super'and self.context.inFunctionBody:
            expr = self.createNode()
            self.nextToken()
            expr = self.finalize(expr, Node.Super())
            if not self.match('('and not self.match('.'and not self.match('['):
                self.throwUnexpectedToken(self.lookahead)
        else:
            expr = self.inheritCoverGrammar(self.parseNewExpression if self.matchKeyword('new'else self.parsePrimaryExpression)

        while True:
            if self.match('.'):
                self.context.isBindingElement = False
                self.context.isAssignmentTarget = True
                self.expect('.')
                property = self.parseIdentifierName()
                expr = self.finalize(self.startNode(startToken), Node.StaticMemberExpression(expr, property))

            elif self.match('('):
                asyncArrow = maybeAsync and (startToken.lineNumber == self.lookahead.lineNumber)
                self.context.isBindingElement = False
                self.context.isAssignmentTarget = False
                if asyncArrow:
                    args = self.parseAsyncArguments()
                else:
                    args = self.parseArguments()
                if expr.type is Syntax.Import and len(args) != 1:
                    self.tolerateError(Messages.BadImportCallArity)
                expr = self.finalize(self.startNode(startToken), Node.CallExpression(expr, args))
                if asyncArrow and self.match('=>'):
                    for arg in args:
                        self.reinterpretExpressionAsPattern(arg)
                    expr = Node.AsyncArrowParameterPlaceHolder(args)
            elif self.match('['):
                self.context.isBindingElement = False
                self.context.isAssignmentTarget = True
                self.expect('[')
                property = self.isolateCoverGrammar(self.parseExpression)
                self.expect(']')
                expr = self.finalize(self.startNode(startToken), Node.ComputedMemberExpression(expr, property))

            elif self.lookahead.type is Token.Template and self.lookahead.head:
                quasi = self.parseTemplateLiteral()
                expr = self.finalize(self.startNode(startToken), Node.TaggedTemplateExpression(expr, quasi))

            else:
                break

        self.context.allowIn = previousAllowIn

        return expr

    def parseSuper(self):
        node = self.createNode()

        self.expectKeyword('super')
        if not self.match('['and not self.match('.'):
            self.throwUnexpectedToken(self.lookahead)

        return self.finalize(node, Node.Super())

    def parseLeftHandSideExpression(self):
        assert self.context.allowIn, 'callee of new expression always allow in keyword.'

        node = self.startNode(self.lookahead)
        if self.matchKeyword('super'and self.context.inFunctionBody:
            expr = self.parseSuper()
        else:
            expr = self.inheritCoverGrammar(self.parseNewExpression if self.matchKeyword('new'else self.parsePrimaryExpression)

        while True:
            if self.match('['):
                self.context.isBindingElement = False
                self.context.isAssignmentTarget = True
                self.expect('[')
                property = self.isolateCoverGrammar(self.parseExpression)
                self.expect(']')
                expr = self.finalize(node, Node.ComputedMemberExpression(expr, property))

            elif self.match('.'):
                self.context.isBindingElement = False
                self.context.isAssignmentTarget = True
                self.expect('.')
                property = self.parseIdentifierName()
                expr = self.finalize(node, Node.StaticMemberExpression(expr, property))

            elif self.lookahead.type is Token.Template and self.lookahead.head:
                quasi = self.parseTemplateLiteral()
                expr = self.finalize(node, Node.TaggedTemplateExpression(expr, quasi))

            else:
                break

        return expr

    https://tc39.github.io/ecma262/#sec-update-expressions

    def parseUpdateExpression(self):
        startToken = self.lookahead

        if self.match('++''--'):
            node = self.startNode(startToken)
            token = self.nextToken()
            expr = self.inheritCoverGrammar(self.parseUnaryExpression)
            if self.context.strict and expr.type is Syntax.Identifier and self.scanner.isRestrictedWord(expr.name):
                self.tolerateError(Messages.StrictLHSPrefix)
            if not self.context.isAssignmentTarget:
                self.tolerateError(Messages.InvalidLHSInAssignment)
            prefix = True
            expr = self.finalize(node, Node.UpdateExpression(token.value, expr, prefix))
            self.context.isAssignmentTarget = False
            self.context.isBindingElement = False
        else:
            expr = self.inheritCoverGrammar(self.parseLeftHandSideExpressionAllowCall)
            if not self.hasLineTerminator and self.lookahead.type is Token.Punctuator:
                if self.match('++''--'):
                    if self.context.strict and expr.type is Syntax.Identifier and self.scanner.isRestrictedWord(expr.name):
                        self.tolerateError(Messages.StrictLHSPostfix)
                    if not self.context.isAssignmentTarget:
                        self.tolerateError(Messages.InvalidLHSInAssignment)
                    self.context.isAssignmentTarget = False
                    self.context.isBindingElement = False
                    operator = self.nextToken().value
                    prefix = False
                    expr = self.finalize(self.startNode(startToken), Node.UpdateExpression(operator, expr, prefix))

        return expr

    https://tc39.github.io/ecma262/#sec-unary-operators

    def parseAwaitExpression(self):
        node = self.createNode()
        self.nextToken()
        argument = self.parseUnaryExpression()
        return self.finalize(node, Node.AwaitExpression(argument))

    def parseUnaryExpression(self):
        if (
            self.match('+''-''~''!'or
            self.matchKeyword('delete''void''typeof')
        ):
            node = self.startNode(self.lookahead)
            token = self.nextToken()
            expr = self.inheritCoverGrammar(self.parseUnaryExpression)
            expr = self.finalize(node, Node.UnaryExpression(token.value, expr))
            if self.context.strict and expr.operator == 'delete' and expr.argument.type is Syntax.Identifier:
                self.tolerateError(Messages.StrictDelete)
            self.context.isAssignmentTarget = False
            self.context.isBindingElement = False
        elif self.context.allowAwait and self.matchContextualKeyword('await'):
            expr = self.parseAwaitExpression()
        else:
            expr = self.parseUpdateExpression()

        return expr

    def parseExponentiationExpression(self):
        startToken = self.lookahead

        expr = self.inheritCoverGrammar(self.parseUnaryExpression)
        if expr.type is not Syntax.UnaryExpression and self.match('**'):
            self.nextToken()
            self.context.isAssignmentTarget = False
            self.context.isBindingElement = False
            left = expr
            right = self.isolateCoverGrammar(self.parseExponentiationExpression)
            expr = self.finalize(self.startNode(startToken), Node.BinaryExpression('**', left, right))

        return expr

    https://tc39.github.io/ecma262/#sec-exp-operator
    https://tc39.github.io/ecma262/#sec-multiplicative-operators
    https://tc39.github.io/ecma262/#sec-additive-operators
    https://tc39.github.io/ecma262/#sec-bitwise-shift-operators
    https://tc39.github.io/ecma262/#sec-relational-operators
    https://tc39.github.io/ecma262/#sec-equality-operators
    https://tc39.github.io/ecma262/#sec-binary-bitwise-operators
    https://tc39.github.io/ecma262/#sec-binary-logical-operators

    def binaryPrecedence(self, token):
        op = token.value
        if token.type is Token.Punctuator:
            precedence = self.operatorPrecedence.get(op, 0)
        elif token.type is Token.Keyword:
            precedence = 7 if (op == 'instanceof' or (self.context.allowIn and op == 'in')) else 0
        else:
            precedence = 0
        return precedence

    def parseBinaryExpression(self):
        startToken = self.lookahead

        expr = self.inheritCoverGrammar(self.parseExponentiationExpression)

        token = self.lookahead
        prec = self.binaryPrecedence(token)
        if prec > 0:
            self.nextToken()

            self.context.isAssignmentTarget = False
            self.context.isBindingElement = False

            markers = [startToken, self.lookahead]
            left = expr
            right = self.isolateCoverGrammar(self.parseExponentiationExpression)

            stack = [left, token.value, right]
            precedences = [prec]
            while True:
                prec = self.binaryPrecedence(self.lookahead)
                if prec <= 0:
                    break

                # Reduce: make a binary expression from the three topmost entries.
                while len(stack) > 2 and prec <= precedences[-1]:
                    right = stack.pop()
                    operator = stack.pop()
                    precedences.pop()
                    left = stack.pop()
                    markers.pop()
                    node = self.startNode(markers[-1])
                    stack.append(self.finalize(node, Node.BinaryExpression(operator, left, right)))

                # Shift.
                stack.append(self.nextToken().value)
                precedences.append(prec)
                markers.append(self.lookahead)
                stack.append(self.isolateCoverGrammar(self.parseExponentiationExpression))

            # Final reduce to clean-up the stack.
            i = len(stack) - 1
            expr = stack[i]

            lastMarker = markers.pop()
            while i > 1:
                marker = markers.pop()
                lastLineStart = lastMarker.lineStart if lastMarker else 0
                node = self.startNode(marker, lastLineStart)
                operator = stack[i - 1]
                expr = self.finalize(node, Node.BinaryExpression(operator, stack[i - 2], expr))
                i -= 2
                lastMarker = marker

        return expr

    https://tc39.github.io/ecma262/#sec-conditional-operator

    def parseConditionalExpression(self):
        startToken = self.lookahead

        expr = self.inheritCoverGrammar(self.parseBinaryExpression)
        if self.match('?'):
            self.nextToken()

            previousAllowIn = self.context.allowIn
            self.context.allowIn = True
            consequent = self.isolateCoverGrammar(self.parseAssignmentExpression)
            self.context.allowIn = previousAllowIn

            self.expect(':')
            alternate = self.isolateCoverGrammar(self.parseAssignmentExpression)

            expr = self.finalize(self.startNode(startToken), Node.ConditionalExpression(expr, consequent, alternate))
            self.context.isAssignmentTarget = False
            self.context.isBindingElement = False

        return expr

    https://tc39.github.io/ecma262/#sec-assignment-operators

    def checkPatternParam(self, options, param):
        typ = param.type
        if typ is Syntax.Identifier:
            self.validateParam(options, param, param.name)
        elif typ is Syntax.RestElement:
            self.checkPatternParam(options, param.argument)
        elif typ is Syntax.AssignmentPattern:
            self.checkPatternParam(options, param.left)
        elif typ is Syntax.ArrayPattern:
            for element in param.elements:
                if element is not None:
                    self.checkPatternParam(options, element)
        elif typ is Syntax.ObjectPattern:
            for prop in param.properties:
                self.checkPatternParam(options, prop if prop.type is Syntax.RestElement else prop.value)

        options.simple = options.simple and isinstance(param, Node.Identifier)

    def reinterpretAsCoverFormalsList(self, expr):
        params = [expr]

        asyncArrow = False
        typ = expr.type
        if typ is Syntax.Identifier:
            pass
        elif typ is Syntax.ArrowParameterPlaceHolder:
            params = expr.params
            asyncArrow = expr.isAsync
        else:
            return None

        options = Params(
            simple=True,
            paramSet={},
        )

        for param in params:
            if param.type is Syntax.AssignmentPattern:
                if param.right.type is Syntax.YieldExpression:
                    if param.right.argument:
                        self.throwUnexpectedToken(self.lookahead)
                    param.right.type = Syntax.Identifier
                    param.right.name = 'yield'
                    del param.right.argument
                    del param.right.delegate
            elif asyncArrow and param.type is Syntax.Identifier and param.name == 'await':
                self.throwUnexpectedToken(self.lookahead)
            self.checkPatternParam(options, param)

        if self.context.strict or not self.context.allowYield:
            for param in params:
                if param.type is Syntax.YieldExpression:
                    self.throwUnexpectedToken(self.lookahead)

        if options.message is Messages.StrictParamDupe:
            token = options.stricted if self.context.strict else options.firstRestricted
            self.throwUnexpectedToken(token, options.message)

        return Params(
            simple=options.simple,
            params=params,
            stricted=options.stricted,
            firstRestricted=options.firstRestricted,
            message=options.message
        )

    def parseAssignmentExpression(self):
        if not self.context.allowYield and self.matchKeyword('yield'):
            expr = self.parseYieldExpression()
        else:
            startToken = self.lookahead
            token = startToken
            expr = self.parseConditionalExpression()

            if token.type is Token.Identifier and (token.lineNumber == self.lookahead.lineNumber) and token.value == 'async':
                if self.lookahead.type is Token.Identifier or self.matchKeyword('yield'):
                    arg = self.parsePrimaryExpression()
                    self.reinterpretExpressionAsPattern(arg)
                    expr = Node.AsyncArrowParameterPlaceHolder([arg])

            if expr.type is Syntax.ArrowParameterPlaceHolder or self.match('=>'):

                https://tc39.github.io/ecma262/#sec-arrow-function-definitions
                self.context.isAssignmentTarget = False
                self.context.isBindingElement = False
                isAsync = expr.isAsync
                list = self.reinterpretAsCoverFormalsList(expr)

                if list:
                    if self.hasLineTerminator:
                        self.tolerateUnexpectedToken(self.lookahead)
                    self.context.firstCoverInitializedNameError = None

                    previousStrict = self.context.strict
                    previousAllowStrictDirective = self.context.allowStrictDirective
                    self.context.allowStrictDirective = list.simple

                    previousAllowYield = self.context.allowYield
                    previousAwait = self.context.allowAwait
                    self.context.allowYield = True
                    self.context.allowAwait = isAsync

                    node = self.startNode(startToken)
                    self.expect('=>')
                    if self.match('{'):
                        previousAllowIn = self.context.allowIn
                        self.context.allowIn = True
                        body = self.parseFunctionSourceElements()
                        self.context.allowIn = previousAllowIn
                    else:
                        body = self.isolateCoverGrammar(self.parseAssignmentExpression)
                    expression = body.type is not Syntax.BlockStatement

                    if self.context.strict and list.firstRestricted:
                        self.throwUnexpectedToken(list.firstRestricted, list.message)
                    if self.context.strict and list.stricted:
                        self.tolerateUnexpectedToken(list.stricted, list.message)
                    if isAsync:
                        expr = self.finalize(node, Node.AsyncArrowFunctionExpression(list.params, body, expression))
                    else:
                        expr = self.finalize(node, Node.ArrowFunctionExpression(list.params, body, expression))

                    self.context.strict = previousStrict
                    self.context.allowStrictDirective = previousAllowStrictDirective
                    self.context.allowYield = previousAllowYield
                    self.context.allowAwait = previousAwait
            else:
                if self.matchAssign():
                    if not self.context.isAssignmentTarget:
                        self.tolerateError(Messages.InvalidLHSInAssignment)

                    if self.context.strict and expr.type is Syntax.Identifier:
                        id = expr
                        if self.scanner.isRestrictedWord(id.name):
                            self.tolerateUnexpectedToken(token, Messages.StrictLHSAssignment)
                        if self.scanner.isStrictModeReservedWord(id.name):
                            self.tolerateUnexpectedToken(token, Messages.StrictReservedWord)

                    if not self.match('='):
                        self.context.isAssignmentTarget = False
                        self.context.isBindingElement = False
                    else:
                        self.reinterpretExpressionAsPattern(expr)

                    token = self.nextToken()
                    operator = token.value
                    right = self.isolateCoverGrammar(self.parseAssignmentExpression)
                    expr = self.finalize(self.startNode(startToken), Node.AssignmentExpression(operator, expr, right))
                    self.context.firstCoverInitializedNameError = None

        return expr

    https://tc39.github.io/ecma262/#sec-comma-operator

    def parseExpression(self):
        startToken = self.lookahead
        expr = self.isolateCoverGrammar(self.parseAssignmentExpression)

        if self.match(','):
            expressions = []
            expressions.append(expr)
            while self.lookahead.type is not Token.EOF:
                if not self.match(','):
                    break
                self.nextToken()
                expressions.append(self.isolateCoverGrammar(self.parseAssignmentExpression))

            expr = self.finalize(self.startNode(startToken), Node.SequenceExpression(expressions))

        return expr

    https://tc39.github.io/ecma262/#sec-block

    def parseStatementListItem(self):
        self.context.isAssignmentTarget = True
        self.context.isBindingElement = True
        if self.lookahead.type is Token.Keyword:
            value = self.lookahead.value
            if value == 'export':
                if not self.context.isModule:
                    self.tolerateUnexpectedToken(self.lookahead, Messages.IllegalExportDeclaration)
                statement = self.parseExportDeclaration()
            elif value == 'import':
                if self.matchImportCall():
                    statement = self.parseExpressionStatement()
                else:
                    if not self.context.isModule:
                        self.tolerateUnexpectedToken(self.lookahead, Messages.IllegalImportDeclaration)
                    statement = self.parseImportDeclaration()
            elif value == 'const':
                statement = self.parseLexicalDeclaration(Params(inFor=False))
            elif value == 'function':
                statement = self.parseFunctionDeclaration()
            elif value == 'class':
                statement = self.parseClassDeclaration()
            elif value == 'let':
                statement = self.parseLexicalDeclaration(Params(inFor=False)) if self.isLexicalDeclaration() else self.parseStatement()
            else:
                statement = self.parseStatement()
        else:
            statement = self.parseStatement()

        return statement

    def parseBlock(self):
        node = self.createNode()

        self.expect('{')
        block = []
        while True:
            if self.match('}'):
                break
            block.append(self.parseStatementListItem())
        self.expect('}')

        return self.finalize(node, Node.BlockStatement(block))

    https://tc39.github.io/ecma262/#sec-let-and-const-declarations

    def parseLexicalBinding(self, kind, options):
        node = self.createNode()
        params = []
        id = self.parsePattern(params, kind)

        if self.context.strict and id.type is Syntax.Identifier:
            if self.scanner.isRestrictedWord(id.name):
                self.tolerateError(Messages.StrictVarName)

        init = None
        if kind == 'const':
            if not self.matchKeyword('in'and not self.matchContextualKeyword('of'):
                if self.match('='):
                    self.nextToken()
                    init = self.isolateCoverGrammar(self.parseAssignmentExpression)
                else:
                    self.throwError(Messages.DeclarationMissingInitializer, 'const')
        elif (not options.inFor and id.type is not Syntax.Identifier) or self.match('='):
            self.expect('=')
            init = self.isolateCoverGrammar(self.parseAssignmentExpression)

        return self.finalize(node, Node.VariableDeclarator(id, init))

    def parseBindingList(self, kind, options):
        lst = [self.parseLexicalBinding(kind, options)]

        while self.match(','):
            self.nextToken()
            lst.append(self.parseLexicalBinding(kind, options))

        return lst

    def isLexicalDeclaration(self):
        state = self.scanner.saveState()
        self.scanner.scanComments()
        next = self.scanner.lex()
        self.scanner.restoreState(state)

        return (
            (next.type is Token.Identifier) or
            (next.type is Token.Punctuator and next.value == '['or
            (next.type is Token.Punctuator and next.value == '{'or
            (next.type is Token.Keyword and next.value == 'let'or
            (next.type is Token.Keyword and next.value == 'yield')
        )

    def parseLexicalDeclaration(self, options):
        node = self.createNode()
        kind = self.nextToken().value
        assert kind == 'let' or kind == 'const''Lexical declaration must be either or const'

        declarations = self.parseBindingList(kind, options)
        self.consumeSemicolon()

        return self.finalize(node, Node.VariableDeclaration(declarations, kind))

    https://tc39.github.io/ecma262/#sec-destructuring-binding-patterns

    def parseBindingRestElement(self, params, kind=None):
        node = self.createNode()

        self.expect('...')
        arg = self.parsePattern(params, kind)

        return self.finalize(node, Node.RestElement(arg))

    def parseArrayPattern(self, params, kind=None):
        node = self.createNode()

        self.expect('[')
        elements = []
        while not self.match(']'):
            if self.match(','):
                self.nextToken()
                elements.append(None)
            else:
                if self.match('...'):
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=95 H=92 G=93

¤ Dauer der Verarbeitung: 0.24 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge