解析子例程列表



我已经编写了可以解析subroutineparser_sub.mlylexer_sub.mllsubroutine是由SubEnd Sub包围的语句块。

实际上,我想处理的原始文件包含子例程列表和一些无用的文本。下面是一个示例:

' a example file
Sub f1()
  ...
End Sub
haha
' hehe
Sub f2()
  ...
End Sub

所以我需要编写parser.mlylexer.mll,它可以通过忽略所有注释来解析此文件(例如 haha' hehe等)并调用 parser_sub.main ,并返回子例程的列表。

  1. 谁能告诉我如何让解析器忽略所有无用的句子(SubEnd Sub之外的句子)?

    这是我尝试写parser.mly的一部分:

    %{
      open Syntax
    %}
    %start main
    %type <Syntax.ev> main
    %%
    main:
      subroutine_declaration*  { $1 };
    subroutine_declaration:
      SUB name = subroutine_name LPAREN RPAREN EOS
      body = procedure_body?
      END SUB 
      { { subroutine_name = name;
          procedure_body_EOS_opt = body; } }
    
  2. procedure_body的规则和解析很复杂,实际上是在parser_sub.mlylexer_sub.mll中定义的,所以我怎么能让parser.mlylexer.mll不重复定义它,而只是调用parser_sub.main

也许我们可以在子例程中设置一些标志:

sub_starts:
  SUB { inside:=true };
sub_ends:
  ENDSUB { inside:=false };    
subroutine_declaration:
  sub_starts name body sub_ends { ... }

当未设置此标志时,您只需跳过任何输入?

如果你想要跳过的东西可以有任何形式(不一定是你的语言的有效标记),你几乎必须通过破解你的词法分析器来解决这个问题,正如 Kakadu 所建议的那样。无论如何,这可能是最简单的事情。

如果填充物(要跳过的内容)由有效令牌组成,并且您想使用语法规则跳过,在我看来,主要问题是定义一个与 END 以外的任何标记匹配的非终端。保持最新状态会令人不快,但似乎是可能的。

最后,您会遇到一个问题,即结束标记是两个符号,END SUB。您必须处理看到 END 后跟 SUB 的情况。这甚至更棘手,因为 SUB 也是您的开始标记。同样,简化这一点的一种方法是破解您的词法分析器,以便它将 END SUB 视为单个令牌。(通常这比你想象的要棘手,比如如果你想允许 END 和 SUB 之间的注释。

最新更新