如何合并两个 flex (.l) 文件并在一个 Bison 文件 (.y) 中使用它们?
How to combine two flex (.l) files and use them in one Bison file (.y)?
我对 Bison/Flex 很陌生。我创建了一个程序来读取 c 文件并识别定义的函数。有效。我想知道,如何使用来自另一个开源的一些预定义的 lex 文件并将其标记用于我的 lex 文件并生成输出?
简而言之,是否可以组合两个或多个 lex 文件并作为输入(Bison (.y) 文件从中读取标记)?
请推荐我。
谢谢
为了说清楚,这里是示例,
c.l(来源 --> http://www.lysator.liu.se/c/ANSI-C-grammar-l.html)
D [0-9]
L [a-zA-Z_]
H [a-fA-F0-9]
E [Ee][+-]?{D}+
FS (f|F|l|L)
IS (u|U|l|L)*
%{
/* this scanner sourced from: http://www.lysator.liu.se/c/ANSI-C-grammar-l.html */
void count();
#include <stdio.h>
#include <string.h>
#define YYSTYPE void *
%}
%%
"/*" { comment(); }
"auto" { count(); return(AUTO); }
"break" { count(); return(BREAK); }
"case" { count(); return(CASE); }
"char" { count(); return(CHAR); }
"const" { count(); return(CONST); }
"continue" { count(); return(CONTINUE); }
"default" { count(); return(DEFAULT); }
"do" { count(); return(DO); }
"double" { count(); return(DOUBLE); }
"else" { count(); return(ELSE); }
"enum" { count(); return(ENUM); }
"extern" { count(); return(EXTERN); }
"float" { count(); return(FLOAT); }
"for" { count(); return(FOR); }
"goto" { count(); return(GOTO); }
"if" { count(); return(IF); }
"int" { count(); return(INT); }
"long" { count(); return(LONG); }
"register" { count(); return(REGISTER); }
"return" { count(); return(RETURN); }
"short" { count(); return(SHORT); }
"signed" { count(); return(SIGNED); }
"sizeof" { count(); return(SIZEOF); }
"static" { count(); return(STATIC); }
"struct" { count(); return(STRUCT); }
"switch" { count(); return(SWITCH); }
"typedef" { count(); return(TYPEDEF); }
"union" { count(); return(UNION); }
"unsigned" { count(); return(UNSIGNED); }
"void" { count(); return(VOID); }
"volatile" { count(); return(VOLATILE); }
"while" { count(); return(WHILE); }
{L}({L}|{D})* { count(); return(check_type()); }
0[xX]{H}+{IS}? { count(); return(CONSTANT); }
0{D}+{IS}? { count(); return(CONSTANT); }
{D}+{IS}? { count(); return(CONSTANT); }
L?'(\.|[^\'])+' { count(); return(CONSTANT); }
{D}+{E}{FS}? { count(); return(CONSTANT); }
{D}*"."{D}+({E})?{FS}? { count(); return(CONSTANT); }
{D}+"."{D}*({E})?{FS}? { count(); return(CONSTANT); }
L?\"(\.|[^\"])*\" { count(); return(STRING_LITERAL); }
"..." { count(); return(ELLIPSIS); }
">>=" { count(); return(RIGHT_ASSIGN); }
"<<=" { count(); return(LEFT_ASSIGN); }
"+=" { count(); return(ADD_ASSIGN); }
"-=" { count(); return(SUB_ASSIGN); }
"*=" { count(); return(MUL_ASSIGN); }
"/=" { count(); return(DIV_ASSIGN); }
"%=" { count(); return(MOD_ASSIGN); }
"&=" { count(); return(AND_ASSIGN); }
"^=" { count(); return(XOR_ASSIGN); }
"|=" { count(); return(OR_ASSIGN); }
">>" { count(); return(RIGHT_OP); }
"<<" { count(); return(LEFT_OP); }
"++" { count(); return(INC_OP); }
"--" { count(); return(DEC_OP); }
"->" { count(); return(PTR_OP); }
"&&" { count(); return(BOOL_AND_OP); }
"||" { count(); return(BOOL_OR_OP); }
"<=" { count(); return(LE_OP); }
">=" { count(); return(GE_OP); }
"==" { count(); return(EQ_OP); }
"!=" { count(); return(NE_OP); }
";" { count(); return(SEMICOLON); }
("{"|"<%") { count(); return(OCB); }
("}"|"%>") { count(); return(CCB); }
"," { count(); return(COMMA); }
":" { count(); return(COLON); }
"=" { count(); return(EQU); }
"(" { count(); return(OP); }
")" { count(); return(CP); }
("["|"<:") { count(); return(LBRACKET); }
("]"|":>") { count(); return(RBRACKET); }
"." { count(); return(PERIOD); }
"&" { count(); return(AND_OP); }
"!" { count(); return(BANG); }
"~" { count(); return(TILDE); }
"-" { count(); return(MINUS); }
"+" { count(); return(ADD); }
"*" { count(); return(STAR); }
"/" { count(); return(SLASH); }
"%" { count(); return(PERCENT); }
"<" { count(); return(LT_OP); }
">" { count(); return(GT_OP); }
"^" { count(); return(CIRCUMFLEX); }
"|" { count(); return(OR_OP); }
"?" { count(); return(QUESTIONMARK); }
[ \t\v\n\f] { count(); }
. { /* ignore bad characters */ }
%%
comment()
{
char c, c1;
loop:
while ((c = input()) != '*' && c != 0)
/*putchar(c)*/;
if ((c1 = input()) != '/' && c != 0)
{
unput(c1);
goto loop;
}
if (c != 0)
/*putchar(c1)*/;
}
int column = 0;
void count()
{
int i;
for (i = 0; yytext[i] != '[=10=]'; i++)
if (yytext[i] == '\n')
column = 0;
else if (yytext[i] == '\t')
column += 8 - (column % 8);
else
column++;
/*ECHO*/;
}
int check_type()
{
/*
* pseudo code --- this is what it should check
*
* if (yytext == type_name)
* return(TYPE_NAME);
*
* return(IDENTIFIER);
*/
/*
* it actually will only return IDENTIFIER
*/
return(IDENTIFIER);
}
我想将它与下面的文件结合/使用,即
lexer.l
%{
#include "c.l"
#include <stdio.h>
#include "parser_test.tab.h"
%}
%%
"{" { yylval.str = strdup(yytext); return OCB; }
"}" { yylval.str = strdup(yytext); return CCB; }
/* MANY MORE TOKENS TO ADD */
%%
最后是唯一使用这两个标记的野牛文件 (.y),
parser_test.y
%{
#include <stdio.h>
#include "lex.yy.c"
int yyerror ();
int yylineno;
char* a;
char* b;
%}
%union {
char *str;
}
%define parse.error verbose
%type <str> INT CONST CONSTANT RETURN IDENTIFIER ADD EQU PTR SEMICOLON OP CP OCB CCB COMMA
%token INT CONST CONSTANT RETURN IDENTIFIER ADD EQU PTR SEMICOLON NUMBER OP CP OCB CCB COMMA
%start Program
%%
Program: outStatements
functions
;
functions: function
| functions function
;
function: INT IDENTIFIER OP parametersList CP OCB statementList CCB { a=; printf("\nFunction Defined : %s\n", ); }
;
parametersList: /*empty*/
| parameters
;
parameters: parameter
| parameters COMMA parameter
;
parameter: INT IDENTIFIER { printf("\nPARAMETER NAME: %s\nPARAMETER INT :%s\n", , ); }
;
statementList: /*empty*/
| statements
;
statements: statement
| statements statement
;
statement: RETURN IDENTIFIER ADD IDENTIFIER SEMICOLON
| INT IDENTIFIER COMMA IDENTIFIER EQU CONSTANT COMMA IDENTIFIER EQU CONSTANT SEMICOLON
| IDENTIFIER EQU IDENTIFIER OP IDENTIFIER COMMA IDENTIFIER CP SEMICOLON { b = ; }
;
outStatements: outStatement
| outStatements outStatement
;
outStatement: INT PTR IDENTIFIER SEMICOLON
| CONST INT IDENTIFIER EQU CONSTANT SEMICOLON
;
%%
int main (int argc, char * argv[])
{
yyin = fopen(argv[1], "r");
int err_code = yyparse();
if (err_code == 0)
{
printf("\nFunction called : '%s' from '%s'\n", b, a);
printf("\nParsing Done !!!\n");
}
else
{
printf("\nUNSUCCESSFUL ....\n");
}
fclose(yyin);
return 0;
}
int yyerror (char* s)
{
fprintf(stderr, "\nError on Line: %d :: %s\n" , yylineno, s);
}
int yywrap()
{
return 1;
}
我怎样才能实现?
To put in simpler way, Is it possible to combine two or more lex files and given as an input ( from where Bison (.y) file reads the tokens) ?
lex
(或flex
)实用程序根据一个输入文件为(除其他外)扫描仪功能生成C源代码。如果您 运行 通过它进行两个单独的输入,那么您将获得两个单独的功能。使用某些版本的 lex
和一些额外的工作,您可以使这些函数具有不同的名称,但是您无法成功地使它们扫描相同的输入流,因为它们维护自己的输入缓冲区和扫描状态信息,因此它们会干扰彼此。
您也不能连接 lex
个输入文件以将它们合并为一个,至少因为每个文件都包含两个或三个部分,其相对顺序很重要。连接两个 lex
输入文件不会产生有效的 lex
输入文件。
您可能能够逐节将两个 lex
输入文件合并为一个,但是如果文件所涉及的是任何复杂的。仅仅组合每对对应部分的内容可能会生成一个有效的 lex
输入文件,但它不太可能是完成您想要的工作的文件。
如果您有描述扫描规则的第三方 lex
输入与您想要的类似,并且您希望以某种方式重用该代码,那么最好的办法可能是接受并修改它适合你。这可能很棘手,因为您首先需要对现有输入有很好的理解,然后才能根据需要对其进行修改。但是你无论如何都需要那个和更多来合并两个 lex
输入。
或者,您可以简单地将现有文件作为编写您自己的文件的灵感。研究它,从中收集关于如何实现类似目标的想法,等..这是我会推荐给自己的选项。您可能会通过这种方式了解更多信息,并且您可能会更好地理解生成的代码。
我对 Bison/Flex 很陌生。我创建了一个程序来读取 c 文件并识别定义的函数。有效。我想知道,如何使用来自另一个开源的一些预定义的 lex 文件并将其标记用于我的 lex 文件并生成输出?
简而言之,是否可以组合两个或多个 lex 文件并作为输入(Bison (.y) 文件从中读取标记)?
请推荐我。 谢谢
为了说清楚,这里是示例,
c.l(来源 --> http://www.lysator.liu.se/c/ANSI-C-grammar-l.html)
D [0-9]
L [a-zA-Z_]
H [a-fA-F0-9]
E [Ee][+-]?{D}+
FS (f|F|l|L)
IS (u|U|l|L)*
%{
/* this scanner sourced from: http://www.lysator.liu.se/c/ANSI-C-grammar-l.html */
void count();
#include <stdio.h>
#include <string.h>
#define YYSTYPE void *
%}
%%
"/*" { comment(); }
"auto" { count(); return(AUTO); }
"break" { count(); return(BREAK); }
"case" { count(); return(CASE); }
"char" { count(); return(CHAR); }
"const" { count(); return(CONST); }
"continue" { count(); return(CONTINUE); }
"default" { count(); return(DEFAULT); }
"do" { count(); return(DO); }
"double" { count(); return(DOUBLE); }
"else" { count(); return(ELSE); }
"enum" { count(); return(ENUM); }
"extern" { count(); return(EXTERN); }
"float" { count(); return(FLOAT); }
"for" { count(); return(FOR); }
"goto" { count(); return(GOTO); }
"if" { count(); return(IF); }
"int" { count(); return(INT); }
"long" { count(); return(LONG); }
"register" { count(); return(REGISTER); }
"return" { count(); return(RETURN); }
"short" { count(); return(SHORT); }
"signed" { count(); return(SIGNED); }
"sizeof" { count(); return(SIZEOF); }
"static" { count(); return(STATIC); }
"struct" { count(); return(STRUCT); }
"switch" { count(); return(SWITCH); }
"typedef" { count(); return(TYPEDEF); }
"union" { count(); return(UNION); }
"unsigned" { count(); return(UNSIGNED); }
"void" { count(); return(VOID); }
"volatile" { count(); return(VOLATILE); }
"while" { count(); return(WHILE); }
{L}({L}|{D})* { count(); return(check_type()); }
0[xX]{H}+{IS}? { count(); return(CONSTANT); }
0{D}+{IS}? { count(); return(CONSTANT); }
{D}+{IS}? { count(); return(CONSTANT); }
L?'(\.|[^\'])+' { count(); return(CONSTANT); }
{D}+{E}{FS}? { count(); return(CONSTANT); }
{D}*"."{D}+({E})?{FS}? { count(); return(CONSTANT); }
{D}+"."{D}*({E})?{FS}? { count(); return(CONSTANT); }
L?\"(\.|[^\"])*\" { count(); return(STRING_LITERAL); }
"..." { count(); return(ELLIPSIS); }
">>=" { count(); return(RIGHT_ASSIGN); }
"<<=" { count(); return(LEFT_ASSIGN); }
"+=" { count(); return(ADD_ASSIGN); }
"-=" { count(); return(SUB_ASSIGN); }
"*=" { count(); return(MUL_ASSIGN); }
"/=" { count(); return(DIV_ASSIGN); }
"%=" { count(); return(MOD_ASSIGN); }
"&=" { count(); return(AND_ASSIGN); }
"^=" { count(); return(XOR_ASSIGN); }
"|=" { count(); return(OR_ASSIGN); }
">>" { count(); return(RIGHT_OP); }
"<<" { count(); return(LEFT_OP); }
"++" { count(); return(INC_OP); }
"--" { count(); return(DEC_OP); }
"->" { count(); return(PTR_OP); }
"&&" { count(); return(BOOL_AND_OP); }
"||" { count(); return(BOOL_OR_OP); }
"<=" { count(); return(LE_OP); }
">=" { count(); return(GE_OP); }
"==" { count(); return(EQ_OP); }
"!=" { count(); return(NE_OP); }
";" { count(); return(SEMICOLON); }
("{"|"<%") { count(); return(OCB); }
("}"|"%>") { count(); return(CCB); }
"," { count(); return(COMMA); }
":" { count(); return(COLON); }
"=" { count(); return(EQU); }
"(" { count(); return(OP); }
")" { count(); return(CP); }
("["|"<:") { count(); return(LBRACKET); }
("]"|":>") { count(); return(RBRACKET); }
"." { count(); return(PERIOD); }
"&" { count(); return(AND_OP); }
"!" { count(); return(BANG); }
"~" { count(); return(TILDE); }
"-" { count(); return(MINUS); }
"+" { count(); return(ADD); }
"*" { count(); return(STAR); }
"/" { count(); return(SLASH); }
"%" { count(); return(PERCENT); }
"<" { count(); return(LT_OP); }
">" { count(); return(GT_OP); }
"^" { count(); return(CIRCUMFLEX); }
"|" { count(); return(OR_OP); }
"?" { count(); return(QUESTIONMARK); }
[ \t\v\n\f] { count(); }
. { /* ignore bad characters */ }
%%
comment()
{
char c, c1;
loop:
while ((c = input()) != '*' && c != 0)
/*putchar(c)*/;
if ((c1 = input()) != '/' && c != 0)
{
unput(c1);
goto loop;
}
if (c != 0)
/*putchar(c1)*/;
}
int column = 0;
void count()
{
int i;
for (i = 0; yytext[i] != '[=10=]'; i++)
if (yytext[i] == '\n')
column = 0;
else if (yytext[i] == '\t')
column += 8 - (column % 8);
else
column++;
/*ECHO*/;
}
int check_type()
{
/*
* pseudo code --- this is what it should check
*
* if (yytext == type_name)
* return(TYPE_NAME);
*
* return(IDENTIFIER);
*/
/*
* it actually will only return IDENTIFIER
*/
return(IDENTIFIER);
}
我想将它与下面的文件结合/使用,即
lexer.l
%{
#include "c.l"
#include <stdio.h>
#include "parser_test.tab.h"
%}
%%
"{" { yylval.str = strdup(yytext); return OCB; }
"}" { yylval.str = strdup(yytext); return CCB; }
/* MANY MORE TOKENS TO ADD */
%%
最后是唯一使用这两个标记的野牛文件 (.y),
parser_test.y
%{
#include <stdio.h>
#include "lex.yy.c"
int yyerror ();
int yylineno;
char* a;
char* b;
%}
%union {
char *str;
}
%define parse.error verbose
%type <str> INT CONST CONSTANT RETURN IDENTIFIER ADD EQU PTR SEMICOLON OP CP OCB CCB COMMA
%token INT CONST CONSTANT RETURN IDENTIFIER ADD EQU PTR SEMICOLON NUMBER OP CP OCB CCB COMMA
%start Program
%%
Program: outStatements
functions
;
functions: function
| functions function
;
function: INT IDENTIFIER OP parametersList CP OCB statementList CCB { a=; printf("\nFunction Defined : %s\n", ); }
;
parametersList: /*empty*/
| parameters
;
parameters: parameter
| parameters COMMA parameter
;
parameter: INT IDENTIFIER { printf("\nPARAMETER NAME: %s\nPARAMETER INT :%s\n", , ); }
;
statementList: /*empty*/
| statements
;
statements: statement
| statements statement
;
statement: RETURN IDENTIFIER ADD IDENTIFIER SEMICOLON
| INT IDENTIFIER COMMA IDENTIFIER EQU CONSTANT COMMA IDENTIFIER EQU CONSTANT SEMICOLON
| IDENTIFIER EQU IDENTIFIER OP IDENTIFIER COMMA IDENTIFIER CP SEMICOLON { b = ; }
;
outStatements: outStatement
| outStatements outStatement
;
outStatement: INT PTR IDENTIFIER SEMICOLON
| CONST INT IDENTIFIER EQU CONSTANT SEMICOLON
;
%%
int main (int argc, char * argv[])
{
yyin = fopen(argv[1], "r");
int err_code = yyparse();
if (err_code == 0)
{
printf("\nFunction called : '%s' from '%s'\n", b, a);
printf("\nParsing Done !!!\n");
}
else
{
printf("\nUNSUCCESSFUL ....\n");
}
fclose(yyin);
return 0;
}
int yyerror (char* s)
{
fprintf(stderr, "\nError on Line: %d :: %s\n" , yylineno, s);
}
int yywrap()
{
return 1;
}
我怎样才能实现?
To put in simpler way, Is it possible to combine two or more lex files and given as an input ( from where Bison (.y) file reads the tokens) ?
lex
(或flex
)实用程序根据一个输入文件为(除其他外)扫描仪功能生成C源代码。如果您 运行 通过它进行两个单独的输入,那么您将获得两个单独的功能。使用某些版本的 lex
和一些额外的工作,您可以使这些函数具有不同的名称,但是您无法成功地使它们扫描相同的输入流,因为它们维护自己的输入缓冲区和扫描状态信息,因此它们会干扰彼此。
您也不能连接 lex
个输入文件以将它们合并为一个,至少因为每个文件都包含两个或三个部分,其相对顺序很重要。连接两个 lex
输入文件不会产生有效的 lex
输入文件。
您可能能够逐节将两个 lex
输入文件合并为一个,但是如果文件所涉及的是任何复杂的。仅仅组合每对对应部分的内容可能会生成一个有效的 lex
输入文件,但它不太可能是完成您想要的工作的文件。
如果您有描述扫描规则的第三方 lex
输入与您想要的类似,并且您希望以某种方式重用该代码,那么最好的办法可能是接受并修改它适合你。这可能很棘手,因为您首先需要对现有输入有很好的理解,然后才能根据需要对其进行修改。但是你无论如何都需要那个和更多来合并两个 lex
输入。
或者,您可以简单地将现有文件作为编写您自己的文件的灵感。研究它,从中收集关于如何实现类似目标的想法,等..这是我会推荐给自己的选项。您可能会通过这种方式了解更多信息,并且您可能会更好地理解生成的代码。