Exemplo n.º 1
0
        private Node ReadNestable(ReadParams p, DataType refDataType, Span openSpan, string text, string[] stopStrings)
        {
            GroupNode groupNode;
            string    endText;

            switch (text)
            {
            case "(":
                groupNode = new BracketsNode(p.Statement, openSpan);
                endText   = ")";
                break;

            default:
                throw new ArgumentOutOfRangeException("text");
            }

            if (stopStrings == null)
            {
                stopStrings = new string[] { endText }
            }
            ;
            else
            {
                stopStrings = stopStrings.Concat(new string[] { endText }).ToArray();
            }

            while (!p.Code.EndOfFile)
            {
                if (p.Code.ReadExact(endText))
                {
                    groupNode.Span = groupNode.Span.Envelope(p.Code.Span);
                    break;
                }

                var exp = ExpressionNode.Read(p, refDataType, stopStrings);
                if (exp == null)
                {
                    break;
                }
                groupNode.AddChild(exp);
            }

            return(groupNode);
        }
Exemplo n.º 2
0
        public static ConditionalNode Read(ReadParams p, DataType refDataType, Span opSpan, string[] stopStrings)
        {
            var code = p.Code;
            var ret  = new ConditionalNode(p.Statement, opSpan);

            var condStopStrings = stopStrings == null || stopStrings.Length == 0 ? s_stopStrings : stopStrings.Concat(s_stopStrings).ToArray();
            var trueExp         = ExpressionNode.Read(p, refDataType, condStopStrings);

            if (trueExp == null)
            {
                p.Statement.ReportError(new Span(code.Position, code.Position + 1), CAError.CA0042);                    // Expected value to follow conditional '?'.
                return(ret);
            }
            ret._trueExp = trueExp;

            if (!code.ReadExact(':'))
            {
                p.Statement.ReportError(new Span(code.Position, code.Position + 1), CAError.CA0041);                    // Expected ':' to follow conditional result.
                return(ret);
            }

            var falseExp = ExpressionNode.Read(p, refDataType, condStopStrings);

            if (falseExp == null)
            {
                p.Statement.ReportError(new Span(code.Position, code.Position + 1), CAError.CA0043);                    // Expected value to follow conditional ':'.
                return(ret);
            }

            if (code.ReadExact('?'))
            {
                // Stacked conditional
                var group = new GroupNode(p.Statement, null);
                group.AddChild(falseExp);
                group.AddChild(ConditionalNode.Read(p, refDataType, code.Span, stopStrings));
                ret._falseExp = group;
            }
            else
            {
                ret._falseExp = falseExp;
            }

            return(ret);
        }
Exemplo n.º 3
0
        private IdentifierNode TryReadSubscript(ReadParams p, Span nameSpan, string name, Definition def)
        {
            if (def.DataType == null || def.DataType.AllowsSubscript == false)
            {
                return(new IdentifierNode(p.Statement, nameSpan, name, def));
            }

            var code     = p.Code;
            var resetPos = code.Position;

            if (code.ReadExact('['))
            {
                var exp1 = ExpressionNode.Read(p, null, "]", ",");
                if (exp1 != null)
                {
                    if (code.ReadExact(','))
                    {
                        var exp2 = ExpressionNode.Read(p, null, "]", ",");
                        if (exp2 != null)
                        {
                            if (code.ReadExact(']'))
                            {
                                return(new IdentifierNode(p.Statement, nameSpan, name, def,
                                                          subscriptAccessExps: new ExpressionNode[] { exp1, exp2 }));
                            }
                        }
                    }
                    else if (code.ReadExact(']'))
                    {
                        return(new IdentifierNode(p.Statement, nameSpan, name, def,
                                                  subscriptAccessExps: new ExpressionNode[] { exp1 }));
                    }
                }
            }

            // No match; reset back to before the array accessors started
            code.Position = resetPos;

            return(new IdentifierNode(p.Statement, nameSpan, name, def));
        }
Exemplo n.º 4
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);
        }
Exemplo n.º 5
0
        public static ExpressionNode Read(ReadParams p, DataType refDataType, bool stayOnSameLine, params string[] stopStrings)
        {
            ExpressionNode exp           = null;
            var            code          = p.Code;
            var            lastPos       = code.Position;
            var            parseDataType = refDataType;

            while (!code.EndOfFile)
            {
                switch (code.PeekChar())
                {
                case ';':
                case '{':
                case '}':
                    return(exp);
                }

                if (stopStrings != null)
                {
                    foreach (var str in stopStrings)
                    {
                        if (str.IsWord())
                        {
                            if (code.PeekExactWholeWord(str))
                            {
                                return(exp);
                            }
                        }
                        else
                        {
                            if (code.PeekExact(str))
                            {
                                return(exp);
                            }
                        }
                    }
                }

                if (!code.Read())
                {
                    break;
                }

                if (stayOnSameLine)
                {
                    if (code.PositionsAreOnDifferentLines(lastPos, code.TokenStartPostion))
                    {
                        code.Position = code.TokenStartPostion;
                        break;
                    }
                    lastPos = code.Position;
                }

                if (exp == null)
                {
                    exp = new ExpressionNode(p.Statement);
                }

                switch (code.Type)
                {
                case CodeType.Number:
                    exp.AddChild(new NumberNode(p.Statement, code.Span, code.Text));
                    break;

                case CodeType.StringLiteral:
                    if (code.Text.StartsWith("'"))
                    {
                        exp.AddChild(new CharLiteralNode(p.Statement, code.Span, CodeParser.StringLiteralToString(code.Text)));
                    }
                    else
                    {
                        exp.AddChild(new StringLiteralNode(p.Statement, code.Span, CodeParser.StringLiteralToString(code.Text)));
                    }
                    break;

                case CodeType.Word:
                    exp.AddChild(exp.ReadWord(p, parseDataType));
                    break;

                case CodeType.Operator:
                    switch (code.Text)
                    {
                    case "(":
                    {
                        var opText    = code.Text;
                        var startPos  = code.Span.Start;
                        var resumePos = code.Position;
                        var dataType  = DataType.TryParse(new DataType.ParseArgs
                            {
                                Code             = code,
                                Flags            = DataType.ParseFlag.Strict,
                                DataTypeCallback = name =>
                                {
                                    return(p.Statement.CodeAnalyzer.PreprocessorModel.DefinitionProvider.
                                           GetAny <DataTypeDefinition>(startPos + p.FuncOffset, name).FirstOrDefault());
                                },
                                VariableCallback = name =>
                                {
                                    return(p.Statement.CodeAnalyzer.PreprocessorModel.DefinitionProvider.
                                           GetAny <VariableDefinition>(startPos + p.FuncOffset, name).FirstOrDefault());
                                },
                                TableFieldCallback = (tableName, fieldName) =>
                                {
                                    foreach (var tableDef in p.Statement.CodeAnalyzer.PreprocessorModel.DefinitionProvider.GetGlobalFromFile(tableName))
                                    {
                                        if (tableDef.AllowsChild)
                                        {
                                            foreach (var fieldDef in tableDef.GetChildDefinitions(fieldName))
                                            {
                                                return(new Definition[] { tableDef, fieldDef });
                                            }
                                        }
                                    }

                                    return(null);
                                },
                                VisibleModel = false
                            });
                        if (dataType != null && code.ReadExact(')'))
                        {
                            // This is a cast
                            var span = new Span(startPos, code.Span.End);
                            exp.AddChild(new CastNode(p.Statement, span, dataType, ExpressionNode.Read(p, dataType, stayOnSameLine, stopStrings)));
                        }
                        else
                        {
                            code.Position = resumePos;
                            exp.AddChild(exp.ReadNestable(p, parseDataType, code.Span, opText, null));
                        }
                    }
                    break;

                    //case "[":
                    //	exp.AddChild(exp.ReadNestable(p, code.Span, code.Text, stopStrings));
                    //	break;
                    case "-":
                    {
                        var lastNode = exp.LastChild;
                        if (lastNode == null || lastNode is OperatorNode)
                        {
                            exp.AddChild(new OperatorNode(p.Statement, code.Span, code.Text, SpecialOperator.UnaryMinus));
                        }
                        else
                        {
                            exp.AddChild(new OperatorNode(p.Statement, code.Span, code.Text, null));
                        }
                    }
                    break;

                    case "?":
                        parseDataType = refDataType;
                        exp.AddChild(ConditionalNode.Read(p, parseDataType, code.Span, stopStrings));
                        break;

                    case "=":
                    {
                        var rDataType = exp.NumChildren > 0 ? exp.LastChild.DataType : null;
                        exp.AddChild(new OperatorNode(p.Statement, code.Span, code.Text, null));
                        exp.AddChild(ExpressionNode.Read(p, rDataType, stopStrings));
                    }
                    break;

                    case "==":
                    case "!=":
                    case "<":
                    case "<=":
                    case ">":
                    case ">=":
                    {
                        if (exp.NumChildren > 0)
                        {
                            var dt = exp.LastChild.DataType;
                            if (dt != null)
                            {
                                parseDataType = dt;
                            }
                        }
                        exp.AddChild(new OperatorNode(p.Statement, code.Span, code.Text, null));
                    }
                    break;

                    default:
                        exp.AddChild(new OperatorNode(p.Statement, code.Span, code.Text, null));
                        break;
                    }
                    break;

                default:
                    exp.ReportError(code.Span, CAError.CA0001, code.Text);                              // Unknown '{0}'.
                    exp.AddChild(new UnknownNode(p.Statement, code.Span, code.Text));
                    break;
                }
            }

            return(exp);
        }
Exemplo n.º 6
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);
        }
Exemplo n.º 7
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);
        }