Esempio n. 1
0
        public static AggregateFunctionCallNode Read(ReadParams p, Span funcNameSpan, string funcName)
        {
            var ret  = new AggregateFunctionCallNode(p.Statement, funcNameSpan, funcName);
            var code = p.Code;

            if (funcName == "count")
            {
                if (!code.ReadExact('*'))
                {
                    ret.ReportError(CAError.CA0060);                            // Expected '*' in count().
                    return(ret);
                }
            }
            else
            {
                var exp = ExpressionNode.Read(p, null, ",", ")");
                if (exp == null)
                {
                    ret.ReportError(CAError.CA0061);                            // Expected aggregate expression.
                    return(ret);
                }
                ret._aggExp = exp;
            }

            while (!code.EndOfFile)
            {
                if (code.ReadExact(')'))
                {
                    break;
                }

                if (code.ReadExact(','))
                {
                    if (code.ReadExactWholeWord("where"))
                    {
                        var exp = ExpressionNode.Read(p, null, ",", ")");
                        if (exp == null)
                        {
                            ret.ReportError(code.Span, CAError.CA0062, "where");                                // Expected expression to follow '{0}'.
                            return(ret);
                        }
                        ret._whereExp = exp;
                    }
                    else if (code.ReadExactWholeWord("group"))
                    {
                        var startPos = code.Position;
                        if (code.ReadWord())
                        {
                            var tableDef = (from d in p.CodeAnalyzer.PreprocessorModel.DefinitionProvider.GetGlobalFromAnywhere(code.Text)
                                            where d is TableDefinition || d is ExtractTableDefinition
                                            select d).FirstOrDefault();
                            if (tableDef == null)
                            {
                                ret.ReportError(code.Span, CAError.CA0064, code.Text);                                  // Table '{0}' does not exist.
                                return(ret);
                            }

                            if (!code.ReadExact('.'))
                            {
                                ret.ReportError(code.Span, CAError.CA0066);                                     // Expected '.'
                                return(ret);
                            }

                            Definition fieldDef = null;
                            if (!code.ReadWord() || (fieldDef = tableDef.GetChildDefinitions(code.Text).FirstOrDefault()) == null)
                            {
                                ret.ReportError(code.Span, CAError.CA0067);                                 // Expected column name.
                                return(ret);
                            }
                        }
                        else
                        {
                            ret.ReportError(code.Span, CAError.CA0065);                                 // Expected table name to follow 'group'.
                            return(ret);
                        }
                    }
                    else if (code.ReadExactWholeWord("all"))
                    {
                        // Nothing follows 'all'
                    }
                    else if (code.ReadExactWholeWord("in"))
                    {
                        if (!code.ReadStringLiteral())
                        {
                            ret.ReportError(code.Span, CAError.CA0068);                                 // Expected select name to follow 'in'.
                            return(ret);
                        }
                    }
                }
                else
                {
                    ret.ReportError(CAError.CA0063);                            // Expected ')'.
                }
            }

            return(ret);
        }
Esempio n. 2
0
        private Node ReadWord(ReadParams p, DataType refDataType)
        {
            var code     = p.Code;
            var word     = code.Text;
            var wordSpan = code.Span;

            if (code.ReadExact('('))
            {
                // This is a function call

                switch (word)
                {
                case "avg":
                case "count":
                case "sum":
                case "max":
                case "min":
                    return(AggregateFunctionCallNode.Read(p, wordSpan, word));
                }

                return(FunctionCallNode.Read(p, wordSpan, word));
            }

            if (code.ReadExact('.'))
            {
                var dotSpan = code.Span;

                if (code.ReadWord())
                {
                    var childWord    = code.Text;
                    var combinedWord = string.Concat(word, ".", childWord);
                    var combinedSpan = wordSpan.Envelope(code.Span);

                    if (code.ReadExact('('))
                    {
                        foreach (var parentDef in (from d in p.CodeAnalyzer.PreprocessorModel.DefinitionProvider.GetAny(code.Position + p.FuncOffset, word)
                                                   where d.AllowsChild
                                                   select d))
                        {
                            var childDef = parentDef.ChildDefinitions.FirstOrDefault(c => c.Name == childWord && c.ArgumentsRequired);
                            if (childDef != null)
                            {
                                return(FunctionCallNode.Read(p, combinedSpan, combinedWord, childDef));
                            }
                        }

                        ReportError(combinedSpan, CAError.CA0003, combinedWord);                                // Function '{0}' not found.
                        return(new UnknownNode(p.Statement, combinedSpan, combinedWord));
                    }
                    else                     // No opening bracket
                    {
                        foreach (var parentDef in (from d in p.CodeAnalyzer.PreprocessorModel.DefinitionProvider.GetAny(code.Position + p.FuncOffset, word)
                                                   where d.AllowsChild
                                                   select d))
                        {
                            var childDef = parentDef.ChildDefinitions.FirstOrDefault(c => c.Name == childWord && !c.ArgumentsRequired);
                            if (childDef != null)
                            {
                                return(TryReadSubscript(p, combinedSpan, combinedWord, childDef));
                            }
                        }

                        ReportError(combinedSpan, CAError.CA0001, combinedWord);                                // Unknown '{0}'.
                        return(new UnknownNode(p.Statement, combinedSpan, combinedWord));
                    }
                }
                else                                      // No word after dot
                {
                    ReportError(dotSpan, CAError.CA0004); // Expected identifier to follow '.'
                    return(new UnknownNode(p.Statement, wordSpan.Envelope(dotSpan), string.Concat(word, ".")));
                }
            }

            // Try to read array accessor
            if (code.PeekExact('['))
            {
                // Read a list of array accessors with a single expression
                var arrayResetPos     = code.TokenStartPostion;
                var arrayExps         = new List <ExpressionNode[]>();
                var lastArrayStartPos = code.Position;
                while (!code.EndOfFile)
                {
                    lastArrayStartPos = code.Position;
                    if (code.ReadExact('['))
                    {
                        var exp1 = ExpressionNode.Read(p, null, "]", ",");
                        if (exp1 != null)
                        {
                            if (code.ReadExact(']'))
                            {
                                // Brackets with single expression
                                arrayExps.Add(new ExpressionNode[] { exp1 });
                            }
                            else if (code.ReadExact(','))
                            {
                                var exp2 = ExpressionNode.Read(p, null, "]");
                                if (exp2 != null)
                                {
                                    if (code.ReadExact(']'))
                                    {
                                        arrayExps.Add(new ExpressionNode[] { exp1, exp2 });
                                    }
                                    else
                                    {
                                        code.Position = lastArrayStartPos;
                                        break;
                                    }
                                }
                                else
                                {
                                    code.Position = lastArrayStartPos;
                                    break;
                                }
                            }
                            else
                            {
                                code.Position = lastArrayStartPos;
                                break;
                            }
                        }
                        else
                        {
                            code.Position = lastArrayStartPos;
                            break;
                        }
                    }
                    else
                    {
                        break;
                    }
                }

                var defs = p.CodeAnalyzer.PreprocessorModel.DefinitionProvider.GetAny(code.Position + p.FuncOffset, word).ToArray();

                // Try to match to a variable defined as an array
                if (arrayExps.Count > 0)
                {
                    // Check if it's a variable being accessed
                    foreach (var def in defs)
                    {
                        if (def is VariableDefinition)
                        {
                            var vardef       = def as VariableDefinition;
                            var arrayLengths = vardef.ArrayLengths;
                            if (arrayLengths == null)
                            {
                                continue;
                            }

                            if (arrayLengths.Length == arrayExps.Count && arrayExps.All(x => x.Length == 1))
                            {
                                return(new IdentifierNode(p.Statement, wordSpan, word, def, (from e in arrayExps select e[0])));
                            }
                            else if (arrayLengths.Length == arrayExps.Count - 1 &&
                                     vardef.DataType != null &&
                                     vardef.DataType.AllowsSubscript &&
                                     arrayExps.Take(arrayLengths.Length).All(x => x.Length == 1))
                            {
                                // Last array accessor is a string subscript
                                return(new IdentifierNode(p.Statement, wordSpan, word, def,
                                                          (from e in arrayExps.Take(arrayExps.Count - 1) select e[0]),
                                                          arrayExps.Last()));
                            }
                        }
                    }
                }

                // Try to match to a string that allows a subscript with 1 or 2 arguments
                code.Position = arrayResetPos;
                var subDef = (from d in defs where d.DataType != null && d.DataType.AllowsSubscript select d).FirstOrDefault();
                if (subDef != null)
                {
                    return(TryReadSubscript(p, wordSpan, word, subDef));
                }
            }

            if (refDataType != null)
            {
                if (refDataType.HasCompletionOptions)
                {
                    var enumOptDef = refDataType.GetEnumOption(word);
                    if (enumOptDef != null)
                    {
                        return(new IdentifierNode(p.Statement, wordSpan, word, enumOptDef));
                    }
                }

                switch (refDataType.ValueType)
                {
                case ValType.Table:
                {
                    var table = DkDict.Dict.GetTable(word);
                    if (table != null)
                    {
                        return(new IdentifierNode(p.Statement, wordSpan, word, table.Definition));
                    }

                    var indrel = DkDict.Dict.GetRelInd(word);
                    if (indrel != null)
                    {
                        return(new IdentifierNode(p.Statement, wordSpan, word, indrel.Definition));
                    }
                }
                break;

                case ValType.IndRel:
                {
                    var indrel = DkDict.Dict.GetRelInd(word);
                    if (indrel != null)
                    {
                        return(new IdentifierNode(p.Statement, wordSpan, word, indrel.Definition));
                    }
                }
                break;
                }
            }

            var wordDefs = (from d in p.CodeAnalyzer.PreprocessorModel.DefinitionProvider.GetAny(code.Position + p.FuncOffset, word)
                            where !d.RequiresChild && !d.ArgumentsRequired && !d.RequiresRefDataType
                            orderby d.SelectionOrder descending
                            select d).ToArray();

            if (wordDefs.Length > 0)
            {
                return(new IdentifierNode(p.Statement, wordSpan, word, wordDefs[0]));
            }

            return(new UnknownNode(p.Statement, wordSpan, word));

            // Single word. Don't attempt to find the definition now because it could be an enum option.
            //return new IdentifierNode(p.Statement, wordSpan, word, null);
        }