Represents a reserved word in the source code.
Inheritance: Jurassic.Compiler.Token
示例#1
0
        /// <summary>
        /// Reads an identifier token.
        /// </summary>
        /// <param name="firstChar"> The first character of the identifier. </param>
        /// <returns> An identifier token, literal token or a keyword token. </returns>
        private Token ReadIdentifier(int firstChar)
        {
            // Process the first character.
            var name = new StringBuilder();

            if (firstChar == '\\')
            {
                // Unicode escape sequence.
                if (ReadNextChar() != 'u')
                {
                    throw new JavaScriptException(this.engine, "SyntaxError", "Invalid escape sequence in identifier.", this.lineNumber, this.Source.Path);
                }
                firstChar = ReadHexEscapeSequence(4);
                if (IsIdentifierChar(firstChar) == false)
                {
                    throw new JavaScriptException(this.engine, "SyntaxError", "Invalid character in identifier.", this.lineNumber, this.Source.Path);
                }
            }
            name.Append((char)firstChar);

            // Read characters until we hit the first non-identifier character.
            while (true)
            {
                int c = this.reader.Peek();
                if (IsIdentifierChar(c) == false || c == -1)
                {
                    break;
                }

                if (c == '\\')
                {
                    // Unicode escape sequence.
                    ReadNextChar();
                    if (ReadNextChar() != 'u')
                    {
                        throw new JavaScriptException(this.engine, "SyntaxError", "Invalid escape sequence in identifier.", this.lineNumber, this.Source.Path);
                    }
                    c = ReadHexEscapeSequence(4);
                    if (IsIdentifierChar(c) == false)
                    {
                        throw new JavaScriptException(this.engine, "SyntaxError", "Invalid character in identifier.", this.lineNumber, this.Source.Path);
                    }
                    name.Append((char)c);
                }
                else
                {
                    // Add the character we peeked at to the identifier name.
                    name.Append((char)c);

                    // Advance the input stream.
                    ReadNextChar();
                }
            }

            // Check if the identifier is actually a keyword, boolean literal, or null literal.
            return(KeywordToken.FromString(name.ToString(), this.engine.CompatibilityMode, this.StrictMode));
        }
示例#2
0
文件: Scope.cs 项目: oujunke/jurassic
        /// <summary>
        /// Declares a variable or function in this scope.  This will be initialized with the value
        /// of the given expression.
        /// </summary>
        /// <param name="keyword"> The keyword that was used to declare the variable (var, let or
        /// const). </param>
        /// <param name="name"> The name of the variable. </param>
        /// <param name="hoistedFunction"> The function value to hoist to the top of the scope.
        /// Should be <c>null</c> for everything except function declarations. </param>
        /// <returns> A reference to the variable that was declared. </returns>
        internal void DeclareVariable(KeywordToken keyword, string name, FunctionExpression hoistedFunction = null)
        {
            if (name == null)
            {
                throw new ArgumentNullException(nameof(name));
            }

            // If variables cannot be declared in the scope, try the parent scope instead.
            var declarationScope = this;

            if (keyword == KeywordToken.Var)
            {
                while (declarationScope != null && (declarationScope.Type == ScopeType.Block || declarationScope.Type == ScopeType.With))
                {
                    declarationScope = declarationScope.ParentScope;
                }
            }

            if (declarationScope != null && !declarationScope.variables.ContainsKey(name))
            {
                // This is a local variable that has not been declared before.
                var variable = new DeclaredVariable()
                {
                    Scope   = declarationScope,
                    Index   = declarationScope.variables.Count,
                    Keyword = keyword,
                    Name    = name,
                };
                declarationScope.variables.Add(name, variable);
            }

            if (hoistedFunction != null)
            {
                var hoistedScope = this;
                while (hoistedScope != null && hoistedScope.Type == ScopeType.Block)
                {
                    hoistedScope = hoistedScope.ParentScope;
                }
                if (hoistedScope.hoistedFunctions == null)
                {
                    hoistedScope.hoistedFunctions = new Dictionary <string, FunctionExpression>();
                }
                hoistedScope.hoistedFunctions[name] = hoistedFunction;
            }
        }
示例#3
0
        /// <summary>
        /// Parses a var, let or const statement.
        /// </summary>
        /// <param name="keyword"> Indicates which type of statement is being parsed.  Must be var,
        /// let or const. </param>
        /// <returns> A variable declaration statement. </returns>
        private VarStatement ParseVarLetOrConst(KeywordToken keyword)
        {
            var result = new VarStatement(this.labelsForCurrentStatement, keyword == KeywordToken.Var ? this.currentVarScope : this.currentLetScope);

            // Read past the first token (var, let or const).
            this.Expect(keyword);

            // Keep track of the start of the statement so that source debugging works correctly.
            var start = this.PositionAfterWhitespace;

            // There can be multiple declarations.
            while (true)
            {
                var declaration = new VariableDeclaration();

                // The next token must be a variable name.
                declaration.VariableName = this.ExpectIdentifier();
                ValidateVariableName(declaration.VariableName);

                // Add the variable to the current function's list of local variables.
                this.currentVarScope.DeclareVariable(declaration.VariableName,
                    this.context == CodeContext.Function ? null : new LiteralExpression(Undefined.Value),
                    writable: true, deletable: this.context == CodeContext.Eval);

                // The next token is either an equals sign (=), a semi-colon or a comma.
                if (this.nextToken == PunctuatorToken.Assignment)
                {
                    // Read past the equals token (=).
                    this.Expect(PunctuatorToken.Assignment);

                    // Read the setter expression.
                    declaration.InitExpression = ParseExpression(PunctuatorToken.Semicolon, PunctuatorToken.Comma);

                    // Record the portion of the source document that will be highlighted when debugging.
                    declaration.SourceSpan = new SourceCodeSpan(start, this.PositionBeforeWhitespace);
                }

                // Add the declaration to the result.
                result.Declarations.Add(declaration);

                // Check if we are at the end of the statement.
                if (this.AtValidEndOfStatement() == true && this.nextToken != PunctuatorToken.Comma)
                    break;

                // Read past the comma token.
                this.Expect(PunctuatorToken.Comma);

                // Keep track of the start of the statement so that source debugging works correctly.
                start = this.PositionAfterWhitespace;
            }

            // Consume the end of the statement.
            this.ExpectEndOfStatement();

            return result;
        }
 public VariableDeclaration(KeywordToken keyword, string name)
 {
     Keyword      = keyword;
     VariableName = name;
 }