Fortran 中的嵌套名单

Nested namelists in fortran

namelist 是一种有用的 fortran 结构,可以从文件中快速初始化变量。 namelist 有一个名称并包含一组已知类型的变量。这使得它类似于 type 结构。

通常情况下,给程序或子例程的参数最好不要组织为列表,而是组织为层次结构,如菜单界面。像 type, extends(simple) :: advanced 这样的扩展类型似乎很好地表示了这种层次结构。

但是,使用 namelist 构造读取此数据表示似乎很尴尬,因为最终可能会得到非常长的那种

&options
 very_long_option_X   =  1,
 very_long_option_Y   =  2,
 long_option_B%long_descriptive_name_a = 10,
 long_option_B%long_descriptive_name_b = 20,
 long_option_D%long_suboption_DD%long_descriptive_name_a = 300,
 long_option_D%long_suboption_DD%long_descriptive_name_b = 400,
 long_option_D%long_suboption_DD%long_descriptive_name_c = 500,
/

很多人会说不理想,他们宁愿选择

&options
   very_long_option_X   =  1,
   very_long_option_Y   =  2,
   &long_option_B
      long_descriptive_name_a = 10,
      long_descriptive_name_b = 20
   /
   &long_option_D
      &long_suboption_DD
         long_descriptive_name_a = 300,
         long_descriptive_name_b = 400,
         long_descriptive_name_c = 500
      /
   /
/

所以想请教一下这种数据结构有什么好的读取方法。你如何处理这种情况?

由于不存在嵌套的 NAMELIST,因此其他方法可能会更好。 XML 似乎是一个受欢迎的选择。有可用的 Fortran-XML 库,例如 XML-Fortran and FoX.

我在我的代码中做的是在名单中有一个额外的变量指向另一个文件,然后读取内容。因此:

&options
very_long_option_X   =  1,
very_long_option_Y   =  2,
long_option_B_filename = 'a_file'
long_option_D_filename = 'another_file'
/

然后在a_file:

&long_option_B

  long_descriptive_name_a = 10,
  long_descriptive_name_b = 20
/

another_file:

&long_option_D
  long_suboption_DD_filename = 'another_another_file'
/

等等

这只是读取每个名单以查看文件名是否已设置的情况,如果是,则将该文件读入下一个名单。

配置文件实际上是一个经常实现自定义语言或至少自定义语法解析器的区域。不仅 Fortran 程序员,而且(或主要)许多其他语言的程序员。

基本上,人们会勾勒出配置文件应遵循的语法,然后手动为这种语法编写解析器,通常是作为由使用语法的各种元素的递归函数组成的递归下降解析器,或者作为状态机和定义的状态之间的转换。如果想避免手动路由,可以使用解析器生成器(例如 ANTLR)或解析器组合器。这些工具通常不以 Fortran 为目标。但是,搜索 github.com 会显示最近的一些 parser generators for Fortran!

几年前,当我需要一个 Fortran 中的配置文件解析器时,我采用了手动递归下降的方式。在https://bitbucket.org/LadaF/elmm/src/master/src/strings.f90 but it is far from perfect. I only show it for illustration. It reads config files like https://bitbucket.org/LadaF/elmm/src/master/examples/DIPLOS/area_sources.conf.

中的ParseTrees模块中可以找到我的拙劣尝试

像JSON这样的通用格式的库当然可以使用(还有Fortran实现,比如https://github.com/jacobwilliams/json-fortran),但是你必须遵循它们的格式规范。例如,JSON 不允许评论,这对我来说是禁忌。

无论您选择哪种高级方式,您都将负责将数据从已解析的语法树转换为您的数据结构。 AFAIAA,没有任何工具可以为您做到这一点。这就是标准名单真正闪耀的方面。