Bison/yacc 解析器在未被 space - "unexpected $end" 分隔时跳过语法
Bison/yacc parser skipping grammer when not separated by space - "unexpected $end"
你好我有一个场景,如果有 space 分隔语法,野牛将成功解析我的输入...
情况如下:我正在尝试声明一个变量:
int a = 31 ;
这个yyin解析成功
int a = 31;
没有解析成功
我收到的错误是:
syntax error, unexpected $end, expecting TSEMI
这是野牛代码的部分
%token <string> TIDENTIFIER TINTEGER TDOUBLE
%token <token> TCEQUAL TCNE TCLT TCLE TCGT TCGE TASSIGN
%token <token> TLPAREN TRPAREN TLBRACE TRBRACE TCOMMA TDOT TSEMI
%token <token> TPLUS TMINUS TMUL TDIV
...
var_decl : ident ident TSEMI { $$ = new VarDel(, ); }
| ident ident TASSIGN expr TSEMI {$$ = new VarDel(, , );}
;
ident : TIDENTIFIER { $$ = new Var(->c_str()); delete ; }
;
expr : ident { $<ident>$ = ; }
| numeric
;
numeric : TINTEGER { $$ = new Num(atol(->c_str())); delete ; }
| TDOUBLE { $$ = new Num(atof(->c_str())); delete ; }
;
这是我的 flex 文件的一部分
[ \t\n] ;
[a-zA-Z_][a-zA-Z0-9_]* SAVE_TOKEN; return TIDENTIFIER;
[0-9]+.[0-9]* SAVE_TOKEN; return TDOUBLE;
[0-9]+ SAVE_TOKEN; return TINTEGER;
"=" return TOKEN(TASSIGN);
"==" return TOKEN(TCEQUAL);
"!=" return TOKEN(TCNE);
"<" return TOKEN(TCLT);
"<=" return TOKEN(TCLE);
">" return TOKEN(TCGT);
">=" return TOKEN(TCGE);
"(" return TOKEN(TLPAREN);
")" return TOKEN(TRPAREN);
"{" return TOKEN(TLBRACE);
"}" return TOKEN(TRBRACE);
"." return TOKEN(TDOT);
"," return TOKEN(TCOMMA);
"+" return TOKEN(TPLUS);
"-" return TOKEN(TMINUS);
";" return TOKEN(TSEMI);
"*" return TOKEN(TMUL);
"/" return TOKEN(TDIV);
. printf("Unknown token!n"); yyterminate();
为什么有space就解析成功,有
就解析不成功?
谢谢
[0-9]+.[0-9]*
应该是 [0-9]+\.[0-9]*
。正如所写,它匹配 31;
.
您最好启用 flex 调试(-d
命令行标志)以查看它是如何标记的。此外,使用 atof
默默地隐藏了令牌不是有效数字的事实。考虑使用更安全的字符串→数字转换器;你会在 C++ 标准库中找到一个;在 C 中,它将是 strtod
,然后检查 endptr
是否在末尾。 (你可以在词法分析器中进行这种转换,避免不必要的字符串分配和释放。)
你好我有一个场景,如果有 space 分隔语法,野牛将成功解析我的输入...
情况如下:我正在尝试声明一个变量:
int a = 31 ;
这个yyin解析成功
int a = 31;
没有解析成功
我收到的错误是:
syntax error, unexpected $end, expecting TSEMI
这是野牛代码的部分
%token <string> TIDENTIFIER TINTEGER TDOUBLE
%token <token> TCEQUAL TCNE TCLT TCLE TCGT TCGE TASSIGN
%token <token> TLPAREN TRPAREN TLBRACE TRBRACE TCOMMA TDOT TSEMI
%token <token> TPLUS TMINUS TMUL TDIV
...
var_decl : ident ident TSEMI { $$ = new VarDel(, ); }
| ident ident TASSIGN expr TSEMI {$$ = new VarDel(, , );}
;
ident : TIDENTIFIER { $$ = new Var(->c_str()); delete ; }
;
expr : ident { $<ident>$ = ; }
| numeric
;
numeric : TINTEGER { $$ = new Num(atol(->c_str())); delete ; }
| TDOUBLE { $$ = new Num(atof(->c_str())); delete ; }
;
这是我的 flex 文件的一部分
[ \t\n] ;
[a-zA-Z_][a-zA-Z0-9_]* SAVE_TOKEN; return TIDENTIFIER;
[0-9]+.[0-9]* SAVE_TOKEN; return TDOUBLE;
[0-9]+ SAVE_TOKEN; return TINTEGER;
"=" return TOKEN(TASSIGN);
"==" return TOKEN(TCEQUAL);
"!=" return TOKEN(TCNE);
"<" return TOKEN(TCLT);
"<=" return TOKEN(TCLE);
">" return TOKEN(TCGT);
">=" return TOKEN(TCGE);
"(" return TOKEN(TLPAREN);
")" return TOKEN(TRPAREN);
"{" return TOKEN(TLBRACE);
"}" return TOKEN(TRBRACE);
"." return TOKEN(TDOT);
"," return TOKEN(TCOMMA);
"+" return TOKEN(TPLUS);
"-" return TOKEN(TMINUS);
";" return TOKEN(TSEMI);
"*" return TOKEN(TMUL);
"/" return TOKEN(TDIV);
. printf("Unknown token!n"); yyterminate();
为什么有space就解析成功,有
就解析不成功?谢谢
[0-9]+.[0-9]*
应该是 [0-9]+\.[0-9]*
。正如所写,它匹配 31;
.
您最好启用 flex 调试(-d
命令行标志)以查看它是如何标记的。此外,使用 atof
默默地隐藏了令牌不是有效数字的事实。考虑使用更安全的字符串→数字转换器;你会在 C++ 标准库中找到一个;在 C 中,它将是 strtod
,然后检查 endptr
是否在末尾。 (你可以在词法分析器中进行这种转换,避免不必要的字符串分配和释放。)