Bison/Flex 字符串标记识别

Bison/Flex String Token Recognition

我必须写的而不是

identifier      [a-zA-Z0-9]+

为了也接受仅由数字组成的字符串?

我写了新的 bison 和 flex 文件来澄清我的问题。 野牛档案:

%{
#include <stdio.h>
#include <string>
using namespace std;
extern int yylex();
extern void yyerror(char*);
%}

//Symbols
%union
{
    double double_val;
    char *str_val;
};

%token START
%token STOP
%token BEGIN_NUM
%token END_NUM
%token BEGIN_STRING
%token END_STRING

%token <double_val> NUMBER
%token <str_val>    IDENTIFIER

%start MyTest

%%

MyTest:
    START Block STOP
    ;

Block:
    /* empty */
    | Block BEGIN_STRING IDENTIFIER END_STRING { printf("received string: %s \n", ); }
    | Block BEGIN_NUM NUMBER END_NUM { printf("received number: %f \n", ); }
    ;

%%

弹性文件:

%{
#include <string>
#include "test.tab.h"
void yyerror(char*);
int yyparse(void);
%}
blanks          [ \t\n]+
identifier      [a-zA-Z0-9]+
number          [0-9][0-9]*(.[0-9]+)?
%%

{blanks}        { /* ignore */ };

"<test>"        return(START);
"</test>"   return(STOP);
"<string>"      return(BEGIN_STRING);
"</string>"     return(END_STRING);
"<num>"     return(BEGIN_NUM);
"</num>"        return(END_NUM);

{number}        { yylval.double_val = atof(yytext);
                  return(NUMBER);
                }
{identifier}    { 
                  yylval.str_val=strdup(yytext);
                  return(IDENTIFIER);
                }

%%

void yyerror (char* str){ printf (" ERROR : Could not parse! %s\n", str );}
int yywrap (void){ }
int main(int num_args, char** args){
    if(num_args != 2) {printf("usage: ./parser filename\n"); exit(0);}
    FILE* file = fopen(args[1],"r");
    if(file == NULL) {printf("couldn't open %s\n",args[1]); exit(0);}
    yyin = file;
    yyparse();
    fclose(file);
}

当我输入这个文件时一切正常:

<test>
<num>1</num>
<string>eeeeee</string>
<num>2</num>
<string>cccc</string>
<num>3</num>
<num>4</num>
<string>asaa</string>
<string>dsa</string>
</test>

但是如果我用一个只有数字的值更改字符串的一个字段,例如:

<string>323</string>

我收到语法错误...

只有数字的字符串 return 是令牌 NUMBER,因此您可以添加规则:

Block: Block BEGIN_STRING NUMBER END_STRING { printf("received number as string: %f \n", ); }

或者,让你的词法分析器只为 <..> 中不存在的所有内容提供 return TEXT 标记,并在任何地方使用它:

[^<>]+  { 
              yylval.str_val=strdup(yytext);
              return(TEXT);
        }

另外,你的词法分析器应该有这样的规则:

.      fprintf(stderr, "Ignoring unknown character '%c'\n", *yytext);

.      return *yytext;

最后。

如果没有这样的规则,您输入中的奇数字符只会被回显到输出中,这几乎肯定不是您想要的编译器(尽管对于一个简单的文本处理器来说可能没问题,它只是制作一些更改输入,并将其余部分单独作为传递)。你想要哪种取决于你想如何处理错误——如果你的语法中没有错误恢复规则并且只想忽略额外的字符,前者很好,而如果你已经在你的语法中实现了错误恢复方案,后者将任何额外的字符作为单个标记提供给解析器,您的错误恢复可以用它们做一些更聪明的事情。