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;
}