Распознавание бизонов / гибких токенов

Что я должен написать вместо

identifier      [a-zA-Z0-9]+

чтобы принять также строку, сделанную только числами?

Я написал новые файлы бизонов и гибких дисков, чтобы прояснить мою проблему. Файл зубра:

%{
#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); }
    ;

%%

Файл Flex:

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

Я получаю синтаксическую ошибку...

1 ответ

Решение

Строка только цифр возвращает токен NUMBERтак что вы можете добавить правило:

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

Альтернативно, пусть ваш лексер просто вернется TEXT токены для всего, что не в <..>и используйте это везде:

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

Кроме того, ваш лексер должен иметь такое правило:

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

или же

.      return *yytext;

в конце.

Без такого правила нечетные символы в вашем вводе будут просто отображаться на выходе, что почти наверняка не то, что вы хотите для компилятора (хотя это может быть хорошо для простого текстового процессора, который просто вносит некоторые изменения в ввод, и оставляя остальное в покое) То, что вы хотите, зависит от того, как вы хотите обрабатывать ошибки - если у вас нет правил восстановления ошибок в вашей грамматике и вы просто хотите игнорировать дополнительные символы, то первый вариант подойдет, хотя вы внедрили схему восстановления ошибок в своей грамматике последний дает любые дополнительные символы в виде одиночных токенов парсеру, где ваше восстановление после ошибок может сделать с ними что-то более умное.

Другие вопросы по тегам