использовать необъявленные идентификаторы `yylex` и` yyin`? - PullRequest
0 голосов
/ 08 января 2020

Вот мой простой исходный код проекта:

  • 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`

Нужно ли определять yyin и yylex перед основной функцией с кодом ниже?

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

1 Ответ

1 голос
/ 08 января 2020

Даже если цитируемый код будет добавлен в выходной файл, вы все равно получите жалобы на неопределенные yylex и yyin. Ваш код только объявляет эти вещи, но не определяет их. Ни yacc, ни bison не определяют их для вас, вы должны сами предоставить эти функции (например, вы можете использовать lex или flex для их генерации). Посмотрите документацию 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.

Это не включает в себя то, что вы указали в прологе, в частности, не объявление yyin и yylex. Если вам нужны эти объявления в нескольких файлах, вы можете объявить их в отдельном заголовочном файле и включить этот заголовочный файл из bison.y и все другие файлы, для которых требуется это объявление (например, flex_bison.cpp).

...