private static SourceSpan GetSpan(TokenWithSpan context) {
     return new SourceSpan(
         new SourceLocation(
             context.Start,
             context.StartLine,
             context.StartColumn
         ),
         new SourceLocation(
             context.End,
             context.EndLine,
             context.EndColumn
         )
     );
 }
        private static TokenInfo ToTokenKind(TokenWithSpan context) {
            switch (context.Token) {
                case JSToken.Semicolon:                      // ;
                    return new TokenInfo(
                        GetSpan(context),
                        TokenCategory.Delimiter,
                        TokenTriggers.None
                    );
                case JSToken.RightCurly:                     // }
                case JSToken.LeftCurly:                      // {
                    return new TokenInfo(
                        GetSpan(context),
                        TokenCategory.Grouping,
                        TokenTriggers.MatchBraces
                    );
                case JSToken.Debugger:
                case JSToken.Var:
                case JSToken.If:
                case JSToken.For:
                case JSToken.Do:
                case JSToken.While:
                case JSToken.Continue:
                case JSToken.Break:
                case JSToken.Return:
                case JSToken.With:
                case JSToken.Switch:
                case JSToken.Throw:
                case JSToken.Try:
                case JSToken.Function:
                case JSToken.Else:
                case JSToken.Null:
                case JSToken.True:
                case JSToken.False:
                case JSToken.This:
                case JSToken.Void:
                case JSToken.TypeOf:
                case JSToken.Delete:
                case JSToken.Case:
                case JSToken.Catch:
                case JSToken.Default:
                case JSToken.Finally:
                case JSToken.New:
                case JSToken.Class:
                case JSToken.Const:
                case JSToken.Enum:
                case JSToken.Export:
                case JSToken.Extends:
                case JSToken.Import:
                case JSToken.Super:

                // ECMA strict reserved words
                case JSToken.Implements:
                case JSToken.In:
                case JSToken.InstanceOf:
                case JSToken.Interface:
                case JSToken.Let:
                case JSToken.Package:
                case JSToken.Private:
                case JSToken.Protected:
                case JSToken.Public:
                case JSToken.Static:
                case JSToken.Yield:
                // always okay for identifiers
                case JSToken.Get:
                case JSToken.Set:

                    return new TokenInfo(
                        GetSpan(context),
                        TokenCategory.Keyword,
                        TokenTriggers.None
                    );

                // used by both statement and expression switches

                // main expression switch
                case JSToken.Identifier:
                    return new TokenInfo(
                        GetSpan(context),
                        TokenCategory.Identifier,
                        TokenTriggers.None
                    );

                case JSToken.StringLiteral:
                    return new TokenInfo(
                        GetSpan(context),
                        TokenCategory.StringLiteral,
                        TokenTriggers.None
                    );
                case JSToken.IntegerLiteral:
                case JSToken.NumericLiteral:
                    return new TokenInfo(
                        GetSpan(context),
                        TokenCategory.NumericLiteral,
                        TokenTriggers.None
                    );

                case JSToken.LeftParenthesis:                // (
                    return new TokenInfo(
                        GetSpan(context),
                        TokenCategory.Grouping,
                        TokenTriggers.ParameterStart | TokenTriggers.MatchBraces
                    );
                case JSToken.RightParenthesis:               // )
                    return new TokenInfo(
                        GetSpan(context),
                        TokenCategory.Grouping,
                        TokenTriggers.ParameterEnd | TokenTriggers.MatchBraces
                    );
                case JSToken.LeftBracket:                    // [
                    return new TokenInfo(
                        GetSpan(context),
                        TokenCategory.Grouping,
                        TokenTriggers.MatchBraces
                    );
                case JSToken.RightBracket:                   // ]
                    return new TokenInfo(
                        GetSpan(context),
                        TokenCategory.Grouping,
                        TokenTriggers.MatchBraces
                    );
                case JSToken.AccessField:                    // .
                    return new TokenInfo(
                        GetSpan(context),
                        TokenCategory.Operator,
                        TokenTriggers.MemberSelect
                    );
                // unary ops
                case JSToken.Increment:                      // ++
                case JSToken.Decrement:                      // --
                case JSToken.LogicalNot:     // !
                case JSToken.BitwiseNot:                     // ~
                case JSToken.Plus:     // +
                case JSToken.Minus:                          // -
                case JSToken.Multiply:                       // *
                case JSToken.Divide:                         // /
                case JSToken.Modulo:                         // %
                case JSToken.BitwiseAnd:                     // &
                case JSToken.BitwiseOr:                      // |
                case JSToken.BitwiseXor:                     // ^
                case JSToken.LeftShift:                      // <<
                case JSToken.RightShift:                     // >>
                case JSToken.UnsignedRightShift:             // >>>

                case JSToken.Equal:                          // ==
                case JSToken.NotEqual:                       // !=
                case JSToken.StrictEqual:                    // ===
                case JSToken.StrictNotEqual:                 // !==
                case JSToken.LessThan:                       // <
                case JSToken.LessThanEqual:                  // <=
                case JSToken.GreaterThan:                    // >
                case JSToken.GreaterThanEqual:               // >=

                case JSToken.LogicalAnd:                     // &&
                case JSToken.LogicalOr:                      // ||

                case JSToken.Assign:                         // =
                case JSToken.PlusAssign:                     // +=
                case JSToken.MinusAssign:                    // -=
                case JSToken.MultiplyAssign:                 // *=
                case JSToken.DivideAssign:                   // /=
                case JSToken.ModuloAssign:                   // %=
                case JSToken.BitwiseAndAssign:               // &=
                case JSToken.BitwiseOrAssign:                // |=
                case JSToken.BitwiseXorAssign:               // ^=
                case JSToken.LeftShiftAssign:                // <<=
                case JSToken.RightShiftAssign:               // >>=
                case JSToken.UnsignedRightShiftAssign:       // >>>=

                case JSToken.ConditionalIf:                  // ? // MUST FOLLOW LastBinaryOp
                case JSToken.Colon:                          // :
                    return new TokenInfo(
                        GetSpan(context),
                        TokenCategory.Operator,
                        TokenTriggers.None
                    );

                case JSToken.Comma:                          // :
                    return new TokenInfo(
                        GetSpan(context),
                        TokenCategory.Delimiter,
                        TokenTriggers.ParameterNext
                    );
                case JSToken.SingleLineComment:              // for authoring
                    return new TokenInfo(
                        GetSpan(context),
                        TokenCategory.LineComment,
                        TokenTriggers.None
                    );
                case JSToken.MultipleLineComment:            // for authoring
                case JSToken.UnterminatedComment:            // for authoring
                    return new TokenInfo(
                        GetSpan(context),
                        TokenCategory.Comment,
                        TokenTriggers.None
                    );
                case JSToken.RegularExpression: // only returned if the RawTokens flag is set on the scanner
                    return new TokenInfo(
                        GetSpan(context),
                        TokenCategory.RegularExpressionLiteral,
                        TokenTriggers.None
                    );
            }
            return new TokenInfo(
                GetSpan(context),
                TokenCategory.None,
                TokenTriggers.None
            );
        }