编译问题

时间:2015-02-25 04:53:34

标签: c bison

所以我必须为Tiny C语言创建一个编译器,但是我无法编译它,我有.y和.l文件并且都可以正常工作,但是当我尝试编译.tab.c文件时,

显示3个错误
  • 对'install_id'的未定义引用
  • 对printSymtab'
  • 的未定义引用
  • 未定义对'lookup_id'的引用

以下是代码:

Symtab.h

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

typedef struct symtab_node * SYMTAB;

typedef struct symtab_node {
    char * nombre;
    int type;
    float fval;
    SYMTAB next;
} SYMTAB_NODE;

SYMTAB lookup_id(SYMTAB st, char * name);

SYMTAB install_id(SYMTAB st, char * name, int typ);

void printSymtab(SYMTAB t);

Symtab.c

#include "symtab.h"
#include <stdio.h>
int next_num() {
    static int i = 1;
    return i++;
}
/* looks up an is in ST. Returns pointer to cell if found else NULL */
SYMTAB lookup_id(SYMTAB st, char * name) {
    SYMTAB tmp = st;
    if (tmp == NULL) {/* empty list */
        return NULL;
    } else {
        while (tmp != NULL) {
            if (strcmp(tmp->idname,name) == 0) {
                return tmp; /* found */
            } else {
                tmp = tmp->next; /* go to next cell */
            }
        }
        return NULL; /* not found */
    }
}
/* adds an id to ST if not present */
SYMTAB install_id(SYMTAB st, char * name, int typ) {
    if (lookup_id(st, name) == NULL) {
        SYMTAB nst = (SYMTAB)malloc(sizeof(SYMTAB_NODE));
        nst->idname = (char *) strdup(name);
        nst->idnum = next_num();
        nst->next = st;
        return nst;
    } else {
        return st;
    }
}
/* print out ST */
void printSymtab(SYMTAB t) {
    SYMTAB tmp = t;
    while (tmp != NULL) {
        printf("%s\t%d\n", tmp->idname, tmp->idnum);
        tmp = tmp->next;
    }
}

grammar.y

    %{

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

char * concat (char * str1, char * str2);

extern int yylex();
extern char * yytext;
extern int yylineno;

SYMTAB st;

int typev;

  /* Function definitions */

    void yyerror (char *string);

    %}

    %union{ 
        char *strval; 
        int value;
        float fvalue; 
        SYMTAB st;
   }

/* Declaramos todos los tokens que recibirá el programa y que provienen del   cparser.l */
%token SEMI INTEGER FLOAT 
%token IF THEN ELSE WHILE DO
%token READ WRITE
%token LPAREN RPAREN LBRACE RBRACE
%token LT EQ 
%token PLUS MINUS TIMES DIV ASSIGN
%token<value> INT_NUM
%token<fvalue> FLOAT_NUM
%token<strval> ID

%%

/* Definimos las reglas de producción para el mini-lenguaje C */
 program: var_dec stmt_seq       { printf ("No hay errores sintacticos\n");}
    ;

var_dec: var_dec single_dec    
    |                           
    ;

single_dec: type ID SEMI   { st = install_id(st,$2,typev); printSymtab(st);   }
    ;

type: INTEGER          { typev = 1; }             
    | FLOAT            { typev = 2; }                             
    ;

stmt_seq: stmt_seq stmt         
    |                          
    ;

stmt: IF exp THEN else          
    | WHILE exp DO stmt
    | variable ASSIGN exp SEMI         { /*st = install_id(st,$1); */}
    | READ LPAREN variable RPAREN SEMI { /*st = install_id(st,$3); */}
    | WRITE LPAREN exp RPAREN SEMI 
    | block 
    | error SEMI       { yyerrok;}
    ;

else: stmt
    | ELSE stmt
    ;

block: LBRACE stmt_seq RBRACE
    ;

exp: simple_exp LT simple_exp
    | simple_exp EQ simple_exp 
    | simple_exp            
    ;

simple_exp: simple_exp PLUS term    
    | simple_exp MINUS term       
    | term 
    ;

term: term TIMES factor
    | term DIV factor
    | factor 
    ;

factor: LPAREN exp RPAREN 
    | INT_NUM    
    | FLOAT_NUM 
    | variable 
    ;

variable: ID   
    {  if(lookup_id(st,$1) == NULL){
             yyerror(concat("Error: Undeclared Identifier ", $1)); 
        }
    }
    ;
%%

/* A function that concatenates two strings and returns the result */
char * concat(char * str1, char * str2){
    char *str3; 
    str3 = (char *) calloc(strlen(str1)+strlen(str2)+1, sizeof(char));
    strcpy(str3,str1);
    strcat(str3,str2);
    return str3;
}

#include "lex.yy.c"

/* Bison does NOT implement yyerror, so define it here */
void yyerror (char *string){
  printf ("ERROR NEAR LINE %d: %s\n",yylineno,string);
}

/* Bison does NOT define the main entry point so define it here */
main (){
  yyparse();
  yylex();
}

lexem.y

%{
    #include <string.h>
    #include <stdlib.h>

    char * strval;
    int value;
    float fvalue;
    int error;

    extern YYSTYPE yylval;
%}

  /* This is the rule definition */
%option noyywrap
%option yylineno

ids          [A-Za-z_][A-Za-z0-9_]*
digits       0|[1-9][0-9]*|0(c|C)[0-7]+|0(x|X)[0-9A-Fa-f]+
floats       [0-9]*"."[0-9]+([eE][-+]?[0-9]+)?

%%

  /* Consume los comentarios*/
(\/\*([^\*]|\*[^/])*\*\/)|(\/\/.*)

  /* Consume los espacios, tabulaciones y saltos de linea*/
[[:space:]]|[[:blank:]]|\n

  /* Palabras reservadas */
"int"     { return INTEGER; }
"float"   { return FLOAT; }
"if"      { return IF; }
"then"    { return THEN; }
"else"    { return ELSE; }
"do"      { return DO; }
"while"   { return WHILE; }
"read"    { return READ; }
"write"   { return WRITE; }

  /* Simbolos de puntuacion, operadores y relacionales */
  /* Puntuacion */
";" { return SEMI; }
"(" { return LPAREN; }
")" { return RPAREN; }
"{" { return LBRACE; }
"}" { return RBRACE; }

  /* Relacionales */
">"  { return LT; }
"==" { return EQ; }

  /* Operadores */
"+" { return PLUS; }
"-" { return MINUS; }
"*" { return TIMES; }
"/" { return DIV; }
"=" { return ASSIGN; }

{ids} { yylval.strval = (char *) strdup(yytext);
        return (ID); }

{digits} { yylval.value = atoi(yytext);
         return (INT_NUM); }

{floats} { yylval.fvalue = atof(yytext);
         return (FLOAT_NUM); }

  /* Consume los simbolos que sobran y marca error */
. { printf("LEXICAL ERROR NEAR LINE %d:  %s \n", yyget_lineno(),     yyget_text()); error++; }

%%

1 个答案:

答案 0 :(得分:1)

你不应该编译whatever.tab.h文件,那个包含语法的YACC元素的标题文件,用于包含进入lexyacc代码部分,以及您自己的代码,如果您需要访问它。

您应该编译whatever.tab.c,确保您还包括您的symtab.c(或其等效的目标文件)以及任何其他C源文件。< / p>

根据您的评论,这不包含symtab.c文件,这确实会导致您的即时错误。

当我执行你的步骤时(略微修改了不同的名字):

flex lexem.l
yacc -d -v grammar.y
gcc -o par y.tab.c

然后我遇到了类似的问题:

/tmp/ccI5DpZQ.o:y.tab.c:(.text+0x35c): undefined reference to `install_id'
/tmp/ccI5DpZQ.o:y.tab.c:(.text+0x36e): undefined reference to `printSymtab'
/tmp/ccI5DpZQ.o:y.tab.c:(.text+0x3a7): undefined reference to `lookup_id'

但是,当我将symtab.c文件合并到编译行中时(并将idnameidnum个缺失位添加到symtab.h中的结构以解决编译问题) ,它的工作正常:

gcc -o par y.tab.c symtab.c