parser.y 12.8 KB
Newer Older
1
%{
2 3 4 5 6 7 8 9
/*
 * Gnumeric Parser
 *
 * (C) 1998 the Free Software Foundation
 *
 * Author:
 *    Miguel de Icaza (miguel@gnu.org)
 */
10
#include <config.h>
11
#include <glib.h>
12
#include <ctype.h>
Arturo Espinosa's avatar
Arturo Espinosa committed
13
#include <string.h>
14
#include "numbers.h"
Miguel de Icaza's avatar
Today:  
Miguel de Icaza committed
15
#include "symbol.h"	
16
#include "str.h"
17
#include "expr.h"
18
#include "utils.h"
Miguel de Icaza's avatar
New:  
Miguel de Icaza committed
19 20
#include "number-match.h"
	
21
/* Allocation with disposal-on-error */ 
Arturo Espinosa's avatar
Arturo Espinosa committed
22 23 24 25 26
static void *alloc_buffer    (int size);
static void register_symbol  (Symbol *sym);
static void alloc_clean      (void);
static void alloc_glist      (GList *l); 
static void forget_glist     (GList *list);
Arturo Espinosa's avatar
Arturo Espinosa committed
27
static void forget_tree      (ExprTree *tree);
Arturo Espinosa's avatar
Arturo Espinosa committed
28
static void alloc_list_free  (void); 
29
static void *v_new (void);
30
	
31 32 33 34 35 36 37
#define ERROR -1
 
/* Types of items we know how to dispose on error */ 
typedef enum {
	ALLOC_SYMBOL,
	ALLOC_VALUE,
	ALLOC_BUFFER,
Arturo Espinosa's avatar
Arturo Espinosa committed
38
	ALLOC_LIST
39 40 41 42 43 44 45 46 47 48 49 50
} AllocType;

/* How we keep track of them */ 
typedef struct {
	AllocType type;
	void      *data;
} AllocRec;

/* This keeps a list of  AllocRecs */
static GList *alloc_list;
 
/* Debugging */ 
51
static void dump_tree (ExprTree *tree);
52 53 54 55 56

/* Bison/Yacc internals */ 
static int  yylex (void);
static int  yyerror (char *s);

57 58
#define p_new(type) \
	((type *) alloc_buffer ((unsigned) sizeof (type)))
59
		
60
%}
61

62
%union {
63
	ExprTree *tree;
64 65 66
	CellRef  *cell;
	GList    *list;
}
67
%type  <tree>  exp
68
%type  <list>  arg_list
Arturo Espinosa's avatar
Arturo Espinosa committed
69
%token <tree>  NUMBER STRING FUNCALL CONSTANT CELLREF GTE LTE NE
Arturo Espinosa's avatar
Arturo Espinosa committed
70 71

%left '<' '>' '=' GTE LTE NE
72 73
%left '-' '+' '&'
%left '*' '/'
Miguel de Icaza's avatar
Miguel de Icaza committed
74
%left NEG PLUS
75 76 77 78
%left '!'
%right '^'

%%
79 80 81 82
line:	  exp           { parser_result = $1;
                          /* dump_tree (parser_result);*/
                          alloc_list_free (); 
                        }
Arturo Espinosa's avatar
Arturo Espinosa committed
83 84 85 86
	| error 	{
				alloc_clean ();
				parser_error = PARSE_ERR_SYNTAX;
			}
87 88 89
	;

exp:	  NUMBER 	{ $$ = $1 }
Arturo Espinosa's avatar
Arturo Espinosa committed
90
	| STRING        { $$ = $1 }
91
        | CELLREF       { $$ = $1 }
Arturo Espinosa's avatar
Arturo Espinosa committed
92
	| CONSTANT      { $$ = $1 }
93
	| exp '+' exp	{
94
		$$ = p_new (ExprTree);
Arturo Espinosa's avatar
Arturo Espinosa committed
95
		$$->ref_count = 1;
96
		$$->oper = OPER_ADD;
97 98 99 100 101
		$$->u.binary.value_a = $1;
		$$->u.binary.value_b = $3;
	}

	| exp '-' exp {
102
		$$ = p_new (ExprTree);
Arturo Espinosa's avatar
Arturo Espinosa committed
103
		$$->ref_count = 1;
104
		$$->oper = OPER_SUB;
105 106 107 108 109
		$$->u.binary.value_a = $1;
		$$->u.binary.value_b = $3;
	}

	| exp '*' exp { 
110
		$$ = p_new (ExprTree);
Arturo Espinosa's avatar
Arturo Espinosa committed
111
		$$->ref_count = 1;
112
		$$->oper = OPER_MULT;
113 114 115 116 117
		$$->u.binary.value_a = $1;
		$$->u.binary.value_b = $3;
	}

	| exp '/' exp {
118
		$$ = p_new (ExprTree);
Arturo Espinosa's avatar
Arturo Espinosa committed
119
		$$->ref_count = 1;
120
		$$->oper = OPER_DIV;
121 122 123 124
		$$->u.binary.value_a = $1;
		$$->u.binary.value_b = $3;
	}

Arturo Espinosa's avatar
Arturo Espinosa committed
125 126
	| exp '=' exp {
		$$ = p_new (ExprTree);
Arturo Espinosa's avatar
Arturo Espinosa committed
127
		$$->ref_count = 1;
128
		$$->oper = OPER_EQUAL;
Arturo Espinosa's avatar
Arturo Espinosa committed
129 130 131 132 133
		$$->u.binary.value_a = $1;
		$$->u.binary.value_b = $3;
	}
	| exp '<' exp {
		$$ = p_new (ExprTree);
Arturo Espinosa's avatar
Arturo Espinosa committed
134
		$$->ref_count = 1;
135
		$$->oper = OPER_LT;
Arturo Espinosa's avatar
Arturo Espinosa committed
136 137 138 139 140
		$$->u.binary.value_a = $1;
		$$->u.binary.value_b = $3;
	}
	| exp '>' exp {
		$$ = p_new (ExprTree);
Arturo Espinosa's avatar
Arturo Espinosa committed
141
		$$->ref_count = 1;
142
		$$->oper = OPER_GT;
Arturo Espinosa's avatar
Arturo Espinosa committed
143 144 145 146 147 148
		$$->u.binary.value_a = $1;
		$$->u.binary.value_b = $3;
	}

        | exp GTE exp {
		$$ = p_new (ExprTree);
Arturo Espinosa's avatar
Arturo Espinosa committed
149
		$$->ref_count = 1;
150
		$$->oper = OPER_GTE;
Arturo Espinosa's avatar
Arturo Espinosa committed
151 152 153 154 155 156
		$$->u.binary.value_a = $1;
		$$->u.binary.value_b = $3;
	}

        | exp NE exp {
		$$ = p_new (ExprTree);
Arturo Espinosa's avatar
Arturo Espinosa committed
157
		$$->ref_count = 1;
158
		$$->oper = OPER_NOT_EQUAL;
Arturo Espinosa's avatar
Arturo Espinosa committed
159 160 161 162 163 164
		$$->u.binary.value_a = $1;
		$$->u.binary.value_b = $3;
	}

        | exp LTE exp {
		$$ = p_new (ExprTree);
Arturo Espinosa's avatar
Arturo Espinosa committed
165
		$$->ref_count = 1;
166
		$$->oper = OPER_LTE;
Arturo Espinosa's avatar
Arturo Espinosa committed
167 168 169 170
		$$->u.binary.value_a = $1;
		$$->u.binary.value_b = $3;
	}

171 172 173 174
	| '(' exp ')'  {
		$$ = $2;
	}

175 176
        | '-' exp %prec NEG {
		$$ = p_new (ExprTree);
Arturo Espinosa's avatar
Arturo Espinosa committed
177
		$$->ref_count = 1;
178
		$$->oper = OPER_NEG;
179 180
		$$->u.value = $2;
	}
Miguel de Icaza's avatar
Miguel de Icaza committed
181 182 183 184 185

        | '+' exp %prec PLUS {
		$$ = $2;
	}

186
	| exp '&' exp {
187
		$$ = p_new (ExprTree);
Arturo Espinosa's avatar
Arturo Espinosa committed
188
		$$->ref_count = 1;
189
		$$->oper = OPER_CONCAT;
190 191 192 193 194
		$$->u.binary.value_a = $1;
		$$->u.binary.value_b = $3;
	}
	;

Arturo Espinosa's avatar
Arturo Espinosa committed
195 196 197 198 199 200 201
        | CELLREF ':' CELLREF {
		CellRef a, b;

		a = $1->u.constant->v.cell;
		b = $3->u.constant->v.cell;

		$$ = p_new (ExprTree);
Arturo Espinosa's avatar
Arturo Espinosa committed
202
		$$->ref_count = 1;
203
		$$->oper = OPER_CONSTANT;
Arturo Espinosa's avatar
Arturo Espinosa committed
204 205 206 207 208 209 210 211
		$$->u.constant = v_new ();
		$$->u.constant->type = VALUE_CELLRANGE;
		$$->u.constant->v.cell_range.cell_a = a;
		$$->u.constant->v.cell_range.cell_b = b;

		forget_tree ($1);
		forget_tree ($3);
	}
212

213
	| FUNCALL '(' arg_list ')' {
Arturo Espinosa's avatar
Arturo Espinosa committed
214
		$$ = $1;
215 216 217 218
		$$->u.function.arg_list = $3;
	}
	;

Arturo Espinosa's avatar
Arturo Espinosa committed
219 220 221 222 223 224 225 226
arg_list: exp {
		$$ = g_list_prepend (NULL, $1);
		alloc_glist ($$);
        }
	| exp ',' arg_list {
		forget_glist ($3);
		$$ = g_list_prepend ($3, $1);
		alloc_glist ($$);
Arturo Espinosa's avatar
Arturo Espinosa committed
227 228
	}
        | { $$ = NULL; }
229 230 231 232
	;

%%

233 234 235
static int
return_cellref (char *p)
{
236 237
	int col_relative = TRUE;
	int row_relative = TRUE;
238 239
	int col = 0;
	int row = 0;
240
	ExprTree *e;
241
	Value    *v;
Arturo Espinosa's avatar
Arturo Espinosa committed
242
	CellRef  *ref;
Arturo Espinosa's avatar
Arturo Espinosa committed
243

244 245
	/* Try to parse a column */
	if (*p == '$'){
246
		col_relative = FALSE;
247 248 249 250 251 252 253 254
		p++;
	}
	if (!(toupper (*p) >= 'A' && toupper (*p) <= 'Z'))
		return 0;

	col = toupper (*p++) - 'A';
	
	if (toupper (*p) >= 'A' && toupper (*p) <= 'Z')
255
		col = (col+1) * ('Z'-'A'+1) + toupper (*p++) - 'A';
256 257 258

	/* Try to parse a row */
	if (*p == '$'){
259
		row_relative = FALSE;
260 261 262 263 264 265
		p++;
	}
	
	if (!(*p >= '1' && *p <= '9'))
		return 0;

Arturo Espinosa's avatar
Arturo Espinosa committed
266
	while (isdigit (*p)){
267
		row = row * 10 + *p - '0';
Arturo Espinosa's avatar
Arturo Espinosa committed
268 269 270
		p++;
	}
	row--;
271 272 273

	/*  Ok, parsed successfully, create the return value */
	e = p_new (ExprTree);
Arturo Espinosa's avatar
Arturo Espinosa committed
274
	e->ref_count = 1;
275 276
	v = v_new ();

277
	e->oper = OPER_VAR;
278

Arturo Espinosa's avatar
Arturo Espinosa committed
279
	ref = &v->v.cell;
280

281 282
	/* Setup the cell reference information */
	if (row_relative)
Arturo Espinosa's avatar
Arturo Espinosa committed
283 284 285
		ref->row = row - parser_row;
	else
		ref->row = row;
286 287

	if (col_relative)
Arturo Espinosa's avatar
Arturo Espinosa committed
288 289 290
		ref->col = col - parser_col;
	else
		ref->col = col;
291 292 293
	
	ref->col_relative = col_relative;
	ref->row_relative = row_relative;
Arturo Espinosa's avatar
Arturo Espinosa committed
294

Arturo Espinosa's avatar
Arturo Espinosa committed
295
	e->u.constant = v;
296
	
297
	yylval.tree = e;
Arturo Espinosa's avatar
Arturo Espinosa committed
298

299 300 301 302 303 304
	return CELLREF;
}

static int
return_symbol (char *string)
{
305
	ExprTree *e = p_new (ExprTree);
306
	Symbol *sym;
Arturo Espinosa's avatar
Arturo Espinosa committed
307
	int type;
Arturo Espinosa's avatar
Arturo Espinosa committed
308 309

	e->ref_count = 1;
310 311
	sym = symbol_lookup (string);
	type = STRING;
Arturo Espinosa's avatar
Arturo Espinosa committed
312 313 314
	
	if (!sym)
	{
Arturo Espinosa's avatar
Arturo Espinosa committed
315
		Value *v = v_new ();
Miguel de Icaza's avatar
New:  
Miguel de Icaza committed
316 317 318 319 320 321 322 323 324 325 326 327
		double fv;
		char *format;
		
		if (format_match (string, &fv, &format)){
			v->type = VALUE_FLOAT;
			v->v.v_float = fv;
			if (!parser_desired_format)
				parser_desired_format = format;
		} else {
			v->v.str = string_get (string);
			v->type = VALUE_STRING;
		}
Arturo Espinosa's avatar
Arturo Espinosa committed
328
		
329
		e->oper = OPER_CONSTANT;
Arturo Espinosa's avatar
Arturo Espinosa committed
330
		e->u.constant = v;
Arturo Espinosa's avatar
Arturo Espinosa committed
331 332 333
	}
	else
	{
334 335
		symbol_ref (sym);
		if (sym->type == SYMBOL_FUNCTION)
Arturo Espinosa's avatar
Arturo Espinosa committed
336
		{
337
			e->oper = OPER_FUNCALL;
338
			type = FUNCALL;
Arturo Espinosa's avatar
Arturo Espinosa committed
339 340 341 342 343 344 345 346 347 348 349 350
			e->u.function.symbol = sym;
			e->u.function.arg_list = NULL;
		}
		else
		{
			Value *v, *dv;

			/* Make a copy of the value */
			dv = (Value *) sym->data;
			v = v_new ();
			value_copy_to (v, dv);
			
351
			e->oper = OPER_CONSTANT;
Arturo Espinosa's avatar
Arturo Espinosa committed
352 353
			e->u.constant = v;
			type = CONSTANT;
Arturo Espinosa's avatar
Arturo Espinosa committed
354 355
		}
		register_symbol (sym);
356 357
	}
	
358
	yylval.tree = e;
Arturo Espinosa's avatar
Arturo Espinosa committed
359
	return type;
360 361 362 363 364
}

static int
try_symbol (char *string)
{
Arturo Espinosa's avatar
Arturo Espinosa committed
365 366
	int v;
	
367 368 369 370
	v = return_cellref (string);
	if (v)
		return v;

Arturo Espinosa's avatar
Arturo Espinosa committed
371
	return return_symbol (string);
372 373
}

374 375 376
int yylex (void)
{
	int c;
377 378 379 380 381 382 383 384 385
	char *p, *tmp;
	int is_float;
	
        while(isspace (*parser_expr))
                parser_expr++;                                                                                       

	c = *parser_expr++;
        if (c == '(' || c == ',' || c == ')')
                return c;
386

387 388 389
	switch (c){
        case '0': case '1': case '2': case '3': case '4': case '5':
	case '6': case '7': case '8': case '9': case '.': {
390
		ExprTree *e = p_new (ExprTree);
391
		Value *v = v_new ();
Arturo Espinosa's avatar
Arturo Espinosa committed
392 393

		e->ref_count = 1;
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
		is_float = c == '.';
		p = parser_expr-1;
		tmp = parser_expr;
		
                while (isdigit (*tmp) || (!is_float && *tmp=='.' && ++is_float))
                        tmp++;
		
		if (*tmp == 'e' || *tmp == 'E') {
			is_float = 1;
			tmp++;
			if (*tmp == '-' || *tmp == '+')
				tmp++;
			while (isdigit (*tmp))
				tmp++;
		}
409

410 411 412 413 414 415 416 417 418 419
		/* Ok, we have skipped over a number, now load its value */
		if (is_float){
			v->type = VALUE_FLOAT;
			float_get_from_range (p, tmp, &v->v.v_float);
		} else {
			v->type = VALUE_INTEGER;
			int_get_from_range (p, tmp, &v->v.v_int);
		}

		/* Return the value to the parser */
420
		e->oper = OPER_CONSTANT;
421
		e->u.constant = v;
422
		yylval.tree = e;
423 424

		parser_expr = tmp;
425 426
		return NUMBER;
	}
427
	case '"': {
Arturo Espinosa's avatar
Arturo Espinosa committed
428 429
		char *string, *s;
		int v;
430

431 432 433 434 435 436 437 438 439 440 441
                p = parser_expr;
                while(*parser_expr && *parser_expr != '"') {
                        if (*parser_expr == '\\' && parser_expr [1])
                                parser_expr++;
                        parser_expr++;
                }
                if(!*parser_expr){
                        parser_error = PARSE_ERR_NO_QUOTE;
                        return ERROR;
                }
		
Arturo Espinosa's avatar
Arturo Espinosa committed
442
		s = string = (char *) alloca (1 + parser_expr - p);
443 444 445
		while (p != parser_expr){
			if (*p== '\\'){
				p++;
Arturo Espinosa's avatar
Arturo Espinosa committed
446
				*s++ = *p++;
447
			} else
Arturo Espinosa's avatar
Arturo Espinosa committed
448
				*s++ = *p++;
449 450
			
		}
Arturo Espinosa's avatar
Arturo Espinosa committed
451
		*s = 0;
452
		parser_expr++;
453

Arturo Espinosa's avatar
Arturo Espinosa committed
454 455
		v = return_symbol (string);
		return v;
456
	}
457
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
458
	
459
	if (isalpha (c) || c == '_' || c == '$'){
Arturo Espinosa's avatar
Arturo Espinosa committed
460 461 462 463
		char *start = parser_expr - 1;
		char *str;
		int  len;
		
464
		while (isalnum (*parser_expr) || *parser_expr == '_' || *parser_expr == '$')
Arturo Espinosa's avatar
Arturo Espinosa committed
465 466 467 468 469 470 471
			parser_expr++;

		len = parser_expr - start;
		str = alloca (len + 1);
		strncpy (str, start, len);
		str [len] = 0;
		return try_symbol (str);
472 473 474 475 476 477
	}
	if (c == '\n')
		return 0;
	
	if (c == EOF)
		return 0;
Arturo Espinosa's avatar
Arturo Espinosa committed
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497

	if (c == '<'){
		if (*parser_expr == '='){
			parser_expr++;
			return LTE;
		}
		if (*parser_expr == '>'){
			parser_expr++;
			return NE;
		}
		return c;
	}
	
	if (c == '>'){
		if (*parser_expr == '='){
			parser_expr++;
			return GTE;
		}
		return c;
	}
498 499 500 501 502 503 504 505 506 507 508 509
	
	return c;
}

int
yyerror (char *s)
{
    printf ("Error: %s\n", s);
    return 0;
}

static void
Arturo Espinosa's avatar
Arturo Espinosa committed
510
alloc_register (void *a_info)
511 512 513 514
{
	alloc_list = g_list_prepend (alloc_list, a_info);
}

515
static void
Arturo Espinosa's avatar
Arturo Espinosa committed
516
register_symbol (Symbol *sym)
517 518 519
{
	AllocRec *a_info = g_new (AllocRec, 1);

Arturo Espinosa's avatar
Arturo Espinosa committed
520 521 522
	a_info->type = ALLOC_SYMBOL;
	a_info->data = sym;
	alloc_register (a_info);
523 524
}

525 526 527 528 529 530 531 532
void *
alloc_buffer (int size)
{
	AllocRec *a_info = g_new (AllocRec, 1);
	char *res = g_malloc (size);

	a_info->type = ALLOC_BUFFER;
	a_info->data = res;
Arturo Espinosa's avatar
Arturo Espinosa committed
533
	alloc_register (a_info);
534 535 536 537

	return res;
}

538
static void *
539 540 541 542 543 544 545
v_new (void)
{
	AllocRec *a_info = g_new (AllocRec, 1);
	char *res = g_malloc (sizeof (Value));

	a_info->type = ALLOC_VALUE;
	a_info->data = res;
Arturo Espinosa's avatar
Arturo Espinosa committed
546
	alloc_register (a_info);
547 548 549 550

	return res;
}

551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566
static void
alloc_clean (void)
{
	GList *l = alloc_list;
	
	for (; l; l = l->next){
		AllocRec *rec = l->data;

		switch (rec->type){
		case ALLOC_BUFFER:
			g_free (rec->data);
			break;
			
		case ALLOC_SYMBOL:
			symbol_unref ((Symbol *)rec->data);
			break;
567

Arturo Espinosa's avatar
Arturo Espinosa committed
568 569
		case ALLOC_VALUE:
			value_release ((Value *)rec->data);
570 571
			break;
			
Arturo Espinosa's avatar
Arturo Espinosa committed
572 573
		case ALLOC_LIST:
			g_list_free ((GList *) rec->data);
Arturo Espinosa's avatar
Arturo Espinosa committed
574
			break;
575
		}
576
		g_free (rec);
577 578 579 580 581 582
	}

	g_list_free (l);
	alloc_list = NULL;
}

583 584 585 586 587 588 589 590 591 592 593 594
static void
alloc_list_free (void)
{
	GList *l = alloc_list;
	
	for (; l; l = l->next)
		g_free (l->data);

	g_list_free (l);
	alloc_list = NULL;
}

Arturo Espinosa's avatar
Arturo Espinosa committed
595 596 597 598 599 600 601
static void
alloc_glist (GList *list)
{
	AllocRec *a_info = g_new (AllocRec, 1);

	a_info->type = ALLOC_LIST;
	a_info->data = list;
Arturo Espinosa's avatar
Arturo Espinosa committed
602
	alloc_register (a_info);
Arturo Espinosa's avatar
Arturo Espinosa committed
603 604 605
}

static void
606
forget (AllocType type, void *data)
Arturo Espinosa's avatar
Arturo Espinosa committed
607 608 609 610 611 612
{
	GList *l;

	for (l = alloc_list; l; l = l->next){
		AllocRec *a_info = (AllocRec *) l->data;

Arturo Espinosa's avatar
Arturo Espinosa committed
613
		if (a_info->type == type && a_info->data == data){
Arturo Espinosa's avatar
Arturo Espinosa committed
614 615 616 617 618 619
			alloc_list = g_list_remove_link (alloc_list, l);
			return;
		}
	}
}

Arturo Espinosa's avatar
Arturo Espinosa committed
620 621 622 623 624 625 626 627 628 629
static void
forget_glist (GList *list)
{
	forget (ALLOC_LIST, list);
}

static void
forget_tree (ExprTree *tree)
{
	forget (ALLOC_BUFFER, tree);
Arturo Espinosa's avatar
Arturo Espinosa committed
630
	expr_tree_unref (tree); 
Arturo Espinosa's avatar
Arturo Espinosa committed
631 632
}

Arturo Espinosa's avatar
Arturo Espinosa committed
633
void
634
value_dump (Value *value)
Arturo Espinosa's avatar
Arturo Espinosa committed
635
{
636 637 638 639 640
	switch (value->type){
	case VALUE_STRING:
		printf ("STRING: %s\n", value->v.str->str);
		break;

641
	case VALUE_INTEGER:
Arturo Espinosa's avatar
Arturo Espinosa committed
642
		printf ("NUM: %d\n", value->v.v_int);
643 644
		break;

645
	case VALUE_FLOAT:
Arturo Espinosa's avatar
Arturo Espinosa committed
646
		printf ("Float: %f\n", value->v.v_float);
647
		break;
Arturo Espinosa's avatar
Arturo Espinosa committed
648 649 650 651 652 653 654 655 656 657

	case VALUE_ARRAY: {
		GList *l;

		printf ("Array: { ");
		for (l = value->v.array; l; l = l->next){
			value_dump (l->data);
		}
		printf ("}\n");
	}
658 659 660 661 662 663
	default:
		printf ("Unhandled item type\n");
	}
}

void
664
dump_tree (ExprTree *tree)
665 666
{
	Symbol *s;
667
	CellRef *cr;
668
	
669
	switch (tree->oper){
670
	case OPER_VAR:
671
		cr = &tree->u.constant->v.cell;
672
		printf ("Cell: %s%c%s%d\n",
673
			cr->col_relative ? "" : "$",
674
			cr->col + 'A',
675
			cr->row_relative ? "" : "$",
676 677 678
			cr->row + '1');
		return;
		
679
	case OPER_CONSTANT:
680
		value_dump (tree->u.constant);
681 682
		return;

683
	case OPER_FUNCALL:
684
		s = symbol_lookup (tree->u.function.symbol->str);
685 686
		printf ("Function call: %s\n", s->str);
		break;
Arturo Espinosa's avatar
Arturo Espinosa committed
687

688 689 690 691 692 693 694 695 696 697 698 699
	case OPER_EQUAL:
	case OPER_NOT_EQUAL:
	case OPER_LT:
	case OPER_LTE:
	case OPER_GT:
	case OPER_GTE:
	case OPER_ADD:
	case OPER_SUB:
	case OPER_MULT:
	case OPER_DIV:
	case OPER_EXP:
	case OPER_CONCAT:
700 701 702
		dump_tree (tree->u.binary.value_a);
		dump_tree (tree->u.binary.value_b);
		switch (tree->oper){
703 704 705 706 707 708 709 710 711 712 713 714
		case OPER_ADD: printf ("ADD\n"); break;
		case OPER_SUB: printf ("SUB\n"); break;
		case OPER_MULT: printf ("MULT\n"); break;
		case OPER_DIV: printf ("DIV\n"); break;
		case OPER_CONCAT: printf ("CONCAT\n"); break;
		case OPER_EQUAL: printf ("==\n"); break;
		case OPER_NOT_EQUAL: printf ("!=\n"); break;
		case OPER_LT: printf ("<\n"); break;
		case OPER_GT: printf (">\n"); break;
		case OPER_GTE: printf (">=\n"); break;
		case OPER_LTE: printf ("<=\n"); break;
		case OPER_EXP: printf ("EXP\n"); break;
715 716 717 718 719
		default:
			printf ("Error\n");
		}
		break;
		
720
	case OPER_NEG:
721
		dump_tree (tree->u.value);
722 723 724 725 726
		printf ("NEGATIVE\n");
		break;
		
	}
}