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

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

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

  • bison.y
  • 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;
[ \t\v\n\f\r]                     ;
[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();

%%

bison.y:

%{
#include <string>
#include <cstring>
#include <cstdio>
extern FILE *yyin;
extern int yylex();
void yyerror(const char *s) { printf("yyerror: %s\n", 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: %s\n", 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`

我是否必须在具有以下代码的主要功能之前定义yyinyylex

extern FILE *yyin;
extern int yylex(void);
c++ bison flex-lexer yacc lex
1个回答
1
投票

即使将引用的代码添加到输出文件中,您仍然会抱怨未定义的yylexyyin。您的代码仅declares这些东西,而没有define它们。 yaccbison都没有为您定义这些功能,您必须自己提供这些功能(例如,可以使用lexflex生成它们)。看一下bison文档。 RPN示例包含yylex函数的简短示例。

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