Hello,

I'm using bison for the first time. After composing a grammar
the generated C file compiles but linking fails because of:

parser.tab.c:2778: undefined reference to `yyerror'
parser.tab.c:2920: undefined reference to `yyerror'

So what can I do to get the missing function?
Is a library to be linked? (The man-pages do not mention one,
and I do not see one in the common "lib" directories.)
Also the scanner (not in the attachment) does not provide one.

I'm using version "bison (GNU Bison) 2.5" downloaded and
installed a few days ago on Linux Ubuntu; bison command was:

bison --defines parser.y


Best regards
Wolfgang

PS:
The attachment contains the .y file in question and some related files.
C compilation is done by a command like
gcc -g -c parser.tab.c `pkg-config --libs --cflags gtk+-2.0`

--
Dr. Wolfgang Jansen
Lauenburger Straße 40
12169 Berlin
Germany
Tel: +49 - 0172-4086916
mailto: [email protected]

#include "expr.h"
#include <stdlib.h>

static GE_EXPRESSION **expr_list;
static uint32_t expr_cap = 0;
static uint32_t expr_count = 0;
static GE_EXPRESSION expr0 = {""};

GE_EXPRESSION *GE_new_expression() {
  GE_EXPRESSION *expr;
  if (expr_count==expr_cap) {
    uint32_t n = expr_count ? 2*expr_count : 100;
    expr_list = (GE_EXPRESSION**)realloc(expr_list, n*sizeof(GE_EXPRESSION *));
    expr_cap = n;
    for (; n-->expr_count;) 
      expr_list[n] = (GE_EXPRESSION*)malloc(sizeof(GE_EXPRESSION));
  }
  expr = expr_list[expr_count];
  ++expr_count;
  *expr = expr0;
  return expr;
}

void GE_push_back(GE_EXPRESSION **expr) {
  GE_EXPRESSION *ex = *expr;
  if (ex) {
    GE_push_back(&ex->details);
    GE_push_back(&ex->arg);
    GE_push_back(&ex->next);
    GE_push_back(&ex->down);
    --expr_count;
    expr_list[expr_count] = ex;
    *expr = NULL;
  }
}

GE_EXPRESSION *expr_bottom(GE_EXPRESSION* expr) {
  GE_EXPRESSION *ex = 0;
  for (; expr; expr=expr->down)  ex = expr;
  return ex;
}

GE_EXPRESSION *expr_last(GE_EXPRESSION* expr) {
  GE_EXPRESSION *ex = 0;
  for (; expr; expr=expr->next)  ex = expr;
  return ex;
}

#ifndef _GE_EXPR_
#define _GE_EXPR_

#include <inttypes.h>

typedef struct GE_EXPRESSION_ GE_EXPRESSION;
struct GE_EXPRESSION_ {
  char *name;
  const char *type;
  GE_EXPRESSION *next;
  GE_EXPRESSION *down;
  GE_EXPRESSION *arg;
  GE_EXPRESSION *details;
  GE_EXPRESSION *parent;
  uint8_t is_range;
  uint8_t kind;
  uint16_t up_frame_count;
  int32_t column;
};

typedef enum {
  is_count = 1,
  is_all,
  is_if,
  is_bracket,
  is_details,
  is_placeholder,
  is_equality,
  is_character,
  is_integer,
  is_real,
  is_string,
} KindOfExpression;

enum {
  plus_op = 1,
  minus_op,
  mult_op,
  div_op,
  idiv_op,
  imod_op,
  power_op,
  not_op,
  and_op,
  or_op,
  xor_op,
  implies_op,
  interval_op,
  eq_op,
  ne_op,
  le_op,
  lt_op,
  ge_op,
  gt_op,
  sim_op,
  nsim_op,
} OpearationSymbol;

extern GE_EXPRESSION *GE_new_expression();
extern void GE_push_back(GE_EXPRESSION **ex);

extern GE_EXPRESSION *expr_bottom(GE_EXPRESSION *expr);
extern GE_EXPRESSION *expr_last(GE_EXPRESSION *expr);

#endif
%{ 
#include <gtk/gtk.h>
#include <string.h>
#include "expr.h"

static gint op_column = 0;
static gint yycolumn = 0; /* !! to be taken from scanner */

static GE_EXPRESSION *ph = NULL;
static GList *placeholders = NULL;

static compose_prefix(GE_EXPRESSION *arg, guint op);
static compose_infix(GE_EXPRESSION *left, GE_EXPRESSION *right,
                                                                                
 guint op, guint prec, gint kind);
static compose_free(GE_EXPRESSION *left, GE_EXPRESSION *right, gchar *op);
static GE_EXPRESSION* as_alias(const gchar *str);
static GE_EXPRESSION* int_to_closure(gint i);

static void message(const gchar *msg, gint col);
static gchar *No_expression = "No expression.";

#define is_character 2
#define is_integer 7
#define is_real 13
#define is_string 17

%} 

%union {
gchar c;
gint i;
guint n;
gdouble d; 
gchar *s;
GList *l;
GE_EXPRESSION *x;
};

%token GE_COMMENT 
%token GE_LBB "[[" 
%token GE_LCC "{{" 
%token GE_RCC "}}" 
%token GE_PP "++" 
%token E_WHEN E_CHECK E_UNTIL E_CLASS E_IF E_LOOP E_DO E_FROM
%token E_ALL E_DEBUG E_ONCE E_CREATE E_OLD GE_ASSIGN E_LIKE
%token E_SYMBOL E_ONCE_STRING E_STRFREEOP E_COMMENT E_BREAK E_KEYWORD
%token <s> GE_INLINE GE_ALIAS GE_CLOSURE GE_PLACEHOLDER 
%token <s> GE_ARROW 
%token <i> GE_UP_FRAME 
%token <c> E_CHARACTER 
%token <i> E_INTEGER 
%token <d> E_REAL 
%token <s> E_IDENTIFIER E_STRING 
%token <s> '=' E_NE E_NOT_TILDE E_GE '>' E_LE '<' 
%token <s> '^'  E_MOD '*' '/' E_DIV E_FREEOP '+' '-' E_DOTDOT 
%token E_CHARERR E_INTERR E_REALERR E_STRERR 
 
%left E_IMPLIES 
%left E_OR E_XOR 
%left E_AND 
%left '=' E_NE '<' '>' E_LE E_GE '~' E_NOT_TILDE 
%left '+' '-' 
%left '*' '/' E_DIV E_MOD 
%right '^' 
%left E_DOTDOT 
%left E_FREEOP 
%left E_NOT 
 
%type <x> multi_dot left query alias_name qualified 
%type <x> args indices 
%type <x> brackets 
%type <x> single range open_indices detailed open_detail 
%type <x> multi multi_or_all 
%type <x> closure_id 
%type <s> ident
%type <i> up_frame 
 
%% 
 
multi   :       detailed
                        { $$ = $1; } 
        |       multi ',' detailed
                        { $$ = expr_last($1);
                          $$->next = $3;
                                if ($$->details) {
                                        placeholders = 
g_list_last(placeholders);
                                        
GE_push_back((GE_EXPRESSION**)&placeholders->data);
                                }
                                $$ = $1;
                        } 
        |       multi ',' error
                        { $$ = $1;
                          message(No_expression, yycolumn-1);
                        }
        ; 
 
detailed:       range
                        { $$ = $1; } 
        |       open_detail multi_or_all GE_RCC
                        { $$ = $1;
                          $$->details = $2;
                                placeholders = g_list_last(placeholders);
                                
GE_push_back((GE_EXPRESSION**)&placeholders->data);
                        } 
        |       open_detail multi_or_all error
                        { message("Right double brace expected.", yycolumn); }
        |       open_detail error
                        { message("Expression expected.", yycolumn); } 
        ; 
  
open_detail:    range GE_LCC
                        { $$ = $1;
                                placeholders = g_list_append(placeholders, 
expr_bottom($1));
                        } 
                |       range '{'
                        { message("Left double brace expected.", yycolumn); }
        ; 
 
multi_or_all:   multi
                        { $$ = $1; } 
        |       E_ALL
                        { $$ = GE_new_expression();
                                $$->kind = is_all;
                                $$->name = "1";
                        } 
        |       E_ALL E_INTEGER
                        { $$ = GE_new_expression();
                                $$->kind = is_all;
                                $$->name = "2";
                        }
        ; 
 
range   :       single
                        { $$ = $1; } 
        |       open_indices indices ']' ']' 
                        { $$ = expr_bottom($1);
                                $$->arg = $2;
                                $$ = $1;
                                placeholders = g_list_last(placeholders);
                                
GE_push_back((GE_EXPRESSION**)&placeholders->data);
                        } 
        |       open_indices indices error
                        { message("Right double bracket expected.", yycolumn); 
} 
        |       open_indices error
                        { message("Indices expected.", yycolumn); } 
        ; 
 
open_indices:   single GE_LBB
                        { $$ = GE_new_expression();
                                $$->parent = expr_bottom($1);
                                $$->column = $1->column;
                                $$->is_range = TRUE;
                                $1->down = $$;
                          placeholders = g_list_append(placeholders, $$);
                          $$ = $1;
                        } 
        ; 
 
indices :       single ',' single
                        { $$ = $1;
                          $$->next = $3;
                        } 
        |       single '`' single
                        { $$ = GE_new_expression();
                                $$->column = $3->column;
                          $$->kind = is_count;
                          $$->arg = $3;
                          $1->next = $$;
                          $$ = $1;
                        } 
        |       E_ALL
                        { $$ = GE_new_expression();
                                $$->column = yycolumn;
                          $$->kind = is_all;
                        } 
        |       E_IF single
                        { $$ = GE_new_expression();
                                $$->column = $2->column;
                          $$->kind = is_if;
                        } 
        |       E_IF error
                        { message(No_expression, yycolumn); } 
        |       single
                        { message("Count or upper index expected.", yycolumn); 
} 
        |       single ',' error
                        { message("Upper index expected.", yycolumn); } 
        ; 
 
single  :       multi_dot
                        { $$ = $1; } 
        |       '+' single %prec E_NOT
                        { compose_prefix($2, plus_op);
                          $$ = $2;
                         } 
        |       '-' single %prec E_NOT
                        { compose_prefix($2, minus_op);
                          $$ = $2;
                        } 
        |       E_NOT single
                        { compose_prefix($2, not_op);
                          $$ = $2;
                        } 
        |       E_FREEOP single
                        { compose_free(NULL, $2, $1);
                          $$ = $2;
                        } 
        |       '+' error
                        { message("Operand expected.", yycolumn); } 
        |       '-' error
                        { message("Operand expected.", yycolumn); } 
        |       E_NOT error
                        { message("Operand expected.", yycolumn); } 
        |       E_FREEOP error
                        { message("Operand expected.", yycolumn); } 
        |       single E_FREEOP single
                        { compose_free($1,$3,$2);
                          $$ = $1;
                        } 
        |       single '^' single
                        { compose_infix($1,$3,power_op,7,0);
                          $$ = $1;
                        } 
        |       single '*' single
                        { compose_infix($1,$3,mult_op,6,0);
                          $$ = $1;
                        } 
        |       single '/' single
                        { compose_infix($1,$3,div_op,6,0);
                          $$ = $1;
                        } 
        |       single E_DIV single
                        { compose_infix($1,$3,idiv_op,6,0);
                          $$ = $1;
                        } 
        |       single E_MOD single
                        { compose_infix($1,$3,imod_op,6,0);
                          $$ = $1;
                        } 
        |       single '+' single
                        { compose_infix($1,$3,plus_op,5,0);
                          $$ = $1;
                        } 
        |       single '-' single
                        { compose_infix($1,$3,minus_op,5,0);
                          $$ = $1;
                        } 
        |       single E_DOTDOT single
                        { compose_infix($1,$3,interval_op,5,0);
                          $$ = $1;
                        } 
        |       single '=' single
                        { compose_infix($1,$3,eq_op,4,is_equality);
                          $$ = $1;
                        } 
        |       single E_NE single
                        { compose_infix($1,$3,ne_op,4,is_equality);
                          $$ = $1;
                        } 
        |       single '~' single
                        { compose_infix($1,$3,sim_op,4,is_equality);
                          $$ = $1;
                        } 
        |       single E_NOT_TILDE single
                        { compose_infix($1,$3,nsim_op,4,is_equality);
                          $$ = $1;
                        } 
        |       single '<' single
                        { compose_infix($1,$3,lt_op,4,0);
                          $$ = $1;
                        } 
        |       single E_LE single
                        { compose_infix($1,$3,le_op,4,0);
                          $$ = $1;
                        } 
        |       single '>' single
                        { compose_infix($1,$3,gt_op,4,0);
                          $$ = $1;
                        } 
        |       single E_GE single
                        { compose_infix($1,$3,ge_op,4,0);
                          $$ = $1;
                        } 
        |       single E_AND single
                        { compose_infix($1,$3,and_op,3,0);
                          $$ = $1;
                        } 
        |       single E_OR single
                        { compose_infix($1,$3,or_op,2,0);
                          $$ = $1;
                        } 
        |       single E_XOR single
                        { compose_infix($1,$3,2,xor_op,0);
                          $$ = $1;
                        } 
        |       single E_IMPLIES single
                        { compose_infix($1,$3,implies_op,1,0);
                          $$ = $1;
                        } 
        |       single E_FREEOP error
                        { message("Right operand expected.", yycolumn); } 
        |       single '^' error
                        { message("Right operand expected.", yycolumn); } 
        |       single '*' error
                        { message("Right operand expected.", yycolumn); } 
        |       single '/' error
                        { message("Right operand expected.", yycolumn); } 
        |       single E_DIV error
                        { message("Right operand expected.", yycolumn); } 
        |       single E_MOD error
                        { message("Right operand expected.", yycolumn); } 
        |       single '+' error
                        { message("Right operand expected.", yycolumn); } 
        |       single '-' error
                        { message("Right operand expected.", yycolumn); } 
        |       single '=' error
                        { message("Right operand expected.", yycolumn); } 
        |       single E_NE error
                        { message("Right operand expected.", yycolumn); } 
        |       single '<' error
                        { message("Right operand expected.", yycolumn); } 
        |       single '>' error
                        { message("Right operand expected.", yycolumn); } 
        |       single E_LE error
                        { message("Right operand expected.", yycolumn); } 
        |       single E_GE error
                        { message("Right operand expected.", yycolumn); } 
        |       single '~' error
                        { message("Right operand expected.", yycolumn); } 
        |       single E_NOT_TILDE error
                        { message("Right operand expected.", yycolumn); } 
        |       single E_AND error
                        { message("Right operand expected.", yycolumn); } 
        |       single E_OR error
                        { message("Right operand expected.", yycolumn); } 
        |       single E_XOR error
                        { message("Right operand expected.", yycolumn); } 
        |       single E_IMPLIES error
                        { message("Right operand expected.", yycolumn); } 
        ; 
 
multi_dot:      left
                        { $$ = $1; } 
        |       multi_dot '.' qualified
                        { $$ = expr_bottom($1);
                          if ($3->kind == is_details) {
                            $$->details = $3;
                            $3->parent = $$;
                          } else {;
                            $$->down = $3;
                                }
                                $$ = $1;
                        } 
        |       multi_dot brackets
                        { $$ = GE_new_expression();
                                $$->column = $2->column;
                                expr_bottom($1)->down = $$;
                                $$->parent = $1;
                          $$->kind = is_bracket;
                          $$->arg = $2;
                          $$ = $1;
                        } 
        ; 
 
qualified:      query
                        { $$ = $1; } 
        |       alias_name
                        { if ($1->kind>0 && $1->kind!=is_details) {
                                        message("Immediate alias name must not 
be qualified.", yycolumn);
                          }
                        $$ = $1;
                } 
        ; 
 
up_frame:       '^' 
                        { $$ = 1; } 
        |      GE_UP_FRAME
                        { $$ = $1; } 
        ; 
 
left    :       query
                        { $$ = $1; } 
        |       up_frame query
                        { $$ = $2;
                          $$->up_frame_count = $1;
                        } 
        |       alias_name
                        { if ($1->kind = is_details) {;
                    message("Details may not start an expression.", yycolumn);
                  }
                  $$ = $1;
                } 
        |       '(' single ')' 
                        { $$ = $2; } 
        |       '(' single error
                        { message("Right parenthesis expected.", yycolumn); } 
        |       '(' error ')' 
                        { message(No_expression, yycolumn); } 
        |       closure_id
                        { $$ = $1; }
        |       E_CHARACTER
                        { $$ = GE_new_expression();
                                $$->column = yycolumn;
                                $$->kind = is_character;
                                $$->name = ""; /* !! should be yytext; */
                        } 
        | E_STRING
                        { $$ = GE_new_expression();
                                $$->column = yycolumn;
                                $$->kind = is_string;
                                $$->name = $1;
                        } 
        | E_INTEGER
                        { $$ = GE_new_expression();
                                $$->column = yycolumn;
                                $$->kind = is_integer;
                                $$->name = ""; /* !! should be yytext; */
                        } 
        | E_REAL
                        { $$ = GE_new_expression();
                                $$->column = yycolumn;
                                $$->kind = is_real;
                                $$->name = ""; /* !! should be yytext; */
                        } 
        |       GE_PLACEHOLDER 
                        { if (!placeholders) {
                                message("Placeholders are not allowed here.", 
yycolumn);
                        } else if (g_list_length(placeholders) < strlen($1)) {
                                message("Not as many nested details.", 
yycolumn);
                        }
                        ph = g_list_nth_data(placeholders, 
g_list_length(placeholders)-strlen($1));
                        if (ph) {
                                if ($1[0]=':' && !ph->is_range) {
                                message("Index placeholders are not allowed 
here.", yycolumn);
                                }
                                $$ = GE_new_expression();
                                $$->column = yycolumn-1;
                                $$->kind = is_placeholder;
                                $$->name = $1;
                                $$->parent = ph;
                        }
                }
        ; 
 
brackets:       '[' args ']' 
                        { $$ = $2;
                          op_column = yycolumn;
                        } 
        |       '[' args error
                        { message("Right bracket expected.", yycolumn); } 
        |       '[' error 
                        { message(No_expression, yycolumn); } 
        ; 
 
args:           single 
                        { $$ = $1; } 
        |       args ',' single 
                        {       $$ = expr_last($1);
                                $$->next = $3;
                                $$ = $1;
                        } 
        |       args ',' error 
                        { message(No_expression, yycolumn); } 
        ; 
 
query   :       ident 
                        { $$ = GE_new_expression();
                                $$->column = op_column;
                          $$->name = $1;
                        } 
        |       ident '(' args ')' 
                        { $$ = GE_new_expression();
                                $$->column = op_column;
                          $$->name = $1;
                          $$->arg = $3; 
                        } 
        |       ident '(' ')' 
                        { message(No_expression, yycolumn); } 
        |       ident '(' args error
                        { message("Right parenthesis expected.", yycolumn); } 
        |       ident '(' error 
                        { message(No_expression, yycolumn); } 
        ; 
 
alias_name:     GE_ALIAS 
                        { $$ = GE_new_expression();
                                *($$) = *as_alias($1);
                        } 
        ; 
 
closure_id:     GE_CLOSURE 
                        { $$ = int_to_closure(atoi($1+1)); } 
        ;

ident   :       E_IDENTIFIER 
                        { $$ = $1;
                          op_column = yycolumn;
                        } 
        ;

%%


static compose_prefix(GE_EXPRESSION *arg, guint op) {

}
                                                                                
                                                                                
                                                 
static compose_infix(GE_EXPRESSION *left, GE_EXPRESSION * right,
                                                                                
 guint op, guint prec, gint kind) {

}

static compose_free(GE_EXPRESSION *left, GE_EXPRESSION * right, gchar *op) {
                                                                                
                                                                                
                                                                                
                                                         
}

static GE_EXPRESSION* as_alias(const gchar *str) {
}

static GE_EXPRESSION* int_to_closure(gint i) {
}
                                                                                
                                                                                
                        
static void message(const gchar *msg, gint col) {
}

#include <stdio.h>

int main(int argc, char **argv) 
{

  return 0;
}

Reply via email to