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

非常简单。

以下是源lexer过滤器。l:

%{
#include <stdlib.h>
void yyerror(char *);
#include "grammar-filter.tab.h"
%}
%%
"&" {
printf("LEX: & parsedn");
return AND;
}
"|" {
printf("LEX: | parsedn");
return OR;
}
"logvar" {
printf("LEX: logvar parsedn");
return LOGVAR;
}
[a-z ]+ {
yylval.sValue = strdup(yytext);
printf("LEX: string parsed: %sn", 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("%dn", $1); }
;

logassigned :
LOGVAR '=' STRING { log_line = $3; }
;
expr:
STRING { if (strstr(log_line, $1) != NULL) {
printf("%s is substring of %sn", $1, log_line);
$$ = 1;
} else {
printf("%s doesn't substring of %sn", $1, log_line);
$$ = 0;
}
}
| expr OR expr { if ($1 == 1 || $3 == 1) { $$ = 1; } else { $$ = 0; } }
| expr AND expr { $$ = $1 * $3; }
| NOT expr { if ($2 == 1) { $$ = 0; } else { $$ = 1; } }
| '(' expr ')' { $$ = $2; }
;
%%
#include "lex.yy.c"
void yyerror(char *s) {
fprintf(stderr, "%sn", 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()在我的图书馆?以及如何从automake脚本运行flex和bison来生成文件(lex.yy.c语法过滤器.tab.c语法过滤器.tap.h)

问候,最大)

问候,最大

Autotools内置了对flex和bison的支持,尽管它有点古怪(或链接文档中所说的"特殊")。

至少,你需要做两件事:

  1. AC_PROG_LEXAC_PROG_YACC添加到configure.ac

  2. Makefile.am添加一个BUILT_SOURCES的定义,该定义列出了生成的头文件。

请参阅此答案以获取示例。

您还需要稍微清理一下您的项目。Autotools假设解析器和扫描程序将分别构建,因此您需要将它们分开。#include在解析器中使用扫描仪可能看起来很方便,但这并不是一个很好的项目组织。(换句话说,这个要求不是Autotools的怪癖之一。)您需要适当地使用#include头:bison生成的头文件需要是scanner源代码中的#includedd,而flex头文件(您可以使用flex选项请求)需要是调用flex函数的源代码的#included。

与其直接使用flex生成的头,您可能需要将自己的小包装器写入扫描仪本身,并为包装器函数编写自己的头文件。我通常这样做是为了避免对flex的过度依赖。

您可以通过向扫描仪添加%option声明来提高扫描仪的可编译性,至少:

%option noinput nounput noyywrap

前两个选项避免了编译器对未使用函数的警告,最后一个选项消除了对yywrap的需要,从而消除了对-ll(或-lfl)的需要。我通常也会添加nodefault,这样,如果某些输入回到默认规则,flex就会产生错误,这通常表明扫描仪规范中存在错误。

总的来说,通常最好将生成的文件包括在发行版中,而不是坚持要提供flex和bison的正确版本。自动工具也可以以这种方式使用。

最新更新