Ejemplo n.º 1
0
        private static ExpressionBase ParseClauseCore(PositionalTokenizer tokenizer)
        {
            ExpressionBase clause;

            switch (tokenizer.NextChar)
            {
            case '!':
                tokenizer.Advance();
                clause = ParseClause(tokenizer);
                if (clause.Type == ExpressionType.ParseError)
                {
                    return(clause);
                }

                return(new ConditionalExpression(null, ConditionalOperation.Not, clause));

            case '(':
                if (AnonymousUserFunctionDefinitionExpression.IsAnonymousParameterList(tokenizer))
                {
                    return(AnonymousUserFunctionDefinitionExpression.ParseAnonymous(tokenizer));
                }

                tokenizer.Advance();
                clause = ExpressionBase.Parse(tokenizer);
                if (clause.Type == ExpressionType.ParseError)
                {
                    return(clause);
                }

                if (tokenizer.NextChar != ')')
                {
                    if (tokenizer.NextChar == '\0')
                    {
                        return(ParseError(tokenizer, "No closing parenthesis found"));
                    }

                    return(ParseError(tokenizer, "Expected closing parenthesis, found: " + tokenizer.NextChar));
                }

                clause.IsLogicalUnit = true;
                tokenizer.Advance();

                return(clause);

            case '"':
                try
                {
                    var stringValue = tokenizer.ReadQuotedString().ToString();
                    return(new StringConstantExpression(stringValue));
                }
                catch (InvalidOperationException ex)
                {
                    return(ParseError(tokenizer, ex.Message));
                }

            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
                return(ParseNumber(tokenizer, true));

            case '-':
                var tokenStart = tokenizer.Location;
                tokenizer.Advance();
                if (tokenizer.NextChar >= '0' && tokenizer.NextChar <= '9')
                {
                    var result   = ParseNumber(tokenizer, false);
                    var tokenEnd = result.Location.End;
                    switch (result.Type)
                    {
                    case ExpressionType.IntegerConstant:
                        result = new IntegerConstantExpression(-((IntegerConstantExpression)result).Value);
                        break;

                    case ExpressionType.FloatConstant:
                        result = new FloatConstantExpression(-((FloatConstantExpression)result).Value);
                        break;

                    default:
                        return(result);
                    }

                    result.Location = new TextRange(tokenStart, tokenEnd);
                    return(result);
                }
                return(ParseError(tokenizer, "Minus without value", tokenStart.Line, tokenStart.Column));

            case '{':
                tokenizer.Advance();
                return(DictionaryExpression.Parse(tokenizer));

            case '[':
                tokenizer.Advance();
                return(ParseArray(tokenizer));

            default:
                var line       = tokenizer.Line;
                var column     = tokenizer.Column;
                var identifier = tokenizer.ReadIdentifier();
                if (identifier.IsEmpty)
                {
                    var error = ParseError(tokenizer, "Unexpected character: " + tokenizer.NextChar);
                    tokenizer.Advance();
                    return(error);
                }

                SkipWhitespace(tokenizer);

                if (identifier == "return")
                {
                    clause = ExpressionBase.Parse(tokenizer);
                    if (clause.Type == ExpressionType.ParseError)
                    {
                        return(clause);
                    }

                    return(new ReturnExpression(new KeywordExpression(identifier.ToString(), line, column), clause));
                }

                if (identifier == "function")
                {
                    return(UserFunctionDefinitionExpression.Parse(tokenizer, line, column));
                }
                if (identifier == "for")
                {
                    return(ForExpression.Parse(tokenizer, line, column));
                }
                if (identifier == "if")
                {
                    return(IfExpression.Parse(tokenizer, line, column));
                }

                if (identifier == "true")
                {
                    return(new BooleanConstantExpression(true, line, column));
                }
                if (identifier == "false")
                {
                    return(new BooleanConstantExpression(false, line, column));
                }

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

                    var parameters = new List <ExpressionBase>();
                    ParseParameters(tokenizer, parameters);

                    var functionCall = new FunctionCallExpression(new FunctionNameExpression(identifier.ToString(), line, column), parameters);
                    functionCall.Location = new TextRange(line, column, tokenizer.Line, tokenizer.Column - 1);
                    return(functionCall);
                }

                if (tokenizer.NextChar == '[')
                {
                    IndexedVariableExpression parent = null;

                    do
                    {
                        tokenizer.Advance();

                        var index = ExpressionBase.Parse(tokenizer);
                        if (index.Type == ExpressionType.ParseError)
                        {
                            return(index);
                        }

                        SkipWhitespace(tokenizer);
                        if (tokenizer.NextChar != ']')
                        {
                            return(ParseError(tokenizer, "Expecting closing bracket after index"));
                        }
                        tokenizer.Advance();
                        SkipWhitespace(tokenizer);

                        if (parent != null)
                        {
                            parent = new IndexedVariableExpression(parent, index);
                        }
                        else
                        {
                            parent = new IndexedVariableExpression(new VariableExpression(identifier.ToString(), line, column), index);
                        }
                    } while (tokenizer.NextChar == '[');

                    return(parent);
                }

                return(new VariableExpression(identifier.ToString(), line, column));
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Replaces the variables in the expression with values from <paramref name="scope" />.
        /// </summary>
        /// <param name="scope">The scope object containing variable values.</param>
        /// <param name="result">[out] The new expression containing the replaced variables.</param>
        /// <returns>
        ///   <c>true</c> if substitution was successful, <c>false</c> if something went wrong, in which case <paramref name="result" /> will likely be a <see cref="ParseErrorExpression" />.
        /// </returns>
        public override bool ReplaceVariables(InterpreterScope scope, out ExpressionBase result)
        {
            if (Entries.Count == 0)
            {
                result = this;
                return(true);
            }

            var dictScope = new InterpreterScope(scope);

            var entries = new List <DictionaryEntry>();

            foreach (var entry in Entries)
            {
                ExpressionBase key, value;
                key = entry.Key;

                dictScope.Context = new AssignmentExpression(new VariableExpression("@key"), key);

                if (key.Type == ExpressionType.FunctionCall)
                {
                    var expression = (FunctionCallExpression)key;
                    if (!expression.ReplaceVariables(dictScope, out value))
                    {
                        result = value;
                        return(false);
                    }

                    key = value;
                }

                if (!key.ReplaceVariables(dictScope, out key))
                {
                    result = key;
                    return(false);
                }

                switch (key.Type)
                {
                case ExpressionType.StringConstant:
                    dictScope.Context = new AssignmentExpression(new VariableExpression("[" + ((StringConstantExpression)key).Value + "]"), entry.Value);
                    break;

                case ExpressionType.IntegerConstant:
                    dictScope.Context = new AssignmentExpression(new VariableExpression("[" + ((IntegerConstantExpression)key).Value.ToString() + "]"), entry.Value);
                    break;

                default:
                    result = new ParseErrorExpression("Dictionary key must evaluate to a constant", key);
                    return(false);
                }

                if (!entry.Value.ReplaceVariables(dictScope, out value))
                {
                    result = value;
                    return(false);
                }

                if (entries.Exists(e => e.Key == key))
                {
                    StringBuilder builder = new StringBuilder();
                    key.AppendString(builder);
                    builder.Append(" already exists in dictionary");
                    result = new ParseErrorExpression(builder.ToString(), entry.Key);
                    return(false);
                }

                entries.Add(new DictionaryEntry {
                    Key = key, Value = value
                });
            }

            result = new DictionaryExpression {
                Entries = entries
            };
            return(true);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Replaces the variables in the expression with values from <paramref name="scope" />.
        /// </summary>
        /// <param name="scope">The scope object containing variable values.</param>
        /// <param name="result">[out] The new expression containing the replaced variables.</param>
        /// <returns>
        ///   <c>true</c> if substitution was successful, <c>false</c> if something went wrong, in which case <paramref name="result" /> will likely be a <see cref="ParseErrorExpression" />.
        /// </returns>
        public override bool ReplaceVariables(InterpreterScope scope, out ExpressionBase result)
        {
            var newDict = new DictionaryExpression();
            var entries = newDict._entries;

            if (_state == DictionaryState.Unprocessed)
            {
                result = UpdateState();
                if (result != null)
                {
                    return(false);
                }
            }

            // constant dictionary
            if (_state == DictionaryState.ConstantSorted)
            {
                entries.AddRange(_entries);
                result = newDict;
                CopyLocation(result);
                return(true);
            }

            // non-constant dictionary - have to evaluate
            var dictScope = new InterpreterScope(scope);

            foreach (var entry in _entries)
            {
                ExpressionBase key, value;
                key = entry.Key;

                if (!key.IsConstant)
                {
                    dictScope.Context = new AssignmentExpression(new VariableExpression("@key"), key);
                    if (!key.ReplaceVariables(dictScope, out value))
                    {
                        result = value;
                        return(false);
                    }

                    if (!value.IsConstant)
                    {
                        result = new ParseErrorExpression("Dictionary key must evaluate to a constant", key);
                        return(false);
                    }

                    key = value;
                }

                if (entry.Value.IsConstant)
                {
                    value = entry.Value;
                }
                else
                {
                    var builder = new StringBuilder();
                    builder.Append('[');
                    key.AppendString(builder);
                    builder.Append(']');
                    dictScope.Context = new AssignmentExpression(new VariableExpression(builder.ToString()), entry.Value);

                    if (!entry.Value.ReplaceVariables(dictScope, out value))
                    {
                        result = value;
                        return(false);
                    }
                }

                var newEntry = new DictionaryEntry {
                    Key = key, Value = value
                };

                if (_state == DictionaryState.ConstantKeysSorted)
                {
                    entries.Add(newEntry);
                }
                else
                {
                    var index = entries.BinarySearch(newEntry, newEntry);
                    if (index >= 0)
                    {
                        StringBuilder builder = new StringBuilder();
                        key.AppendString(builder);
                        builder.Append(" already exists in dictionary");
                        result = new ParseErrorExpression(builder.ToString(), entry.Key);
                        return(false);
                    }

                    entries.Insert(~index, newEntry);
                }
            }

            newDict._state = DictionaryState.ConstantSorted;
            result         = newDict;
            CopyLocation(result);
            return(true);
        }
Ejemplo n.º 4
0
        private static ExpressionBase ParseClauseCore(PositionalTokenizer tokenizer)
        {
            ExpressionBase clause;

            switch (tokenizer.NextChar)
            {
            case '!':
                tokenizer.Advance();
                clause = ParseClause(tokenizer);
                if (clause.Type == ExpressionType.ParseError)
                {
                    return(clause);
                }

                return(new ConditionalExpression(null, ConditionalOperation.Not, clause));

            case '(':
                tokenizer.Advance();
                clause = ExpressionBase.Parse(tokenizer);
                if (clause.Type == ExpressionType.ParseError)
                {
                    return(clause);
                }

                if (tokenizer.NextChar != ')')
                {
                    if (tokenizer.NextChar == '\0')
                    {
                        return(ParseError(tokenizer, "No closing parenthesis found"));
                    }

                    return(ParseError(tokenizer, "Expected closing parenthesis, found: " + tokenizer.NextChar));
                }

                clause.IsLogicalUnit = true;
                tokenizer.Advance();
                return(clause);

            case '"':
                try
                {
                    var stringValue = tokenizer.ReadQuotedString().ToString();
                    return(new StringConstantExpression(stringValue));
                }
                catch (InvalidOperationException ex)
                {
                    return(ParseError(tokenizer, ex.Message));
                }

            case '0':
                if (tokenizer.Match("0x"))
                {
                    string hexNumber = "";
                    while (Char.IsDigit(tokenizer.NextChar) || (tokenizer.NextChar >= 'A' && tokenizer.NextChar <= 'F') || (tokenizer.NextChar >= 'a' && tokenizer.NextChar <= 'f'))
                    {
                        hexNumber += tokenizer.NextChar;
                        tokenizer.Advance();
                    }

                    int hexValue = 0;
                    Int32.TryParse(hexNumber, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.CurrentCulture, out hexValue);
                    return(new IntegerConstantExpression(hexValue));
                }
                goto case '1';

            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
            {
                var  number = tokenizer.ReadNumber();
                uint value;
                UInt32.TryParse(number.ToString(), out value);
                return(new IntegerConstantExpression((int)value));
            }

            case '-':
                tokenizer.Advance();
                if (tokenizer.NextChar >= '0' && tokenizer.NextChar <= '9')
                {
                    if (tokenizer.Match("0x"))
                    {
                        string hexNumber = "";
                        while (Char.IsDigit(tokenizer.NextChar) || (tokenizer.NextChar >= 'A' && tokenizer.NextChar <= 'F') || (tokenizer.NextChar >= 'a' && tokenizer.NextChar <= 'f'))
                        {
                            hexNumber += tokenizer.NextChar;
                            tokenizer.Advance();
                        }

                        int hexValue = 0;
                        Int32.TryParse(hexNumber, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.CurrentCulture, out hexValue);
                        return(new IntegerConstantExpression(-hexValue));
                    }

                    var number = tokenizer.ReadNumber();
                    int value;
                    Int32.TryParse(number.ToString(), out value);
                    return(new IntegerConstantExpression(-value));
                }
                return(ParseError(tokenizer, "Minus without value"));

            case '{':
                tokenizer.Advance();
                return(DictionaryExpression.Parse(tokenizer));

            case '[':
                tokenizer.Advance();
                return(ParseArray(tokenizer));

            default:
                var line       = tokenizer.Line;
                var column     = tokenizer.Column;
                var identifier = tokenizer.ReadIdentifier();
                if (identifier.IsEmpty)
                {
                    var error = ParseError(tokenizer, "Unexpected character: " + tokenizer.NextChar);
                    tokenizer.Advance();
                    return(error);
                }

                SkipWhitespace(tokenizer);

                if (identifier == "return")
                {
                    clause = ExpressionBase.Parse(tokenizer);
                    if (clause.Type == ExpressionType.ParseError)
                    {
                        return(clause);
                    }

                    return(new ReturnExpression(new KeywordExpression(identifier.ToString(), line, column), clause));
                }

                if (identifier == "function")
                {
                    return(FunctionDefinitionExpression.Parse(tokenizer, line, column));
                }
                if (identifier == "for")
                {
                    return(ForExpression.Parse(tokenizer, line, column));
                }
                if (identifier == "if")
                {
                    return(IfExpression.Parse(tokenizer, line, column));
                }

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

                    var parameters = new List <ExpressionBase>();
                    ParseParameters(tokenizer, parameters);

                    var functionCall = new FunctionCallExpression(new VariableExpression(identifier.ToString(), line, column), parameters);
                    functionCall.EndLine   = tokenizer.Line;
                    functionCall.EndColumn = tokenizer.Column - 1;
                    return(functionCall);
                }

                if (tokenizer.NextChar == '[')
                {
                    IndexedVariableExpression parent = null;

                    do
                    {
                        tokenizer.Advance();

                        var index = ExpressionBase.Parse(tokenizer);
                        if (index.Type == ExpressionType.ParseError)
                        {
                            return(index);
                        }

                        SkipWhitespace(tokenizer);
                        if (tokenizer.NextChar != ']')
                        {
                            return(ParseError(tokenizer, "Expecting closing bracket after index"));
                        }
                        tokenizer.Advance();
                        SkipWhitespace(tokenizer);

                        if (parent != null)
                        {
                            parent = new IndexedVariableExpression(parent, index);
                        }
                        else
                        {
                            parent = new IndexedVariableExpression(new VariableExpression(identifier.ToString(), line, column), index);
                        }
                    } while (tokenizer.NextChar == '[');

                    return(parent);
                }

                return(new VariableExpression(identifier.ToString(), line, column));
            }
        }