如何查找子串

时间:2018-01-05 14:21:23

标签: c bison yacc lex

鉴于包含字符串的文本文件,我会在此字符串中找到一些特定的子字符串/序列。

野牛档案.y (声明+规则)

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

%%
series: STARTCODON seq STOPCODON {printf("%s", $2);}
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,我怀疑:

  • bison规则series: STARTCODON seq STOPCODON {printf("%s", $2);}不正确。

  • Flex没有将整个字符串正确细分为3个字符的标记。

修改

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

输入字符串:cccATGAATTATTAGzzz,其中较低的字符(ccczzz)生成(右)输出-ATG是{{1 } {},STARTCODON是两个AATTAT AAT TAT )的序列,AMINOTAG

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

修改

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

现在它返回finalseries: series ENDTXT;的错误消息,指出解析错误。 我想我们需要一个yyerror令牌,但我不知道如何实现它。

1 个答案:

答案 0 :(得分:3)

  

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

     
      
  • 野牛规则系列:STARTCODON seq STOPCODON {printf(&#34;%s&#34;,$ 2);}不正确。
  •   

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

  
      
  • Flex没有将整个字符串正确细分为3个字符的标记。
  •   

实际上,您的Flex输入对我来说很合适。您提供的示例输入/输出表明Flex确实正在识别从charATG的所有三元组,否则TAG的规则将被触发三次以上。

数据类型问题是您需要整理的详细信息,但问题是您的.生产未设置其语义值。当seq生产用于减少时,如何(似乎)没有打印的结果取决于您尚未公开的细节,并且可能涉及未定义的行为。

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

char *

您可以考虑使用seq: AMINO { $$ = calloc(MAX_AMINO_ACIDS + 1, 1); /* check for allocation failure ... */ strcpy($$, $1); } | seq AMINO { $$ = $1; strcat($$, $2); } ; 作为char的语义值的类型,并将AMINO定义为具有不同的类型(即seq)。这样,您的更改可能仅限于语法文件。然而,这将要求char *的生产中的语义动作的不同实现。

最后,请注意,尽管你说

  

这里我要打印STARTCODON和STOPCODON之间的每个序列

如您所示,您的语法以seq作为开始符号。因此,一旦它将令牌序列减少到series,它就会完成。如果跟随其他令牌(比如另一个series的那些),那么这将是错误的。如果您需要支持,那么您需要一个更高级别的起始符号来表示多个series的序列。