yylval 未定义与 lex 和 yacc
yylval undefined with lex and yacc
我正在尝试一个使用 lex 和 yacc 创建抽象语法树的简单程序。
我的yacc_file.y是
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node
{
struct node *left;
struct node *right;
char *token;
} node;
node *mknode(node *left, node *right, char *token);
void printtree(node *tree);
#define YYSTYPE struct node *
%}
%start lines
%token NUMBER
%token PLUS MINUS TIMES
%token LEFT_PARENTHESIS RIGHT_PARENTHESIS
%token END
%left PLUS MINUS
%left TIMES
%%
lines: /* empty */
| lines line /* do nothing */
line: exp END { printtree(); printf("\n");}
;
exp : term {$$ = ;}
| exp PLUS term {$$ = mknode(, , "+");}
| exp MINUS term {$$ = mknode(, , "-");}
;
term : factor {$$ = ;}
| term TIMES factor {$$ = mknode(, , "*");}
;
factor : NUMBER {$$ = mknode(0,0,(char *)yylval);}
| LEFT_PARENTHESIS exp RIGHT_PARENTHESIS {$$ = ;}
;
%%
int main (void) {return yyparse ( );}
node *mknode(node *left, node *right, char *token)
{
/* malloc the node */
node *newnode = (node *)malloc(sizeof(node));
char *newstr = (char *)malloc(strlen(token)+1);
strcpy(newstr, token);
newnode->left = left;
newnode->right = right;
newnode->token = newstr;
return(newnode);
}
void printtree(node *tree)
{
int i;
if (tree->left || tree->right)
printf("(");
printf(" %s ", tree->token);
if (tree->left)
printtree(tree->left);
if (tree->right)
printtree(tree->right);
if (tree->left || tree->right)
printf(")");
}
int yyerror (char *s) {fprintf (stderr, "%s\n", s);}
我的 lex_file.l 文件是
%{
#include "yacc_file.tab.h"
%}
%%
[0-9]+ {yylval = (int)yytext; return NUMBER;}
/* cast pointer to int for compiler warning */
[ \t\n] ;
"+" return(PLUS);
"-" return(MINUS);
"*" return(TIMES);
"(" return(LEFT_PARENTHESIS);
")" return(RIGHT_PARENTHESIS);
";" return(END);
%%
int yywrap (void) {return 1;}
为了运行,我做了以下
yacc -d yacc_file.y
lex lex_file.y
cc y.tab.c lex.yy.c -o a.exe
我收到以下错误
lexfile.l: In function 'yylex':
lex_file.l:10:2: error: 'yylval' undeclared(first used in this function)
[0-9]+ {yylval=(int)yytext; return NUMBER;}
我在 google 上搜索过,%union 似乎可以解决问题。但是不知道怎么用。
命令
yacc -d yacc_file.y
生成一个名为 y.tab.h
的 header 文件和一个名为 y.tab.c
的 C 文件。这是 yacc-compatible 默认命名,它与您的 flex 文件不一致,它期望 header 被称为 yacc_file.tab.h
.
您可以只更改 flex 文件中的 #include
语句,但这与您大学的构建系统不兼容。所以我建议您更改为命令 bison -d yacc_file.y
而不是 yacc
命令。这将生成一个名为 yacc_file.tab.h
的 header 文件和一个名为 yacc_file.tab.c
的 C 文件。 (当然,您随后必须更改 cc
命令以编译 yacc_file.tab.c
而不是 y.tab.c
。)
您的机器上可能存在一些不正确的 yacc_file.tab.h
,其中不包括 yylval
的声明。因此编译错误。
为了避免进一步混淆,当您修复构建过程时,我建议删除所有中间文件——y.tab.h
和 y.tab.c
以及 yacc_file.tab.c
和 yacc_file.tab.h
,和 lex.yy.c
。然后您就可以进行干净的构建,而不必担心会拾取一些过时的中间文件。
此外,在 yacc_file.y
中,您 #define
YYSTYPE
为 struct node *
。很好,但是 #define
不会被复制到生成的 header 文件中;在 header 文件中,如果在 header 文件 [=14] 之前没有其他 #define
,则 YYSTYPE
将 #define
d 为 int
=]d.
此外,在 lex_file.l
中你使用 yylval
就好像它是一个 int
(yylval = (int)yytext;
) 但我认为该声明并没有按照你的想法去做.它所做的是将 yytext
的 地址 重新解释为整数。那是合法的,但毫无意义。我认为你想要做的是将 yytext
中的字符串转换为整数。为此,您需要使用 strtod
或标准 C 库中的一些类似函数。
无论如何,扫描器和解析器就 yylval
的类型达成一致至关重要。否则,事情会大错特错。
如您所述,可以使用 %union
声明将 YYSTYPE
声明为联合类型。您应该确保您了解 C 联合类型,并阅读 bison manual section on semantics..
我正在尝试一个使用 lex 和 yacc 创建抽象语法树的简单程序。
我的yacc_file.y是
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node
{
struct node *left;
struct node *right;
char *token;
} node;
node *mknode(node *left, node *right, char *token);
void printtree(node *tree);
#define YYSTYPE struct node *
%}
%start lines
%token NUMBER
%token PLUS MINUS TIMES
%token LEFT_PARENTHESIS RIGHT_PARENTHESIS
%token END
%left PLUS MINUS
%left TIMES
%%
lines: /* empty */
| lines line /* do nothing */
line: exp END { printtree(); printf("\n");}
;
exp : term {$$ = ;}
| exp PLUS term {$$ = mknode(, , "+");}
| exp MINUS term {$$ = mknode(, , "-");}
;
term : factor {$$ = ;}
| term TIMES factor {$$ = mknode(, , "*");}
;
factor : NUMBER {$$ = mknode(0,0,(char *)yylval);}
| LEFT_PARENTHESIS exp RIGHT_PARENTHESIS {$$ = ;}
;
%%
int main (void) {return yyparse ( );}
node *mknode(node *left, node *right, char *token)
{
/* malloc the node */
node *newnode = (node *)malloc(sizeof(node));
char *newstr = (char *)malloc(strlen(token)+1);
strcpy(newstr, token);
newnode->left = left;
newnode->right = right;
newnode->token = newstr;
return(newnode);
}
void printtree(node *tree)
{
int i;
if (tree->left || tree->right)
printf("(");
printf(" %s ", tree->token);
if (tree->left)
printtree(tree->left);
if (tree->right)
printtree(tree->right);
if (tree->left || tree->right)
printf(")");
}
int yyerror (char *s) {fprintf (stderr, "%s\n", s);}
我的 lex_file.l 文件是
%{
#include "yacc_file.tab.h"
%}
%%
[0-9]+ {yylval = (int)yytext; return NUMBER;}
/* cast pointer to int for compiler warning */
[ \t\n] ;
"+" return(PLUS);
"-" return(MINUS);
"*" return(TIMES);
"(" return(LEFT_PARENTHESIS);
")" return(RIGHT_PARENTHESIS);
";" return(END);
%%
int yywrap (void) {return 1;}
为了运行,我做了以下
yacc -d yacc_file.y
lex lex_file.y
cc y.tab.c lex.yy.c -o a.exe
我收到以下错误
lexfile.l: In function 'yylex':
lex_file.l:10:2: error: 'yylval' undeclared(first used in this function)
[0-9]+ {yylval=(int)yytext; return NUMBER;}
我在 google 上搜索过,%union 似乎可以解决问题。但是不知道怎么用。
命令
yacc -d yacc_file.y
生成一个名为 y.tab.h
的 header 文件和一个名为 y.tab.c
的 C 文件。这是 yacc-compatible 默认命名,它与您的 flex 文件不一致,它期望 header 被称为 yacc_file.tab.h
.
您可以只更改 flex 文件中的 #include
语句,但这与您大学的构建系统不兼容。所以我建议您更改为命令 bison -d yacc_file.y
而不是 yacc
命令。这将生成一个名为 yacc_file.tab.h
的 header 文件和一个名为 yacc_file.tab.c
的 C 文件。 (当然,您随后必须更改 cc
命令以编译 yacc_file.tab.c
而不是 y.tab.c
。)
您的机器上可能存在一些不正确的 yacc_file.tab.h
,其中不包括 yylval
的声明。因此编译错误。
为了避免进一步混淆,当您修复构建过程时,我建议删除所有中间文件——y.tab.h
和 y.tab.c
以及 yacc_file.tab.c
和 yacc_file.tab.h
,和 lex.yy.c
。然后您就可以进行干净的构建,而不必担心会拾取一些过时的中间文件。
此外,在 yacc_file.y
中,您 #define
YYSTYPE
为 struct node *
。很好,但是 #define
不会被复制到生成的 header 文件中;在 header 文件中,如果在 header 文件 [=14] 之前没有其他 #define
,则 YYSTYPE
将 #define
d 为 int
=]d.
此外,在 lex_file.l
中你使用 yylval
就好像它是一个 int
(yylval = (int)yytext;
) 但我认为该声明并没有按照你的想法去做.它所做的是将 yytext
的 地址 重新解释为整数。那是合法的,但毫无意义。我认为你想要做的是将 yytext
中的字符串转换为整数。为此,您需要使用 strtod
或标准 C 库中的一些类似函数。
无论如何,扫描器和解析器就 yylval
的类型达成一致至关重要。否则,事情会大错特错。
如您所述,可以使用 %union
声明将 YYSTYPE
声明为联合类型。您应该确保您了解 C 联合类型,并阅读 bison manual section on semantics..