コード例 #1
0
        public static WhileStatement Parse(Scope scope, KeywordToken whileToken)
        {
            var code = scope.Code;
            var ret  = new WhileStatement(scope, whileToken);

            scope               = scope.Clone();
            scope.BreakOwner    = ret;
            scope.ContinueOwner = ret;

            // Expression
            var expressionScope = scope.Clone();

            expressionScope.Hint |= ScopeHint.SuppressDataType | ScopeHint.SuppressFunctionDefinition | ScopeHint.SuppressVarDecl;

            ret._expressionToken = ExpressionToken.TryParse(scope, null);
            if (ret._expressionToken != null)
            {
                ret.AddToken(ret._expressionToken);

                if (code.PeekExact('{'))
                {
                    var bodyScope = scope.Clone();
                    bodyScope.Hint |= ScopeHint.SuppressFunctionDefinition;

                    ret.AddToken(ret._bodyToken = BracesToken.Parse(bodyScope, null));
                }
            }

            return(ret);
        }
コード例 #2
0
        private static void ParseFunctionAttributes(ExpressionToken exp, Scope scope, CompositeToken funcToken)
        {
            var             code = scope.Code;
            string          word;
            ExpressionToken exp2;

            while (true)
            {
                word = code.PeekWordR();
                switch (word)
                {
                case "description":
                case "prompt":
                case "comment":
                case "accel":
                    funcToken.AddToken(new KeywordToken(scope, code.MovePeekedSpan(), code.Text));
                    exp2 = ExpressionToken.TryParse(scope, _functionAttribsEndTokens);
                    if (exp2 != null)
                    {
                        funcToken.AddToken(exp2);
                    }
                    break;

                case "nomenu":
                    funcToken.AddToken(new KeywordToken(scope, code.MovePeekedSpan(), code.Text));
                    break;

                case "BEGINHLP":
                    funcToken.AddToken(new KeywordToken(scope, code.MovePeekedSpan(), code.Text));
                    while (code.ReadStringLiteral())
                    {
                        funcToken.AddToken(new StringLiteralToken(scope, code.Span, code.Text));
                    }
                    if (code.ReadExactWholeWord("ENDHLP"))
                    {
                        funcToken.AddToken(new KeywordToken(scope, code.Span, code.Text));
                    }
                    break;

                case "tag":
                    if (code.ReadTagName())
                    {
                        funcToken.AddToken(new KeywordToken(scope, code.Span, code.Text));
                    }
                    exp2 = ExpressionToken.TryParse(scope, _functionAttribsEndTokens);
                    if (exp2 != null)
                    {
                        funcToken.AddToken(exp2);
                    }
                    break;

                default:
                    return;
                }
            }
        }
コード例 #3
0
ファイル: ArrayBracesToken.cs プロジェクト: cmrazek/DkTools
        public static ArrayBracesToken Parse(Scope scope)
        {
            var code = scope.Code;

            if (!code.ReadExact('['))
            {
                throw new InvalidOperationException("ArrayBracesToken.Parse expected next char to be '['.");
            }
            var openBracketSpan = code.Span;

            var indentScope = scope.CloneIndentNonRoot();

            indentScope.Hint |= ScopeHint.SuppressFunctionDefinition | ScopeHint.SuppressStatementStarts;

            var ret = new ArrayBracesToken(scope);

            ret.AddToken(ret._openToken = new ArrayBraceToken(scope, openBracketSpan, ret, true));

            while (!code.EndOfFile)
            {
                if (code.ReadExact(']'))
                {
                    ret.AddToken(ret._closeToken = new ArrayBraceToken(scope, code.Span, ret, false));
                    break;
                }

                if (code.ReadExact(','))
                {
                    ret.AddToken(new DelimiterToken(indentScope, code.Span));
                    continue;
                }

                var exp = ExpressionToken.TryParse(indentScope, _endTokens);
                if (exp != null)
                {
                    ret.AddToken(exp);
                }
                else
                {
                    break;
                }
            }

            return(ret);
        }
コード例 #4
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);
        }
コード例 #5
0
        public static IfStatement Parse(Scope scope, KeywordToken ifToken)
        {
            var code = scope.Code;

            var ret = new IfStatement(scope);

            ret.AddToken(ifToken);

            var scopeIndent = scope.Clone();

            scopeIndent.Hint |= ScopeHint.NotOnRoot | ScopeHint.SuppressFunctionDefinition | ScopeHint.SuppressVarDecl;

            ret._condition = ExpressionToken.TryParse(scopeIndent, null);
            if (ret._condition != null)
            {
                ret.AddToken(ret._condition);
            }

            if (code.PeekExact('{'))
            {
                ret.AddToken(ret._trueBody = BracesToken.Parse(scopeIndent, null));

                if (code.ReadExactWholeWord("else"))
                {
                    ret.AddToken(ret._elseToken = new KeywordToken(scopeIndent, code.Span, "else"));

                    if (code.PeekExact('{'))
                    {
                        ret.AddToken(ret._falseBody = BracesToken.Parse(scopeIndent, null));
                    }
                    else if (code.ReadExactWholeWord("if"))
                    {
                        var ifToken2 = new KeywordToken(scopeIndent, code.Span, "if");
                        ret.AddToken(ret._falseBody = IfStatement.Parse(scopeIndent, ifToken2));
                    }
                }
            }

            return(ret);
        }
コード例 #6
0
ファイル: StatementToken.cs プロジェクト: cmrazek/DkTools
        public static StatementToken TryParse(Scope scope, StatementParseCallback callback = null)
        {
            var code = scope.Code;

            if (!code.SkipWhiteSpace())
            {
                return(null);
            }

            var ret = new StatementToken(scope);

            if (!code.Peek())
            {
                return(null);
            }

            switch (code.Type)
            {
            case CodeType.Word:
                switch (code.Text)
                {
                case "alter":
                {
                    var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text);
                    var token        = CreateStatement.ParseAlter(scope, keywordToken);
                    ret.AddToken(token);
                    if (callback != null)
                    {
                        callback(token);
                    }
                    return(ret);
                }

                case "break":
                    if (scope.BreakOwner != null)
                    {
                        var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text);
                        var breakToken   = BreakStatement.Parse(scope, keywordToken);
                        ret.AddToken(breakToken);
                        if (callback != null)
                        {
                            callback(breakToken);
                        }
                        scope.BreakOwner.OnBreakAttached(breakToken);
                        return(ret);
                    }
                    break;

                case "create":
                {
                    var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text);
                    var token        = CreateStatement.ParseCreate(scope, keywordToken);
                    ret.AddToken(token);
                    if (callback != null)
                    {
                        callback(token);
                    }
                    return(ret);
                }

                case "col":
                case "row":
                case "colff":
                case "page":
                {
                    var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text);
                    var token        = RowColStatement.Parse(scope, keywordToken);
                    ret.AddToken(token);
                    if (callback != null)
                    {
                        callback(token);
                    }
                    return(ret);
                }

                case "continue":
                    if (scope.ContinueOwner != null)
                    {
                        var keywordToken  = new KeywordToken(scope, code.MovePeekedSpan(), code.Text);
                        var continueToken = ContinueStatement.Parse(scope, keywordToken);
                        ret.AddToken(continueToken);
                        if (callback != null)
                        {
                            callback(continueToken);
                        }
                        scope.ContinueOwner.OnContinueAttached(continueToken);
                        return(ret);
                    }
                    break;

                case "extern":
                {
                    var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text);
                    var token        = ExternStatement.Parse(scope, keywordToken);
                    ret.AddToken(token);
                    if (callback != null)
                    {
                        callback(token);
                    }
                    return(ret);
                }

                case "extract":
                {
                    var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text);
                    var token        = ExtractStatement.Parse(scope, keywordToken);
                    ret.AddToken(token);
                    if (callback != null)
                    {
                        callback(token);
                    }
                    return(ret);
                }

                case "footer":
                {
                    var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text);
                    var token        = FooterStatement.Parse(scope, keywordToken);
                    ret.AddToken(token);
                    if (callback != null)
                    {
                        callback(token);
                    }
                    return(ret);
                }

                case "for":
                {
                    var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text);
                    var token        = ForStatement.Parse(scope, keywordToken);
                    ret.AddToken(token);
                    if (callback != null)
                    {
                        callback(token);
                    }
                    return(ret);
                }

                case "format":
                {
                    var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text);
                    var token        = FormatStatement.Parse(scope, keywordToken);
                    ret.AddToken(token);
                    if (callback != null)
                    {
                        callback(token);
                    }
                    return(ret);
                }

                case "header":
                {
                    var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text);
                    var token        = HeaderStatement.Parse(scope, keywordToken);
                    ret.AddToken(token);
                    if (callback != null)
                    {
                        callback(token);
                    }
                    return(ret);
                }

                case "if":
                {
                    var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text);
                    var token        = IfStatement.Parse(scope, keywordToken);
                    ret.AddToken(token);
                    if (callback != null)
                    {
                        callback(token);
                    }
                    return(ret);
                }

                case "public":
                case "private":
                case "protected":
                    if (scope.Model.FileContext.IsClass())
                    {
                        var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text);
                        ret.AddToken(keywordToken);
                        if (callback != null)
                        {
                            callback(keywordToken);
                        }
                        return(ret);
                    }
                    else
                    {
                        break;
                    }

                case "return":
                {
                    var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text);
                    var token        = ReturnStatement.Parse(scope, keywordToken);
                    ret.AddToken(token);
                    if (callback != null)
                    {
                        callback(token);
                    }
                    return(ret);
                }

                case "select":
                {
                    var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text);
                    var token        = SelectStatement.Parse(scope, keywordToken);
                    ret.AddToken(token);
                    if (callback != null)
                    {
                        callback(token);
                    }
                    return(ret);
                }

                case "switch":
                {
                    var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text);
                    var token        = SwitchStatement.Parse(scope, keywordToken);
                    ret.AddToken(token);
                    if (callback != null)
                    {
                        callback(token);
                    }
                    return(ret);
                }

                case "while":
                {
                    var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text);
                    var token        = WhileStatement.Parse(scope, keywordToken);
                    ret.AddToken(token);
                    if (callback != null)
                    {
                        callback(token);
                    }
                    return(ret);
                }
                }
                break;

            case CodeType.Preprocessor:
                switch (code.Text)
                {
                case "#insert":
                {
                    var token = InsertToken.Parse(scope, new InsertStartToken(scope, code.MovePeekedSpan()));
                    ret.AddToken(token);
                    if (callback != null)
                    {
                        callback(token);
                    }
                    return(ret);
                }

                case "#endinsert":
                {
                    var token = new InsertEndToken(scope, code.MovePeekedSpan());
                    ret.AddToken(token);
                    if (callback != null)
                    {
                        callback(token);
                    }
                    return(ret);
                }

                case "#replace":
                {
                    var token = ReplaceToken.Parse(scope, new ReplaceStartToken(scope, code.MovePeekedSpan()));
                    ret.AddToken(token);
                    if (callback != null)
                    {
                        callback(token);
                    }
                    return(ret);
                }

                case "#with":
                {
                    var token = new ReplaceWithToken(scope, code.MovePeekedSpan());
                    ret.AddToken(token);
                    if (callback != null)
                    {
                        callback(token);
                    }
                    return(ret);
                }

                case "#endreplace":
                {
                    var token = new ReplaceEndToken(scope, code.MovePeekedSpan());
                    ret.AddToken(token);
                    if (callback != null)
                    {
                        callback(token);
                    }
                    return(ret);
                }

                case "#include":
                {
                    var token = IncludeToken.Parse(scope, new PreprocessorToken(scope, code.MovePeekedSpan(), code.Text));
                    ret.AddToken(token);
                    if (callback != null)
                    {
                        callback(token);
                    }
                    return(ret);
                }

                default:
                {
                    var token = new PreprocessorToken(scope, code.MovePeekedSpan(), code.Text);
                    ret.AddToken(token);
                    if (callback != null)
                    {
                        callback(token);
                    }
                    return(ret);
                }
                }

            case CodeType.Operator:
                switch (code.Text)
                {
                case "{":
                {
                    // Start of a 'scope'. This is not allowed in PROBE/WBDK but allow it here anyway.
                    var token = BracesToken.Parse(scope, null);
                    ret.AddToken(token);
                    if (callback != null)
                    {
                        callback(token);
                    }
                    return(ret);
                }

                case "}":
                {
                    // Unmatched '}'. This is a syntax error, but since it's a statement breaking token, add it here and end the statement.
                    var token = new OperatorToken(scope, code.MovePeekedSpan(), "}");
                    ret.AddToken(token);
                    if (callback != null)
                    {
                        callback(token);
                    }
                    return(ret);
                }
                }
                break;
            }

            var exp = ExpressionToken.TryParse(scope, null);

            if (exp != null)
            {
                ret.AddToken(exp);
                if (callback != null)
                {
                    callback(exp);
                }

                code.SkipWhiteSpace();
            }

            if (code.ReadExact(';'))
            {
                // Empty statement. This is not allowed in PROBE/WBDK, but allow it here anyway.
                var token = new StatementEndToken(scope, code.Span);
                ret.AddToken(token);
                if (callback != null)
                {
                    callback(token);
                }
                return(ret);
            }

            return(ret);
        }
コード例 #7
0
ファイル: SwitchStatement.cs プロジェクト: cmrazek/DkTools
        public static SwitchStatement Parse(Scope scope, KeywordToken switchToken)
        {
            var ret = new SwitchStatement(scope, switchToken);

            scope            = scope.Clone();
            scope.BreakOwner = ret;

            var code = scope.Code;

            var expressionScope = scope.Clone();

            expressionScope.Hint |= ScopeHint.SuppressDataType | ScopeHint.SuppressFunctionDefinition | ScopeHint.SuppressVarDecl;

            ret._expressionToken = ExpressionToken.TryParse(expressionScope, null);
            if (ret._expressionToken != null)
            {
                ret.AddToken(ret._expressionToken);
            }

            if (code.ReadExact('{'))
            {
                var bodyScope = scope.Clone();
                bodyScope.Hint |= ScopeHint.SuppressFunctionDefinition;

                ret._bodyToken = new BracesToken(bodyScope, code.Span);
                ret.AddToken(ret._bodyToken);

                var switchDataType = ret.ExpressionDataType;

                while (true)
                {
                    if (code.ReadExact('}'))
                    {
                        ret._bodyToken.AddClose(code.Span);
                        return(ret);
                    }

                    if (code.ReadExactWholeWord("case"))
                    {
                        ret.AddToken(new KeywordToken(scope, code.Span, "case"));

                        var caseExp = ExpressionToken.TryParse(scope, _caseEndTokens, expectedDataType: switchDataType);
                        if (caseExp != null)
                        {
                            ret.AddToken(caseExp);
                        }

                        if (code.ReadExact(':'))
                        {
                            ret.AddToken(new OperatorToken(scope, code.Span, ":"));
                        }
                        continue;
                    }

                    if (code.ReadExactWholeWord("default"))
                    {
                        ret.AddToken(new KeywordToken(scope, code.Span, "default"));
                        if (code.ReadExact(':'))
                        {
                            ret.AddToken(new OperatorToken(scope, code.Span, ":"));
                        }
                        continue;
                    }

                    var stmt = StatementToken.TryParse(bodyScope);
                    if (stmt != null)
                    {
                        ret._bodyToken.AddToken(stmt);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            return(ret);
        }
コード例 #8
0
        public static SelectStatement Parse(Scope parentScope, KeywordToken selectToken)
        {
            var ret   = new SelectStatement(parentScope, selectToken);
            var scope = parentScope.Clone();

            scope.BreakOwner    = ret;
            scope.ContinueOwner = ret;

            var code = scope.Code;

            if (code.ReadStringLiteral())
            {
                ret.AddToken(new StringLiteralToken(scope, code.Span, code.Text));
            }
            if (code.ReadExact('*'))
            {
                ret.AddToken(new OperatorToken(scope, code.Span, "*"));
            }

            if (!code.ReadExactWholeWord("from"))
            {
                return(ret);
            }
            ret.AddToken(new KeywordToken(scope, code.Span, "from"));

            ExtractTableDefinition extractDef = null;

            DkDict.Table table = null;

            if (code.ReadWord())
            {
                if ((table = DkDict.Dict.GetTable(code.Text)) != null)
                {
                    ret.AddToken(new TableToken(scope, code.Span, code.Text, table.Definition));
                }
                else if ((extractDef = scope.DefinitionProvider.GetAny <ExtractTableDefinition>(code.TokenStartPostion, code.Text).FirstOrDefault()) != null)
                {
                    ret.AddToken(new IdentifierToken(scope, code.Span, code.Text, extractDef));
                }
                else
                {
                    ret.AddToken(new UnknownToken(scope, code.Span, code.Text));
                }
            }

            if (code.ReadExactWholeWord("of"))
            {
                ret.AddToken(new KeywordToken(scope, code.Span, "of"));

                if (code.ReadWord())
                {
                    if ((table = DkDict.Dict.GetTable(code.Text)) != null)
                    {
                        ret.AddToken(new TableToken(scope, code.Span, code.Text, table.Definition));
                    }
                    else
                    {
                        ret.AddToken(new UnknownToken(scope, code.Span, code.Text));
                    }
                }
            }
            else if (code.ReadExact(','))
            {
                ret.AddToken(new DelimiterToken(scope, code.Span));

                var expectingComma = false;

                while (!code.EndOfFile)
                {
                    if (code.PeekExact('{'))
                    {
                        break;
                    }
                    if (expectingComma)
                    {
                        if (code.ReadExact(','))
                        {
                            ret.AddToken(new DelimiterToken(scope, code.Span));
                            expectingComma = false;
                        }
                        else
                        {
                            break;
                        }
                    }
                    else if (code.ReadWord())
                    {
                        if ((table = DkDict.Dict.GetTable(code.Text)) != null)
                        {
                            ret.AddToken(new TableToken(scope, code.Span, code.Text, table.Definition));
                        }
                        else
                        {
                            ret.AddToken(new UnknownToken(scope, code.Span, code.Text));
                        }
                        expectingComma = true;
                    }
                    else
                    {
                        break;
                    }
                }
            }

            // WHERE and ORDER BY
            var gotWhere   = false;
            var gotOrderBy = false;

            while (!code.EndOfFile)
            {
                if (code.PeekExact('{'))
                {
                    break;
                }
                if (!gotWhere && code.ReadExactWholeWord("where"))
                {
                    ret.AddToken(new KeywordToken(scope, code.Span, code.Text));
                    gotWhere = true;

                    var exp = ExpressionToken.TryParse(scope, _whereEndTokens);
                    if (exp != null)
                    {
                        ret.AddToken(exp);
                    }
                    else
                    {
                        break;
                    }
                }
                else if (!gotOrderBy && code.ReadExactWholeWord("order"))
                {
                    ret.AddToken(new KeywordToken(scope, code.Span, code.Text));
                    gotOrderBy = true;

                    if (!code.ReadExactWholeWord("by"))
                    {
                        break;
                    }
                    ret.AddToken(new KeywordToken(scope, code.Span, code.Text));

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

                        if (code.ReadExact(','))
                        {
                            ret.AddToken(new DelimiterToken(scope, code.Span));
                            continue;
                        }

                        if (code.ReadExactWholeWord("asc") || code.ReadExactWholeWord("desc"))
                        {
                            ret.AddToken(new KeywordToken(scope, code.Span, code.Text));
                            continue;
                        }

                        if (TryParseColumn(scope, ret, true, extractDef))
                        {
                            continue;
                        }

                        break;
                    }
                }
                else
                {
                    break;
                }
            }

            // Body
            if (code.ReadExact('{'))
            {
                var braces = new BracesToken(scope);
                braces.AddOpen(code.Span);
                ret.AddToken(braces);

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

                    if (code.ReadExactWholeWord("for"))
                    {
                        braces.AddToken(new KeywordToken(scope, code.Span, "for"));

                        if (!code.ReadExactWholeWord("each"))
                        {
                            continue;
                        }
                        braces.AddToken(new KeywordToken(scope, code.Span, "each"));

                        if (!code.ReadExact(':'))
                        {
                            continue;
                        }
                        braces.AddToken(new OperatorToken(scope, code.Span, ":"));
                    }
                    else if (code.ReadExactWholeWord("before") || code.ReadExactWholeWord("after"))
                    {
                        braces.AddToken(new KeywordToken(scope, code.Span, code.Text));

                        if (!code.ReadExactWholeWord("group"))
                        {
                            continue;
                        }
                        braces.AddToken(new KeywordToken(scope, code.Span, "group"));

                        if (code.ReadExactWholeWord("all"))
                        {
                            braces.AddToken(new KeywordToken(scope, code.Span, "all"));

                            if (!code.ReadExact(':'))
                            {
                                continue;
                            }
                            braces.AddToken(new OperatorToken(scope, code.Span, ":"));
                        }
                        else if (TryParseColumn(scope, braces, false, extractDef))
                        {
                            if (!code.ReadExact(':'))
                            {
                                continue;
                            }
                            braces.AddToken(new OperatorToken(scope, code.Span, ":"));
                        }
                    }
                    else if (code.ReadExactWholeWord("default"))
                    {
                        braces.AddToken(new KeywordToken(scope, code.Span, "default"));

                        if (!code.ReadExact(':'))
                        {
                            continue;
                        }
                        braces.AddToken(new OperatorToken(scope, code.Span, ":"));
                    }
                    else
                    {
                        var stmt = StatementToken.TryParse(scope);
                        if (stmt != null)
                        {
                            braces.AddToken(stmt);
                        }
                    }
                }
            }

            return(ret);
        }
コード例 #9
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);
        }
コード例 #10
0
ファイル: BracketsToken.cs プロジェクト: cmrazek/DkTools
        public static BracketsToken Parse(Scope scope, DataType expectedDataType)
        {
            var code = scope.Code;

            if (!code.ReadExact('('))
            {
                throw new InvalidOperationException("BracketsToken.Parse expected next char to be '('.");
            }
            var openBracketSpan = code.Span;

            var indentScope = scope.CloneIndentNonRoot();

            indentScope.Hint |= ScopeHint.SuppressFunctionDefinition | ScopeHint.SuppressControlStatements | ScopeHint.SuppressStatementStarts;

            var ret = new BracketsToken(scope);

            ret.AddToken(ret._openToken = new OpenBracketToken(scope, openBracketSpan, ret));

            List <Token> dataTypeTokens = null;
            var          dataType       = DataType.TryParse(new DataType.ParseArgs
            {
                Code             = code,
                Scope            = scope,
                DataTypeCallback = name =>
                {
                    return(indentScope.DefinitionProvider.GetAny <Defs.DataTypeDefinition>(openBracketSpan.End, name).FirstOrDefault());
                },
                VariableCallback = name =>
                {
                    return(indentScope.DefinitionProvider.GetAny <Defs.VariableDefinition>(openBracketSpan.End, name).FirstOrDefault());
                },
                TableFieldCallback = (tableName, fieldName) =>
                {
                    foreach (var tableDef in indentScope.DefinitionProvider.GetGlobalFromFile(tableName))
                    {
                        if (tableDef.AllowsChild)
                        {
                            foreach (var fieldDef in tableDef.GetChildDefinitions(fieldName))
                            {
                                return(new Defs.Definition[] { tableDef, fieldDef });
                            }
                        }
                    }

                    return(null);
                },
                TokenCreateCallback = token =>
                {
                    if (dataTypeTokens == null)
                    {
                        dataTypeTokens = new List <Token>();
                    }
                    dataTypeTokens.Add(token);
                },
                VisibleModel = scope.Visible
            });

            if (dataType != null && code.ReadExact(')'))
            {
                ret._cast = dataType;
                if (dataTypeTokens != null)
                {
                    foreach (var token in dataTypeTokens)
                    {
                        ret.AddToken(token);
                    }
                }
                ret.AddToken(ret._closeToken = new CloseBracketToken(scope, code.Span, ret));
            }
            else
            {
                while (!code.EndOfFile)
                {
                    if (code.ReadExact(')'))
                    {
                        ret.AddToken(ret._closeToken = new CloseBracketToken(scope, code.Span, ret));
                        break;
                    }

                    var exp = ExpressionToken.TryParse(indentScope, _endTokens, expectedDataType: expectedDataType);
                    if (exp != null)
                    {
                        ret._innerTokens.Add(exp);
                        ret.AddToken(exp);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            return(ret);
        }