예제 #1
0
        private bool TryReadElementString(string elementName, bool mustEndInWhitespace)
        {
            var fileContents = streamReader.Text;

            var readTo = streamReader.ReadIndex + elementName.Length;
            var eof    = readTo == fileContents.Length;

            if (readTo <= fileContents.Length)
            {
                if (StringEqual(fileContents.Substring(streamReader.ReadIndex, elementName.Length), elementName))
                {
                    if (!mustEndInWhitespace ||
                        eof ||
                        FortranParseHelper.IsWhiteSpace(fileContents[streamReader.ReadIndex + elementName.Length]))
                    {
                        streamReader.ReadIndex += elementName.Length;
                        if (!eof && fileContents[streamReader.ReadIndex] != '\n')
                        {
                            streamReader.ReadIndex += 1; //plus space
                        }
                        return(true);
                    }
                }
            }
            return(false);
        }
        private static LocationInFile FindFirstLocationOfElementNameInLines(IMember member, string variableName, string[] allLines, ref int lineHint)
        {
            for (var i = lineHint; i < allLines.Length; i++)
            {
                var line       = allLines[i];
                var startIndex = 0;
                int indexInLine;
                do
                {
                    indexInLine = line.IndexOf(variableName, startIndex, StringComparison.InvariantCultureIgnoreCase);
                    startIndex  = indexInLine + 2; //+1 = space, so at least +2
                    if (indexInLine >= 0)
                    {
                        if (indexInLine > 0 && FortranParseHelper.IsWordCharacter(line[indexInLine - 1]))
                        {
                            continue; //part of other string
                        }
                        var endOfNameIndex = indexInLine + variableName.Length;
                        if (endOfNameIndex < line.Length && FortranParseHelper.IsWordCharacter(line[endOfNameIndex]))
                        {
                            continue;
                        }

                        lineHint = i;
                        return(new LocationInFile(member.Location.Line + i, indexInLine, -1));
                    }
                } while (indexInLine >= 0 && startIndex < line.Length); //while matches in line
            }
            throw new ArgumentException(string.Format("Cannot find variable {0} in variable declarations, in file {1}",
                                                      variableName, member.Root.CodeFile.ProjectName));
        }
예제 #3
0
        private bool CheckNotFalsePositive(string line, int matchOffset, string searchString)
        {
            if (matchOffset > 0)
            {
                //begin of match is begin of word
                var previousChar = line[matchOffset - 1];
                if (FortranParseHelper.IsWordCharacter(previousChar))
                {
                    return(false);
                }
            }
            var endOfMatch = searchString.Length + matchOffset;

            if (endOfMatch < line.Length)
            {
                //end of match is end of word
                var nextChar = line[endOfMatch];
                if (FortranParseHelper.IsWordCharacter(nextChar))
                {
                    return(false);
                }
            }

            return(!FortranParseHelper.IsIndexInsideCharacterString(line, matchOffset));
        }
        public string FindEffectiveStatementAtOffset(string line, int offsetInLine, out int beginOfStatement)
        {
            var endOfStatement   = offsetInLine - 1;
            var parenthesisLevel = 0;
            int i;
            var statement = new StringBuilder();

            for (i = endOfStatement; i >= 0; i--)
            {
                var c = line[i];

                if (c == ')')
                {
                    if (statement.Length == 0)
                    {
                        break;
                    }
                    parenthesisLevel++;
                }
                else if (parenthesisLevel > 0)
                {
                    //next
                    if (c == '(')
                    {
                        parenthesisLevel--;
                    }
                }
                else
                {
                    if (FortranParseHelper.IsNonStatementCharacter(c))
                    {
                        break;
                    }
                    else
                    {
                        statement.Insert(0, c);
                    }
                }
            }

            beginOfStatement = i + 1;
            var originalBegin = beginOfStatement;

            for (int j = 0; j < statement.Length; j++)
            {
                var c = statement[j];
                if (FortranParseHelper.IsWhiteSpace(c))
                {
                    beginOfStatement++;
                }
                else
                {
                    break;
                }
            }

            return(statement.ToString().Substring(beginOfStatement - originalBegin));
        }
예제 #5
0
        private bool TryReadType(string memberName, SyntaxTree sourceAST, ref IMember parentMember)
        {
            //todo: we're not skipping comments in this code

            if (IsMemberExpected <Type>(parentMember) && TryReadElementString(memberName, false))
            {
                var remainingLine = FortranParseHelper.GetStringUptoEndOfLineOrBeginOfComment(streamReader.Text, streamReader.ReadIndex - 1);
                var skip          = false;

                if (remainingLine.IndexOf("(") >= 0)
                {
                    //type use, not a type declaration
                }
                else
                {
                    var indexOfDoubleDots = remainingLine.IndexOf("::");

                    if (indexOfDoubleDots >= 0)
                    {
                        streamReader.ReadIndex--; //read back one
                        streamReader.ReadIndex += indexOfDoubleDots + 2;
                        char c = streamReader.Text[streamReader.ReadIndex];
                        while (FortranParseHelper.IsWhiteSpace(c)) //skip whitespace
                        {
                            c = streamReader.Text[++streamReader.ReadIndex];
                        }
                    }
                    else
                    {
                        //expect whitespace
                        if (!FortranParseHelper.IsWhiteSpace(streamReader.Text[streamReader.ReadIndex - 1]))
                        {
                            skip = true;
                        }
                    }
                    if (!skip)
                    {
                        var name = streamReader.ReadElementName();
                        if (!String.IsNullOrEmpty(name))
                        {
                            OnMemberFound <Type>(ref parentMember, name, sourceAST);
                            return(true);
                        }
                    }
                }
            }
            return(TryReadEndOfMember <Type>(ref parentMember, memberName));
        }
예제 #6
0
        public IEnumerable <LocationInFile> FindInFileContents(MemberOrSearchTerm memberUsageToFind, string fileContents)
        {
            var results = new List <LocationInFile>();

            //remove comments:
            var cleanedLines = FortranParseHelper.CleanLines(fileContents.Split('\n'), false, false).ToList();

            int lineNr = 0;

            foreach (var line in cleanedLines)
            {
                lineNr++;
                SearchInLine(line, memberUsageToFind.Name, lineNr, results);
            }

            return(results);
        }
예제 #7
0
        public IEnumerable <UsageResult> FindInFile(MemberOrSearchTerm memberUsageToFind, SyntaxTree syntaxTree)
        {
            var results      = new List <UsageResult>();
            var fileContents = syntaxTree.CodeFile.Contents;
            var locations    = FindInFileContents(memberUsageToFind, fileContents);

            foreach (var location in locations)
            {
                var enclosingMember = FortranParseHelper.GetEnclosingMember(syntaxTree.Members, location.Line);

                if (enclosingMember != null && enclosingMember == memberUsageToFind.Member)
                {
                    continue; //definition/declaration, not usage
                }
                results.Add(new UsageResult(syntaxTree, location, enclosingMember, location.LineStr));
            }

            return(results);
        }
        public string FindMethodAtOffset(string currentLine, int currentIndex)
        {
            var parenthesisLevel = 0;
            var functionEnd      = -1;

            for (int i = currentIndex - 1; i >= 0; i--)
            {
                var c = currentLine[i];

                if (c == ')')
                {
                    parenthesisLevel++;
                }
                else if (c == '(')
                {
                    parenthesisLevel--;

                    if (parenthesisLevel == -1)
                    {
                        functionEnd = i;
                        break;
                    }
                }
            }

            if (functionEnd >= 0)
            {
                var lineWithFunctionName = currentLine.Substring(0, functionEnd).TrimEnd();
                var methodName           = "";
                try
                {
                    var beginOfMethodName = -1;
                    methodName = FortranParseHelper.GetElementName(lineWithFunctionName, lineWithFunctionName.Length - 1, out beginOfMethodName);
                }
                catch (Exception e)
                {
                    Log.Error(String.Format("GetElementName failed (line: {0})", lineWithFunctionName), e);
                }

                return(methodName);
            }
            return(null);
        }
예제 #9
0
        private bool TryReadEndOfMember <T>(ref IMember parentMember, string memberName)
        {
            if (!(parentMember is T))
            {
                return(false);
            }

            if (TryReadElementString("end " + memberName, true))
            {
                HandleEndOfMember(ref parentMember);
                return(true);
            }
            //endsubroutine (for example) without space is also valid f90:
            if (TryReadElementString("end" + memberName, true))
            {
                HandleEndOfMember(ref parentMember);
                return(true);
            }
            if (TryReadElementString("end", true))
            {
                var remainingLine = FortranParseHelper.GetStringUptoEndOfLineOrBeginOfComment(streamReader.Text, streamReader.ReadIndex);
                if (String.IsNullOrEmpty(remainingLine))
                {
                    HandleEndOfMember(ref parentMember);
                    return(true);
                }
                else
                {
                    var trimmedLine = remainingLine.TrimStart();
                    var charsToSkip = remainingLine.Length - trimmedLine.Length;
                    streamReader.ReadIndex += charsToSkip;

                    if (TryReadElementString(memberName, true))
                    {
                        HandleEndOfMember(ref parentMember);
                        return(true);
                    }
                }
            }
            return(false);
        }
예제 #10
0
        public string ReadElementName()
        {
            bool nameStarted = false;

            var start = ReadIndex;

            for (ReadIndex = start; ReadIndex < Text.Length; ReadIndex++)
            {
                var c = Text[ReadIndex];

                if (!nameStarted && c == ' ') //skip spaces in front of name
                {
                    start++;
                    continue;
                }

                nameStarted = true;

                if (FortranParseHelper.IsWhiteSpace(c)) //quick loop
                {
                    //end of name
                    break;
                }

                if (!FortranParseHelper.IsWordCharacter(c))
                {
                    //non valid name characters: end of name
                    break;
                }
            }
            if (ReadIndex < Text.Length)
            {
                var name = Text.Substring(start, ReadIndex - start);
                if (!String.IsNullOrEmpty(name))
                {
                    ReadIndex--;
                }
                return(name);
            }
            return("");
        }
예제 #11
0
        public void ParseMethodSignature(IMethod method)
        {
            if (method.Parameters != null)
            {
                return; //already set
            }
            var lines     = FortranParseHelper.CleanLinesAndMerge(FortranParseHelper.ExtractMemberLines(method), false, true);
            var firstLine = lines.FirstOrDefault();

            if (firstLine == null)
            {
                throw new ArgumentException("Empty header");
            }
            if (!firstLine.StartsWith(method.Name, StringComparison.InvariantCultureIgnoreCase))
            {
                throw new ArgumentException("Signature does not start with method name");
            }

            var parameterString = firstLine.Substring(method.Name.Length);
            var resultKeyword   = " result";
            var indexOfResult   = parameterString.IndexOf(resultKeyword, StringComparison.InvariantCultureIgnoreCase);

            if (indexOfResult >= 0)
            {
                var resultString = parameterString.Substring(indexOfResult + resultKeyword.Length);
                parameterString           = parameterString.Substring(0, indexOfResult);
                method.ResultVariableName = RemoveUndesiredCharacters(resultString).Trim();
            }

            parameterString = RemoveUndesiredCharacters(parameterString);
            var parameters = parameterString.Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries);

            var parameterList = new List <Variable>();

            foreach (var parameter in parameters)
            {
                var parameterName = parameter.Trim();

                if (String.IsNullOrEmpty(parameterName))
                {
                    continue;
                }

                var matchingDeclaration = FindDeclaration(method, parameterName);

                if (matchingDeclaration == null)
                {
                    if (method.ImplicitNone)
                    {
                        throw new ArgumentException(String.Format("Could not find matching declaration in method {0} for parameter {1}, while implicit none is true.", method.Name, parameterName));
                    }
                }
                else
                {
                    parameterList.Add(new Variable {
                        Name = parameterName, Member = method, TypeString = matchingDeclaration.TypeString, IsBuildInType = matchingDeclaration.IsBuildInType
                    });
                }
            }

            method.SetParameters(parameterList);
        }
 private static string RemoveBetweenSlashes(string input)
 {
     return(FortranParseHelper.RemoveBetweenCharacter(input, '/'));
 }
        public void ParseDeclarationsAndUses(IMember member)
        {
            if (member.LocalVariables.Any() || member.Uses.Any())
            {
                return; //already parsed (on file modification they are cleared)
            }
            member.ClearLocalVariables();
            member.ClearUses();

            var memberLines  = FortranParseHelper.ExtractMemberLines(member);
            var cleanedLines = FortranParseHelper.CleanLines(memberLines, false, false).ToArray();

            var mergedLines = FortranParseHelper.CleanLinesAndMerge(memberLines, true, true);

            var lineHint = 1;

            foreach (var line in mergedLines)
            {
                if (TryReadAndEat("#", line)) //preprocessor directives
                {
                    continue;
                }
                if (TryReadAndEat("private", line)) //preprocessor directives
                {
                    continue;
                }
                if (TryReadAndEat("public", line)) //preprocessor directives
                {
                    continue;
                }
                if (TryReadAndEat("write", line)) //allowed?!?!?!
                {
                    continue;
                }
                if (TryReadAndEat("implicit ", line))
                {
                    if (line.IndexOf("none", StringComparison.InvariantCultureIgnoreCase) >= 0)
                    {
                        member.ImplicitNone = true;
                    }
                    continue;
                }
                if (TryReadUses(member, line))
                {
                    continue;
                }
                if (TryReadVariableDeclaration(member, line, cleanedLines, ref lineHint))
                {
                    continue;
                }
                if (TryReadAndEat("parameter", line))
                {
                    continue;
                }
                if (TryReadAndEat("data", line))
                {
                    continue;
                }
                if (TryReadAndEat("common", line))
                {
                    continue;
                }
                if (TryReadAndEat("save", line))
                {
                    continue;
                }
                if (TryReadAndEat("intent", line))
                {
                    continue;
                }
                if (TryReadAndEat("include", line))
                {
                    continue;
                }
                //if we get here, it's the end of variable declarations because the line is non-empty and
                //non-commment, yet doesn't start with an expected string (variable, implicit, etc)
                break;
            }
        }
예제 #14
0
        public bool SkipToNextPotentialCodeElement()
        {
            if (lastIndexVisited == ReadIndex)
            {
                ReadIndex++; //continue to next character if we already got here
            }

            var start = ReadIndex;

            for (ReadIndex = start; ReadIndex < Text.Length; ReadIndex++)
            {
                var c = Text[ReadIndex];

                if (c == '\n')
                {
                    LineNumber++;
                    StartOfLineIndex = ReadIndex + 1;
                }

                if (FortranParseHelper.IsWhiteSpace(c))
                {
                    continue; //shortcut
                }

                if (!insideCharacterString && c == '"')
                {
                    insideQuoteString = !insideQuoteString; //toggle
                    continue;
                }
                if (!insideQuoteString && c == '\'')
                {
                    insideCharacterString = !insideCharacterString; //toggle
                    continue;
                }

                if (!insideCharacterString && !insideQuoteString)
                {
                    //read comment
                    if (c == '!')
                    {
                        SeekEndOfLine(); //skip comments
                        continue;
                    }

                    if (Style == FortranStyle.Fortran77 && ReadIndex == StartOfLineIndex && (c == 'c' || c == 'C' || c == '*'))
                    {
                        SeekEndOfLine(); //skip comments (f77 style?)
                        continue;
                    }

                    var previousCharWasWhitespace = (ReadIndex > 0) ? FortranParseHelper.IsWhiteSpace(Text[ReadIndex - 1]) : true;

                    if (!previousCharWasWhitespace) //still inside a word
                    {
                        continue;
                    }

                    //this would improve performance and simply some things, but unfortunately the keywords
                    //we're looking for are not always the first word on the line. For example the 'function'
                    //keyword can be prefixed by a type.

                    //if (beginOfLineOnly && lastVisitedLine == LineNumber)
                    //    continue;

                    lastIndexVisited = ReadIndex;
                    return(true);
                }
            }
            return(false); //eof
        }