我正在开发一个项目,其中使用 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]
错误信息的原因是生成的
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
定义。