コード例 #1
0
ファイル: ForExpression.cs プロジェクト: Jamiras/RATools
 public ForExpression(VariableDefinitionExpression iteratorName, ExpressionBase range)
     : base(ExpressionType.For)
 {
     IteratorName = iteratorName;
     Range        = range;
     Expressions  = new List <ExpressionBase>();
 }
コード例 #2
0
ファイル: InterpreterScope.cs プロジェクト: Jamiras/RATools
        /// <summary>
        /// Updates the value of a variable.
        /// </summary>
        /// <param name="variable">The variable.</param>
        /// <param name="value">The value.</param>
        public ParseErrorExpression AssignVariable(VariableExpression variable, ExpressionBase value)
        {
            var indexedVariable = variable as IndexedVariableExpression;

            if (indexedVariable != null)
            {
                return(indexedVariable.Assign(this, value));
            }

            var variableDefinition = new VariableDefinitionExpression(variable);

            // find the scope where the variable is defined and update it there.
            foreach (var scope in VisibleScopes)
            {
                if (scope._variables != null && scope._variables.ContainsKey(variable.Name))
                {
                    scope._variables[variable.Name] = new VariableDefinitionPair(variableDefinition, value);
                    return(null);
                }

                if (scope._variable.Key != null && scope._variable.Key.Name == variable.Name)
                {
                    scope._variable = new VariableDefinitionPair(variableDefinition, value);
                    return(null);
                }
            }

            // variable not defined, store in the current scope.
            DefineVariable(variableDefinition, value);
            return(null);
        }
コード例 #3
0
 protected FunctionDefinitionExpression(VariableDefinitionExpression name)
     : base(ExpressionType.FunctionDefinition)
 {
     Name              = name;
     Parameters        = new List <VariableDefinitionExpression>();
     Expressions       = new List <ExpressionBase>();
     DefaultParameters = new TinyDictionary <string, ExpressionBase>();
 }
コード例 #4
0
        /// <summary>
        /// Parses a for loop.
        /// </summary>
        /// <remarks>
        /// Assumes the 'for' keyword has already been consumed.
        /// </remarks>
        internal static ExpressionBase Parse(PositionalTokenizer tokenizer, int line = 0, int column = 0)
        {
            ExpressionBase.SkipWhitespace(tokenizer);
            var keywordFor = new KeywordExpression("for", line, column);

            line   = tokenizer.Line;
            column = tokenizer.Column;
            var iteratorName = tokenizer.ReadIdentifier();

            if (iteratorName.IsEmpty)
            {
                return(ParseError(tokenizer, "Invalid function name", line, column));
            }
            var iterator = new VariableDefinitionExpression(iteratorName.ToString(), line, column);

            ExpressionBase.SkipWhitespace(tokenizer);

            line   = tokenizer.Line;
            column = tokenizer.Column;
            if (!tokenizer.Match("in"))
            {
                return(ParseError(tokenizer, "Expected 'in' after loop variable"));
            }
            var keywordIn = new KeywordExpression("in", line, column);

            var range = ExpressionBase.Parse(tokenizer);

            if (range.Type == ExpressionType.ParseError)
            {
                return(range);
            }

            var loop = new ForExpression(iterator, range);

            var error = ExpressionBase.ParseStatementBlock(tokenizer, loop.Expressions);

            if (error != null)
            {
                return(error);
            }

            loop._keywordFor = keywordFor;
            loop._keywordIn  = keywordIn;
            loop.Line        = keywordFor.Line;
            loop.Column      = keywordFor.Column;
            loop.EndLine     = tokenizer.Line;
            loop.EndColumn   = tokenizer.Column;

            return(loop);
        }
コード例 #5
0
ファイル: InterpreterScope.cs プロジェクト: Jamiras/RATools
        /// <summary>
        /// Assigns the value to a variable for the current scope.
        /// </summary>
        /// <param name="variable">The variable.</param>
        /// <param name="value">The value.</param>
        public void DefineVariable(VariableDefinitionExpression variable, ExpressionBase value)
        {
            if (_variables == null)
            {
                if (_variable.Key == null)
                {
                    _variable = new VariableDefinitionPair(variable, value);
                    return;
                }

                _variables = new Dictionary <string, VariableDefinitionPair>();
                _variables.Add(_variable.Key.Name, _variable);
                _variable = new VariableDefinitionPair();
            }

            _variables[variable.Name] = new VariableDefinitionPair(variable, value);
        }
コード例 #6
0
        /// <summary>
        /// Parses a function definition.
        /// </summary>
        /// <remarks>
        /// Assumes the 'function' keyword has already been consumed.
        /// </remarks>
        internal static ExpressionBase Parse(PositionalTokenizer tokenizer, int line = 0, int column = 0)
        {
            var locationStart = new TextLocation(line, column); // location of 'function' keyword

            ExpressionBase.SkipWhitespace(tokenizer);

            line   = tokenizer.Line;
            column = tokenizer.Column;

            var functionName         = tokenizer.ReadIdentifier();
            var functionNameVariable = new VariableDefinitionExpression(functionName.ToString(), line, column);
            var function             = new UserFunctionDefinitionExpression(functionNameVariable);

            function.Location = new TextRange(locationStart.Line, locationStart.Column, 0, 0);

            if (functionName.IsEmpty)
            {
                return(ExpressionBase.ParseError(tokenizer, "Invalid function name"));
            }

            return(function.Parse(tokenizer));
        }
コード例 #7
0
 public VariableReferenceExpression(VariableDefinitionExpression variable, ExpressionBase expression)
     : base(ExpressionType.VariableReference)
 {
     Variable   = variable;
     Expression = expression;
 }
コード例 #8
0
 /// <summary>
 /// Assigns the value to a variable for the current scope.
 /// </summary>
 /// <param name="variable">The variable.</param>
 /// <param name="value">The value.</param>
 public void DefineVariable(VariableDefinitionExpression variable, ExpressionBase value)
 {
     _variables[variable.Name] = new KeyValuePair <VariableDefinitionExpression, ExpressionBase>(variable, value);
 }
コード例 #9
0
 protected AnonymousUserFunctionDefinitionExpression(VariableDefinitionExpression name)
     : base(name)
 {
     CapturedVariables = Enumerable.Empty <VariableReferenceExpression>();
 }
コード例 #10
0
        protected new ExpressionBase Parse(PositionalTokenizer tokenizer)
        {
            ExpressionBase.SkipWhitespace(tokenizer);
            if (tokenizer.NextChar != '(')
            {
                return(ExpressionBase.ParseError(tokenizer, "Expected '(' after function name", Name));
            }
            tokenizer.Advance();

            ExpressionBase.SkipWhitespace(tokenizer);
            if (tokenizer.NextChar != ')')
            {
                do
                {
                    var line   = tokenizer.Line;
                    var column = tokenizer.Column;

                    var parameter = tokenizer.ReadIdentifier();
                    if (parameter.IsEmpty)
                    {
                        return(ExpressionBase.ParseError(tokenizer, "Invalid parameter name", line, column));
                    }

                    var variableDefinition = new VariableDefinitionExpression(parameter.ToString(), line, column);
                    Parameters.Add(variableDefinition);

                    ExpressionBase.SkipWhitespace(tokenizer);

                    if (tokenizer.NextChar == '=')
                    {
                        tokenizer.Advance();
                        ExpressionBase.SkipWhitespace(tokenizer);

                        var value = ExpressionBase.Parse(tokenizer);
                        if (value.Type == ExpressionType.ParseError)
                        {
                            return(ExpressionBase.ParseError(tokenizer, "Invalid default value for " + parameter.ToString(), value));
                        }

                        var scope = new InterpreterScope(AchievementScriptInterpreter.GetGlobalScope());
                        scope.Context = new TriggerBuilderContext(); // prevent errors passing memory references as default parameters

                        ExpressionBase evaluated;
                        if (!value.ReplaceVariables(scope, out evaluated))
                        {
                            return(ExpressionBase.ParseError(tokenizer, "Default value for " + parameter.ToString() + " is not constant", evaluated));
                        }

                        DefaultParameters[parameter.ToString()] = evaluated;
                    }
                    else if (DefaultParameters.Count > 0)
                    {
                        return(ExpressionBase.ParseError(tokenizer,
                                                         string.Format("Non-default parameter {0} appears after default parameters", parameter.ToString()), variableDefinition));
                    }

                    if (tokenizer.NextChar == ')')
                    {
                        break;
                    }

                    if (tokenizer.NextChar != ',')
                    {
                        return(ExpressionBase.ParseError(tokenizer, "Expected ',' or ')' after parameter name, found: " + tokenizer.NextChar));
                    }

                    tokenizer.Advance();
                    ExpressionBase.SkipWhitespace(tokenizer);
                } while (true);
            }

            tokenizer.Advance(); // closing parenthesis
            ExpressionBase.SkipWhitespace(tokenizer);

            ExpressionBase expression;

            if (tokenizer.Match("=>"))
            {
                return(ParseShorthandBody(tokenizer));
            }

            if (tokenizer.NextChar != '{')
            {
                return(ExpressionBase.ParseError(tokenizer, "Expected '{' after function declaration", Name));
            }

            tokenizer.Advance();
            ExpressionBase.SkipWhitespace(tokenizer);

            bool seenReturn = false;

            while (tokenizer.NextChar != '}')
            {
                expression = ExpressionBase.Parse(tokenizer);
                if (expression.Type == ExpressionType.ParseError)
                {
                    // the ExpressionTokenizer will capture the error, we should still return the incomplete FunctionDefinition
                    if (tokenizer is ExpressionTokenizer)
                    {
                        break;
                    }

                    // not an ExpressionTokenizer, just return the error
                    return(expression);
                }

                if (expression.Type == ExpressionType.Return)
                {
                    seenReturn = true;
                }
                else if (seenReturn)
                {
                    ExpressionBase.ParseError(tokenizer, "Expression after return statement", expression);
                }

                Expressions.Add(expression);

                ExpressionBase.SkipWhitespace(tokenizer);
            }

            Location = new TextRange(Location.Start, tokenizer.Location);
            tokenizer.Advance();
            return(MakeReadOnly(this));
        }
コード例 #11
0
 protected UserFunctionDefinitionExpression(VariableDefinitionExpression name)
     : base(name)
 {
 }
コード例 #12
0
 public FunctionDefinitionExpression(string name)
     : this()
 {
     Name = new VariableDefinitionExpression(name);
 }