【问题标题】:Flex: lexical analyzer to remove multicomment line in HaskellFlex:词法分析器删除 Haskell 中的多注释行
【发布时间】:2020-10-17 15:24:39
【问题描述】:

我有以下代码:

%{
    #include<stdio.h>
%}

%x multicomment

%option noyywrap
%% 

--(.*) ; 
  
"{-"      BEGIN(multicomment);
<multicomment>[^*\n]+    
<multicomment>"*"        
<multicomment>\n         
<multicomment>"-}"    BEGIN(INITIAL);
%% 
  
int main(int argc,char **argv) 
{ 
    yyin=fopen("Code.txt","r"); 
    yyout=fopen("out.c","w");

    yylex(); 
    return 0; 
} 

实现的任务非常简单...从 haskell 代码中删除单行/多行注释。

-- 单行; {- -} 表示多行;

如果我使用 "/*" & "*/" (用于 C 注释)而不是 "{-"强> & “-}”。当我使用最后两个时,我不知道为什么 flex 会删除 {-.

之后的所有其他字符

例如,假设要清理以下输入文本:

some text

{- some other text
    in multiline
    with haskel comment
-}

/* another text
    always in multiline
    but with C comment
*/

some text without comment

如果上面的代码设置如下:

    "/*"      BEGIN(multicomment);
    <multicomment>[^*\n]+    
    <multicomment>"*"        
    <multicomment>\n         
    <multicomment>"*/"    BEGIN(INITIAL);

/*" & "*/" 输出是正确的:

some text

{- some other text
    in multiline
    with haskel comment initiator
-}

some text without comment

如果我使用原始代码

    "{-"      BEGIN(multicomment);
    <multicomment>[^*\n]+    
    <multicomment>"*"        
    <multicomment>\n         
    <multicomment>"-}"    BEGIN(INITIAL);

"{-" & "-}",不起作用,输出为:

一些文字

它会删除 "{-" 中的所有字符直到文件末尾,我还尝试了其他论坛中推荐的其他设置:

<multicomment>"-\}"    BEGIN(INITIAL);
<multicomment>"-"+"}"    BEGIN(INITIAL);
<multicomment>"-" + "}"    BEGIN(INITIAL);
<multicomment>[-}]    BEGIN(INITIAL);

但在这些情况下,当我尝试使用 flex CommentClean.l 进行编译时,结果如下:

CommentClean.l:16:警告,无法匹配规则

有人可以帮助我吗?我哪里错了?我该怎么办?

【问题讨论】:

  • 除非识别字符串文字,否则无法准确删除 cmets。

标签: parsing haskell comments flex-lexer


【解决方案1】:

您只更改了开始和结束分隔符,但没有更改匹配内容的规则

原始规则说“在multicomment 状态下,忽略一个或多个非星号和换行符;忽略一个星号;并忽略换行符”。后跟斜杠的星号将作为最长匹配规则的结束分隔符进行匹配。

    <multicomment>[^*\n]+    
    <multicomment>"*"        
    <multicomment>\n 

当您只更改分隔符时,代码中发生的情况是 {- 将开始注释,然后结束分隔符 -} 将作为内容的一部分使用,“一系列非星号/换行符”,因为它匹配一个(很多!)更长的字符串。

我认为您只需要将星号更改为连字符:

    <multicomment>[^-\n]+    
    <multicomment>"-"        
    <multicomment>\n 

但是,请注意,这并不能说明在 Haskell 中,与 C 不同,多行 cmets 可能像这样嵌套

{-

a multi-line comment

  {-
    containing another comment

    {- containing yet another comment -}

  -}

-}

所以要严格正确,您还应该包含一个递归匹配多行 cmets 的规则。另请记住,-- 如果不是运算符的一部分,则只是单行注释,因此例如 --&gt;|-- 是有效的运算符,而不是注释的开头。 (是的,人们在实际代码中使用这些!)

您可以在Haskell Report §2.3 中找到 cmets 的规范。它说一个符号是:

  • 这些字符中的任何一个(ascSymbol):!#$%&amp;+./@9876 987654341@&gt;?@\^|-~:;或

  • 具有符号 (S) 或标点符号 (P) (uniSymbol) 属性的任何 Unicode 字符,( ) , ; [ ] @ 除外987654357@{}特殊)和_"'

【讨论】:

  • 非常感谢。问题解决了!正是从星号变为连字符。我知道 cmets 可以嵌套,但这将是下一个成就。
猜你喜欢
  • 2013-02-23
  • 1970-01-01
  • 2012-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-12
  • 2015-03-22
  • 2019-12-29
相关资源
最近更新 更多