Example #1
0
        public static FunctionCallNode Read(ReadParams p, Span funcNameSpan, string funcName, Definition funcDef = null)
        {
            if (funcDef != null)
            {
                var node = ParseArguments(p, funcNameSpan, funcName, funcDef);
                if (node != null)
                {
                    return(node);
                }
            }

            var funcDefs = (from d in p.Statement.CodeAnalyzer.PreprocessorModel.DefinitionProvider.GetAny(funcNameSpan.Start, funcName)
                            where d.ArgumentsRequired && !d.RequiresParent(p.CodeAnalyzer.CodeModel.ClassName)
                            select d).ToArray();

            foreach (var def in funcDefs)
            {
                var fd = def as FunctionDefinition;
                if (fd == null)
                {
                    continue;
                }

                var node = ParseArguments(p, funcNameSpan, funcName, fd);
                if (node != null)
                {
                    return(node);
                }
            }

            var funcCallNode = new FunctionCallNode(p.Statement, funcNameSpan, funcName, null);

            funcCallNode.ReportError(funcNameSpan, CAError.CA0003, funcName);                   // Function '{0}' not found.
            return(funcCallNode);
        }
Example #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);
        }
Example #3
0
        private static FunctionCallNode ParseArguments(ReadParams p, Span funcNameSpan, string funcName, Definition funcDef)
        {
            var funcCallNode  = new FunctionCallNode(p.Statement, funcNameSpan, funcName, funcDef);
            var code          = p.Code;
            var resetPos      = code.Position;
            var commaExpected = false;
            var closed        = false;
            var argIndex      = 0;
            var args          = new List <GroupNode>();
            var argDefs       = funcDef.Arguments.ToArray();

            if (code.ReadExact(')'))
            {
                closed = true;
            }
            else
            {
                while (!code.EndOfFile)
                {
                    if (commaExpected)
                    {
                        if (code.ReadExact(')'))
                        {
                            closed = true;
                            break;
                        }
                        if (!code.ReadExact(','))
                        {
                            code.Position = resetPos;
                            return(null);
                        }
                        commaExpected = false;
                    }
                    else
                    {
                        var argDef = argDefs != null && argIndex < argDefs.Length ? argDefs[argIndex] : null;

                        var arg = ExpressionNode.Read(p, argDef != null ? argDef.DataType : null, ",", ")");
                        if (arg != null)
                        {
                            funcCallNode.AddArgument(arg);
                        }
                        commaExpected = true;
                        argIndex++;
                    }
                }
            }

            if (!closed)
            {
                code.Position = resetPos;
                return(null);
            }

            //if (argDefs.Length != funcCallNode.NumArguments)
            //{
            //	code.Position = resetPos;
            //	return null;
            //}

            return(funcCallNode);
        }