当我似乎包含正确的 header 时,找不到符号错误

Symbols not found error when I appear to be including proper header

我希望这没有得到回答,很难阅读类似的问题,因为它们似乎都是关于 iOS 在 Xcode 中的发展。我正在编写一个解析器,需要在我的语法 (.y) 和词法分析器 (.l) 文件中包含一个 header。最初只包含 header 而未定义函数会产生重复符号错误。我阅读了一些关于 C++ 的内容,并尝试制作一个 header 文件和一个 cpp 文件。现在我得到 symbol(s) not found error。我想我只需要比我更了解 C++ 的人的帮助。此外,我正在慢慢地将此代码从 C 转换为 C++,因此现在有一些 non-C++ 做事的方法。

准确的错误是:

Undefined symbols for architecture x86_64:
  "symlook(char*)", referenced from:
      yylex() in lex.yy.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [outfile] Error 1

symtab.h

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define NSYMS 20

struct symtab
{
    char *name;
    // ptr to C function to call if this entry is a fucntion name
    double (*funcptr)();
    double value;
};

extern symtab table[];

struct symtab *symlook(char *s);
void addfunc(char *name, double (*func)());

symtab.cpp

#include "symtab.h"

symtab table[NSYMS];

struct symtab *symlook(char *s) {
    char *p;
    struct symtab *sp;

    for(sp = table; sp < &table[NSYMS]; sp++) {
        /* is it already here? */
        if(sp->name && !strcmp(sp->name, s))
            return sp;
        if(!sp->name) { /* is it free */
            sp->name = strdup(s);
            return sp; 
        }
        /* otherwise continue to next */
    }
    fprintf(stderr, "%s\n", "Too many symbols");
    exit(1);    /* cannot continue */
} /* symlook */

void addfunc(char *name, double (*func)())
{
    struct symtab *sp = symlook(name);
    sp->funcptr = func;
}

simple.l

%{
#include "y.tab.h"
#include <math.h>
#include "symtab.h"
%}

%%

"if"    return IF;

"true"  return TRUE;
"false" return FALSE;

([0-9]+|([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?) {
        yylval.dval = atof(yytext); 
        return NUMBER; 
}

[ \t] ;  /* ignore whitespace */
[A-Za-z][A-Za-z0-9]*   { 
        yylval.symp = symlook(yytext);
        return NAME; 
}

"$"     return 0; /* logical EOF */

\n      |
.       return yytext[0];
%%

simple.y

%{
    #include "symtab.h"
    #include "ast.h"
    #include <string>
    #include <stdio.h>
    int yylex(void);
    void yyerror(char *);
%}

%union {
    double dval;
    int ival;
    struct symtab *symp;
}

%token <symp> NAME
%token <ival> INTEGER_LITERAL
%token <dval> NUMBER
%token IF TRUE FALSE WHILE
%left '-' '+'
%left '*' '/'
%nonassoc UMINUS

%type <dval> num_expression
%%

statement_list: statement '\n'
    |   statement_list statement '\n'
    ;

statement:  NAME '=' num_expression  { ->value = ; }
    |       num_expression           { fprintf(stderr, "= %g\n", ); }
    |       if_expression
    |       bool_expression
    |       while_expression
    ;

num_expression: num_expression '+' num_expression   { $$ =  + ; }
    |       num_expression '-' num_expression       { $$ =  - ; }
    |       num_expression '*' num_expression       { $$ =  * ; }
    |       num_expression '/' num_expression   
                { 
                    if( == 0.0)
                        yyerror("divide by zero");
                    else
                        $$ =  / ;
                }
    |       '-' num_expression %prec UMINUS { $$ = -; }
    |       '(' num_expression ')'          { $$ = ; }
    |       NUMBER                      
    |       NAME                            { $$ = ->value; }
    |       NAME '(' num_expression ')'     { } //$$ = (->funcptr()); }
    ;
bool_expression: FALSE
    |            TRUE
    ;

if_expression:   IF '('  bool_expression ')' '{' statement '}'
    |            IF '(' ')' '{' '}'
    ;

while_expression: WHILE '('  bool_expression ')' '{' statement '}'
    |             WHILE '(' ')' '{' '}'
    ;

%% 

void yyerror(char *str)
{
    fprintf(stderr, "Error %s", str);
}


int main() {
    yyparse();
    return 0;
}

生成文件

CC=g++
outfile=simple
lexfile=simple
yaccfile=simple

outfile: compile
    ${CC} -o ${outfile}.out lex.yy.o y.tab.o -ll

compile: build
    ${CC} -c symtab.cpp
    ${CC} -c lex.yy.c y.tab.c -ll


build:
    yacc -d ${yaccfile}.y
    flex ${lexfile}.l

您的 compile: build 步骤生成了一个文件 symtab.o,您没有将其包含在 link 行中。

这是一个很常见的错误。问题出在这里:

#include "y.tab.h"
#include <math.h>
#include "symtab.h"
  1. 在您的 Makefile 中,您需要首先执行 yacc's 命令,因为 yacc 正在生成您的 "y.tab.h" 文件。
  2. 你需要#include "y.tab.h"在所有其他包括之后!想想这个! y.tab.h 将包含 "symtab.h" 中的内容,但 Lex 不知道那是什么,因为您在 "y.tab.h".
  3. 之后包含了 "symtab.h"

所以记住: 你总是必须在所有其他包含之后包含 "y.tab.h" 以避免这个错误!