private new LexerToken ScanIdentifierOrKeyword(string line, ref int startAt)
    {
        var token = Lexer_Base.ScanIdentifierOrKeyword(line, ref startAt);

        if (token != null && token.tokenKind == LexerToken.Kind.Keyword && !IsKeyword(token.text) && !IsBuiltInType(token.text))
        {
            token.tokenKind = LexerToken.Kind.Identifier;
        }
        return(token);
    }
예제 #2
0
    private void Preprocess(string sData, ref int iIndex, FormatedLine formatedLine)
    {
        TryScan_Whitespace(sData, ref iIndex, formatedLine);

        var error        = false;
        var commentsOnly = false;

        int iLength = sData.Length;
        List <LexerToken> tokens = formatedLine.tokens;
        LexerToken        token  = ScanWord(sData, ref iIndex);

        if (!preprocessorKeywords.Contains(token.text))
        {
            token.tokenKind = LexerToken.Kind.PreprocessorDirectiveExpected;
            tokens.Add(token);
            token.formatedLine = formatedLine;
            error = true;
        }
        else
        {
            token.tokenKind = LexerToken.Kind.Preprocessor;
            tokens.Add(token);
            token.formatedLine = formatedLine;
            TryScan_Whitespace(sData, ref iIndex, formatedLine);

            switch (token.text)
            {
            case "if":
                if (ParsePPOrExpression(sData, formatedLine, ref iIndex) && formatedLine.regionTree.kind <= RegionTree.Kind.LastActive)
                {
                    OpenRegion(formatedLine, RegionTree.Kind.If);
                }
                else
                {
                    OpenRegion(formatedLine, RegionTree.Kind.InactiveIf);
                }
                commentsOnly = true;
                break;

            case "elif":
                bool active = ParsePPOrExpression(sData, formatedLine, ref iIndex);
                switch (formatedLine.regionTree.kind)
                {
                case RegionTree.Kind.If:
                case RegionTree.Kind.Elif:
                case RegionTree.Kind.InactiveElif:
                    OpenRegion(formatedLine, RegionTree.Kind.InactiveElif); break;

                case RegionTree.Kind.InactiveIf:
                    if (active && formatedLine.regionTree.kind <= RegionTree.Kind.LastActive)
                    {
                        OpenRegion(formatedLine, RegionTree.Kind.Elif);
                    }
                    else
                    {
                        OpenRegion(formatedLine, RegionTree.Kind.InactiveElif);
                    }
                    break;

                default:
                    token.tokenKind = LexerToken.Kind.PreprocessorUnexpectedDirective; break;
                }
                break;

            case "else":
                if (formatedLine.regionTree.kind == RegionTree.Kind.If ||
                    formatedLine.regionTree.kind == RegionTree.Kind.Elif)
                {
                    OpenRegion(formatedLine, RegionTree.Kind.InactiveElse);
                }
                else if (formatedLine.regionTree.kind == RegionTree.Kind.InactiveIf ||
                         formatedLine.regionTree.kind == RegionTree.Kind.InactiveElif)
                {
                    if (formatedLine.regionTree.parent.kind > RegionTree.Kind.LastActive)
                    {
                        OpenRegion(formatedLine, RegionTree.Kind.InactiveElse);
                    }
                    else
                    {
                        OpenRegion(formatedLine, RegionTree.Kind.Else);
                    }
                }
                else
                {
                    token.tokenKind = LexerToken.Kind.PreprocessorUnexpectedDirective;
                }
                break;

            case "endif":
                if (formatedLine.regionTree.kind == RegionTree.Kind.If ||
                    formatedLine.regionTree.kind == RegionTree.Kind.Elif ||
                    formatedLine.regionTree.kind == RegionTree.Kind.Else ||
                    formatedLine.regionTree.kind == RegionTree.Kind.InactiveIf ||
                    formatedLine.regionTree.kind == RegionTree.Kind.InactiveElif ||
                    formatedLine.regionTree.kind == RegionTree.Kind.InactiveElse)
                {
                    CloseRegion(formatedLine);
                }
                else
                {
                    token.tokenKind = LexerToken.Kind.PreprocessorUnexpectedDirective;
                }
                break;

            case "define":
            case "undef":
            {
                var symbol = Lexer_Base.ScanIdentifierOrKeyword(sData, ref iIndex);
                if (symbol != null && symbol.text != "true" && symbol.text != "false")
                {
                    symbol.tokenKind = LexerToken.Kind.PreprocessorSymbol;
                    formatedLine.tokens.Add(symbol);
                    symbol.formatedLine  = formatedLine;
                    scriptDefinesChanged = true;

                    var inactive = formatedLine.regionTree.kind > RegionTree.Kind.LastActive;
                    if (!inactive)
                    {
                        if (token.text == "define")
                        {
                            if (!CompilationDefines.Contains(symbol.text))
                            {
                                CompilationDefines.Add(symbol.text);
                            }
                        }
                        else if (CompilationDefines.Contains(symbol.text))
                        {
                            CompilationDefines.Remove(symbol.text);
                        }
                    }
                }
            }
            break;


            case "region":
                if (formatedLine.regionTree.kind > RegionTree.Kind.LastActive)
                {
                    OpenRegion(formatedLine, RegionTree.Kind.InactiveRegion);
                }
                else
                {
                    OpenRegion(formatedLine, RegionTree.Kind.Region);
                }
                break;

            case "endregion":
                if (formatedLine.regionTree.kind == RegionTree.Kind.Region ||
                    formatedLine.regionTree.kind == RegionTree.Kind.InactiveRegion)
                {
                    CloseRegion(formatedLine);
                }
                else
                {
                    token.tokenKind = LexerToken.Kind.PreprocessorUnexpectedDirective;
                }
                break;

            case "error":
            case "warning":
                break;
            }
        }

        switch (token.text)
        {
        case "region":
        case "endregion":
        case "error":
        case "warning":
            TryScan_Whitespace(sData, ref iIndex, formatedLine);
            if (iIndex < iLength)
            {
                var textArgument = sData.Substring(iIndex);
                textArgument.TrimEnd(new[] { ' ', '\t' });
                tokens.Add(new LexerToken(LexerToken.Kind.PreprocessorArguments, textArgument)
                {
                    formatedLine = formatedLine
                });
                iIndex = iLength - textArgument.Length;
                if (iIndex < iLength)
                {
                    tokens.Add(new LexerToken(LexerToken.Kind.Whitespace, sData.Substring(iIndex))
                    {
                        formatedLine = formatedLine
                    });
                }
            }
            return;
        }

        while (iIndex < iLength)
        {
            if (TryScan_Whitespace(sData, ref iIndex, formatedLine))
            {
                continue;
            }

            var firstChar = sData[iIndex];
            if (iIndex < iLength - 1 && firstChar == '/' && sData[iIndex + 1] == '/')
            {
                tokens.Add(new LexerToken(LexerToken.Kind.Comment, sData.Substring(iIndex))
                {
                    formatedLine = formatedLine
                });
                break;
            }
            else if (commentsOnly)
            {
                tokens.Add(new LexerToken(LexerToken.Kind.PreprocessorCommentExpected, sData.Substring(iIndex))
                {
                    formatedLine = formatedLine
                });
                break;
            }

            if (char.IsLetterOrDigit(firstChar) || firstChar == '_')
            {
                token           = ScanWord(sData, ref iIndex);
                token.tokenKind = LexerToken.Kind.PreprocessorArguments;
                tokens.Add(token);
                token.formatedLine = formatedLine;
            }
            else if (firstChar == '"')
            {
                token           = ScanStringLiteral(sData, ref iIndex);
                token.tokenKind = LexerToken.Kind.PreprocessorArguments;
                tokens.Add(token);
                token.formatedLine = formatedLine;
            }
            else if (firstChar == '\'')
            {
                token           = ScanCharLiteral(sData, ref iIndex);
                token.tokenKind = LexerToken.Kind.PreprocessorArguments;
                tokens.Add(token);
                token.formatedLine = formatedLine;
            }
            else
            {
                token = new LexerToken(LexerToken.Kind.PreprocessorArguments, firstChar.ToString())
                {
                    formatedLine = formatedLine
                };
                tokens.Add(token);
                ++iIndex;
            }

            if (error)
            {
                token.tokenKind = LexerToken.Kind.PreprocessorDirectiveExpected;
            }
        }
    }