Flex Bison 和 Gnu Automake
Flex Bison and Gnu Automake
我写了一个基于 flex-lexer 和 bison 的小文本过滤器。
布尔表达式应用于指定的字符串 (logvar)。布尔表达式由字符串和布尔运算组成。
示例:
*intput*:
logvar=aa bb cc dd ee
aa & bb
*result*:
true
*input*:
logvar=aa bb cc dd ee
aa & rr
*result*:
false
*input*:
logvar=aa bb cc dd ee
aa | rr
*result*:
true
很简单。
这是词法分析器的来源-filter.l:
%{
#include <stdlib.h>
void yyerror(char *);
#include "grammar-filter.tab.h"
%}
%%
"&" {
printf("LEX: & parsed\n");
return AND;
}
"|" {
printf("LEX: | parsed\n");
return OR;
}
"logvar" {
printf("LEX: logvar parsed\n");
return LOGVAR;
}
[a-z ]+ {
yylval.sValue = strdup(yytext);
printf("LEX: string parsed: %s\n", yylval.sValue);
return STRING;
}
[()=\n] { return *yytext; }
[ \t] ;
, { return *yytext; }
. yyerror("invalid character");
%%
int yywrap(void) {
return 1;
}
和语法野牛文件:
%{
#include <string.h>
#include <stdio.h>
void yyerror(char *);
int yylex(void);
int sym[26];
char* log_line;
%}
%union {
char *sValue;
int iValue;
}
%token <iValue> BOOLEAN
%token <sValue> STRING
%token LOGVAR
%token AND OR
%left AND OR
%type<iValue> expr
%%
prog :
prog logassigned '\n' statement '\n'
;
statement :
expr { printf("%d\n", ); }
;
logassigned :
LOGVAR '=' STRING { log_line = ; }
;
expr:
STRING { if (strstr(log_line, ) != NULL) {
printf("%s is substring of %s\n", , log_line);
$$ = 1;
} else {
printf("%s doesn't substring of %s\n", , log_line);
$$ = 0;
}
}
| expr OR expr { if ( == 1 || == 1) { $$ = 1; } else { $$ = 0; } }
| expr AND expr { $$ = * ; }
| NOT expr { if ( == 1) { $$ = 0; } else { $$ = 1; } }
| '(' expr ')' { $$ = ; }
;
%%
#include "lex.yy.c"
void yyerror(char *s) {
fprintf(stderr, "%s\n", s);
}
int main(void) {
// yy_scan_string(some_string_buffer);
yyparse();
// yylex_destroy();
return 0;
}
最终的二进制文件是由一个简单的 make 文件构建的:
all:
flex lexer-filter.l
bison grammar-filter.y -d
gcc grammar-filter.tab.c -ll
我有一个基于 gnu autotools 的库(automake、autoconf...)。是否可以将此解析器添加到库中并使用这三个结构 yy_scan_string(some_string_buffer); yyparse(); yylex_destroy(); 在我的图书馆?我如何 运行 flex 和 bison 从 automake 脚本生成文件(lex.yy.c grammar-filter.tab.c grammar-filter.tab.h)
问候,最大)
问候,最大
Autotools 有 built-in support for flex and bison,尽管它有点古怪(或如链接文档所说的“特殊”)。
至少,您需要做两件事:
将 AC_PROG_LEX
和 AC_PROG_YACC
添加到 configure.ac
。
添加 BUILT_SOURCES
的定义,它列出生成的 header 文件到 Makefile.am
。
参见 this answer for an example。
您还需要稍微清理一下您的项目。 Autotools 假定解析器和扫描器将单独构建,因此您需要将它们分开。 #include
在解析器中使用扫描器可能看起来很方便,但它并不是很好的项目组织。 (换句话说,这个要求不是 Autotools 的怪癖之一。)你需要 #include
headers 适当的: bison-generated header 文件需要#included
d 在扫描仪源代码中,flex header 文件(您可以使用 flex 选项请求)需要在调用 flex 函数的源代码中为 #include
d。
而不是直接使用 flex-generated header,您可能想将自己的小包装器写入扫描仪本身,并为包装器函数编写自己的 header 文件。我通常这样做是为了避免对 flex 的紧密依赖。
您可以通过向扫描器添加 %option
声明来提高扫描器的可编译性,至少:
%option noinput nounput noyywrap
前两个选项避免了关于未使用函数的编译器警告,最后一个选项消除了对 yywrap
的需要,因此不需要 -ll
(或 -lfl
)。我通常也会添加 nodefault
,这样如果某些输入会回退到默认规则,flex 就会产生错误,这通常表示扫描仪规范中存在错误。
总的来说,通常最好将生成的文件包含在分发中,而不是坚持要存在正确版本的 flex 和 bison。 Autotools 也可以以这种方式使用。
我写了一个基于 flex-lexer 和 bison 的小文本过滤器。 布尔表达式应用于指定的字符串 (logvar)。布尔表达式由字符串和布尔运算组成。
示例:
*intput*:
logvar=aa bb cc dd ee
aa & bb
*result*:
true
*input*:
logvar=aa bb cc dd ee
aa & rr
*result*:
false
*input*:
logvar=aa bb cc dd ee
aa | rr
*result*:
true
很简单。
这是词法分析器的来源-filter.l:
%{
#include <stdlib.h>
void yyerror(char *);
#include "grammar-filter.tab.h"
%}
%%
"&" {
printf("LEX: & parsed\n");
return AND;
}
"|" {
printf("LEX: | parsed\n");
return OR;
}
"logvar" {
printf("LEX: logvar parsed\n");
return LOGVAR;
}
[a-z ]+ {
yylval.sValue = strdup(yytext);
printf("LEX: string parsed: %s\n", yylval.sValue);
return STRING;
}
[()=\n] { return *yytext; }
[ \t] ;
, { return *yytext; }
. yyerror("invalid character");
%%
int yywrap(void) {
return 1;
}
和语法野牛文件:
%{
#include <string.h>
#include <stdio.h>
void yyerror(char *);
int yylex(void);
int sym[26];
char* log_line;
%}
%union {
char *sValue;
int iValue;
}
%token <iValue> BOOLEAN
%token <sValue> STRING
%token LOGVAR
%token AND OR
%left AND OR
%type<iValue> expr
%%
prog :
prog logassigned '\n' statement '\n'
;
statement :
expr { printf("%d\n", ); }
;
logassigned :
LOGVAR '=' STRING { log_line = ; }
;
expr:
STRING { if (strstr(log_line, ) != NULL) {
printf("%s is substring of %s\n", , log_line);
$$ = 1;
} else {
printf("%s doesn't substring of %s\n", , log_line);
$$ = 0;
}
}
| expr OR expr { if ( == 1 || == 1) { $$ = 1; } else { $$ = 0; } }
| expr AND expr { $$ = * ; }
| NOT expr { if ( == 1) { $$ = 0; } else { $$ = 1; } }
| '(' expr ')' { $$ = ; }
;
%%
#include "lex.yy.c"
void yyerror(char *s) {
fprintf(stderr, "%s\n", s);
}
int main(void) {
// yy_scan_string(some_string_buffer);
yyparse();
// yylex_destroy();
return 0;
}
最终的二进制文件是由一个简单的 make 文件构建的:
all:
flex lexer-filter.l
bison grammar-filter.y -d
gcc grammar-filter.tab.c -ll
我有一个基于 gnu autotools 的库(automake、autoconf...)。是否可以将此解析器添加到库中并使用这三个结构 yy_scan_string(some_string_buffer); yyparse(); yylex_destroy(); 在我的图书馆?我如何 运行 flex 和 bison 从 automake 脚本生成文件(lex.yy.c grammar-filter.tab.c grammar-filter.tab.h)
问候,最大)
问候,最大
Autotools 有 built-in support for flex and bison,尽管它有点古怪(或如链接文档所说的“特殊”)。
至少,您需要做两件事:
将
AC_PROG_LEX
和AC_PROG_YACC
添加到configure.ac
。添加
BUILT_SOURCES
的定义,它列出生成的 header 文件到Makefile.am
。
参见 this answer for an example。
您还需要稍微清理一下您的项目。 Autotools 假定解析器和扫描器将单独构建,因此您需要将它们分开。 #include
在解析器中使用扫描器可能看起来很方便,但它并不是很好的项目组织。 (换句话说,这个要求不是 Autotools 的怪癖之一。)你需要 #include
headers 适当的: bison-generated header 文件需要#included
d 在扫描仪源代码中,flex header 文件(您可以使用 flex 选项请求)需要在调用 flex 函数的源代码中为 #include
d。
而不是直接使用 flex-generated header,您可能想将自己的小包装器写入扫描仪本身,并为包装器函数编写自己的 header 文件。我通常这样做是为了避免对 flex 的紧密依赖。
您可以通过向扫描器添加 %option
声明来提高扫描器的可编译性,至少:
%option noinput nounput noyywrap
前两个选项避免了关于未使用函数的编译器警告,最后一个选项消除了对 yywrap
的需要,因此不需要 -ll
(或 -lfl
)。我通常也会添加 nodefault
,这样如果某些输入会回退到默认规则,flex 就会产生错误,这通常表示扫描仪规范中存在错误。
总的来说,通常最好将生成的文件包含在分发中,而不是坚持要存在正确版本的 flex 和 bison。 Autotools 也可以以这种方式使用。