【问题标题】:Bison/Flex String Token RecognitionBison/Flex 字符串令牌识别
【发布时间】:2015-08-01 17:57:38
【问题描述】:

我必须写什么而不是

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", $3); }
    | Block BEGIN_NUM NUMBER END_NUM { printf("received number: %f \n", $3); }
    ;

%%

弹性文件:

%{
#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>

我收到语法错误...

【问题讨论】:

    标签: string compiler-construction bison


    【解决方案1】:

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

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

    或者,让您的词法分析器为不在&lt;..&gt; 中的所有内容返回TEXT 标记,并在任何地方使用它:

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

    此外,您的词法分析器应该有如下规则:

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

    .      return *yytext;
    

    在最后。

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

    【讨论】:

    • . return yytext[0]; 更好,因为它允许解析器进行错误恢复,并消除了单个特殊字符的所有 lex 规则。
    • 好的,我明白了,非常感谢。您能否更好地解释为什么我应该使用. fprintf(stderr, "Ignoring unknown character '%c'\n", *yytext);. return yytext[0];?有哪些区别?再次感谢您
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-16
    • 1970-01-01
    相关资源
    最近更新 更多