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