0

我已经写了parser_sub.mlylexer_sub.mll它可以解析一个subroutine. A是由andsubroutine包围的语句块。SubEnd Sub

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

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

所以我需要编写parser.mlyand lexer.mllwhich 可以通过忽略所有注释(例如haha' hehe等)和调用来解析这个文件parser_sub.main,并返回一个子例程列表。

  1. 谁能告诉我如何让解析器忽略所有无用的句子( a Suband之外的句子End 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. for 的规则和解析procedure_body很复杂,实际上是在parser_sub.mlyand中定义的lexer_sub.mll,那么我怎么能允许parser.mly并且lexer.mll不重复定义它,而只是调用parser_sub.main呢?

4

2 回答 2

1

当我们在子程序中时,也许我们可以设置一些标志:

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

当这个标志没有设置时,你只是跳过任何输入?

于 2013-10-14T14:20:27.347 回答
0

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

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

最后,您遇到的问题是结束标记是两个符号 END SUB。您必须处理看到 END 后面没有 SUB 的情况。这甚至更棘手,因为 SUB 也是您的开始标记。同样,简化此操作的一种方法是破解您的词法分析器,以便它将 END SUB 视为单个标记。(通常这比你想象的要复杂,比如如果你想允许 END 和 SUB 之间的评论。)

于 2013-10-14T17:41:16.277 回答