1 %{
2
3 /* Parse ip's macro language.
4 */
5
6 /*
7
8 Copyright (C) 1991-2003 The National Gallery
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License along
21 with this program; if not, write to the Free Software Foundation, Inc.,
22 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23
24 */
25
26 /*
27
28 These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
29
30 */
31
32 #include "ip.h"
33
34 /*
35 #define DEBUG
36 */
37
38 /* trace text read system
39 #define DEBUG_CHARACTER
40 */
41
42 /* The lexer from lex.l.
43 */
44 int yylex( void );
45 void yyrestart( FILE *input_file );
46
47 /* Declare file-private stuff, shared with the lexer. Bison will put this
48 * stuff into parse.h, so just declare, don't define. Sadly we can't have
49 * these things static :(
50 */
51
52 /* Global .. the symbol whose definition we are currently parsing, the symbol
53 * which all defs in this parse action should be made local to.
54 */
55 extern Symbol *current_symbol;
56 extern Symbol *root_symbol;
57
58 /* The current parse context.
59 */
60 extern Compile *current_compile;
61 extern ParseNode *current_parsenode;
62
63 /* The kit we are adding new symbols to.
64 */
65 extern Toolkit *current_kit;
66
67 /* Where it should go in the kit.
68 */
69 extern int tool_position;
70
71 /* Lineno of start of last top-level def.
72 */
73 extern int last_top_lineno;
74
75 /* Text we've gathered in this lex.
76 */
77 extern char lex_text_buffer[MAX_STRSIZE];
78
79 /* Stack of symbols for parser - each represents a new scope level.
80 */
81 extern Symbol *scope_stack_symbol[MAX_SSTACK];
82 extern Compile *scope_stack_compile[MAX_SSTACK];
83 extern int scope_sp;
84
85 /* Use to generate unique ids for anonymouse parse objects (eg. lambdas etc).
86 */
87 extern int parse_object_id;
88
89 /* Get text for parsed objects.
90 */
91 char *input_text( char *out );
92 void input_reset( void );
93 void input_push( int n );
94 void input_backtoch( char ch );
95 void input_back1( void );
96 void input_pop( void );
97
98 /* Nest and unnest scopes.
99 */
100 void scope_push( void );
101 void scope_pop( void );
102 void scope_pop_all( void );
103 void scope_reset( void );
104
105 /* Helper functions.
106 */
107 void *parse_toplevel_end( Symbol *sym );
108 void *parse_access_end( Symbol *sym, Symbol *main );
109
110 %}
111
112 %union {
113 struct sym_table *yy_symtab;
114 ParseNode *yy_node;
115 char *yy_name;
116 ParseConst yy_const;
117 UnOp yy_uop;
118 BinOp yy_binop;
119 }
120
121 %token TK_TAG TK_IDENT TK_CONST TK_DOTDOTDOT TK_LAMBDA TK_FROM TK_TO TK_SUCHTHAT
122 %token TK_UMINUS TK_UPLUS TK_POW
123 %token TK_LESS TK_LESSEQ TK_MORE TK_MOREEQ TK_NOTEQ
124 %token TK_LAND TK_LOR TK_BAND TK_BOR TK_JOIN TK_DIFF
125 %token TK_IF TK_THEN TK_ELSE
126 %token TK_CHAR TK_SHORT TK_CLASS TK_SCOPE
127 %token TK_INT TK_FLOAT TK_DOUBLE TK_SIGNED TK_UNSIGNED TK_COMPLEX
128 %token TK_SEPARATOR TK_DIALOG TK_LSHIFT TK_RSHIFT
129
130 %type <yy_node> expr binop uop rhs list_expression comma_list body
131 %type <yy_node> simple_pattern complex_pattern list_pattern
132 %type <yy_node> leaf_pattern
133 %type <yy_node> crhs cexprlist prhs lambda
134 %type <yy_const> TK_CONST
135 %type <yy_name> TK_IDENT TK_TAG
136
137 %left TK_SUCHTHAT
138 %left TK_LAMBDA
139 %nonassoc TK_IF
140 %left ','
141 %left TK_TO
142 %left TK_LOR
143 %left TK_LAND '@'
144 %left TK_BOR
145 %left '^'
146 %left TK_BAND
147 %nonassoc TK_EQ TK_NOTEQ TK_PEQ TK_PNOTEQ
148 %nonassoc TK_LESS TK_LESSEQ TK_MORE TK_MOREEQ
149 %left TK_LSHIFT TK_RSHIFT
150 %left '+' '-'
151 %left '*' '/' '%'
152 %left '!' '~' TK_JOIN TK_DIFF TK_UMINUS TK_UPLUS
153 %right TK_POW ':'
154 %right TK_CONST '('
155 %right TK_IDENT TK_TAG TK_SCOPE '['
156 %right TK_APPLICATION
157 %left '?' '.'
158
159 %start select
160
161 /*
162
163 Our syntax for list comprehensions is not LALR(1). We have:
164
165 simple_pattern '<-' expr ';' |
166 expr ';'
167
168 simple_pattern can be something like
169
170 a:x
171
172 which is also an expr. We don't know which branch to take until we see a
173 '<' or a ';'.
174
175 Use bison's GLR system to parse this, and ignore the first 13 reduce/reduce
176 conflicts caused by this ambiguity.
177
178 FIXME ... we now depend on bison, but we still have some yacc compatibility
179 stuff in here, and we don't use all of bison's nice features (eg. for
180 tracking line numbers in the source file). Fix this up at some stage.
181
182 */
183
184 %glr-parser
185 %expect-rr 13
186
187 %error-verbose
188
189 %%
190
191 select:
192 ',' main |
193 '^' single_definition |
194 '*' params_plus_rhs optsemi {
195 compile_check( current_compile );
196 } |
197 prhs {
198 char buf[MAX_STRSIZE];
199
200 current_compile->tree = $1;
201
202 /* Junk any old text.
203 */
204 IM_FREE( current_compile->text );
205 IM_FREE( current_compile->prhstext );
206 IM_FREE( current_compile->rhstext );
207
208 /* Set new text.
209 */
210 IM_SETSTR( current_compile->rhstext, input_text( buf ) );
211
212 compile_check( current_compile );
213 }
214 ;
215
216 prhs:
217 TK_BAND expr {
218 $$ = $2;
219 } |
220 '@' cexprlist {
221 $$ = $2;
222 }
223 ;
224
225 main:
226 /* Empty */ |
227 main single_definition
228 ;
229
230 single_definition:
231 directive {
232 tool_position += 1;
233 } |
234 toplevel_definition optsemi {
235 tool_position += 1;
236 }
237 ;
238
239 directive:
240 TK_SEPARATOR {
241 Tool *tool;
242
243 if( !is_top( current_symbol ) )
244 yyerror( _( "not top level" ) );
245
246 tool = tool_new_sep( current_kit, tool_position );
247 tool->lineno = input_state.lineno;
248
249 input_reset();
250 } |
251 TK_DIALOG TK_CONST TK_CONST {
252 Tool *tool;
253
254 if( !is_top( current_symbol ) )
255 yyerror( _( "not top level" ) );
256
257 /* Should have two strings.
258 */
259 if( $2.type != PARSE_CONST_STR || $3.type != PARSE_CONST_STR )
260 yyerror( _( "not strings" ) );
261
262 /* Add tool.
263 */
264 tool = tool_new_dia( current_kit, tool_position,
265 $2.val.str, $3.val.str );
266 if( !tool )
267 yyerror( error_get_sub() );
268 tool->lineno = input_state.lineno;
269
270 /* Cast away const here.
271 */
272 tree_const_destroy( (ParseConst *) &$2 );
273 tree_const_destroy( (ParseConst *) &$3 );
274
275 input_reset();
276 }
277 ;
278
279 toplevel_definition:
280 {
281 last_top_lineno = input_state.lineno;
282 scope_reset();
283 current_compile = root_symbol->expr->compile;
284 }
285 definition {
286 input_reset();
287 }
288 ;
289
290 /* Parse a new defining occurence. This can be a local or a top-level.
291 */
292 definition:
293 simple_pattern {
294 Symbol *sym;
295
296 /* Two forms: <name pattern-list rhs>, or <pattern rhs>.
297 * Enforce the no-args-to-pattern-assignment rule in the arg
298 * pattern parser.
299 */
300 if( $1->type == NODE_LEAF ) {
301 const char *name = IOBJECT( $1->leaf )->name;
302
303 /* Make a new defining occurence.
304 */
305 sym = symbol_new_defining( current_compile, name );
306
307 (void) symbol_user_init( sym );
308 (void) compile_new_local( sym->expr );
309 }
310 else {
311 char name[256];
312
313 /* We have <pattern rhs>. Make an anon symbol for this
314 * value, then the variables in the pattern become
315 * toplevels which access that.
316 */
317 if( !compile_pattern_has_leaf( $1 ) )
318 yyerror( _( "left-hand-side pattern "
319 "contains no identifiers" ) );
320 im_snprintf( name, 256, "$$pattern_lhs%d",
321 parse_object_id++ );
322 sym = symbol_new_defining( current_compile, name );
323 sym->generated = TRUE;
324 (void) symbol_user_init( sym );
325 (void) compile_new_local( sym->expr );
326 }
327
328 /* Note on the enclosing last_sym. Things like the program
329 * window use this to work out what sym to display after a
330 * parse. symbol_dispose() is careful to NULL this out.
331 */
332 current_compile->last_sym = sym;
333
334 /* Initialise symbol parsing variables. Save old current symbol,
335 * add new one.
336 */
337 scope_push();
338 current_symbol = sym;
339 current_compile = sym->expr->compile;
340
341 g_assert( !current_compile->param );
342 g_assert( current_compile->nparam == 0 );
343
344 /* Junk any old def text.
345 */
346 IM_FREE( current_compile->text );
347 IM_FREE( current_compile->prhstext );
348 IM_FREE( current_compile->rhstext );
349 }
350 params_plus_rhs {
351 compile_check( current_compile );
352
353 /* Link unresolved names into the outer scope.
354 */
355 compile_resolve_names( current_compile,
356 compile_get_parent( current_compile ) );
357
358 /* Is this the end of a top-level? Needs extra work to add to
359 * the enclosing toolkit etc.
360 */
361 if( is_scope( symbol_get_parent( current_symbol ) ) )
362 parse_toplevel_end( current_symbol );
363
364 /* Is this a pattern definition? Expand the pattern to a
365 * set of access defs.
366 */
367 if( $1->type != NODE_LEAF ) {
368 Compile *parent = compile_get_parent( current_compile );
369 GSList *built_syms;
370
371 built_syms = compile_pattern_lhs( parent,
372 current_symbol, $1 );
373
374 if( is_scope( symbol_get_parent( current_symbol ) ) )
375 slist_map( built_syms,
376 (SListMapFn) parse_toplevel_end, NULL );
377 slist_map( built_syms,
378 (SListMapFn) parse_access_end,
379 current_symbol );
380
381 g_slist_free( built_syms );
382 }
383
384 scope_pop();
385 }
386 ;
387
388 /* Parse params/body/locals into current_expr
389 */
390 params_plus_rhs:
391 {
392 input_push( 1 );
393
394 /* We've already read the character past the end of the
395 * identifier (that's why we know the identifier is over).
396 */
397 input_back1();
398 }
399 params {
400 input_push( 2 );
401 input_backtoch( '=' );
402 }
403 body {
404 current_compile->tree = $4;
405 g_assert( current_compile->tree );
406 input_push( 4 );
407 }
408 locals {
409 char buf[MAX_STRSIZE];
410
411 input_pop();
412
413 /* Save body text as rhstext.
414 */
415 IM_SETSTR( current_compile->rhstext, input_text( buf ) );
416 input_pop();
417
418 /* Save params '=' body as prhstext.
419 */
420 IM_SETSTR( current_compile->prhstext, input_text( buf ) );
421 input_pop();
422
423 /* Save full text of definition.
424 */
425 IM_SETSTR( current_compile->text, input_text( buf ) );
426
427 #ifdef DEBUG
428 printf( "%s->compile->text = \"%s\"\n",
429 IOBJECT( current_compile->sym )->name,
430 current_compile->text );
431 printf( "%s->compile->prhstext = \"%s\"\n",
432 IOBJECT( current_compile->sym )->name,
433 current_compile->prhstext );
434 printf( "%s->compile->rhstext = \"%s\"\n",
435 IOBJECT( current_compile->sym )->name,
436 current_compile->rhstext );
437 #endif /*DEBUG*/
438 }
439 ;
440
441 params:
442 /* Empty */ |
443 params simple_pattern {
444 Symbol *sym;
445
446 /* If the pattern is just an identifier, make it a direct
447 * parameter. Otherwise make an anon param and put the pattern
448 * in as a local with the same id.
449 *
450 * fred [a] = 12;
451 *
452 * parses to:
453 *
454 * fred $$arg42 = 12 { $$patt42 = [a]; }
455 *
456 * A later pass creates the "a = $$arg42?0" definition.
457 */
458 if( $2->type == NODE_LEAF ) {
459 const char *name = IOBJECT( $2->leaf )->name;
460
461 /* Make defining occurence.
462 */
463 sym = symbol_new_defining( current_compile, name );
464 (void) symbol_parameter_init( sym );
465 }
466 else {
467 char name[256];
468
469 im_snprintf( name, 256, "$$arg%d", parse_object_id );
470 sym = symbol_new_defining( current_compile, name );
471 sym->generated = TRUE;
472 (void) symbol_parameter_init( sym );
473
474 im_snprintf( name, 256, "$$patt%d", parse_object_id++ );
475 sym = symbol_new_defining( current_compile, name );
476 sym->generated = TRUE;
477 (void) symbol_user_init( sym );
478 (void) compile_new_local( sym->expr );
479 sym->expr->compile->tree = $2;
480 }
481 }
482 ;
483
484 body :
485 '=' TK_CLASS crhs {
486 $$ = $3;
487 } |
488 rhs {
489 $$ = $1;
490 }
491 ;
492
493 crhs:
494 {
495 ParseNode *pn = tree_class_new( current_compile );
496
497 input_push( 3 );
498 scope_push();
499 current_symbol = current_compile->super;
500 current_compile = current_symbol->expr->compile;
501
502 current_parsenode = pn;
503 }
504 cexprlist {
505 Compile *parent = compile_get_parent( current_compile );
506 char buf[MAX_STRSIZE];
507 int len;
508
509 (void) input_text( buf );
510
511 /* Always read 1 char too many.
512 */
513 if( (len = strlen( buf )) > 0 )
514 buf[len - 1] = '\0';
515
516 IM_SETSTR( current_compile->rhstext, buf );
517 input_pop();
518 current_compile->tree = $2;
519
520 if( current_compile->tree->elist )
521 parent->has_super = TRUE;
522
523 /* Do some checking.
524 */
525 compile_check( current_compile );
526
527 /* Link unresolved names.
528 */
529 compile_resolve_names( current_compile, parent );
530
531 scope_pop();
532
533 $$ = current_parsenode;
534 current_parsenode = NULL;
535 }
536 ;
537
538 rhs:
539 '=' expr {
540 $$ = $2;
541 } |
542 '=' expr ',' expr optsemi rhs {
543 $$ = tree_ifelse_new( current_compile, $4, $2, $6 );
544 }
545 ;
546
547 locals:
548 ';' |
549 '{' deflist '}' |
550 '{' '}'
551 ;
552
553 optsemi:
554 /* Empty */ |
555 ';' optsemi
556 ;
557
558 deflist:
559 definition {
560 input_pop();
561 input_push( 5 );
562 }
563 optsemi |
564 deflist definition {
565 input_pop();
566 input_push( 6 );
567 }
568 optsemi
569 ;
570
571 cexprlist:
572 /* Empty */ {
573 $$ = tree_super_new( current_compile );
574 } |
575 cexprlist expr %prec TK_APPLICATION {
576 $$ = tree_super_extend( current_compile, $1, $2 );
577 }
578 ;
579
580 expr:
581 '(' expr ')' {
582 $$ = $2;
583 } |
584 TK_CONST {
585 $$ = tree_const_new( current_compile, $1 );
586 } |
587 TK_IDENT {
588 $$ = tree_leaf_new( current_compile, $1 );
589 im_free( $1 );
590 } |
591 TK_TAG {
592 $$ = tree_tag_new( current_compile, $1 );
593 im_free( $1 );
594 } |
595 TK_SCOPE {
596 $$ = tree_leaf_new( current_compile,
597 IOBJECT( symbol_get_scope( current_symbol ) )->name );
598 } |
599 TK_IF expr TK_THEN expr TK_ELSE expr %prec TK_IF {
600 $$ = tree_ifelse_new( current_compile, $2, $4, $6 );
601 } |
602 expr expr %prec TK_APPLICATION {
603 $$ = tree_appl_new( current_compile, $1, $2 );
604 } |
605 lambda |
606 list_expression {
607 $$ = $1;
608 } |
609 '(' expr ',' expr ')' {
610 $$ = tree_binop_new( current_compile, BI_COMMA, $2, $4 );
611 } |
612 binop |
613 uop
614 ;
615
616 lambda:
617 TK_LAMBDA TK_IDENT %prec TK_LAMBDA {
618 char name[256];
619 Symbol *sym;
620
621 /* Make an anonymous symbol local to the current sym, compile
622 * the expr inside that.
623 */
624 im_snprintf( name, 256, "$$lambda%d", parse_object_id++ );
625 sym = symbol_new_defining( current_compile, name );
626 sym->generated = TRUE;
627 (void) symbol_user_init( sym );
628 (void) compile_new_local( sym->expr );
629
630 /* Initialise symbol parsing variables. Save old current symbol,
631 * add new one.
632 */
633 scope_push();
634 current_symbol = sym;
635 current_compile = sym->expr->compile;
636
637 /* Make the parameter.
638 */
639 sym = symbol_new_defining( current_compile, $2 );
640 symbol_parameter_init( sym );
641 im_free( $2 );
642 }
643 expr {
644 Symbol *sym;
645
646 current_compile->tree = $4;
647
648 if( !compile_check( current_compile ) )
649 yyerror( error_get_sub() );
650
651 /* Link unresolved names in to the outer scope.
652 */
653 compile_resolve_names( current_compile,
654 compile_get_parent( current_compile ) );
655
656 /* The value of the expr is the anon we defined.
657 */
658 sym = current_symbol;
659 scope_pop();
660 $$ = tree_leafsym_new( current_compile, sym );
661 }
662 ;
663
664 list_expression:
665 '[' expr TK_DOTDOTDOT ']' {
666 $$ = tree_generator_new( current_compile, $2, NULL, NULL );
667 } |
668 '[' expr TK_DOTDOTDOT expr ']' {
669 $$ = tree_generator_new( current_compile, $2, NULL, $4 );
670 } |
671 '[' expr ',' expr TK_DOTDOTDOT ']' {
672 $$ = tree_generator_new( current_compile, $2, $4, NULL );
673 } |
674 '[' expr ',' expr TK_DOTDOTDOT expr ']' {
675 $$ = tree_generator_new( current_compile, $2, $4, $6 );
676 } |
677 '[' expr TK_SUCHTHAT {
678 char name[256];
679 Symbol *sym;
680 Compile *enclosing = current_compile;
681
682 /* Make an anonymous symbol local to the current sym, copy
683 * the map expr inside that.
684 */
685 im_snprintf( name, 256, "$$lcomp%d", parse_object_id++ );
686 sym = symbol_new_defining( current_compile, name );
687 (void) symbol_user_init( sym );
688 sym->generated = TRUE;
689 (void) compile_new_local( sym->expr );
690
691 /* Push a new scope.
692 */
693 scope_push();
694 current_symbol = sym;
695 current_compile = sym->expr->compile;
696
697 /* Somewhere to save the result expr. We have to copy the
698 * expr, as we want it to be bound in $$lcomp's context so
699 * that it can see the generators.
700 */
701 sym = symbol_new_defining( current_compile, "$$result" );
702 sym->generated = TRUE;
703 sym->placeholder = TRUE;
704 (void) symbol_user_init( sym );
705 (void) compile_new_local( sym->expr );
706 sym->expr->compile->tree = compile_copy_tree( enclosing, $2,
707 sym->expr->compile );
708 }
709 generator frompred_list ']' {
710 Symbol *sym;
711
712 /* The map expr can refer to generator names. Resolve inwards
713 * so it links to the generators.
714 */
715 compile_resolve_names( compile_get_parent( current_compile ),
716 current_compile );
717
718 /* Generate the code for the list comp.
719 */
720 compile_lcomp( current_compile );
721
722 compile_check( current_compile );
723
724 /* Link unresolved names outwards.
725 */
726 compile_resolve_names( current_compile,
727 compile_get_parent( current_compile ) );
728
729 /* The value of the expr is the anon we defined.
730 */
731 sym = current_symbol;
732 scope_pop();
733 $$ = tree_leafsym_new( current_compile, sym );
734 } |
735 '[' comma_list ']' {
736 $$ = $2;
737 } |
738 '[' ']' {
739 ParseConst elist;
740
741 elist.type = PARSE_CONST_ELIST;
742 $$ = tree_const_new( current_compile, elist );
743 }
744 ;
745
746 frompred_list:
747 /* Empty */ {
748 } |
749 frompred_list ';' frompred {
750 }
751 ;
752
753 generator:
754 simple_pattern TK_FROM expr {
755 char name[256];
756 Symbol *sym;
757
758 im_snprintf( name, 256, "$$pattern%d", parse_object_id );
759 sym = symbol_new_defining( current_compile, name );
760 sym->generated = TRUE;
761 sym->placeholder = TRUE;
762 (void) symbol_user_init( sym );
763 (void) compile_new_local( sym->expr );
764 sym->expr->compile->tree = $1;
765
766 im_snprintf( name, 256, "$$generator%d", parse_object_id++ );
767 sym = symbol_new_defining( current_compile, name );
768 sym->generated = TRUE;
769 sym->placeholder = TRUE;
770 (void) symbol_user_init( sym );
771 (void) compile_new_local( sym->expr );
772 sym->expr->compile->tree = $3;
773 }
774 ;
775
776 frompred:
777 generator |
778 expr {
779 char name[256];
780 Symbol *sym;
781
782 im_snprintf( name, 256, "$$filter%d", parse_object_id++ );
783 sym = symbol_new_defining( current_compile, name );
784 sym->generated = TRUE;
785 sym->placeholder = TRUE;
786 (void) symbol_user_init( sym );
787 (void) compile_new_local( sym->expr );
788 sym->expr->compile->tree = $1;
789 }
790 ;
791
792 comma_list:
793 expr ',' comma_list {
794 $$ = tree_lconst_extend( current_compile, $3, $1 );
795 } |
796 expr {
797 $$ = tree_lconst_new( current_compile, $1 );
798 }
799 ;
800
801 /* How odd, break the "'+' { BI_ADD } | ..." into a separate production and we
802 * get reduce/reduce conflits. Copypaste a lot instead.
803 */
804 binop:
805 expr '+' expr {
806 $$ = tree_binop_new( current_compile, BI_ADD, $1, $3 );
807 } |
808 expr ':' expr {
809 $$ = tree_binop_new( current_compile, BI_CONS, $1, $3 );
810 } |
811 expr '-' expr {
812 $$ = tree_binop_new( current_compile, BI_SUB, $1, $3 );
813 } |
814 expr '?' expr {
815 $$ = tree_binop_new( current_compile, BI_SELECT, $1, $3 );
816 } |
817 expr '/' expr {
818 $$ = tree_binop_new( current_compile, BI_DIV, $1, $3 );
819 } |
820 expr '*' expr {
821 $$ = tree_binop_new( current_compile, BI_MUL, $1, $3 );
822 } |
823 expr '%' expr {
824 $$ = tree_binop_new( current_compile, BI_REM, $1, $3 );
825 } |
826 expr TK_JOIN expr {
827 $$ = tree_binop_new( current_compile, BI_JOIN, $1, $3 );
828 } |
829 expr TK_POW expr {
830 $$ = tree_binop_new( current_compile, BI_POW, $1, $3 );
831 } |
832 expr TK_LSHIFT expr {
833 $$ = tree_binop_new( current_compile, BI_LSHIFT, $1, $3 );
834 } |
835 expr TK_RSHIFT expr {
836 $$ = tree_binop_new( current_compile, BI_RSHIFT, $1, $3 );
837 } |
838 expr '^' expr {
839 $$ = tree_binop_new( current_compile, BI_EOR, $1, $3 );
840 } |
841 expr TK_LAND expr {
842 $$ = tree_binop_new( current_compile, BI_LAND, $1, $3 );
843 } |
844 expr TK_BAND expr {
845 $$ = tree_binop_new( current_compile, BI_BAND, $1, $3 );
846 } |
847 expr '@' expr {
848 $$ = tree_compose_new( current_compile, $1, $3 );
849 } |
850 expr TK_LOR expr {
851 $$ = tree_binop_new( current_compile, BI_LOR, $1, $3 );
852 } |
853 expr TK_BOR expr {
854 $$ = tree_binop_new( current_compile, BI_BOR, $1, $3 );
855 } |
856 expr TK_LESS expr {
857 $$ = tree_binop_new( current_compile, BI_LESS, $1, $3 );
858 } |
859 expr TK_LESSEQ expr {
860 $$ = tree_binop_new( current_compile, BI_LESSEQ, $1, $3 );
861 } |
862 expr TK_MORE expr {
863 $$ = tree_binop_new( current_compile, BI_MORE, $1, $3 );
864 } |
865 expr TK_MOREEQ expr {
866 $$ = tree_binop_new( current_compile, BI_MOREEQ, $1, $3 );
867 } |
868 expr TK_EQ expr {
869 $$ = tree_binop_new( current_compile, BI_EQ, $1, $3 );
870 } |
871 expr TK_NOTEQ expr {
872 $$ = tree_binop_new( current_compile, BI_NOTEQ, $1, $3 );
873 } |
874 expr TK_PEQ expr {
875 $$ = tree_binop_new( current_compile, BI_PEQ, $1, $3 );
876 } |
877 expr TK_PNOTEQ expr {
878 $$ = tree_binop_new( current_compile, BI_PNOTEQ, $1, $3 );
879 } |
880 expr '.' expr {
881 $$ = tree_binop_new( current_compile, BI_DOT, $1, $3 );
882 } |
883 expr TK_DIFF expr {
884 ParseNode *pn1, *pn2;
885
886 pn1 = tree_leaf_new( current_compile, "difference" );
887 pn2 = tree_leaf_new( current_compile, "equal" );
888 pn1 = tree_appl_new( current_compile, pn1, pn2 );
889 pn1 = tree_appl_new( current_compile, pn1, $1 );
890 pn1 = tree_appl_new( current_compile, pn1, $3 );
891
892 $$ = pn1;
893 } |
894 expr TK_TO expr {
895 ParseNode *pn;
896
897 pn = tree_leaf_new( current_compile, "mknvpair" );
898 pn = tree_appl_new( current_compile, pn, $1 );
899 pn = tree_appl_new( current_compile, pn, $3 );
900
901 $$ = pn;
902 }
903 ;
904
905 signed:
906 /* Nothing */ |
907 TK_SIGNED
908 ;
909
910 unsigned:
911 /* Nothing */ |
912 TK_UNSIGNED
913 ;
914
915 uop:
916 '(' unsigned TK_CHAR ')' expr %prec TK_UMINUS {
917 $$ = tree_unop_new( current_compile, UN_CUCHAR, $5 );
918 } |
919 '(' TK_SIGNED TK_CHAR ')' expr %prec TK_UMINUS {
920 $$ = tree_unop_new( current_compile, UN_CSCHAR, $5 );
921 } |
922 '(' signed TK_SHORT ')' expr %prec TK_UMINUS {
923 $$ = tree_unop_new( current_compile, UN_CSSHORT, $5 );
924 } |
925 '(' TK_UNSIGNED TK_SHORT ')' expr %prec TK_UMINUS {
926 $$ = tree_unop_new( current_compile, UN_CUSHORT, $5 );
927 } |
928 '(' signed TK_INT ')' expr %prec TK_UMINUS {
929 $$ = tree_unop_new( current_compile, UN_CSINT, $5 );
930 } |
931 '(' TK_UNSIGNED TK_INT ')' expr %prec TK_UMINUS {
932 $$ = tree_unop_new( current_compile, UN_CUINT, $5 );
933 } |
934 '(' TK_FLOAT ')' expr %prec TK_UMINUS {
935 $$ = tree_unop_new( current_compile, UN_CFLOAT, $4 );
936 } |
937 '(' TK_DOUBLE ')' expr %prec TK_UMINUS {
938 $$ = tree_unop_new( current_compile, UN_CDOUBLE, $4 );
939 } |
940 '(' TK_COMPLEX ')' expr %prec TK_UMINUS {
941 $$ = tree_unop_new( current_compile, UN_CCOMPLEX, $4 );
942 } |
943 '(' TK_DOUBLE TK_COMPLEX ')' expr %prec TK_UMINUS {
944 $$ = tree_unop_new( current_compile, UN_CDCOMPLEX, $5 );
945 } |
946 TK_UMINUS expr {
947 $$ = tree_unop_new( current_compile, UN_MINUS, $2 );
948 } |
949 '!' expr {
950 $$ = tree_unop_new( current_compile, UN_NEG, $2 );
951 } |
952 '~' expr {
953 $$ = tree_unop_new( current_compile, UN_COMPLEMENT, $2 );
954 } |
955 TK_UPLUS expr {
956 $$ = tree_unop_new( current_compile, UN_PLUS, $2 );
957 }
958 ;
959
960 /* Stuff that can appear on the LHS of an equals, or as a parameter pattern.
961 */
962 simple_pattern:
963 leaf_pattern |
964 '(' leaf_pattern ',' leaf_pattern ')' {
965 $$ = tree_binop_new( current_compile, BI_COMMA, $2, $4 );
966 } |
967 simple_pattern ':' simple_pattern {
968 $$ = tree_binop_new( current_compile, BI_CONS, $1, $3 );
969 } |
970 '(' complex_pattern ')' {
971 $$ = $2;
972 } |
973 '[' list_pattern ']' {
974 $$ = $2;
975 } |
976 '[' ']' {
977 ParseConst elist;
978
979 elist.type = PARSE_CONST_ELIST;
980 $$ = tree_const_new( current_compile, elist );
981 }
982 ;
983
984 /* Stuff that can appear in a complex (a, b) pattern.
985 */
986 leaf_pattern:
987 TK_IDENT {
988 $$ = tree_leaf_new( current_compile, $1 );
989 im_free( $1 );
990 } |
991 TK_CONST {
992 $$ = tree_const_new( current_compile, $1 );
993 }
994 ;
995
996 /* What can appear in round brackets or a comma list.
997 */
998 complex_pattern:
999 TK_IDENT TK_IDENT {
1000 $$ = tree_pattern_class_new( current_compile, $1,
1001 tree_leaf_new( current_compile, $2 ) );
1002 im_free( $1 );
1003 im_free( $2 );
1004 } |
1005 simple_pattern
1006 ;
1007
1008 list_pattern:
1009 complex_pattern ',' list_pattern {
1010 $$ = tree_lconst_extend( current_compile, $3, $1 );
1011 } |
1012 complex_pattern {
1013 $$ = tree_lconst_new( current_compile, $1 );
1014 }
1015 ;
1016
1017 %%
1018
1019 /* Return point on syntax error.
1020 */
1021 jmp_buf parse_error_point;
1022
1023 /* Text we've lexed.
1024 */
1025 char lex_text_buffer[MAX_STRSIZE];
1026 VipsBuf lex_text = VIPS_BUF_STATIC( lex_text_buffer );
1027
1028 /* State of input system.
1029 */
1030 InputState input_state;
1031
1032 /* Defintions for the static decls at the top. We have to put the defs down
1033 * here to mkake sure they don't creep in to the generated parser.h.
1034 */
1035
1036 /* Actually, we can't make these static :-( since they are declared extern at
1037 * the top of the file.
1038 */
1039 Symbol *current_symbol;
1040 Symbol *root_symbol;
1041 Compile *current_compile = NULL;
1042 ParseNode *current_parsenode = NULL;
1043 Toolkit *current_kit;
1044 int tool_position;
1045 int last_top_lineno;
1046 Symbol *scope_stack_symbol[MAX_SSTACK];
1047 Compile *scope_stack_compile[MAX_SSTACK];
1048 int scope_sp = 0;
1049 int parse_object_id = 0;
1050
1051 /* Here for errors in parse.
1052 *
1053 * Bison calls yyerror with only a char* arg. This printf() version is called
1054 * from nip2 in a few places during parse.
1055 */
1056 void
nip2yyerror(const char * sub,...)1057 nip2yyerror( const char *sub, ... )
1058 {
1059 va_list ap;
1060 char buf[4096];
1061
1062 va_start( ap, sub );
1063 (void) im_vsnprintf( buf, 4096, sub, ap );
1064 va_end( ap );
1065
1066 error_top( _( "Parse error." ) );
1067
1068 if( current_compile && current_compile->last_sym )
1069 error_sub( _( "Error in %s: %s" ),
1070 IOBJECT( current_compile->last_sym )->name, buf );
1071 else
1072 error_sub( _( "Error: %s" ), buf );
1073
1074 longjmp( parse_error_point, -1 );
1075 }
1076
1077 /* Bison calls this.
1078 */
1079 void
yyerror(const char * msg)1080 yyerror( const char *msg )
1081 {
1082 nip2yyerror( "%s", msg );
1083 }
1084
1085 /* Attach yyinput to a file.
1086 */
1087 void
attach_input_file(iOpenFile * of)1088 attach_input_file( iOpenFile *of )
1089 {
1090 InputState *is = &input_state;
1091
1092 #ifdef DEBUG
1093 printf( "attach_input_file: \"%s\"\n", of->fname );
1094 #endif /*DEBUG*/
1095
1096 /* Need to clear flex/bison's buffers in case we abandoned the
1097 * previous parse.
1098 */
1099 yyrestart( NULL );
1100
1101 is->of = of;
1102 is->str = NULL;
1103 is->strpos = NULL;
1104 is->bwp = 0;
1105 is->bspsp = 0;
1106 is->bsp[is->bspsp] = 0;
1107 is->lineno = 1;
1108 is->charno = 0;
1109 is->pcharno = 0;
1110 is->charpos = 0;
1111 is->oldchar = -1;
1112
1113 /* Init text gatherer.
1114 */
1115 vips_buf_rewind( &lex_text );
1116 }
1117
1118 /* Attach yyinput to a string.
1119 */
1120 void
attach_input_string(const char * str)1121 attach_input_string( const char *str )
1122 {
1123 InputState *is = &input_state;
1124
1125 #ifdef DEBUG
1126 printf( "attach_input_string: \"%s\"\n", str );
1127 #endif /*DEBUG*/
1128
1129 yyrestart( NULL );
1130
1131 is->of = NULL;
1132 is->str = (char *) str;
1133 is->strpos = (char *) str;
1134 is->bwp = 0;
1135 is->bspsp = 0;
1136 is->bsp[is->bspsp] = 0;
1137 is->lineno = 1;
1138 is->charno = 0;
1139 is->pcharno = 0;
1140 is->charpos = 0;
1141 is->oldchar = -1;
1142
1143 /* Init text gatherer.
1144 */
1145 vips_buf_rewind( &lex_text );
1146 }
1147
1148 /* Read a character from the input.
1149 */
1150 int
ip_input(void)1151 ip_input( void )
1152 {
1153 InputState *is = &input_state;
1154 int ch;
1155
1156 if( is->oldchar >= 0 ) {
1157 /* From unget buffer.
1158 */
1159 ch = is->oldchar;
1160 is->oldchar = -1;
1161 }
1162 else if( is->of ) {
1163 /* Input from file.
1164 */
1165 if( (ch = getc( is->of->fp )) == EOF )
1166 return( 0 );
1167 }
1168 else {
1169 /* Input from string.
1170 */
1171 if( (ch = *is->strpos) )
1172 is->strpos++;
1173 else
1174 /* No counts to update!
1175 */
1176 return( 0 );
1177 }
1178
1179 /* Update counts.
1180 */
1181 if( ch == '\n' ) {
1182 is->lineno++;
1183 is->pcharno = is->charno + 1;
1184 is->charno = 0;
1185 }
1186 is->charno++;
1187 is->charpos++;
1188
1189 /* Add this character to the characters we have accumulated for this
1190 * definition.
1191 */
1192 if( is->bwp >= MAX_STRSIZE )
1193 yyerror( _( "definition is too long" ) );
1194 if( is->bwp >= 0 )
1195 is->buf[is->bwp] = ch;
1196 is->bwp++;
1197
1198 /* Add to lex text buffer.
1199 */
1200 if( is->charno > 0 )
1201 vips_buf_appendc( &lex_text, ch );
1202
1203 #ifdef DEBUG_CHARACTER
1204 printf( "ip_input: returning '%c'\n", ch );
1205 #endif /*DEBUG_CHARACTER*/
1206
1207 return( ch );
1208 }
1209
1210 /* Unget an input character.
1211 */
1212 void
ip_unput(int ch)1213 ip_unput( int ch )
1214 {
1215 InputState *is = &input_state;
1216
1217 #ifdef DEBUG_CHARACTER
1218 printf( "ip_unput: ungetting '%c'\n", ch );
1219 #endif /*DEBUG_CHARACTER*/
1220
1221 /* Is lex trying to unget the end-of-file marker? Do nothing if it is.
1222 */
1223 if( !ch )
1224 return;
1225
1226 if( is->of ) {
1227 if( ungetc( ch, is->of->fp ) == EOF )
1228 error( "unget buffer overflow" );
1229 }
1230 else
1231 /* Save extra char here.
1232 */
1233 is->oldchar = ch;
1234
1235 /* Redo counts.
1236 */
1237 if( ch == '\n' ) {
1238 is->lineno--;
1239
1240 /* Restore previous charno.
1241 */
1242 is->charno = is->pcharno;
1243 is->pcharno = 0;
1244 }
1245 is->charno--;
1246 is->charpos--;
1247 is->bwp--;
1248
1249 /* Unget from lex text buffer.
1250 */
1251 if( is->charno > 0 )
1252 vips_buf_removec( &lex_text, ch );
1253 }
1254
1255 /* Test for end-of-input.
1256 */
1257 gboolean
is_EOF(void)1258 is_EOF( void )
1259 {
1260 InputState *is = &input_state;
1261
1262 if( is->of )
1263 return( feof( is->of->fp ) );
1264 else
1265 return( *is->str == '\0' );
1266 }
1267
1268 /* Return the text we have accumulated for the current definition. Remove
1269 * leading and trailing whitespace and spare semicolons. out needs to be
1270 * MAX_STRSIZE.
1271 */
1272 char *
input_text(char * out)1273 input_text( char *out )
1274 {
1275 InputState *is = &input_state;
1276 const char *buf = is->buf;
1277
1278 int start = is->bsp[is->bspsp];
1279 int end = is->bwp;
1280 int len;
1281 int i;
1282
1283 for( i = start; i < end &&
1284 (isspace( buf[i] ) || buf[i] == ';'); i++ )
1285 ;
1286 start = i;
1287 for( i = end - 1; i > start &&
1288 (isspace( buf[i] ) || buf[i] == ';'); i-- )
1289 ;
1290 end = i + 1;
1291
1292 len = end - start;
1293
1294 g_assert( len < MAX_STRSIZE - 1 );
1295 im_strncpy( out, buf + start, len + 1 );
1296 out[len] = '\0';
1297
1298 #ifdef DEBUG_CHARACTER
1299 printf( "input_text: level %d, returning \"%s\"\n",
1300 is->bspsp, out );
1301 #endif /*DEBUG_CHARACTER*/
1302
1303 return( out );
1304 }
1305
1306 /* Reset/push/pop input stacks.
1307 */
1308 void
input_reset(void)1309 input_reset( void )
1310 {
1311 InputState *is = &input_state;
1312
1313 #ifdef DEBUG_CHARACTER
1314 printf( "input_reset:\n" );
1315 #endif /*DEBUG_CHARACTER*/
1316
1317 is->bwp = 0;
1318 is->bspsp = 0;
1319 is->bsp[0] = 0;
1320 vips_buf_rewind( &lex_text );
1321 }
1322
1323 void
input_push(int n)1324 input_push( int n )
1325 {
1326 InputState *is = &input_state;
1327
1328 #ifdef DEBUG_CHARACTER
1329 printf( "input_push(%d): going to level %d, %d bytes into buffer\n",
1330 n, is->bspsp + 1, is->bwp );
1331
1332 {
1333 const int len = IM_MIN( is->bwp, 20 );
1334 int i;
1335
1336 for( i = is->bwp - len; i < is->bwp; i++ )
1337 if( is->buf[i] == '\n' )
1338 printf( "@" );
1339 else if( is->buf[i] == ' ' || is->buf[i] == '\t' )
1340 printf( "_" );
1341 else
1342 printf( "%c", is->buf[i] );
1343 printf( "\n" );
1344 for( i = 0; i < len; i++ )
1345 printf( "-" );
1346 printf( "^\n" );
1347 }
1348 #endif /*DEBUG_CHARACTER*/
1349
1350 is->bspsp += 1;
1351 if( is->bspsp >= MAX_SSTACK )
1352 error( "bstack overflow" );
1353
1354 is->bsp[is->bspsp] = is->bwp;
1355 }
1356
1357 /* Yuk! We've just done an input_push() to try to grab the RHS of a
1358 * definition ... unfortunately, due to token readahead, we've probably
1359 * already read the start of the RHS.
1360 *
1361 * Back up the start point to just after the last ch character.
1362 */
1363 void
input_backtoch(char ch)1364 input_backtoch( char ch )
1365 {
1366 InputState *is = &input_state;
1367 int i;
1368
1369 for( i = is->bsp[is->bspsp] - 1; i > 0 && is->buf[i] != ch; i-- )
1370 ;
1371
1372 if( is->buf[i] == ch )
1373 is->bsp[is->bspsp] = i + 1;
1374 }
1375
1376 /* Move the last input_push() point back 1 character.
1377 */
1378 void
input_back1(void)1379 input_back1( void )
1380 {
1381 InputState *is = &input_state;
1382
1383 if( is->bsp[is->bspsp] > 0 )
1384 is->bsp[is->bspsp] -= 1;
1385 }
1386
1387 void
input_pop(void)1388 input_pop( void )
1389 {
1390 InputState *is = &input_state;
1391
1392 #ifdef DEBUG_CHARACTER
1393 printf( "input_pop: %d bytes into buffer\n", input_state.bwp );
1394 #endif /*DEBUG_CHARACTER*/
1395
1396 if( is->bspsp <= 0 )
1397 error( "bstack underflow" );
1398
1399 is->bspsp--;
1400 }
1401
1402 void
scope_push(void)1403 scope_push( void )
1404 {
1405 if( scope_sp == MAX_SSTACK )
1406 error( "sstack overflow" );
1407
1408 scope_stack_symbol[scope_sp] = current_symbol;
1409 scope_stack_compile[scope_sp] = current_compile;
1410 scope_sp += 1;
1411 }
1412
1413 void
scope_pop(void)1414 scope_pop( void )
1415 {
1416 if( scope_sp <= 0 )
1417 error( "sstack underflow" );
1418
1419 scope_sp -= 1;
1420 current_symbol = scope_stack_symbol[scope_sp];
1421 current_compile = scope_stack_compile[scope_sp];
1422 }
1423
1424 /* Back to the outermost scope.
1425 */
1426 void
scope_pop_all(void)1427 scope_pop_all( void )
1428 {
1429 if( scope_sp > 0 ) {
1430 scope_sp = 0;
1431 current_symbol = scope_stack_symbol[scope_sp];
1432 current_compile = scope_stack_compile[scope_sp];
1433 }
1434 }
1435
1436 /* Reset/push/pop parser stacks.
1437 */
1438 void
scope_reset(void)1439 scope_reset( void )
1440 {
1441 scope_sp = 0;
1442 }
1443
1444 /* End of top level parse. Fix up the symbol.
1445 */
1446 void *
parse_toplevel_end(Symbol * sym)1447 parse_toplevel_end( Symbol *sym )
1448 {
1449 Tool *tool;
1450
1451 tool = tool_new_sym( current_kit, tool_position, sym );
1452 tool->lineno = last_top_lineno;
1453 symbol_made( sym );
1454
1455 return( NULL );
1456 }
1457
1458 /* Built a pattern access definition. Set the various text fragments from the
1459 * def we are drived from.
1460 */
1461 void *
parse_access_end(Symbol * sym,Symbol * main)1462 parse_access_end( Symbol *sym, Symbol *main )
1463 {
1464 IM_SETSTR( sym->expr->compile->rhstext,
1465 main->expr->compile->rhstext );
1466 IM_SETSTR( sym->expr->compile->prhstext,
1467 main->expr->compile->prhstext );
1468 IM_SETSTR( sym->expr->compile->text,
1469 main->expr->compile->text );
1470
1471 return( NULL );
1472 }
1473
1474 /* Interface to parser.
1475 */
1476 static gboolean
parse_input(int ch,Symbol * sym,Toolkit * kit,int pos)1477 parse_input( int ch, Symbol *sym, Toolkit *kit, int pos )
1478 {
1479 current_kit = kit;
1480 current_symbol = sym;
1481 root_symbol = sym;
1482 tool_position = pos;
1483
1484 scope_reset();
1485 input_reset();
1486
1487 /* Signal start nonterminal to parser.
1488 */
1489 ip_unput( ch );
1490
1491 if( setjmp( parse_error_point ) ) {
1492 /* Restore current_compile.
1493 */
1494 scope_pop_all();
1495
1496 if( current_compile )
1497 compile_error_set( current_compile );
1498
1499 return( FALSE );
1500 }
1501 yyparse();
1502
1503 /* All ok.
1504 */
1505 return( TRUE );
1506 }
1507
1508 /* Parse the input into a set of symbols at a position in a kit.
1509 * kit may be NULL for no kit.
1510 */
1511 gboolean
parse_toplevel(Toolkit * kit,int pos)1512 parse_toplevel( Toolkit *kit, int pos )
1513 {
1514 gboolean result;
1515
1516 current_compile = NULL;
1517 result = parse_input( ',', kit->kitg->root, kit, pos );
1518 iobject_changed( IOBJECT( kit ) );
1519
1520 return( result );
1521 }
1522
1523 /* Parse a single top-level definition.
1524 */
1525 gboolean
parse_onedef(Toolkit * kit,int pos)1526 parse_onedef( Toolkit *kit, int pos )
1527 {
1528 gboolean result;
1529
1530 current_compile = NULL;
1531 result = parse_input( '^', kit->kitg->root, kit, pos );
1532 iobject_changed( IOBJECT( kit ) );
1533
1534 return( result );
1535 }
1536
1537 /* Parse new text into "expr". If params is set, str should be "a b = a+b"
1538 * (ie. include params), if not, then just rhs (eg. "a+b").
1539 */
1540 gboolean
parse_rhs(Expr * expr,ParseRhsSyntax syntax)1541 parse_rhs( Expr *expr, ParseRhsSyntax syntax )
1542 {
1543 static const char start_ch_table[] = {
1544 '&', /* PARSE_RHS */
1545 '*', /* PARSE_PARAMS */
1546 '@' /* PARSE_SUPER */
1547 };
1548
1549 char start_ch = start_ch_table[(int) syntax];
1550 Compile *compile = compile_new_local( expr );
1551
1552 current_compile = compile;
1553 if( !parse_input( start_ch, expr->sym, NULL, -1 ) ) {
1554 current_compile = NULL;
1555 return( FALSE );
1556 }
1557 current_compile = NULL;
1558
1559 #ifdef DEBUG
1560 printf( "parse_rhs:\n" );
1561 dump_tree( compile->tree );
1562 #endif /*DEBUG*/
1563
1564 /* Resolve any dynamic refs.
1565 */
1566 expr_resolve( expr );
1567
1568 /* Compile.
1569 */
1570 if( compile_object( compile ) )
1571 return( FALSE );
1572
1573 return( TRUE );
1574 }
1575
1576 /* Free any stuff the lexer might have allocated.
1577 */
1578 void
free_lex(int yychar)1579 free_lex( int yychar )
1580 {
1581 switch( yychar ) {
1582 case TK_CONST:
1583 tree_const_destroy( &yylval.yy_const );
1584 break;
1585
1586 case TK_IDENT:
1587 case TK_TAG:
1588 IM_FREE( yylval.yy_name );
1589 break;
1590
1591 default:
1592 break;
1593 }
1594 }
1595
1596 /* Do we have a string of the form "IDENT = .."? Use the lexer to look along
1597 * the string checking components, return the IDENT if we do, NULL otherwise.
1598 */
1599 char *
parse_test_define(void)1600 parse_test_define( void )
1601 {
1602 extern int yylex( void );
1603 int yychar;
1604 char *ident;
1605
1606 ident = NULL;
1607
1608 if( setjmp( parse_error_point ) ) {
1609 /* Here for yyerror in lex.
1610 */
1611 IM_FREE( ident );
1612
1613 return( NULL );
1614 }
1615
1616 if( (yychar = yylex()) != TK_IDENT ) {
1617 free_lex( yychar );
1618
1619 return( NULL );
1620 }
1621 ident = yylval.yy_name;
1622
1623 if( (yychar = yylex()) != '=' ) {
1624 free_lex( yychar );
1625 IM_FREE( ident );
1626
1627 return( NULL );
1628 }
1629
1630 return( ident );
1631 }
1632
1633 /* Do we have a string like "Workspaces.untitled.A1 = .."? Check for the
1634 * symbols as we see them, make the last one and return it. Used by --set.
1635 */
1636 Symbol *
parse_set_symbol(void)1637 parse_set_symbol( void )
1638 {
1639 int yychar;
1640 extern int yylex( void );
1641 Compile *compile = symbol_root->expr->compile;
1642 char *ident;
1643 Symbol *sym;
1644
1645 ident = NULL;
1646
1647 if( setjmp( parse_error_point ) ) {
1648 /* Here for yyerror in lex.
1649 */
1650 IM_FREE( ident );
1651 return( NULL );
1652 }
1653
1654 do {
1655 if( (yychar = yylex()) != TK_IDENT && yychar != TK_TAG ) {
1656 free_lex( yychar );
1657 yyerror( _( "identifier expected" ) );
1658 }
1659 ident = yylval.yy_name;
1660
1661 switch( (yychar = yylex()) ) {
1662 case '.':
1663 /* There's a dot, so we expect another identifier to
1664 * come. Look up this one and move to that context.
1665 */
1666 if( !(sym = compile_lookup( compile, ident )) )
1667 nip2yyerror( _( "'%s' does not exist" ),
1668 ident );
1669 if( !sym->expr ||
1670 !sym->expr->compile )
1671 nip2yyerror( _( "'%s' has no members" ),
1672 ident );
1673 compile = sym->expr->compile;
1674 IM_FREE( ident );
1675 break;
1676
1677 case '=':
1678 /* This is the final identifier: create the symbol in
1679 * this context.
1680 */
1681 sym = symbol_new_defining( compile, ident );
1682 IM_FREE( ident );
1683 break;
1684
1685 default:
1686 free_lex( yychar );
1687 yyerror( _( "'.' or '=' expected" ) );
1688 }
1689 } while( yychar != '=' );
1690
1691 return( sym );
1692 }
1693