错误:与 Flex 词法分析器集成时,Bison 解析器中存在未知类型名称“ASTNode”

问题描述 投票:0回答:1

我正在开发一个项目,其中使用 Bison 生成解析器并使用 Flex 生成词法分析器。我的解析器旨在生成抽象语法树 (AST),并且我已在 Bison 文件中定义了 ASTNode 结构。但是,我不断遇到以下错误:

In file included from lexer.l:5:0:
parser.y:39:5: error: unknown type name 'ASTNode'
    ASTNode *astNode;  // Add ASTNode pointer for expression and other nodes

这是我当前的解析器文件,

parser.y


%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

extern FILE *yyin;
extern FILE *yyout;

void yyerror(const char *s);

// Define NodeType enumeration for AST node types
typedef enum { NODE_VAR, NODE_ICONST, NODE_ADD, NODE_SUB, NODE_MUL, NODE_DIV } NodeType;

// Define the structure for AST nodes
typedef struct ASTNode {
    NodeType type;
    union {
        char *sval; // for variables
        int ival;       // for integer constants
        struct {
            struct ASTNode *left;
            struct ASTNode *right;
        } binary;       // for binary operations
    } data;
} ASTNode;

// Function prototypes for creating AST nodes
ASTNode* createVarNode(char *name);
ASTNode* createIntNode(int value);
ASTNode* createBinaryNode(NodeType type, ASTNode *left, ASTNode *right);
void printAST(ASTNode *node);
%}

// Union for semantic values
%union {
    int ival;
    char *sval;
    ASTNode *astNode; // Add ASTNode pointer for expression and other nodes
}

%token <sval> VAR
%token <ival> ICONST
%token EQUOP ADDOP SUBOP MULOP DIVOP LPAREN RPAREN

%type <astNode> program expression expression_suffix term term_suffix factor 

%start program

%%

// Rules of the grammar
program:
    VAR EQUOP expression {
        printf("Parsed program: %s = <expression>\n", $1);
        free($1); // Free the variable name after use
        $$ = $3; // Set the result of the program to the expression
    }
;

expression:
    term expression_suffix {
        printf("Parsed expression\n");
    }
;

expression_suffix:
    ADDOP term expression_suffix {
        printf("Parsed ADDOP\n");
    }
    | SUBOP term expression_suffix {
        printf("Parsed SUBOP\n");
    }
    | /* empty */ {
    }
;

term:
    factor term_suffix {
        $$ = $1; // Assign the factor to the term result
        printf("Parsed term\n");
    }
;

term_suffix:
    MULOP factor term_suffix {
        printf("Parsed MULOP\n");
    }
    | DIVOP factor term_suffix {
        printf("Parsed DIVOP\n");
    }
    | /* empty */ {
    }
;

factor:
    LPAREN expression RPAREN {
        $$ = $2; // The result is the expression inside the parentheses
        printf("Parsed factor: (expression)\n");
        printAST($$); // Print the AST for the expression inside the parentheses
    }
    | ICONST {
        $$ = createIntNode($1); // Create an integer node
        printf("Parsed ICONST: %d\n", $1);
    }
    | VAR {
        $$ = createVarNode($1); // Create a variable node
        printf("Parsed VAR: %s\n", $1);
    }
;

%% 

void yyerror(const char *s) {
    fprintf(stderr, "Error: %s\n", s);
}

// Function definitions for AST creation and printing
ASTNode* createVarNode(char *name) {
    ASTNode *node = malloc(sizeof(ASTNode));
    node->type = NODE_VAR;
    node->data.sval = strdup(name);
    return node;
}

ASTNode* createIntNode(int value) {
    ASTNode *node = malloc(sizeof(ASTNode));
    node->type = NODE_ICONST;
    node->data.ival = value;
    return node;
}

ASTNode* createBinaryNode(NodeType type, ASTNode *left, ASTNode *right) {
    ASTNode *node = malloc(sizeof(ASTNode));
    node->type = type;
    node->data.binary.left = left;
    node->data.binary.right = right;
    return node;
}

void printAST(ASTNode *node) {
    if (!node) return;
    switch (node->type) {
        case NODE_VAR:
            printf("VAR(%s)\n", node->data.sval);
            break;
        case NODE_ICONST:
            printf("ICONST(%d)\n", node->data.ival);
            break;
        case NODE_ADD:
            printf("ADD\n");
            printAST(node->data.binary.left);
            printAST(node->data.binary.right);
            break;
        case NODE_SUB:
            printf("SUB\n");
            printAST(node->data.binary.left);
            printAST(node->data.binary.right);
            break;
        case NODE_MUL:
            printf("MUL\n");
            printAST(node->data.binary.left);
            printAST(node->data.binary.right);
            break;
        case NODE_DIV:
            printf("DIV\n");
            printAST(node->data.binary.left);
            printAST(node->data.binary.right);
            break;
    }
}

int main() {
    yyin = fopen("input.txt", "r");
    if (!yyin) {
        perror("Failed to open input file");
        return 1;
    }

    yyout = fopen("lexicalOutput.txt", "w");
    if (!yyout) {
        perror("Failed to open output file");
        fclose(yyin);
        return 1;
    }

    yyparse();

    fclose(yyin);
    fclose(yyout);

    return 0; // Add return statement at the end
}

这是我当前的词法分析器文件,

lexer.l

%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "parser.tab.h"

extern int yylex();
%}

/* Lexical analyzer rules */
%% 
[ \t]+ ; /* Ignore whitespace */
[0-9]+  { 
    yylval.ival = atoi(yytext); 
    fprintf(yyout, "Read ICONST: %d\n", yylval.ival);
    return ICONST; 
}

[a-zA-Z_][a-zA-Z0-9_]* { 
    yylval.sval = strdup(yytext); 
    fprintf(yyout, "Read VAR: %s\n", yylval.sval);
    return VAR; 
}

"=" { fprintf(yyout, "Read =\n"); return EQUOP; }
"+" { fprintf(yyout, "Read +\n"); return ADDOP; }
"-" { fprintf(yyout, "Read -\n"); return SUBOP; }
"*" { fprintf(yyout, "Read *\n"); return MULOP; }
"/" { fprintf(yyout, "Read /\n"); return DIVOP; }
"(" { fprintf(yyout, "Read (\n"); return LPAREN; }
")" { fprintf(yyout, "Read )\n"); return RPAREN; }

.   { /* Ignore unrecognized characters */ }
%%

int yywrap(void) {
    return 1;
}

我相信发生错误是因为词法分析器无法识别我的 Bison 文件中的 ASTNode 类型,但我不确定如何解决它,因为我在将其指定为类型之前定义了 AST 节点。

编译词法分析器和 bison 文件的命令行命令:

$ bison -d parser.y  
$ flex lexer.l
$ gcc -o myparser parser.tab.c lex.yy.c
[produces error shown above]
c parsing abstract-syntax-tree bison lexer
1个回答
0
投票

错误信息的原因是生成的

parser.tab.h
文件 不包含
ASTNode
的定义。 您可以打开该文件 运行
bison
后你自己就能看到这一点。 (主要是在 生成的
.tab.h
文件是
enum yytokentype
,它允许词法分析器 知道
bison
选择的令牌代码。)因此,当 编译器尝试编译
lex.yy.c
,但
ASTNode
的定义不是 可用。

要解决此问题,您需要将

ASTNode
的定义放入其自己的定义中 文件并
#include
位于
parser.y
lexer.l
中。

例如,创建

astnode.h
:

#ifndef ASTNODE_H
#define ASTNODE_H

// Define NodeType enumeration for AST node types
typedef enum { NODE_VAR, NODE_ICONST, NODE_ADD, NODE_SUB, NODE_MUL, NODE_DIV } NodeType;

// Define the structure for AST nodes
typedef struct ASTNode {
    NodeType type;
    union {
        char *sval; // for variables
        int ival;       // for integer constants
        struct {
            struct ASTNode *left;
            struct ASTNode *right;
        } binary;       // for binary operations
    } data;
} ASTNode;

#endif // ASTNODE_H

然后从

parser.y
中删除这些定义,并将
#include "astnode.h"
添加到顶部附近的两个文件中。
lexer.l
一定要来 在
#include "parser.tab.h"
之前,因为后一个标头需要
ASTNode
定义。

© www.soinside.com 2019 - 2024. All rights reserved.