2016-01-28 3 views
1

Надеюсь, на это не ответил, трудно прочитать похожие вопросы, потому что все они, похоже, касаются разработки iOS в Xcode. Я пишу парсер и нуждаюсь в заголовке, включенном как в мою грамматику (.y), так и в мои файлы lexer (.l). Первоначально, просто включив заголовок и не определяя функции, получилась дублируемая символьная ошибка. Я немного почитал на C++ и попытался создать файл заголовка и файл cpp. Теперь я получаю symbol(s) not found error. Я думаю, мне просто нужна помощь от кого-то, кто знает C++ лучше меня. Также я медленно конвертирую этот код из C в C++, поэтому есть некоторые не-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 { $1->value = $3; } 
    |  num_expression   { fprintf(stderr, "= %g\n", $1); } 
    |  if_expression 
    |  bool_expression 
    |  while_expression 
    ; 

num_expression: num_expression '+' num_expression { $$ = $1 + $3; } 
    |  num_expression '-' num_expression  { $$ = $1 - $3; } 
    |  num_expression '*' num_expression  { $$ = $1 * $3; } 
    |  num_expression '/' num_expression 
       { 
        if($3 == 0.0) 
         yyerror("divide by zero"); 
        else 
         $$ = $1/$3; 
       } 
    |  '-' num_expression %prec UMINUS { $$ = -$2; } 
    |  '(' num_expression ')'   { $$ = $2; } 
    |  NUMBER      
    |  NAME       { $$ = $1->value; } 
    |  NAME '(' num_expression ')'  { } //$$ = ($1->funcptr($3)); } 
    ; 
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; 
} 

Makefile

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 
+0

не определено *! = Un * указанный *. – immibis

+0

при компиляции любые параметры библиотек '-ll' игнорируются (и их вообще не должно быть) – user3629249

+0

при написании шагов компиляции (эти вызовы $ (CC) с параметром' -c', если вы включили ' -o outputname', тогда было бы очевидно, что в корне проблемы. В общем случае лучше всего попытаться скомпилировать один файл при вызове $ (CC) с параметром '-c'.' ' build', compile' не создают файл с тем же именем, поэтому в начале make-файла должен быть оператор:. .PHONY: build compile' – user3629249

ответ

2

Ваш compile: build шаг создает файл symtab.o, что вы не в том числе по линии связи.

+1

Спасибо, что это сработало, я знал, что это будет что-то простое, но вся документация, которую я нашел, была очень длинной или загадочной. –

0

Это очень распространенная ошибка. Проблема заключается здесь:

#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 не знает, что с того момента, как вы включили "symtab.h" после "y.tab.h".

Так что помните:Вы всегда должны включать"y.tab.h" после всех остальных включает в себя, чтобы избежать этой ошибки!

+0

Разве это не приведет к сбою компиляции, а не к этапу связывания? – Steve

 Смежные вопросы

  • Нет связанных вопросов^_^