如何合并两个 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 输入。

或者,您可以简单地将现有文件作为编写您自己的文件的灵感。研究它,从中收集关于如何实现类似目标的想法,..这是我会推荐给自己的选项。您可能会通过这种方式了解更多信息,并且您可能会更好地理解生成的代码。