如何找到子串

How to find a substring

给定一个包含字符串的文本文件,我会在该字符串中找到一些特定的 substrings/sequences。

Bison 文件.y(声明+规则)

%token <cval> AMINO 
%token STARTCODON STOPCODON
%type <cval> seq

%%
series: STARTCODON seq STOPCODON {printf("%s", );}
seq: AMINO
         | seq AMINO
         ;
%%

这里我想打印 STARTCODONSTOPCODON

之间的每个序列

Flex 文件 .l(规则)

    %%
    ("ATG")+ {return STARTCODON;}
    ("TAA"|"TAG"|"TGA")+ {return STOPCODON;}

    ("GCT"|"GCC"|"GCA"|"GCG")+ {yylval.cval = 'A';
                           return AMINO;}
    ("CGT"|"CGC"|"CGA"|"CGG"|"AGA"|"AGG")+ {yylval.cval = 'R';
                           return AMINO;}
     .
     .
     .

     [ \t]+                  /*ignore whitespace*/
     \n                      /*ignore end of line*/
     . {printf("-");}
     %%

当我 运行 代码时,我只得到规则 . {printf("-");}.

的输出

我是新手Flex/Bison,我怀疑:

编辑:

(示例)输入文件: DnaSequence.txt

输入字符串:cccATGAATTATTAGzzz,其中低位字符(ccczzz)产生(右)输出 -ATGSTARTCODONAATTAT是两个AMINO的序列(AATTAT),TAGSTOPCODON.

此输入字符串产生(错误的)输出 ---

编辑:

根据@JohnBollinger 的建议,我在 Flex 文件中添加了 <<EOF>> {return ENDTXT;},在 Bison 文件中添加了规则 finalseries: series ENDTXT;

现在它返回 yyerror 的错误消息,表示解析错误。 我想我们需要一个 STARTTXT 令牌,但我不知道如何实现它。

I am new Flex/Bison, I suspect that:

  • The bison rule series: STARTCODON seq STOPCODON {printf("%s", );} is not correct.

规则在句法上是可以接受的。如果标记 2 的值是 C 字符串,这在语义上是正确的,在这种情况下,它会导致该值打印到标准输出,但您的 Flex 文件似乎假定类型 <cval>char不是 C 字符串,也不能直接转换为 C 字符串。

  • Flex doesn't subdivide correctly the entire string into tokens of 3 characters.

实际上,您的 Flex 输入在我看来还不错。您提供的示例输入/输出表明 Flex 确实识别了从 ATGTAG 的所有三元组,否则 . 的规则将被触发超过三次。


数据类型问题是您需要解决的一个细节问题,但是主要问题是您对seq的产生式没有设置其语义值.当 series 生产用于减少时,这如何导致(看似)没有被打印取决于您没有披露的细节,并且可能涉及未定义的行为。

如果 <cval> 被声明为字符串 (char *),并且如果您的词法分析器将其值设置为字符串而不是字符,那么设置语义值可能如下所示:

seq: AMINO { $$ = calloc(MAX_AMINO_ACIDS + 1, 1); /* check for allocation failure ... */
             strcpy($$, ); }
         | seq AMINO { $$ = ; strcat($$, ); }
         ;

您可能会考虑坚持使用 char 作为 AMINO 语义值的类型,并将 seq 定义为不同的类型(即 char *)。这样,您的更改可能仅限于语法文件。然而,这将要求在 seq.

的产生式中对语义动作进行不同的实现。

最后,请注意,虽然你说

Here I want to print every sequence between STARTCODON and STOPCODON

你的文法,如前所述,以 series 作为它的开始符号。因此,一旦它将令牌序列减少到 series,它就可以完成。如果后面有其他标记(比如另一个 series 的标记),那将是错误的。如果这是您需要支持的东西,那么您将需要一个更高级别的开始符号来表示多个 series.

的序列