Example #1
0
        /// <summary>
        /// Parses a set of brackets containing arguments.
        /// </summary>
        /// <param name="scope">The scope for this token.</param>
        /// <param name="openBracketToken">The open bracket token.</param>
        /// <param name="sig">(optional) A signature for the function being called.</param>
        /// <returns>A new argument token.</returns>
        /// <remarks>This function assumes the opening bracket has already been read from the stream.</remarks>
        public static ArgsToken Parse(Scope scope, OperatorToken openBracketToken, FunctionSignature sig)
        {
            var code     = scope.Code;
            var ret      = new ArgsToken(scope, openBracketToken);
            var argIndex = 0;

            scope       = scope.Clone();
            scope.Hint |= ScopeHint.SuppressStatementStarts;

            ret._sig = sig;
            var args = sig != null?sig.Arguments.ToArray() : ArgumentDescriptor.EmptyArray;

            while (code.SkipWhiteSpace())
            {
                code.Peek();
                if (code.Text == ")")
                {
                    ret.AddToken(new OperatorToken(scope, code.MovePeekedSpan(), ")"));
                    ret._terminated = true;
                    return(ret);
                }

                if (code.Text == ",")
                {
                    ret.AddToken(new OperatorToken(scope, code.MovePeekedSpan(), ","));
                    argIndex++;
                    continue;
                }


                var dataType = argIndex < args.Length ? args[argIndex].DataType : null;
                var exp      = ExpressionToken.TryParse(scope, _endTokens, expectedDataType: dataType);
                if (exp != null)
                {
                    ret.AddToken(exp);
                }
                else
                {
                    break;
                }
            }

            return(ret);
        }
Example #2
0
        private static Token ProcessWord(ExpressionToken exp, Scope scope, string word, Span wordSpan)
        {
            // Global keyword that take effect anywhere.
            switch (word)
            {
            case "static":
                return(new KeywordToken(scope, wordSpan, word));
            }

            var code = scope.Code;

            if (code.PeekExact('.'))
            {
                var dotSpan = code.MovePeekedSpan();
                var word2   = code.PeekWordR();
                if (!string.IsNullOrEmpty(word2))
                {
                    var word2Span           = code.MovePeekedSpan();
                    var argsPresent         = (scope.Hint & ScopeHint.SuppressFunctionCall) == 0 && code.PeekExact('(');
                    var argsOpenBracketSpan = argsPresent ? code.MovePeekedSpan() : Span.Empty;

                    foreach (var def in scope.DefinitionProvider.GetAny(wordSpan.Start, word))
                    {
                        if (def.AllowsChild)
                        {
                            // When arguments are present, take only the definitions that accept arguments
                            var childDefs = def.GetChildDefinitions(word2).Where(x => argsPresent ? x.ArgumentsRequired : true).ToArray();
                            if (childDefs.Any())
                            {
                                ArgsToken  argsToken = null;
                                Definition childDef  = null;

                                if (argsPresent)
                                {
                                    var openBracketToken = new OperatorToken(scope, argsOpenBracketSpan, "(");
                                    argsToken = ArgsToken.ParseAndChooseArguments(scope, openBracketToken, childDefs, out childDef);
                                }
                                else
                                {
                                    childDef = childDefs[0];
                                }

                                var word1Token = new IdentifierToken(scope, wordSpan, word, def);
                                var dotToken   = new DotToken(scope, dotSpan);
                                var word2Token = new IdentifierToken(scope, word2Span, word2, childDef);
                                var compToken  = new CompositeToken(scope, childDef.DataType);
                                compToken.AddToken(word1Token);
                                compToken.AddToken(dotToken);
                                compToken.AddToken(word2Token);
                                if (argsToken != null)
                                {
                                    compToken.AddToken(argsToken);
                                }
                                return(compToken);
                            }
                        }
                    }
                }
                else
                {
                    code.Position = dotSpan.Start;
                    return(new UnknownToken(scope, wordSpan, word));
                }
            }

            if ((scope.Hint & ScopeHint.SuppressFunctionCall) == 0 && code.PeekExact('('))
            {
                var argsOpenBracketSpan = code.MovePeekedSpan();

                foreach (var def in scope.DefinitionProvider.GetAny(wordSpan.Start, word))
                {
                    if (def.ArgumentsRequired)
                    {
                        var wordToken        = new IdentifierToken(scope, wordSpan, word, def);
                        var openBracketToken = new OperatorToken(scope, argsOpenBracketSpan, "(");
                        var argsToken        = ArgsToken.Parse(scope, openBracketToken, def.Signature);

                        var compToken = new CompositeToken(scope, def.DataType);
                        compToken.AddToken(wordToken);
                        compToken.AddToken(argsToken);

                        if (def.AllowsFunctionBody && (scope.Hint & ScopeHint.SuppressFunctionDefinition) == 0)
                        {
                            ParseFunctionAttributes(exp, scope, compToken);
                            if (code.PeekExact('{'))
                            {
                                compToken.AddToken(BracesToken.Parse(scope, def, argsToken.Span.End + 1));
                            }
                        }

                        return(compToken);
                    }
                }
            }

            foreach (var def in scope.DefinitionProvider.GetAny(wordSpan.Start, word))
            {
                if (def.ArgumentsRequired || def.RequiresChild)
                {
                    continue;
                }

                return(new IdentifierToken(scope, wordSpan, word, def));
            }

            if (StatementToken.IsStatementBreakingWord(scope, word))
            {
                // There could be a statement without a terminating ';' before this.
                // This can happen if it's a macro that already includes the ';'.
                return(null);
            }

            if (Constants.HighlightKeywords.Contains(word))
            {
                return(new KeywordToken(scope, wordSpan, word));
            }

            return(new UnknownToken(scope, wordSpan, word));
        }
Example #3
0
        public static ArgsToken ParseAndChooseArguments(Scope scope, OperatorToken openBracketToken, Definition[] sigDefs, out Definition selectedDef)
        {
#if DEBUG
            if (sigDefs == null)
            {
                throw new ArgumentNullException("sigDefs");
            }
            if (sigDefs.Length == 0)
            {
                throw new ArgumentException("sigDefs must contain at least one signature definition.");
            }
#endif

            if (sigDefs.Length == 1)
            {
                selectedDef = sigDefs[0];
                return(Parse(scope, openBracketToken, sigDefs[0].ArgumentsSignature));
            }

            var code = scope.Code;
            var ret  = new ArgsToken(scope, openBracketToken);

            scope       = scope.Clone();
            scope.Hint |= ScopeHint.SuppressStatementStarts;

            var          tokens         = new List <Token>();
            var          dataTypes      = new List <DataType>();
            List <Token> bestTokens     = null;
            var          bestConfidence = 0.0f;
            Definition   bestSigDef     = null;
            var          codeResetPos   = code.Position;

            foreach (var sigDef in sigDefs)
            {
                var args              = sigDef.Arguments.ToArray();
                var argIndex          = 0;
                var expectingDataType = true;

                tokens.Clear();
                dataTypes.Clear();
                code.Position = codeResetPos;

                while (code.SkipWhiteSpace())
                {
                    code.Peek();
                    if (code.Text == ")")
                    {
                        tokens.Add(new OperatorToken(scope, code.MovePeekedSpan(), ")"));
                        ret._terminated = true;
                        break;
                    }
                    else if (code.Text == ",")
                    {
                        tokens.Add(new OperatorToken(scope, code.MovePeekedSpan(), ","));
                        argIndex++;
                        expectingDataType = true;
                        continue;
                    }

                    var exp = ExpressionToken.TryParse(scope, _endTokens,
                                                       expectedDataType: argIndex < args.Length ? args[argIndex].DataType : null);
                    if (exp != null)
                    {
                        tokens.Add(exp);
                        if (expectingDataType)
                        {
                            dataTypes.Add(exp.ValueDataType);
                        }
                        expectingDataType = false;
                    }
                    else
                    {
                        break;
                    }
                }

                if (dataTypes.Count == args.Length)
                {
                    var confidence = 1.0f;
                    for (int i = 0, ii = args.Length; i < ii; i++)
                    {
                        confidence *= DataType.CalcArgumentCompatibility(args[i].DataType, dataTypes[i]);
                    }

                    if (confidence > bestConfidence)
                    {
                        bestConfidence = confidence;
                        bestTokens     = tokens;
                        bestSigDef     = sigDef;
                    }
                }
                else if (bestTokens == null)
                {
                    bestTokens     = tokens;
                    bestConfidence = 0.0f;
                    bestSigDef     = sigDef;
                }
            }

            ret.AddTokens(bestTokens);
            ret._sig             = bestSigDef.ArgumentsSignature;
            ret._sigAlternatives = (from s in sigDefs where s.ArgumentsSignature != ret._sig select s.ArgumentsSignature).ToArray();
            selectedDef          = bestSigDef;
            return(ret);
        }