我想解析一个从/etc/hosts.allow格式派生的简单语法。 我正在yacc上转换/减少冲突。我可以忽略转换/减少冲突警告,还是可以以某种方式修改它?:
%token ALLOW
%token DENY
%token COMMENT
%token DEFAULT
%token HOSTUSER
%token PRODUCT
%%
lines: line
| lines line
line: product_line
| default_line
product_line: PRODUCT ':' user_host_list ':' allow_deny
{ printf("product line\n"); }
default_line: DEFAULT ':' allow_deny
{ printf ("default line\n"); }
allow_deny: ALLOW
| DENY
user_host_list:
| HOSTUSER
| user_host_list HOSTUSER
%%
#include <stdio.h>
extern FILE *yyin;
extern char *yytext;
main(argc, argv)
int argc;
char **argv;
while(yyparse() && !feof(yyin))
;
return 0;
}
示例文件看起来像这样:
# comments
# comments
DEFAULT : DENY
<some_product_code> : <list_of_users_hosts> : ALLOW
<some_product_code> : <list_of_users_hosts> : ALLOW
(N.B。:评论行#被lexer“吃掉”)
我也会添加词法分析器:
%{
#include <stdio.h>
#include "y.tab.h"
int debug=0;
#define P1(x) if(debug)printf(x)
#define P2(x,y) if(debug)printf(x,y)
#ifdef TEST_LEXER
main()
{
debug=1;
while(yylex())
;
return 0;
}
#endif
%}
%option caseless
/*
"EX-P00V10000-NT-xx"
"FX-P05E64001-NT-xx"
"NX-P07E03400-NT-xx"
"BX-P00B00000-NT-xx"
"VX-P02E08000-NT-xx"
*/
deny DENY
allow ALLOW
default DEFAULT
product [BCEFKNV][X]-[P][0-9][0-9][EBPV]([0-9]{5,})-NT-xx
name [A-Z_0-9][A-Z_\-0-9\.]*
%%
{product} { P1("PRODUCT! ");return PRODUCT;}
{allow} { P1("ALLOW!\n");return ALLOW; }
{deny} { P1("DENY!\n");return DENY; }
{default} { P1("DEFAULT!\n");return DEFAULT; }
\*|\\\\{name}|\\\\{name}\\{name}|\\\\{name}\\\*|{name} { P2("HOSTUSER![%s]",yytext); }
#.*(\n|\r\n) {P1("COMMENT!\n");;}
\n|\r\n|[ ]|\t|, { ; }
. { P2("[%02hx]",(unsigned char)yytext[0]);return yytext[0]; }
%%
yyerror(char *s) { fprintf(stderr,"Zeile %d: %s[%s]\n",
yylineno,s,yytext); fflush(stdout);}
yywrap() { return 1; }
样本输入:
# blah blah hello
DEFAULT : DENY
BX-P00B00000-NT-xx : \\host\user \\another\user1 user2 user3 : allow
BX-P00E00003-NT-xx : * : allow
BX-P01B03000-NT-xx : \\host\* : allow # comment here should work, too
BX-P01B03000-NT-xx : \\host\* : allow
# continuation lines too:
BX-P01B03000-NT-xx : user1
user2
\\host\* : allow
答案 0 :(得分:1)
您的user_host_list
定义:
user_host_list:
| HOSTUSER
| user_host_list HOSTUSER
以您可能不想要的|
开头。它包含3条规则。第一个规则是空的,因此空令牌序列可以减少到user_host_list
。这是导致冲突的不必要的减少。
如果您打算要求至少1 HOSTUSER
,请按以下方式编写:
user_host_list:
HOSTUSER
| user_host_list HOSTUSER
如果您打算允许空列表,请按以下方式编写:
user_host_list:
/* empty */
| user_host_list HOSTUSER