使用未声明的标识符"yylex"和"yyin"?

use of undeclared identifier `yylex` and `yyin`?

本文关键字:quot yyin yylex 标识符 未声明      更新时间:2023-10-16

这是我的简单项目源代码:

  • 野牛
  • flex.l
  • flex_bison.cpp

flex.l:

%option noyywrap
%{
#include <string>
#include <cstring>
#include "bison.tab.hpp"
#define FT_SAVE_TOKEN yylval.literal = strndup(yytext, yyleng)
#define FT_TOKEN(t) (yylval.token = t)
%}
%%
"True"                            return FT_TRUE;
"False"                           return FT_FALSE;
"let"                             return FT_LET;
"Nil"                             return FT_NIL;
"if"                              return FT_IF;
"elseif"                          return FT_ELSEIF;
"else"                            return FT_ELSE;
"switch"                          return FT_SWITCH;
"case"                            return FT_CASE;
"otherwise"                       return FT_OTHERWISE;
"for"                             return FT_FOR;
"while"                           return FT_WHILE;
"break"                           return FT_BREAK;
"continue"                        return FT_CONTINUE;
"func"                            return FT_FUNC;
"class"                           return FT_CLASS;
"type"                            return FT_TYPE;
"isinstance"                      return FT_ISINSTANCE;
"import"                          return FT_IMPORT;
"return"                          return FT_RETURN;
"void"                            return FT_VOID;
"and"                             return FT_LOGICALAND;
"or"                              return FT_LOGICALOR;
"not"                             return FT_LOGICALNOT;
"int"                             return FT_INTEGER_KEYWORD;
"uint"                            return FT_UNSIGNED_INTEGER_KEYWORD;
"double"                          return FT_DOUBLE_KEYWORD;
[ tvnfr]                     ;
[a-zA-Z_][a-zA-Z0-9_]*            FT_SAVE_TOKEN; return FT_IDENTIFIER;
[0-9]+"."[0-9]+([Ee][+-]?[0-9]+)? FT_SAVE_TOKEN; return FT_DOUBLE;
[0-9]+([Ee][+-]?[0-9]+)?          FT_SAVE_TOKEN; return FT_INTEGER;
"(\.|[^\"])*"                 FT_SAVE_TOKEN; return FT_STRING;
"+"                               return FT_TOKEN(FT_ADD);
"-"                               return FT_TOKEN(FT_SUB);
"*"                               return FT_TOKEN(FT_MUL);
"/"                               return FT_TOKEN(FT_DIV);
"%"                               return FT_TOKEN(FT_MOD);
"!"                               return FT_TOKEN(FT_BITNOT);
"&"                               return FT_TOKEN(FT_BITAND);
"|"                               return FT_TOKEN(FT_BITOR);
"~"                               return FT_TOKEN(FT_BITCOMPLEMENT);
"^"                               return FT_TOKEN(FT_BITXOR);
"="                               return FT_TOKEN(FT_ASSIGN);
"+="                              return FT_TOKEN(FT_ADDASSIGN);
"-="                              return FT_TOKEN(FT_SUBASSIGN);
"*="                              return FT_TOKEN(FT_MULASSIGN);
"/="                              return FT_TOKEN(FT_DIVASSIGN);
"%="                              return FT_TOKEN(FT_MODASSIGN);
"=="                              return FT_TOKEN(FT_EQ);
"!="                              return FT_TOKEN(FT_NEQ);
"<"                               return FT_TOKEN(FT_LT);
"<="                              return FT_TOKEN(FT_LE);
">"                               return FT_TOKEN(FT_GT);
">="                              return FT_TOKEN(FT_GE);
"("                               return FT_TOKEN(FT_LPAREN);
")"                               return FT_TOKEN(FT_RPAREN);
"["                               return FT_TOKEN(FT_LBRACKET);
"]"                               return FT_TOKEN(FT_RBRACKET);
"{"                               return FT_TOKEN(FT_LBRACE);
"}"                               return FT_TOKEN(FT_RBRACE);
","                               return FT_TOKEN(FT_COMMA);
";"                               return FT_TOKEN(FT_SEMI);
"?"                               return FT_TOKEN(FT_QUESTION);
":"                               return FT_TOKEN(FT_COLON);
"."                               return FT_TOKEN(FT_DOT);
.                                 printf("Unknown token!n"); yyterminate();
%%

野牛:

%{
#include <string>
#include <cstring>
#include <cstdio>
extern FILE *yyin;
extern int yylex();
void yyerror(const char *s) { printf("yyerror: %sn", s); }
%}
/* Represents the many different ways we can access our data */
%union {
char *literal;
int token;
}
/* union.token: eof, keyword */
%token <token> FT_EOF
%token <token> FT_TRUE FT_FALSE FT_LET FT_NIL FT_IF FT_ELSEIF FT_ELSE FT_FOR FT_WHILE FT_BREAK FT_CONTINUE FT_SWITCH FT_CASE FT_OTHERWISE
%token <token> FT_FUNC FT_CLASS FT_TYPE FT_ISINSTANCE FT_IMPORT FT_RETURN FT_VOID FT_LOGICALAND FT_LOGICALOR FT_LOGICALNOT
%token <token> FT_INTEGER_KEYWORD FT_UNSIGNED_INTEGER_KEYWORD FT_DOUBLE_KEYWORD
/* union.literal, identifier, integer, double number, string */
%token <literal> FT_IDENTIFIER FT_INTEGER FT_DOUBLE FT_STRING
/* union.token: operator, comparator, punctuation */
%token <token> FT_ADD FT_SUB FT_MUL FT_DIV FT_MOD FT_BITNOT FT_BITAND FT_BITOR FT_BITCOMPLEMENT FT_BITXOR
%token <token> FT_ASSIGN FT_ADDASSIGN FT_SUBASSIGN FT_MULASSIGN FT_DIVASSIGN FT_MODASSIGN FT_EQ FT_NEQ FT_LT FT_LE FT_GT FT_GE
%token <token> FT_LPAREN FT_RPAREN FT_LBRACKET FT_RBRACKET FT_LBRACE FT_RBRACE FT_COMMA FT_SEMI FT_QUESTION FT_COLON FT_DOT
/*
%type <ident> ident
%type <expr> numeric expr
%type <varvec> func_decl_args
%type <exprvec> call_args
%type <block> program stmts block
%type <stmt> stmt var_decl func_decl
%type <token> comparison
*/
/* operator/comparator precedence */
%left FT_DOT FT_LPAREN FT_RPAREN FT_LBRACKET FT_RBRACKET
%left FT_MUL FT_DIV FT_MOD
%left FT_ADD FT_SUB
%left FT_LT FT_LE FT_GT FT_GE FT_EQ FT_NEQ
%left FT_BITNOT FT_BITAND FT_BITOR FT_BITXOR FT_BITCOMPLEMENT
%left FT_LOGICALNOT FT_LOGICALAND FT_LOGICALOR
%left FT_ASSIGN FT_ADDASSIGN FT_SUBASSIGN FT_MULASSIGN FT_DIVASSIGN FT_MODASSIGN
/*
%start program
*/
%%
primary_expression : FT_IDENTIFIER
| FT_INTEGER
| FT_DOUBLE
| FT_STRING
| '(' expression ')'
;
postfix_expression : primary_expression
/*| postfix_expression '[' expression ']'*/
| postfix_expression '(' ')'
| postfix_expression '(' argument_expression_list ')'
/*| postfix_expression '.' IDENTIFIER*/
;
argument_expression_list : assignment_expression
| argument_expression_list ',' assignment_expression
;
unary_expression : postfix_expression
| unary_operator postfix_expression
;
unary_operator : FT_BITAND
| FT_BITOR
| FT_BITNOT
| FT_BITCOMPLEMENT
| FT_BITXOR
| FT_ADD
| FT_SUB
;
/*
cast_expression : unary_expression
| '(' type_name ')' cast_expression
;
*/
multiplicative_expression : unary_expression
| multiplicative_expression FT_MUL unary_expression
| multiplicative_expression FT_DIV unary_expression
| multiplicative_expression FT_MOD unary_expression
;
additive_expression : multiplicative_expression
| additive_expression FT_ADD multiplicative_expression
| additive_expression FT_SUB multiplicative_expression
;
/*
shift_expression : additive_expression
| shift_expression '<<' additive_expression
| shift_expression '>>' additive_expression
;
*/
relational_expression : additive_expression
| relational_expression FT_LT additive_expression
| relational_expression FT_LE additive_expression
| relational_expression FT_GT additive_expression
| relational_expression FT_GE additive_expression
;
equality_expression : relational_expression
| equality_expression FT_EQ relational_expression
| equality_expression FT_NEQ relational_expression
;
/*
bit_and_expression : equality_expression
| bitand_expression '&' equality_expression
;
bit_xor_expression : bit_and_expression
| bit_xor_expression '^' bit_and_expression
;
bit_or_expression : bit_xor_expression
| bit_or_expression '|' bit_xor_expression
;
*/
logical_not_expression : equality_expression
| logical_not_expression FT_LOGICALNOT equality_expression
;
logical_and_expression : logical_not_expression
| logical_and_expression FT_LOGICALAND logical_not_expression
;
logical_or_expression : logical_and_expression
| logical_or_expression FT_LOGICALOR logical_and_expression
;
assignment_expression : logical_or_expression
| unary_expression assignment_operator assignment_expression
;
assignment_operator : FT_ASSIGN
| FT_MULASSIGN
| FT_DIVASSIGN
| FT_MODASSIGN
| FT_ADDASSIGN
| FT_SUBASSIGN
;
constant_expression : logical_or_expression
;
expression : assignment_expression
;
unit : external_declaration
| unit external_declaration
;
external_declaration : function_declaration
| declaration
;
declaration : FT_LET declaration_init_list FT_SEMI
;
declaration_init_list : declaration_init
| declaration_init_list declaration_init
;
declaration_init : FT_IDENTIFIER FT_ASSIGN constant_expression
;
function_declaration : FT_FUNC FT_IDENTIFIER FT_LPAREN function_arg_list FT_RPAREN compound_statement
| FT_FUNC FT_IDENTIFIER FT_LPAREN FT_RPAREN compound_statement
;
function_arg_list : function_arg
| function_arg_list FT_COMMA function_arg
;
function_arg : FT_IDENTIFIER
;
compound_statement : FT_LBRACE FT_RBRACE
| FT_LBRACE statement_list FT_RBRACE
| FT_LBRACE declaration_list FT_RBRACE
;
statement_list : statement
| statement_list statement
;
declaration_list : declaration
| declaration_list declaration
;
statement : compound_statement
| expression_statement
| selection_statement
| iteration_statement
| jump_statement
;
expression_statement : FT_SEMI
| expression FT_SEMI
;
selection_statement : FT_IF FT_LPAREN expression FT_RPAREN statement
| FT_IF FT_LPAREN expression FT_RPAREN statement FT_ELSE statement
| FT_SWITCH FT_LPAREN expression FT_RPAREN statement
;
iteration_statement : FT_WHILE FT_LPAREN expression FT_RPAREN statement
| FT_FOR FT_LPAREN expression_statement expression_statement FT_RPAREN statement
| FT_FOR FT_LPAREN expression_statement expression_statement expression FT_RPAREN statement
;
jump_statement : FT_CONTINUE FT_SEMI
| FT_BREAK FT_SEMI
| FT_RETURN FT_SEMI
| FT_RETURN expression FT_SEMI
;
%%

flex_bison.cpp:

#include "bison.tab.hpp"
#include <cstdio>
int main(int argc, char **argv) {
if (argc <= 1) {
printf("error! filename missing!n");
return 0;
}
FILE *fp = fopen(argv[1], "r");
yyin = fp;
int t;
while ((t = yylex()) != 0) {
printf("token: %d", t);
if (t == FT_IDENTIFIER || t == FT_INTEGER || t == FT_DOUBLE ||
t == FT_STRING) {
printf("literal: %sn", yylval.literal);
} else {
printf("n");
}
}
fclose(fp);
return 0;
}

通过命令生成代码:

$ flex -o flex.yy.cpp flex.l
$ bison -d -o bison.tab.hpp bison.y
$ g++ -o test.exe bison.tab.cpp flex.yy.cpp flex_bison.cpp

下面是错误消息:

use of undeclared identifier 'yyin'
use of undeclared identifier 'yylex`

我是否必须在 main 函数之前用下面的代码定义yyinyylex

extern FILE *yyin;
extern int yylex(void);

即使引用的代码被添加到输出文件中,您仍然会收到有关未定义yylexyyin的投诉。你的代码只声明这些东西,它不定义它们。yaccbison都不能为您定义这些函数,您必须自己提供这些功能(例如,您可以使用lexflex来生成它们(。查看bison文档。RPN 示例有一个简短的yylex函数示例。

编辑问题后编辑:根据野牛的文档,从-d选项生成的标题

Pretend that ‘%defines’ was specified, i.e., write an extra output
file containing macro definitions for the token type names defined
in the grammar, as well as a few other declarations.

不包括您在序言中指定的内容,特别是不包括yyinyylex的声明。如果需要在多个文件中声明这些声明,则可能需要在单独的头文件中声明它们,并包含来自bison.y的头文件以及需要该声明的所有其他文件(如flex_bison.cpp(。