查找在fortran源文件中计算变量的位置

时间:2013-11-19 19:18:21

标签: c# fortran fortran77

我正在尝试在C#中编写一个程序,从数据库中获取一个字符串表(变量名),并搜索~30,000个Fortran 77源文件的目录,以确定该变量的计算位置。这些变量通常只在一个fortran文件中计算一次,但在其他文件中多次使用。数据库表中的变量都在fortran文件中的某处显式定义。到目前为止,我已经完成了大部分工作,首先构建每个变量出现的文件列表,然后逐行搜索该列表中的文件。我一直在寻找变量出现的“=”符号的哪一侧做这样的事情:

CompareInfo ci = CultureInfo.CurrentCulture.CompareInfo;
for (int k = 0; k < fullpaths.Count; k++)
{
    string line;
    // Read the file and display it line by line.
    System.IO.StreamReader FortranFile = new System.IO.StreamReader(fullpaths[k]);
    while ((line = FortranFile.ReadLine()) != null)
    {
        // Search the file line-by-line for the variable
        if (ci.IndexOf(line, Variable, CompareOptions.IgnoreCase) > 0)
        {
            // Search for the equals sign
            int equalLocation = ci.IndexOf(line, "=");
            if (equalLocation > 0)
            {
                // substring LHS
                string subLineLHS = line.Substring(0, equalLocation+1);
                // is the line commented out?
                if (Convert.ToString(subLineLHS[0]) == "C" ||
                    Convert.ToString(subLineLHS[0]) == "!" ||
                    Convert.ToString(subLineLHS[0]) == "c" ||
                    Convert.ToString(subLineLHS[0]) == "*")
                {
                    continue;
                }
                // ignore if the line contains a DO, IF, or WHILE loop, 
                // to prevent reading IF [Variable] = xxxx as being calculated.
             else if ( (ci.IndexOf(subLineLHS, "IF", CompareOptions.IgnoreCase) > 0) ||
                       (ci.IndexOf(subLineLHS, "DO", CompareOptions.IgnoreCase) > 0) ||
                      (ci.IndexOf(subLineLHS, "WHILE", CompareOptions.IgnoreCase) > 0))
                {
                    continue;
                }
                // find where the variable is used in the line
            else if (ci.IndexOf(subLineLHS, Variable, CompareOptions.IgnoreCase)  > 0 )
                {
                    isCalculated[k] = true;
                    calculatedLine[k] = counter;
                }
            }
        } //if loop
        counter++;
    } //while loop

    FortranFile.Close();
}

我遇到的问题是IF语句,例如:

   IF(something == xx .AND.
1     variable == xx) THEN
...

这个方法会告诉我变量是在那行“variable = xx”上计算的。 1-if if语句如IF(something)variable = xx也被忽略。具有多个=符号的行也可能给我带来问题。

有关如何解决此问题的任何建议?有没有更好的方法呢?请放轻松 - 我不是程序员。

谢谢!

1 个答案:

答案 0 :(得分:2)

最容易出错的方法是解析Fortran代码并从语法树开始工作。

我的建议:使用ctags 。例如,见Exuberant ctags;它has support for Fortranctags生成一组源代码文件中所有命名实体的索引。索引存储在可从大多数文件编辑器/ IDE中读取的数据结构(标记)中。 如果您在您喜欢的文本编辑器中导入该标记文件,则可以在将光标放在变量上并且采取适当的操作时跳转到变量的定义。

标签文件也很容易阅读和解析:它的结构如下。

named_entity<Tab>file_where_it_is_defined<Tab>location_in_the_file

例如,从一组Fortran文件(这是在Linux上,但Exuberant ctags提供Windows binaries):

gpar    remlf90.f90 /^           xrank,npar,gpar,/;"    v   program:REMLF90
hashia1 ../libs/sparse2.f   /^      subroutine hashia1(/;"  s
hashv1  ../libs/sparse3.f   /^      integer function hashv1(/;" f
hashvr_old  ../libs/sparse2.f   /^      integer function hashvr_old(/;" f

我们可以观察到gpar中定义了remlf90.f90变量,hashia1中定义了../libs/sparse2.f等。