4 static char *RCSid
= "$Id$";
8 * The Regina Rexx Interpreter
9 * Copyright (C) 1992-1994 Anders Christensen <anders@pvv.unit.no>
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Library General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Library General Public License for more details.
21 * You should have received a copy of the GNU Library General Public
22 * License along with this library; if not, write to the Free
23 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #if defined(HAVE_MALLOC_H)
33 #if defined(HAVE_ALLOCA_H)
42 #if defined(_MSC_VER) || defined(MAC)
43 # define __STDC__ 1 /* Hack to allow const since it is not defined */
46 #define YYSTYPE nodeptr
48 /* locals, they are protected by regina_parser (see lexsrc.l) */
49 static int tmplno
, /* lineno of current instruction */
50 tmpchr
, /* character position of current instruction */
51 level
, /* nested do/if/select depth */
52 start_parendepth
; /* see below at parendepth */
55 * parendepth regulates the action which happens detecting a comma or an
56 * empty expression. A negative values indicates an error; both a comma
57 * and an empty expression raise an error.
58 * We regulate the enumeration of arguments with this semantical flag.
59 * Look at "call subroutine args" and "function args". Function itself
60 * contains a parentheses pair, so starting with a depth of just allows
61 * the enumeration. subroutine starts with either 0 or 1. The latter one
62 * is allowed for the support request of "call subroutine(a,b,c)" which
63 * isn't allowed by ANSI but can be enabled for backward compatibility.
65 static int parendepth
;
67 static nodeptr current
, with
= NULL
;
69 static char *nullptr
= NULL
; /* for C++ compilation */
71 typedef
enum { IS_UNKNOWN
,
75 IS_COMP_SYMBOL
} node_type
;
77 typedef
enum { REDUCE_CALL
,
80 REDUCE_SUBEXPR
} reduce_mode
;
82 static node_type gettypeof
( nodeptr thisptr
) ;
83 static void checkconst
( nodeptr thisptr
) ;
84 static nodeptr reduce_expr_list
( nodeptr thisptr
, reduce_mode mode
);
85 static void transform
( nodeptr thisptr
) ;
86 static nodeptr create_head
( const char *name
) ;
87 static nodeptr makenode
( int type
, int numb
, ...
) ;
88 static void checkdosyntax
( cnodeptr thisptr
) ;
89 void newlabel
( const tsd_t
*TSD
, internal_parser_type
*ipt
, nodeptr thisptr
) ;
90 static nodeptr optgluelast
( nodeptr p1
, nodeptr p2
);
91 static void move_labels
( nodeptr front
, nodeptr end
, int level
);
93 #define IS_EXPRLIST(x) ( ( (x) != NULL ) \
94 && ( ( (x
)->type
== X_CEXPRLIST
) \
95 ||
( (x
)->type
== X_EXPRLIST
) ) )
97 #define IS_FUNCTION(x) ( ( (x) != NULL ) \
98 && ( ( (x
)->type
== X_EX_FUNC
) \
99 ||
( (x
)->type
== X_IN_FUNC
) ) )
101 #define AUTO_REDUCE(x,y) { if ( parendepth == 1 ) \
103 x
= reduce_expr_list
( x
, REDUCE_EXPR
); \
104 /* detect "call s (a,b)<op>" and */ \
105 /* "call s ()<op>" */ \
106 if
( IS_EXPRLIST
( x
) ) \
109 exiterror
( ERR_INVALID_EXPRESSION
, 1, y
); \
110 else if
( (x
)->p
[0] == NULL
) \
111 exiterror
( ERR_UNEXPECTED_PARAN
, 0 ); \
113 exiterror
( ERR_UNEXPECTED_PARAN
, 1 ); \
119 %token ADDRESS ARG CALL DO TO BY FOR WHILE UNTIL EXIT IF THEN ELSE
120 %token ITERATE INTERPRET LEAVE NOP NUMERIC PARSE EXTERNAL SOURCE VAR
121 %token VALUE WITH PROCEDURE EXPOSE PULL PUSH QUEUE SAY RETURN SELECT
122 %token WHEN DROP OTHERWISE SIGNAL ON OFF ERROR SYNTAX HALT NOVALUE
123 %token TRACE END UPPER ASSIGNMENTVARIABLE STATSEP FOREVER DIGITS FORM
124 %token FUZZ SCIENTIFIC ENGINEERING NOT CONCATENATE MODULUS GTE GT LTE
125 %token LT DIFFERENT EQUALEQUAL NOTEQUALEQUAL OFFSET SPACE EXP XOR
126 %token PLACEHOLDER NOTREADY CONSYMBOL SIMSYMBOL EXFUNCNAME INFUNCNAME
127 %token LABEL DOVARIABLE HEXSTRING STRING VERSION LINEIN WHATEVER NAME
128 %token FAILURE BINSTRING OPTIONS ENVIRONMENT LOSTDIGITS
129 %token GTGT LTLT NOTGTGT NOTLTLT GTGTE LTLTE
130 %token INPUT OUTPUT ERROR NORMAL APPEND REPLACE STREAM STEM LIFO FIFO
131 %token LOWER CASELESS
137 %left
'=' DIFFERENT GTE GT LT LTE EQUALEQUAL NOTEQUALEQUAL GTGT LTLT NOTGTGT NOTLTLT GTGTE LTLTE
138 %left CONCATENATE SPACE CCAT
140 %left
'*' '/' '%' MODULUS
142 %left UMINUS UPLUS NOT
/*UPLUS and UMINUS are locally used to assign precedence*/
160 if
( get_options_flag
( parser_data.TSD
->currlevel
, EXT_CALLS_AS_FUNCS
)
161 && !get_options_flag
( parser_data.TSD
->currlevel
, EXT_STRICT_ANSI
) )
162 start_parendepth
= 1;
164 start_parendepth
= 0;
169 prog
: nlncl stats
{ $$
= optgluelast
( $1, $2 );
178 stats
: stats ystatement
{ /* fixes bug 579711 */
179 $$
= optgluelast
( $1, $2 ); }
180 | ystatement
{ $$
= $1; }
183 xstats
: xstats statement
{ /* fixes bug 579711 */
184 $$
= optgluelast
( $1, $2 ); }
185 | statement gruff
{ $$
= $1; }
188 ystatement
: statement
{ $$
= $1 ; }
189 | lonely_end
{ exiterror
( ERR_UNMATCHED_END
, 1 ); }
192 lonely_end
: gruff end ncl
/* ncl's label's out of matter, this
193 * rule leads to an error.
197 nxstats
: xstats
{ $$
= $1; }
198 | gruff
{ $$
= NULL
; }
201 ncl
: ncl STATSEP optLabels
{ $$
= optgluelast
( $1, $3 ); }
202 | STATSEP optLabels
{ $$
= $2; }
205 nlncl
: optLabels ncl
{ $$
= optgluelast
( $1, $2 ); }
206 | optLabels
{ $$
= $1; }
209 optLabels
: optLabels label_stat
{ $$
= optgluelast
( $1, $2 ); }
213 statement
: mttstatement
217 gruff
: { tmpchr
=parser_data.tstart
;
218 tmplno
=parser_data.tline
; }
221 mttstatement
: gruff mtstatement
{ $$
=$2; }
224 mtstatement
: nclstatement ncl
{ $$
= optgluelast
( $1, $2 ); }
230 nclstatement
: address_stat
257 call
: CALL
{ $$
= makenode
(X_CALL
,0) ;
258 $$
->lineno
= parser_data.tline
;
259 $$
->charnr
= parser_data.tstart
; }
261 do
: DO
{ $$
= makenode
(X_DO
,0) ;
262 $$
->lineno
= parser_data.tline
;
263 $$
->charnr
= parser_data.tstart
;
266 exit
: EXIT
{ $$
= makenode
(X_EXIT
,0) ;
267 $$
->lineno
= parser_data.tline
;
268 $$
->charnr
= parser_data.tstart
; }
270 if
: IF
{ $$
= makenode
(X_IF
,0) ;
271 $$
->lineno
= parser_data.tline
;
272 $$
->charnr
= parser_data.tstart
;
275 iterate
: ITERATE
{ $$
= makenode
(X_ITERATE
,0) ;
276 $$
->lineno
= parser_data.tline
;
277 $$
->charnr
= parser_data.tstart
; }
279 leave
: LEAVE
{ $$
= makenode
(X_LEAVE
,0) ;
280 $$
->lineno
= parser_data.tline
;
281 $$
->charnr
= parser_data.tstart
; }
283 say
: SAY
{ $$
= makenode
(X_SAY
,0) ;
284 $$
->lineno
= parser_data.tline
;
285 $$
->charnr
= parser_data.tstart
; }
287 return
: RETURN
{ $$
= makenode
(X_RETURN
,0) ;
288 $$
->lineno
= parser_data.tline
;
289 $$
->charnr
= parser_data.tstart
; }
291 address
: ADDRESS
{ $$
= makenode
(X_ADDR_N
,0) ;
292 $$
->lineno
= parser_data.tline
;
293 $$
->charnr
= parser_data.tstart
; }
295 arg
: ARG
{ $$
= makenode
(X_PARSE_ARG
,0) ;
296 $$
->lineno
= parser_data.tline
;
297 $$
->charnr
= parser_data.tstart
; }
299 drop
: DROP
{ $$
= makenode
(X_DROP
,0) ;
300 $$
->lineno
= parser_data.tline
;
301 $$
->charnr
= parser_data.tstart
; }
303 interpret
: INTERPRET
{ $$
= makenode
(X_IPRET
,0) ;
304 $$
->lineno
= parser_data.tline
;
305 $$
->charnr
= parser_data.tstart
; }
307 label
: LABEL
{ $$
= makenode
(X_LABEL
,0) ;
308 $$
->lineno
= parser_data.tline
;
309 $$
->charnr
= parser_data.tstart
; }
311 nop
: NOP
{ $$
= makenode
(X_NULL
,0) ;
312 $$
->lineno
= parser_data.tline
;
313 $$
->charnr
= parser_data.tstart
; }
315 numeric
: NUMERIC
{ $$
= makenode
(0,0) ;
316 $$
->lineno
= parser_data.tline
;
317 $$
->charnr
= parser_data.tstart
; }
319 options
: OPTIONS
{ $$
= makenode
(X_OPTIONS
,0) ;
320 $$
->lineno
= parser_data.tline
;
321 $$
->charnr
= parser_data.tstart
; }
323 parse
: PARSE
{ $$
= makenode
(0,0) ;
324 $$
->lineno
= parser_data.tline
;
325 $$
->charnr
= parser_data.tstart
; }
327 proc
: PROCEDURE
{ $$
= makenode
(X_PROC
,0) ;
328 $$
->lineno
= parser_data.tline
;
329 $$
->charnr
= parser_data.tstart
; }
331 pull
: PULL
{ $$
= makenode
(X_PULL
,0) ;
332 $$
->lineno
= parser_data.tline
;
333 $$
->charnr
= parser_data.tstart
; }
335 push
: PUSH
{ $$
= makenode
(X_PUSH
,0) ;
336 $$
->lineno
= parser_data.tline
;
337 $$
->charnr
= parser_data.tstart
; }
339 queue
: QUEUE
{ $$
= makenode
(X_QUEUE
,0) ;
340 $$
->lineno
= parser_data.tline
;
341 $$
->charnr
= parser_data.tstart
; }
343 select
: SELECT
{ $$
= makenode
(X_SELECT
,0) ;
344 $$
->lineno
= parser_data.tline
;
345 $$
->charnr
= parser_data.tstart
;
348 signal
: SIGNAL
{ $$
= makenode
(X_SIG_LAB
,0) ;
349 $$
->lineno
= parser_data.tline
;
350 $$
->charnr
= parser_data.tstart
; }
352 when
: WHEN
{ $$
= makenode
(X_WHEN
,0) ;
353 $$
->lineno
= parser_data.tline
;
354 $$
->charnr
= parser_data.tstart
; }
356 otherwise
: OTHERWISE
{ $$
= makenode
(X_OTHERWISE
,0) ;
357 $$
->lineno
= parser_data.tline
;
358 $$
->charnr
= parser_data.tstart
; }
360 trace
: TRACE
{ $$
= makenode
(X_TRACE
,0) ;
361 $$
->lineno
= parser_data.tline
;
362 $$
->charnr
= parser_data.tstart
; }
364 upper
: UPPER
{ $$
= makenode
(X_UPPER_VAR
,0) ;
365 $$
->lineno
= parser_data.tline
;
366 $$
->charnr
= parser_data.tstart
; }
368 address_stat
: address
{ $$
= current
= $1 ; }
372 address_stat2: VALUE expr naddr_with
{ current
->type
= X_ADDR_V
;
374 current
->p
[1] = $3 ; }
375 | addr_with
{ exiterror
( ERR_STRING_EXPECTED
, 1, __reginatext
) ;}
376 |
{ current
->type
= X_ADDR_S
; }
377 |
error { exiterror
( ERR_STRING_EXPECTED
, 1, __reginatext
) ;}
379 | nvir nexpr naddr_with
{ current
->name
= (streng
*)$1 ;
380 current
->type
= X_ADDR_N
;
382 current
->p
[1] = $3 ; }
383 |
'(' expr
')' nspace naddr_with
{ current
->type
= X_ADDR_V
;
386 current
->u.nonansi
= 1 ; }
389 arg_stat
: arg templs
{ $$
= makenode
( X_PARSE
, 2, $1, $2 );
390 $$
->u.parseflags
= PARSE_UPPER
;
391 $$
->lineno
= $1->lineno
;
392 $$
->charnr
= $1->charnr
; }
395 call_stat
: call call_name
{ parendepth
= start_parendepth
; }
398 $$
->name
= (streng
*) $2;
400 | call
string { parendepth
= start_parendepth
; }
402 $$
->type
= X_EX_FUNC
;
404 $$
->name
= (streng
*) $2;
406 | call on
error { exiterror
( ERR_INV_SUBKEYWORD
, 1, "ERROR FAILURE HALT NOTREADY", __reginatext
) ;}
407 | call off
error { exiterror
( ERR_INV_SUBKEYWORD
, 2, "ERROR FAILURE HALT NOTREADY", __reginatext
) ;}
408 | call on c_action
error { exiterror
( ERR_EXTRA_DATA
, 1, __reginatext
) ;}
409 | call on c_action namespec
error { exiterror
( ERR_STRING_EXPECTED
, 3, __reginatext
) ;}
410 | call on c_action namespec
412 $$
->type
= X_CALL_SET
;
414 $$
->name
= (streng
*)$4 ;
416 | call on c_action
{ $$
= $1 ;
417 $$
->type
= X_CALL_SET
;
421 | call off c_action
error { exiterror
( ERR_EXTRA_DATA
, 1, __reginatext
) ;}
422 | call off c_action
{ $$
= $1 ;
423 $$
->type
= X_CALL_SET
;
428 call_name
: asymbol
{ $$
= $1; }
429 |
error { exiterror
( ERR_STRING_EXPECTED
, 2, __reginatext
);}
434 * "call_args" accepted probably with
435 * surrounding parentheses. Strip them.
437 $$
= reduce_expr_list
( $1,
440 | exprs
')' { exiterror
(ERR_UNEXPECTED_PARAN
, 2); }
443 expr_stat
: expr
{ $$
= makenode
(X_COMMAND
,0) ;
444 $$
->charnr
= tmpchr
;
449 end_stat
: END
{ $$
= makenode
(X_END
,0) ;
450 $$
->lineno
= parser_data.tline
;
451 $$
->charnr
= parser_data.tstart
;
455 end
: end_stat simsymb
{ $$
= $1 ;
456 $$
->name
= (streng
*)($2) ; }
457 | end_stat
{ $$
= $1 ; }
458 | end_stat simsymb
error { exiterror
( ERR_EXTRA_DATA
, 1, __reginatext
) ;}
461 do_stat
: do repetitor conditional ncl nxstats end
465 $$
->p
[2] = optgluelast
( $4, $5 );
467 $$
->p
[2]->o.last
= NULL
;
469 if
(($$
->p
[0]==NULL || $$
->p
[0]->name
==NULL
)
471 exiterror
( ERR_UNMATCHED_END
, 0 );
472 if
(($$
->p
[0])&&($$
->p
[0]->name
)&&
474 (($$
->p
[3]->name
->len
!= $$
->p
[0]->name
->len
)||
475 (strncmp
($$
->p
[3]->name
->value
,
476 $$
->p
[0]->name
->value
,
477 $$
->p
[0]->name
->len
))))
478 exiterror
( ERR_UNMATCHED_END
, 0 );
482 repetitor
: dovar
'=' expr nspace tobyfor tobyfor tobyfor
483 { $$
=makenode
(X_REP
,4,$3,$5,$6,$7) ;
484 $$
->name
= (streng
*)$1 ;
485 checkdosyntax
($$
) ; }
486 | dovar
'=' expr nspace tobyfor tobyfor
487 { $$
=makenode
(X_REP
,3,$3,$5,$6) ;
488 $$
->name
= (streng
*)$1 ;
489 checkdosyntax
($$
) ; }
490 | dovar
'=' expr nspace tobyfor
491 { $$
= makenode
(X_REP
,2,$3,$5) ;
492 $$
->name
= (streng
*)$1 ;
493 checkdosyntax
($$
) ; }
494 | dovar
'=' expr nspace
{ $$
= makenode
(X_REP
,1,$3) ;
495 $$
->name
= (streng
*)$1 ;
496 checkdosyntax
($$
) ; }
497 | FOREVER nspace
{ $$
= makenode
(X_REP_FOREVER
,0) ; }
498 | FOREVER
error { exiterror
( ERR_INV_SUBKEYWORD
, 16, "WHILE UNTIL", __reginatext
) ; }
499 | expr nspace
{ $1 = makenode
(X_DO_EXPR
,1,$1) ;
500 $$
= makenode
(X_REP
,2,NULL
,$1) ; }
504 nvir
: CONSYMBOL
{ $$
= (nodeptr
)Str_cre_TSD
(parser_data.TSD
,retvalue
) ; }
505 | SIMSYMBOL
{ $$
= (nodeptr
)Str_cre_TSD
(parser_data.TSD
,retvalue
) ; }
506 | STRING
{ $$
= (nodeptr
)Str_cre_TSD
(parser_data.TSD
,retvalue
) ; }
509 naddr_with
: { SymbolDetect |
= SD_ADDRWITH
;
510 $$
= with
= makenode
(X_ADDR_WITH
,0) ;
511 $$
->lineno
= parser_data.tline
;
512 $$
->charnr
= parser_data.tstart
; }
513 addr_with
{ with
= NULL
;
514 SymbolDetect
&= ~SD_ADDRWITH
; }
518 addr_with
: WITH connection
{ $$
= $2; }
519 | WITH connection
error { exiterror
( ERR_INV_SUBKEYWORD
, 5, __reginatext
) ; }
520 | WITH nspace
{ exiterror
( ERR_INV_SUBKEYWORD
, 5, __reginatext
) ; }
523 connection
: inputstmts
526 |
error { exiterror
( ERR_INV_SUBKEYWORD
, 5, __reginatext
) ; }
529 inputstmts
: inputstmt
533 outputstmts
: outputstmt
537 errorstmts
: errorstmt
541 adeo
: outputstmt nspace
542 | outputstmt errorstmt nspace
544 | errorstmt outputstmt nspace
548 adei
: inputstmt nspace
549 | inputstmt errorstmt nspace
551 | errorstmt inputstmt nspace
555 adio
: inputstmt nspace
556 | inputstmt outputstmt nspace
558 | outputstmt inputstmt nspace
562 inputstmt
: nspace INPUT nspace resourcei
{ with
->p
[0] = $4; }
563 | nspace INPUT
error { exiterror
( ERR_INV_SUBKEYWORD
, 6, __reginatext
) ; }
566 outputstmt
: nspace OUTPUT nspace resourceo
{ with
->p
[1] = $4; }
567 | nspace OUTPUT
error { exiterror
( ERR_INV_SUBKEYWORD
, 7, __reginatext
) ; }
570 errorstmt
: nspace ERROR nspace resourceo
{ with
->p
[2] = $4; }
571 | nspace ERROR
error { exiterror
( ERR_INV_SUBKEYWORD
, 14, __reginatext
) ; }
574 resourcei
: resources
{ $$
= $1 ; }
575 | NORMAL
{ $$
= makenode
(X_ADDR_WITH
, 0) ;
576 $$
->lineno
= parser_data.tline
;
577 $$
->charnr
= parser_data.tstart
; }
580 resourceo
: resources
{ $$
= $1 ; }
581 | APPEND resources
{ $$
= $2 ;
582 $$
->u.of.append
= 1 ; }
583 | APPEND
error { exiterror
( ERR_INV_SUBKEYWORD
, 8, __reginatext
) ; }
584 | REPLACE resources
{ $$
= $2 ; }
585 | REPLACE
error { exiterror
( ERR_INV_SUBKEYWORD
, 9, __reginatext
) ; }
586 | NORMAL
{ $$
= makenode
(X_ADDR_WITH
, 0) ;
587 $$
->lineno
= parser_data.tline
;
588 $$
->charnr
= parser_data.tstart
; }
591 resources
: STREAM nnvir
{ /* ANSI extension: nsimsymb is
592 * used by the standard, but I think
593 * there are no reasons why using
594 * it here as a must. FGC
597 $$
->u.of.awt
= awtSTREAM
;
598 SymbolDetect |
= SD_ADDRWITH
; }
599 | STREAM
error { exiterror
( ERR_INVALID_OPTION
, 1, __reginatext
) ; }
601 streng
*tmp
= $2->name
;
605 * expect a single dot as the last character
607 p
= (char *)memchr
( tmp
->value
, '.', tmp
->len
);
608 if
( p
!= tmp
->value
+ tmp
->len
- 1 )
609 exiterror
( ERR_INVALID_OPTION
, 3, __reginatext
);
611 $$
->u.of.awt
= awtSTEM
;
612 SymbolDetect |
= SD_ADDRWITH
; }
613 | STEM
error { exiterror
( ERR_INVALID_OPTION
, 2, __reginatext
) ; }
616 $$
->u.of.awt
= awtLIFO
;
617 SymbolDetect |
= SD_ADDRWITH
; }
618 | LIFO
error { exiterror
( ERR_INVALID_OPTION
, 100, __reginatext
) ; }
621 $$
->u.of.awt
= awtFIFO
;
622 SymbolDetect |
= SD_ADDRWITH
; }
623 | FIFO
error { exiterror
( ERR_INVALID_OPTION
, 101, __reginatext
) ; }
626 nsimsymb
: { SymbolDetect
&= ~SD_ADDRWITH
; }
627 nspace addrSim
{ $$
= $3 ; }
630 nnvir
: { SymbolDetect
&= ~SD_ADDRWITH
; }
631 nspace addrAll
{ $$
= $3 ; }
638 addrAll
: addrSim
{ $$
= $1 ; }
639 | addrString
{ $$
= $1 ; }
642 addrSim
: xsimsymb
{ $$
= makenode
(X_ADDR_WITH
, 0) ;
643 $$
->name
= (streng
*) $1 ;
644 $$
->lineno
= parser_data.tline
;
645 $$
->charnr
= parser_data.tstart
;
646 $$
->u.of.ant
= antSIMSYMBOL
;
650 addrString
: string { $$
= makenode
(X_ADDR_WITH
, 0) ;
651 $$
->name
= (streng
*) $1 ;
652 $$
->lineno
= parser_data.tline
;
653 $$
->charnr
= parser_data.tstart
;
654 $$
->u.of.ant
= antSTRING
;
658 dovar
: DOVARIABLE
{ $$
= (nodeptr
)Str_cre_TSD
(parser_data.TSD
,retvalue
) ; }
661 tobyfor
: TO expr nspace
{ $$
= makenode
(X_DO_TO
,1,$2) ; }
662 | FOR expr nspace
{ $$
= makenode
(X_DO_FOR
,1,$2) ; }
663 | BY expr nspace
{ $$
= makenode
(X_DO_BY
,1,$2) ; }
666 conditional
: WHILE expr nspace
{ $$
= makenode
(X_WHILE
,1,$2) ; }
667 | UNTIL expr nspace
{ $$
= makenode
(X_UNTIL
,1,$2) ; }
671 drop_stat
: drop anyvars
error { exiterror
( ERR_SYMBOL_EXPECTED
, 1, __reginatext
) ;}
672 | drop anyvars
{ $$
= $1 ;
676 upper_stat
: upper anyvars
error { exiterror
( ERR_SYMBOL_EXPECTED
, 1, __reginatext
) ;}
677 | upper anyvars
{ $$
= $1 ;
681 exit_stat
: exit nexpr
{ $$
= $1 ;
685 if_stat
: if expr nlncl THEN nlncl ystatement
686 { move_labels
( $1, $6, level
- 1 );
688 $$
->p
[0] = optgluelast
( $2, $3 );
689 $$
->p
[0]->o.last
= NULL
;
690 $$
->p
[1] = optgluelast
( $5, $6 );
691 $$
->p
[1]->o.last
= NULL
;
693 | if expr nlncl THEN nlncl ystatement ELSE nlncl ystatement
694 { move_labels
( $1, $9, level
- 1 );
696 $$
->p
[0] = optgluelast
( $2, $3 );
697 $$
->p
[0]->o.last
= NULL
;
698 $$
->p
[1] = optgluelast
( $5, $6 );
699 $$
->p
[1]->o.last
= NULL
;
700 $$
->p
[2] = optgluelast
( $8, $9 );
701 $$
->p
[2]->o.last
= NULL
;
703 | if expr nlncl THEN nlncl ystatement ELSE nlncl
error
704 { exiterror
( ERR_INCOMPLETE_STRUCT
, 4 ) ;}
705 | if expr nlncl THEN nlncl
error
706 { exiterror
( ERR_INCOMPLETE_STRUCT
, 3 ) ;}
707 | if ncl
{ exiterror
( ERR_INCOMPLETE_STRUCT
, 0 ) ;}
708 | if expr nlncl
error { exiterror
( ERR_THEN_EXPECTED
, 1, parser_data.if_linenr
, __reginatext
) ; }
711 unexp_then
: gruff THEN
{ exiterror
( ERR_THEN_UNEXPECTED
, 1 ) ; }
714 unexp_else
: gruff ELSE
{ exiterror
( ERR_THEN_UNEXPECTED
, 2 ) ; }
717 ipret_stat
: interpret expr
{ $$
= $1 ;
722 iterate_stat
: iterate simsymb
{ $$
= $1 ;
723 $$
->name
= (streng
*) $2 ; }
724 | iterate simsymb
error { exiterror
( ERR_EXTRA_DATA
, 1, __reginatext
) ;}
725 | iterate
{ $$
= $1 ; }
728 label_stat
: labelname
{ $$
= $1 ;
730 (level
== 0) ?
0 : 1;
731 newlabel
( (const tsd_t
*)parser_data.TSD
,
736 labelname
: label
{ $$
= $1 ;
737 $$
->name
= Str_cre_TSD
(parser_data.TSD
,retvalue
) ; }
740 leave_stat
: leave simsymb
{ $$
= $1 ;
741 $$
->name
= (streng
*) $2 ; }
742 | leave simsymb
error { exiterror
( ERR_EXTRA_DATA
, 1, __reginatext
) ;}
743 | leave
{ $$
= $1 ; }
746 nop_stat
: nop
{ $$
= $1 ; }
747 | nop
error { exiterror
( ERR_EXTRA_DATA
, 1, __reginatext
) ;}
750 numeric_stat
: numeric DIGITS expr
{ $$
= $1 ;
753 | numeric DIGITS
{ $$
= $1; $$
->type
= X_NUM_DDEF
; }
754 | numeric FORM form_expr
error { exiterror
( ERR_EXTRA_DATA
, 1, __reginatext
) ;}
755 | numeric FORM form_expr
{ $$
= $1 ;
758 | numeric FORM
{ /* NOTE! This clashes ANSI! */
759 $$
= $1 ; $$
->type
=X_NUM_FRMDEF
;}
760 | numeric FORM VALUE expr
{ $$
= $1 ; $$
->type
=X_NUM_V
;
762 | numeric FORM
error { exiterror
( ERR_INV_SUBKEYWORD
, 11, "ENGINEERING SCIENTIFIC", __reginatext
) ;}
763 | numeric FUZZ
{ $$
= $1; $$
->type
= X_NUM_FDEF
;}
764 | numeric FUZZ expr
{ $$
= $1 ;
765 $$
->type
= X_NUM_FUZZ
;
767 | numeric
error { exiterror
( ERR_INV_SUBKEYWORD
, 15, "DIGITS FORM FUZZ", __reginatext
) ;}
770 form_expr
: SCIENTIFIC
{ $$
= makenode
(X_NUM_SCI
,0) ; }
771 | ENGINEERING
{ $$
= makenode
(X_NUM_ENG
,0) ; }
774 options_stat
: options nexpr
{ ($$
=$1)->p
[0]=$2 ; }
777 parse_stat
: parse parse_flags parse_param templs
780 $$
->u.parseflags
= (long) $2 ;
783 | parse parse_param templs
786 $$
->u.parseflags
= 0;
789 | parse parse_flags
error { exiterror
( ERR_INV_SUBKEYWORD
, 12, "ARG EXTERNAL LINEIN PULL SOURCE VAR VALUE VERSION", __reginatext
) ;}
790 | parse
error { exiterror
( ERR_INV_SUBKEYWORD
, 12, "ARG CASELESS EXTERNAL LINEIN LOWER PULL SOURCE UPPER VAR VALUE VERSION", __reginatext
) ;}
793 parse_flags
: UPPER
{ $$
= (nodeptr
) (PARSE_UPPER |
795 | UPPER CASELESS
{ $$
= (nodeptr
) (PARSE_UPPER |
797 | CASELESS UPPER
{ $$
= (nodeptr
) (PARSE_UPPER |
799 | LOWER
{ $$
= (nodeptr
) (PARSE_LOWER |
801 | LOWER CASELESS
{ $$
= (nodeptr
) (PARSE_LOWER |
803 | CASELESS LOWER
{ $$
= (nodeptr
) (PARSE_LOWER |
805 | CASELESS
{ $$
= (nodeptr
) (PARSE_NORMAL |
809 templs
: templs
',' template
{ /* fixes bugs like bug 579711 */
810 $$
= optgluelast
( $1, $3 ); }
811 | template
{ $$
= $1 ; }
814 parse_param
: ARG
{ $$
= makenode
(X_PARSE_ARG
,0) ; }
815 | LINEIN
{ $$
= makenode
(X_PARSE_EXT
,0) ; }
816 | EXTERNAL
{ $$
= makenode
(X_PARSE_EXT
,0) ; }
817 | VERSION
{ $$
= makenode
(X_PARSE_VER
,0) ; }
818 | PULL
{ $$
= makenode
(X_PARSE_PULL
,0) ; }
819 | SOURCE
{ $$
= makenode
(X_PARSE_SRC
,0) ; }
820 | VAR simsymb
{ $$
= makenode
(X_PARSE_VAR
,0) ;
821 $$
->name
= (streng
*) $2 ; }
822 | VALUE nexpr WITH
{ $$
= makenode
(X_PARSE_VAL
,1,$2) ; }
823 | VALUE
error { exiterror
( ERR_INVALID_TEMPLATE
, 3 ) ;}
826 proc_stat
: proc
{ $$
= $1 ; }
827 | proc
error { exiterror
( ERR_INV_SUBKEYWORD
, 17, __reginatext
) ;}
828 | proc EXPOSE
error { exiterror
( ERR_SYMBOL_EXPECTED
, 1, __reginatext
) ;}
829 | proc EXPOSE anyvars
error { exiterror
( ERR_SYMBOL_EXPECTED
, 1, __reginatext
) ;}
830 | proc EXPOSE anyvars
{ $$
= $1 ;
834 pull_stat
: pull template
{ $$
= $1 ;
838 push_stat
: push nexpr
{ $$
= $1 ;
842 queue_stat
: queue nexpr
{ $$
= $1 ;
846 say_stat
: say nexpr
{ $$
= $1 ;
850 return_stat
: return nexpr
{ $$
= $1 ;
854 sel_end
: END simsymb
{ exiterror
( ERR_UNMATCHED_END
, 0 ) ;}
855 | END simsymb
error { exiterror
( ERR_EXTRA_DATA
, 1, __reginatext
) ;}
859 select_stat
: select ncl when_stats otherwise_stat sel_end
861 $$
->p
[0] = optgluelast
( $2, $3 );
862 $$
->p
[0]->o.last
= NULL
;
864 | select ncl END
error { exiterror
( ERR_WHEN_EXPECTED
, 0 ) ;}
865 | select ncl otherwise
error
866 { exiterror
( ERR_WHEN_EXPECTED
, 0 ) ;}
867 | select
error { exiterror
( ERR_EXTRA_DATA
, 1, __reginatext
) ;}
868 | select ncl THEN
{ exiterror
( ERR_THEN_UNEXPECTED
, 0 ) ;}
869 | select ncl when_stats otherwise
error
870 { exiterror
( ERR_INCOMPLETE_STRUCT
, 0 ) ;}
873 when_stats
: when_stats when_stat
{ $$
= optgluelast
( $1, $2 ); }
874 | when_stat
{ $$
= $1 ; }
875 |
error { exiterror
( ERR_WHEN_EXPECTED
, 0 ) ;}
878 when_stat
: when expr nlncl THEN nlncl statement
879 { $$
= $1; /* fixes bugs like bug 579711 */
880 $$
->p
[0] = optgluelast
( $2, $3 );
881 $$
->p
[0]->o.last
= NULL
;
882 $$
->p
[1] = optgluelast
( $5, $6 );
883 $$
->p
[1]->o.last
= NULL
; }
884 | when expr nlncl THEN nlncl statement THEN
885 { exiterror
( ERR_THEN_UNEXPECTED
, 0 ) ;}
886 | when expr
{ exiterror
( ERR_THEN_EXPECTED
, 2, parser_data.when_linenr
, __reginatext
) ; }
887 | when
error { exiterror
( ERR_INVALID_EXPRESSION
, 0 ) ;}
894 ex_when_stat
: gruff when_or_other
{ exiterror
( ERR_WHEN_UNEXPECTED
, 0 ); }
897 otherwise_stat
: otherwise nlncl nxstats
{ $$
= $1;
898 $$
->p
[0] = optgluelast
( $2, $3 );
900 $$
->p
[0]->o.last
= NULL
; }
901 |
{ $$
= makenode
(X_NO_OTHERWISE
,0) ;
902 $$
->lineno
= parser_data.tline
;
903 $$
->charnr
= parser_data.tstart
; }
907 signal_stat
: signal VALUE expr
{ $$
= $1 ;
908 $$
->type
= X_SIG_VAL
;
910 | signal signal_name
error { exiterror
( ERR_EXTRA_DATA
, 1, __reginatext
) ;}
911 | signal signal_name
{ $$
= $1 ;
912 $$
->name
= (streng
*)$2 ; }
913 | signal on
error { exiterror
( ERR_INV_SUBKEYWORD
, 3, "ERROR FAILURE HALT NOTREADY NOVALUE SYNTAX LOSTDIGITS", __reginatext
) ;}
914 | signal off
error { exiterror
( ERR_INV_SUBKEYWORD
, 4, "ERROR FAILURE HALT NOTREADY NOVALUE SYNTAX LOSTDIGITS", __reginatext
) ;}
915 | signal on s_action
error { exiterror
( ERR_EXTRA_DATA
, 1, __reginatext
) ;}
916 | signal on s_action namespec
error { exiterror
( ERR_STRING_EXPECTED
, 3, __reginatext
) ;}
917 | signal on s_action namespec
919 $$
->type
= X_SIG_SET
;
921 $$
->name
= (streng
*)$4 ;
923 | signal on s_action
{ $$
= $1 ;
924 $$
->type
= X_SIG_SET
;
927 | signal off s_action
error { exiterror
( ERR_EXTRA_DATA
, 1, __reginatext
) ;}
928 | signal off s_action
{ $$
= $1 ;
929 $$
->type
= X_SIG_SET
;
934 signal_name
: asymbol
{ $$
= $1; }
935 | STRING
{ $$
= (nodeptr
)Str_cre_TSD
(parser_data.TSD
,retvalue
) ; }
936 |
error { exiterror
( ERR_STRING_EXPECTED
, 4, __reginatext
);}
939 namespec
: NAME SIMSYMBOL
{ $$
= (nodeptr
)Str_cre_TSD
(parser_data.TSD
,retvalue
);}
940 | NAME
error { exiterror
( ERR_STRING_EXPECTED
, 3, __reginatext
) ;}
943 asymbol
: CONSYMBOL
{ $$
= (nodeptr
)Str_cre_TSD
(parser_data.TSD
,retvalue
) ; }
944 | SIMSYMBOL
{ $$
= (nodeptr
)Str_cre_TSD
(parser_data.TSD
,retvalue
) ; }
947 on
: ON
{ $$
= makenode
(X_ON
,0) ; }
950 off
: OFF
{ $$
= makenode
(X_OFF
,0) ; }
953 c_action
: ERROR
{ $$
= makenode
(X_S_ERROR
,0) ; }
954 | HALT
{ $$
= makenode
(X_S_HALT
,0) ; }
955 | NOTREADY
{ $$
= makenode
(X_S_NOTREADY
,0) ; }
956 | FAILURE
{ $$
= makenode
(X_S_FAILURE
,0) ; }
959 s_action
: c_action
{ $$
= $1 ; }
960 | NOVALUE
{ $$
= makenode
(X_S_NOVALUE
,0) ; }
961 | SYNTAX
{ $$
= makenode
(X_S_SYNTAX
,0) ; }
962 | LOSTDIGITS
{ $$
= makenode
(X_S_LOSTDIGITS
,0) ; }
965 trace_stat
: trace VALUE expr
{ $$
= $1 ;
967 | trace expr
{ $$
= $1 ;
969 | trace whatever
error { exiterror
( ERR_EXTRA_DATA
, 1, __reginatext
) ;}
970 | trace whatever
{ $$
= $1 ;
971 $$
->name
= (streng
*) $2 ; }
974 whatever
: WHATEVER
{ $$
= (nodeptr
)Str_cre_TSD
(parser_data.TSD
,retvalue
) ; }
978 assignment
: ass_part nexpr
{ $$
= $1 ;
981 * An assignment is a numerical
982 * assignment if and only if we have
983 * to do a numerical operation, which
984 * is equivalent to the existence of
985 * one more argument to $2.
986 * This fixes bug 720166.
990 gettypeof
($2) == IS_A_NUMBER
)
991 $$
->type
= X_NASSIGN
; }
994 ass_part
: ASSIGNMENTVARIABLE
{ $$
= makenode
(X_ASSIGN
,0) ;
995 $$
->charnr
= parser_data.tstart
;
996 $$
->lineno
= parser_data.tline
;
997 $$
->p
[0] = (nodeptr
)create_head
( (const char *)retvalue
); }
1001 expr
: '(' { /* We have to accept exprs here even
1002 * if we just want to accept
1003 * '(' expr ')' only. We do this
1005 * "call '(' exprs ')'" too.
1006 * This kann happen only if the
1007 * related control flag parendepth is
1008 * set. But since the parentheses are
1009 * voided just for the outer ones, we
1010 * can reduce the allowness level.
1011 * We don't have to set it back,
1012 * because the outer parentheses
1013 * either is THE one we look for or
1014 * none. This allows a faster error
1015 * detection and that's a good goal.*/
1017 exprs_sub
{ parendepth
++;
1018 if
( parendepth
== 1 )
1020 /* exprs on as-is basis */
1025 /* Must already be a plain expr.
1026 * The nexpr part of exprs detects
1028 $$
= reduce_expr_list
( $3,
1031 exiterror
( ERR_INTERPRETER_FAILURE
, 1, __FILE__
, __LINE__
, "Reduction of `exprs' not happened." );
1034 | expr
'+' { parendepth
--; }
1035 expr
{ parendepth
++; AUTO_REDUCE
( $1, "+" );
1036 $$
= makenode
( X_PLUSS
, 2, $1, $4 ); }
1037 | expr
'-' { parendepth
--; }
1038 expr
{ parendepth
++; AUTO_REDUCE
( $1, "-" );
1039 $$
= makenode
( X_MINUS
, 2, $1, $4 ); }
1040 | expr
'*' { parendepth
--; }
1041 expr
{ parendepth
++; AUTO_REDUCE
( $1, "*" );
1042 $$
= makenode
( X_MULT
, 2, $1, $4 ); }
1043 |
'*' { exiterror
( ERR_INVALID_EXPRESSION
, 1, "*" ); }
1044 | expr
'/' { parendepth
--; }
1045 expr
{ parendepth
++; AUTO_REDUCE
( $1, "/" );
1046 $$
= makenode
( X_DEVIDE
, 2, $1, $4 ); }
1047 |
'/' { exiterror
( ERR_INVALID_EXPRESSION
, 1, "/" ); }
1048 | expr MODULUS
{ parendepth
--; }
1049 expr
{ parendepth
++; AUTO_REDUCE
( $1, "//" );
1050 $$
= makenode
( X_MODULUS
, 2, $1, $4 ); }
1051 | MODULUS
{ exiterror
( ERR_INVALID_EXPRESSION
, 1, "//" ); }
1052 | expr
'%' { parendepth
--; }
1053 expr
{ parendepth
++; AUTO_REDUCE
( $1, "%" );
1054 $$
= makenode
( X_INTDIV
, 2, $1, $4 ); }
1055 |
'%' { exiterror
( ERR_INVALID_EXPRESSION
, 1, "%" ); }
1056 | expr
'|' { parendepth
--; }
1057 expr
{ parendepth
++; AUTO_REDUCE
( $1, "|" );
1058 $$
= makenode
( X_LOG_OR
, 2, $1, $4 ); }
1059 |
'|' { exiterror
( ERR_INVALID_EXPRESSION
, 1, "|" ); }
1060 | expr
'&' { parendepth
--; }
1061 expr
{ parendepth
++; AUTO_REDUCE
( $1, "&" );
1062 $$
= makenode
( X_LOG_AND
, 2, $1, $4 ); }
1063 |
'&' { exiterror
( ERR_INVALID_EXPRESSION
, 1, "&" ); }
1064 | expr XOR
{ parendepth
--; }
1065 expr
{ parendepth
++; AUTO_REDUCE
( $1, "&&" );
1066 $$
= makenode
( X_LOG_XOR
, 2, $1, $4 ); }
1067 | XOR
{ exiterror
( ERR_INVALID_EXPRESSION
, 1, "&&" ); }
1068 | expr EXP
{ parendepth
--; }
1069 expr
{ parendepth
++; AUTO_REDUCE
( $1, "**" );
1070 $$
= makenode
( X_EXP
, 2, $1, $4 ); }
1071 | EXP
{ exiterror
( ERR_INVALID_EXPRESSION
, 1, "**" ); }
1072 | expr SPACE
{ parendepth
--; }
1073 expr
{ parendepth
++; AUTO_REDUCE
( $1, " " );
1074 $$
= makenode
( X_SPACE
, 2, $1, $4 ); }
1075 | SPACE
{ exiterror
( ERR_INVALID_EXPRESSION
, 1, " " ); }
1076 | expr CONCATENATE
{ parendepth
--; }
1077 expr
{ parendepth
++; AUTO_REDUCE
( $1, "||" );
1078 $$
= makenode
( X_CONCAT
, 2, $1, $4 ); }
1079 | CONCATENATE
{ exiterror
( ERR_INVALID_EXPRESSION
, 1, "||" ); }
1080 | NOT expr
{ AUTO_REDUCE
( $2, "\\" );
1081 $$
= makenode
( X_LOG_NOT
, 1, $2 ); }
1082 | NOT
{ exiterror
( ERR_INVALID_EXPRESSION
, 1, "\\" ); }
1083 | expr
'=' { parendepth
--; }
1084 expr
{ parendepth
++; AUTO_REDUCE
( $1, "=" );
1085 $$
= makenode
( X_EQUAL
, 2, $1, $4 );
1087 |
'=' { exiterror
( ERR_INVALID_EXPRESSION
, 1, "=" ); }
1088 | expr GTE
{ parendepth
--; }
1089 expr
{ parendepth
++; AUTO_REDUCE
( $1, ">=" );
1090 $$
= makenode
( X_GTE
, 2, $1, $4 );
1092 | GTE
{ exiterror
( ERR_INVALID_EXPRESSION
, 1, ">=" ); }
1093 | expr LTE
{ parendepth
--; }
1094 expr
{ parendepth
++; AUTO_REDUCE
( $1, "<=" );
1095 $$
= makenode
( X_LTE
, 2, $1, $4 );
1097 | LTE
{ exiterror
( ERR_INVALID_EXPRESSION
, 1, "<=" ); }
1098 | expr GT
{ parendepth
--; }
1099 expr
{ parendepth
++; AUTO_REDUCE
( $1, ">" );
1100 $$
= makenode
( X_GT
, 2, $1, $4 );
1102 | GT
{ exiterror
( ERR_INVALID_EXPRESSION
, 1, ">" ); }
1103 | expr LT
{ parendepth
--; }
1104 expr
{ parendepth
++; AUTO_REDUCE
( $1, "<" );
1105 $$
= makenode
( X_LT
, 2, $1, $4 );
1107 | LT
{ exiterror
( ERR_INVALID_EXPRESSION
, 1, "<" ); }
1108 | expr DIFFERENT
{ parendepth
--; }
1109 expr
{ parendepth
++; AUTO_REDUCE
( $1, "\\=" );
1110 $$
= makenode
( X_DIFF
, 2, $1, $4 );
1112 | DIFFERENT
{ exiterror
( ERR_INVALID_EXPRESSION
, 1, "\\=" ); }
1113 | expr EQUALEQUAL
{ parendepth
--; }
1114 expr
{ parendepth
++; AUTO_REDUCE
( $1, "==" );
1115 $$
= makenode
( X_S_EQUAL
, 2, $1, $4 ); }
1116 | EQUALEQUAL
{ exiterror
( ERR_INVALID_EXPRESSION
, 1, "==" ); }
1117 | expr NOTEQUALEQUAL
{ parendepth
--; }
1118 expr
{ parendepth
++; AUTO_REDUCE
( $1, "\\==" );
1119 $$
= makenode
( X_S_DIFF
, 2, $1, $4 ); }
1120 | NOTEQUALEQUAL
{ exiterror
( ERR_INVALID_EXPRESSION
, 1, "\\==" ); }
1121 | expr GTGT
{ parendepth
--; }
1122 expr
{ parendepth
++; AUTO_REDUCE
( $1, ">>" );
1123 $$
= makenode
( X_S_GT
, 2, $1, $4 ); }
1124 | GTGT
{ exiterror
( ERR_INVALID_EXPRESSION
, 1, ">>" ); }
1125 | expr LTLT
{ parendepth
--; }
1126 expr
{ parendepth
++; AUTO_REDUCE
( $1, "<<" );
1127 $$
= makenode
( X_S_LT
, 2, $1, $4 ); }
1128 | LTLT
{ exiterror
( ERR_INVALID_EXPRESSION
, 1, "<<" ); }
1129 | expr NOTGTGT
{ parendepth
--; }
1130 expr
{ parendepth
++; AUTO_REDUCE
( $1, "\\>>" );
1131 $$
= makenode
( X_S_NGT
, 2, $1, $4 ); }
1132 | NOTGTGT
{ exiterror
( ERR_INVALID_EXPRESSION
, 1, "\\>>" ); }
1133 | expr NOTLTLT
{ parendepth
--; }
1134 expr
{ parendepth
++; AUTO_REDUCE
( $1, "\\<<" );
1135 $$
= makenode
( X_S_NLT
, 2, $1, $4 ); }
1136 | NOTLTLT
{ exiterror
( ERR_INVALID_EXPRESSION
, 1, "\\<<" ); }
1137 | expr GTGTE
{ parendepth
--; }
1138 expr
{ parendepth
++; AUTO_REDUCE
( $1, ">>=" );
1139 $$
= makenode
( X_S_GTE
, 2, $1, $4 ); }
1140 | GTGTE
{ exiterror
( ERR_INVALID_EXPRESSION
, 1, ">>=" ); }
1141 | expr LTLTE
{ parendepth
--; }
1142 expr
{ parendepth
++; AUTO_REDUCE
( $1, "<<=" );
1143 $$
= makenode
( X_S_LTE
, 2, $1, $4 ); }
1144 | LTLTE
{ exiterror
( ERR_INVALID_EXPRESSION
, 1, "<<=" ); }
1145 | symbtree
{ $$
= $1 ; }
1146 | CONSYMBOL
{ $$
= makenode
( X_STRING
, 0 );
1147 $$
->name
= Str_cre_TSD
(parser_data.TSD
,retvalue
) ; }
1148 | HEXSTRING
{ $$
= makenode
( X_STRING
, 0 );
1149 $$
->name
= Str_make_TSD
(parser_data.TSD
,retlength
) ;
1150 memcpy
($$
->name
->value
,retvalue
,
1151 $$
->name
->len
=retlength
); }
1152 | BINSTRING
{ $$
= makenode
( X_STRING
, 0 );
1153 $$
->name
= Str_make_TSD
(parser_data.TSD
,retlength
) ;
1154 memcpy
($$
->name
->value
,retvalue
,
1155 $$
->name
->len
=retlength
); }
1156 | STRING
{ $$
= makenode
( X_STRING
, 0 );
1157 $$
->name
= Str_cre_TSD
(parser_data.TSD
,retvalue
) ; }
1158 | function
{ $$
= $1 ; }
1159 |
'+' expr %prec UPLUS
{ AUTO_REDUCE
( $2, nullptr
);
1160 $$
= makenode
( X_U_PLUSS
, 1, $2 ); }
1161 |
'-' expr %prec UMINUS
{ AUTO_REDUCE
( $2, nullptr
);
1162 $$
= makenode
( X_U_MINUS
, 1, $2 ); }
1163 |
'+' error { exiterror
( ERR_INVALID_EXPRESSION
, 1, __reginatext
); } /* fixes bug 1107760 */
1164 |
'-' error { exiterror
( ERR_INVALID_EXPRESSION
, 1, __reginatext
); } /* fixes bug 1107760 */
1167 exprs_sub
: exprs
')' { $$
= $1; }
1168 | exprs
error { exiterror
( ERR_UNMATCHED_PARAN
, 0 ); }
1169 | STATSEP
{ exiterror
( ERR_UNMATCHED_PARAN
, 0 ); }
1172 symbtree
: SIMSYMBOL
{ $$
= (nodeptr
)create_head
( (const char *)retvalue
) ; }
1176 function
: extfunc func_args
{ $$
= makenode
(X_EX_FUNC
,1,$2) ;
1177 $$
->name
= (streng
*)$1 ; }
1178 | intfunc func_args
{ $$
= makenode
(X_IN_FUNC
,1,$2) ;
1179 $$
->name
= (streng
*)$1 ; }
1182 func_args
: { /* ugly fake preservs parendepth */
1183 $$
= (YYSTYPE) (long) parendepth
;
1185 exprs_sub
{ parendepth
= (long) $$
;
1189 intfunc
: INFUNCNAME
{ $$
= (nodeptr
)Str_cre_TSD
(parser_data.TSD
,retvalue
) ; }
1192 extfunc
: EXFUNCNAME
{ $$
= (nodeptr
)Str_cre_TSD
(parser_data.TSD
,retvalue
) ; }
1195 template
: pv solid template
{ $$
=makenode
(X_TPL_SOLID
,3,$1,$2,$3);}
1196 | pv
{ $$
=makenode
(X_TPL_SOLID
,1,$1) ; }
1197 |
error { exiterror
( ERR_INVALID_TEMPLATE
, 1, __reginatext
) ;}
1200 solid
: '-' offset
{ $$
= makenode
(X_NEG_OFFS
,0) ;
1201 $$
->name
= (streng
*) $2 ; }
1202 |
'+' offset
{ $$
= makenode
(X_POS_OFFS
,0) ;
1203 $$
->name
= (streng
*) $2 ; }
1204 | offset
{ $$
= makenode
(X_ABS_OFFS
,0) ;
1205 $$
->name
= (streng
*) $1 ; }
1206 |
'=' offset
{ $$
= makenode
(X_ABS_OFFS
,0) ;
1207 $$
->name
= (streng
*) $2 ; }
1208 |
'(' symbtree
')' { $$
= makenode
(X_TPL_VAR
,0) ;
1210 |
'-' '(' symbtree
')' { $$
= makenode
(X_NEG_OFFS
,0) ;
1212 |
'+' '(' symbtree
')' { $$
= makenode
(X_POS_OFFS
,0) ;
1214 |
'=' '(' symbtree
')' { $$
= makenode
(X_ABS_OFFS
,0) ;
1216 |
string { $$
= makenode
(X_TPL_MVE
,0) ;
1217 $$
->name
= (streng
*) $1 ; }
1220 offset
: OFFSET
{ $$
= (nodeptr
)Str_cre_TSD
(parser_data.TSD
,retvalue
) ; }
1221 | CONSYMBOL
{ streng
*sptr
= Str_cre_TSD
(parser_data.TSD
,retvalue
) ;
1222 if
(myisnumber
(parser_data.TSD
, sptr
))
1224 exiterror
( ERR_INVALID_INTEGER
, 4, sptr
->value
) ;
1227 exiterror
( ERR_INVALID_TEMPLATE
, 0 ) ;}
1230 string : STRING
{ $$
= (nodeptr
) Str_cre_TSD
(parser_data.TSD
,retvalue
) ; }
1231 | HEXSTRING
{ streng
*sptr
= Str_make_TSD
(parser_data.TSD
,retlength
) ;
1232 memcpy
(sptr
->value
,retvalue
,
1233 sptr
->len
=retlength
) ;
1234 $$
= (nodeptr
) sptr
; }
1235 | BINSTRING
{ streng
*sptr
= Str_make_TSD
(parser_data.TSD
,retlength
) ;
1236 memcpy
(sptr
->value
,retvalue
,
1237 sptr
->len
=retlength
) ;
1238 $$
= (nodeptr
) sptr
; }
1241 pv
: PLACEHOLDER pv
{ $$
= makenode
(X_TPL_POINT
,1,$2) ; }
1242 | symbtree pv
{ $$
= makenode
(X_TPL_SYMBOL
,2,$2,$1) ; }
1247 * exprs isn't for enumerating arguments
1248 * only, it has to detect missing closing
1249 * parentheses and other stuff.
1250 * parendepth regulates the behaviour.
1251 * Getting negative indicates an error.
1253 exprs
: nexpr
',' { /* detect
1258 * "x = f( ( x,. b ) )",
1259 * "x = f( ( ,. b ) )" */
1260 if
( parendepth
< 0 )
1261 exiterror
( ERR_UNEXPECTED_PARAN
, 1 );
1263 /* With call being the extended kind
1264 * of CALL we may have:
1265 * "x = f( (a),. b )",
1274 * "call s( (a),. b )",
1275 * "call s( a,. b )",
1277 * "call s (a,a),. b",
1281 * detect "(a),." and transform it
1283 $1 = reduce_expr_list
( $1,
1286 /* detect "call s (a,b),. b" and
1287 * "call s (),. b", but every list on
1288 * the left side of "," is wrong, so
1289 * complain about every exprlist. */
1290 if
( IS_EXPRLIST
( $1 ) )
1291 exiterror
( ERR_UNEXPECTED_PARAN
, 1 );
1293 $1 = reduce_expr_list
( $1,
1301 assert
( IS_EXPRLIST
( $4 ) );
1304 if
( IS_EXPRLIST
( $4->p
[0] )
1305 && ( $4->p
[1] == NULL
)
1306 && ( $4->p
[0]->p
[0] == NULL
) )
1307 exiterror
( ERR_UNEXPECTED_PARAN
, 0 );
1309 /* detect ",(a,b)." */
1310 if
( IS_EXPRLIST
( $4->p
[0] )
1311 && ( $4->p
[1] == NULL
)
1312 && IS_EXPRLIST
( $4->p
[0]->p
[1] ) )
1313 exiterror
( ERR_UNEXPECTED_PARAN
, 1 );
1315 /* detect ",(a)." and transform it
1317 $4 = reduce_expr_list
( $4,
1319 assert
( IS_EXPRLIST
( $4 ) );
1321 /* Detect something like
1322 * "call s (a,b)+1" */
1324 if
( ( curr
!= NULL
)
1325 && !IS_EXPRLIST
( curr
)
1326 && !IS_FUNCTION
( curr
)
1327 && ( IS_EXPRLIST
( curr
->p
[0] )
1328 || IS_EXPRLIST
( curr
->p
[1] ) ) )
1329 exiterror
( ERR_INVALID_EXPRESSION
, 0 );
1331 $$
= makenode
( X_EXPRLIST
, 2, $1, $4 );
1338 if
( ( parendepth
< 0 ) && ( $1 == NULL
) )
1339 exiterror
( ERR_UNEXPECTED_PARAN
, 0 );
1341 /* With call being the extended kind
1342 * of CALL we may have:
1361 * "call s (a)+1, .",
1364 * "call s (a), (a).",
1367 * "call s ( a, . )",
1368 * "call s ( a, b. )" */
1370 $1 = reduce_expr_list
( $1,
1372 $$
= makenode
( X_EXPRLIST
, 1, $1 );
1377 nexpr
: expr
{ $$
= $1 ; }
1381 anyvars
: xsimsymb anyvars
{ $$
= makenode
(X_SIM_SYMBOL
,1,$2) ;
1382 $$
->name
= (streng
*) $1 ; }
1383 | xsimsymb
{ $$
= makenode
(X_SIM_SYMBOL
,0) ;
1384 $$
->name
= (streng
*) $1 ; }
1385 |
'(' xsimsymb
')' anyvars
{ $$
= makenode
(X_IND_SYMBOL
,1,$4) ;
1386 $$
->name
= (streng
*) $2 ; }
1387 |
'(' xsimsymb
')' { $$
= makenode
(X_IND_SYMBOL
,0) ;
1388 $$
->name
= (streng
*) $2 ; }
1391 xsimsymb
: SIMSYMBOL
{ $$
= (treenode
*) Str_cre_TSD
(parser_data.TSD
,retvalue
);}
1394 simsymb
: SIMSYMBOL
{ $$
= (treenode
*) Str_cre_TSD
(parser_data.TSD
,retvalue
);}
1395 |
error { exiterror
( ERR_SYMBOL_EXPECTED
, 1, __reginatext
) ;}
1400 static nodeptr makenode
( int type
, int numb
, ...
)
1406 assert
(numb
<= (int) (sizeof
(thisleave
->p
)/sizeof
(thisleave
->p
[0])));
1408 printf
("makenode: making new node, type: %d\n",type
) ;
1409 #endif /* REXXDEBUG */
1411 thisleave
= FreshNode
( ) ;
1412 /* thisleave is initialized to zero except for nodeindex */
1413 va_start
( argptr
, numb
) ;
1414 thisleave
->type
= type
;
1415 thisleave
->lineno
= -1 ;
1416 thisleave
->charnr
= -1 ;
1417 for
(i
=0;i
<numb
;i
++)
1418 thisleave
->p
[i
]=va_arg
(argptr
, nodeptr
) ;
1422 return
( thisleave
) ;
1425 static char *getdokeyword
( int type
)
1430 case X_DO_TO
: ptr
="TO";break
;
1431 case X_DO_BY
: ptr
="BY";break
;
1432 case X_DO_FOR
: ptr
="FOR";break
;
1433 default
: ptr
="";break
;
1438 static void checkdosyntax
( cnodeptr thisptr
)
1440 if
((thisptr
->p
[1]!=NULL
)&&(thisptr
->p
[2]!=NULL
))
1442 if
((thisptr
->p
[1]->type
)==(thisptr
->p
[2]->type
))
1444 exiterror
( ERR_INVALID_DO_SYNTAX
, 1, getdokeyword
(thisptr
->p
[1]->type
) ) ;
1447 if
((thisptr
->p
[2]!=NULL
)&&(thisptr
->p
[3]!=NULL
))
1449 if
((thisptr
->p
[2]->type
)==(thisptr
->p
[3]->type
))
1451 exiterror
( ERR_INVALID_DO_SYNTAX
, 1, getdokeyword
(thisptr
->p
[2]->type
) ) ;
1454 if
((thisptr
->p
[1]!=NULL
)&&(thisptr
->p
[3]!=NULL
))
1456 if
((thisptr
->p
[1]->type
)==(thisptr
->p
[3]->type
))
1458 exiterror
( ERR_INVALID_DO_SYNTAX
, 1, getdokeyword
(thisptr
->p
[1]->type
) ) ;
1465 void newlabel
( const tsd_t
*TSD
, internal_parser_type
*ipt
, nodeptr thisptr
)
1467 labelboxptr newptr
;
1471 newptr
= (labelboxptr
)MallocTSD
(sizeof
(labelbox
)) ;
1473 newptr
->next
= NULL
;
1474 newptr
->entry
= thisptr
;
1475 if
(ipt
->first_label
== NULL
)
1477 ipt
->first_label
= newptr
;
1478 ipt
->last_label
= newptr
; /* must be NULL, too */
1482 ipt
->last_label
->next
= newptr
;
1483 ipt
->last_label
= newptr
;
1488 static nodeptr create_tail
( const char *name
)
1494 tsd_t
*TSD
= parser_data.TSD
;
1498 node
= makenode
( X_CTAIL_SYMBOL
, 0 ) ;
1499 node
->name
= Str_make_TSD
( parser_data.TSD
, 0) ;
1504 constant
= rx_isdigit
(*cptr
) ||
*cptr
=='.' ||
(!*cptr
) ;
1505 node
= makenode
( (constant
) ? X_CTAIL_SYMBOL
: X_VTAIL_SYMBOL
, 0 ) ;
1507 for
(;*cptr
&& *cptr
!='.'; cptr
++) ;
1508 node
->name
= Str_ncre_TSD
( parser_data.TSD
, name
, cptr
-name
) ;
1512 node
->p
[0] = create_tail
( ++cptr
) ;
1513 if
(constant
&& node
->p
[0]->type
==X_CTAIL_SYMBOL
)
1515 streng
*first
, *second
;
1518 first
= node
->name
;
1519 second
= node
->p
[0]->name
;
1521 node
->p
[0]->name
= NULL
;
1522 tname
= Str_makeTSD
( first
->len
+ second
->len
+ 1) ;
1523 memcpy
( tname
->value
, first
->value
, first
->len
) ;
1524 tname
->value
[first
->len
] = '.' ;
1525 memcpy
( tname
->value
+first
->len
+1, second
->value
, second
->len
) ;
1526 tname
->len
= first
->len
+ second
->len
+ 1 ;
1528 Free_stringTSD
( first
) ;
1529 Free_stringTSD
( second
) ;
1530 node
->name
= tname
;
1532 node
->p
[0] = tptr
->p
[0] ;
1540 static nodeptr create_head
( const char *name
)
1545 /* Bypass reserved variables */
1546 cptr
= ( *name
) ?
( name
+ 1 ) : name
;
1547 for
(; *cptr
&& *cptr
!='.'; cptr
++) ;
1548 node
= makenode
( X_SIM_SYMBOL
, 0 ) ;
1549 node
->name
= Str_ncre_TSD
( parser_data.TSD
, name
, cptr
-name
+(*cptr
=='.')) ;
1554 node
->p
[0] = create_tail
( cptr
) ;
1558 node
->type
= (node
->p
[0]) ? X_HEAD_SYMBOL
: X_STEM_SYMBOL
;
1565 static node_type gettypeof
( nodeptr thisptr
)
1567 tsd_t
*TSD
= parser_data.TSD
;
1569 switch
(thisptr
->type
)
1597 return IS_A_NUMBER
;
1601 return IS_SIM_SYMBOL
;
1604 return IS_COMP_SYMBOL
;
1609 if
(thisptr
->u.number
)
1611 fprintf
( stderr
, "Found an internal spot of investigation of the Regina interpreter.\n"
1612 "Please inform Mark Hessling or Florian Coosmann about the\n"
1613 "circumstances and this script.\n"
1616 "email addresses:\n"
1617 "m.hessling@qut.edu.au\n"
1618 "florian@grosse-coosmann.de\n");
1619 /* FIXME: When does this happen?
1620 * It doesn't happen if no feedback is send until end of 2005.
1622 return IS_A_NUMBER
;
1625 if
( ( thisptr
->u.number
= is_a_descr
( TSD
, thisptr
->name
) ) != NULL
)
1627 return IS_NO_NUMBER
;
1635 static void transform
( nodeptr thisptr
)
1638 node_type left
,rght
;
1640 left
= gettypeof
( thisptr
->p
[0] ) ;
1641 rght
= gettypeof
( thisptr
->p
[1] ) ;
1642 type
= thisptr
->type
;
1644 if
( ( left
== IS_A_NUMBER
) && ( rght
== IS_A_NUMBER
) )
1647 thisptr
->type
= X_NEQUAL
;
1648 else if
(type
==X_DIFF
)
1649 thisptr
->type
= X_NDIFF
;
1650 else if
(type
==X_GTE
)
1651 thisptr
->type
= X_NGTE
;
1652 else if
(type
==X_GT
)
1653 thisptr
->type
= X_NGT
;
1654 else if
(type
==X_LTE
)
1655 thisptr
->type
= X_NLTE
;
1656 else if
(type
==X_LT
)
1657 thisptr
->type
= X_NLT
;
1659 else if
( ( left
== IS_NO_NUMBER
) ||
( rght
== IS_NO_NUMBER
) )
1662 thisptr
->type
= X_SEQUAL
;
1663 else if
(type
==X_DIFF
)
1664 thisptr
->type
= X_SDIFF
;
1665 else if
(type
==X_GTE
)
1666 thisptr
->type
= X_SGTE
;
1667 else if
(type
==X_GT
)
1668 thisptr
->type
= X_SGT
;
1669 else if
(type
==X_LTE
)
1670 thisptr
->type
= X_SLTE
;
1671 else if
(type
==X_LT
)
1672 thisptr
->type
= X_SLT
;
1676 type
= thisptr
->p
[0]->type
;
1677 if
( ( left
== IS_A_NUMBER
)
1678 && ( ( type
== X_STRING
) ||
( type
== X_CON_SYMBOL
) ) )
1679 thisptr
->u.flags.lnum
= 1 ;
1680 else if
( left
== IS_SIM_SYMBOL
)
1681 thisptr
->u.flags.lsvar
= 1 ;
1682 else if
( left
== IS_COMP_SYMBOL
)
1683 thisptr
->u.flags.lcvar
= 1 ;
1685 type
= thisptr
->p
[1]->type
;
1686 if
( ( rght
== IS_A_NUMBER
)
1687 && ( ( type
== X_STRING
) ||
( type
== X_CON_SYMBOL
) ) )
1688 thisptr
->u.flags.rnum
= 1 ;
1689 else if
( rght
== IS_SIM_SYMBOL
)
1690 thisptr
->u.flags.rsvar
= 1 ;
1691 else if
( rght
== IS_COMP_SYMBOL
)
1692 thisptr
->u.flags.rcvar
= 1 ;
1697 static int is_const
( cnodeptr thisptr
)
1702 switch
(thisptr
->type
)
1709 Pre
-evaluation is not allowed. DIGITS and FUZZ may change within loops
1710 and the resulting value may or may not be the same. Concatenation with
1711 or without spaces is the sole allowed operation.
1713 NEVER ENABLE THIS AGAIN WITHOUT SOLVING THIS PROBLEMS
!
1717 return is_const
( thisptr
->p
[0] ) ;
1722 /* case X_DEVIDE: Bug 20000807-41821 */
1747 return is_const
( thisptr
->p
[0] ) && is_const
( thisptr
->p
[1] ) ;
1753 static void checkconst
( nodeptr thisptr
)
1755 tsd_t
*TSD
= parser_data.TSD
;
1757 assert
( thisptr
->type
== X_EXPRLIST
) ;
1758 if
(is_const
(thisptr
->p
[0]))
1761 thisptr
->u.strng
= evaluate
( TSD
, thisptr
->p
[0], NULL
) ;
1763 thisptr
->u.strng
= NULL
;
1765 thisptr
->type
= X_CEXPRLIST
;
1770 * reduce_expr_list will be invoked if the reduction of a list expression for
1771 * "call" arguments or a plain "(expr)" is needed. The reduction of the
1772 * outer parentheses of the extended CALL syntax is done with
1773 * mode==REDUCE_CALL, the reduction of a simple "(expr)" is done with
1774 * mode==REDUCE_EXPR. REDUCE_RIGHT is a synonym for REDUCE_CALL currently and
1775 * is intended to be used for reducing the right side of an expression list.
1777 * REDUCE_SUBEXPR detect "call s (a)+1," and "call s 1+(a)," and reduces it.
1778 * Furthermore it detects "call s ()+1", "call s 1+()", "call s 1+(a,b)",
1779 * "call s (a,b)+1" and raises an error in this case.
1781 static nodeptr reduce_expr_list
( nodeptr thisptr
, reduce_mode mode
)
1783 nodeptr h
, retval
= thisptr
;
1788 if
( mode
== REDUCE_SUBEXPR
)
1790 if
( ( parendepth
== 1 ) && !IS_FUNCTION
( thisptr
) && !IS_EXPRLIST
( thisptr
) )
1792 if
( IS_EXPRLIST
( thisptr
->p
[0] ) )
1795 if
( ( h
->p
[0] == NULL
) ||
( h
->p
[1] != NULL
) )
1796 exiterror
( ERR_INVALID_EXPRESSION
, 0 );
1797 thisptr
->p
[0] = h
->p
[0];
1800 if
( IS_EXPRLIST
( thisptr
->p
[1] ) )
1803 if
( ( h
->p
[0] == NULL
) ||
( h
->p
[1] != NULL
) )
1804 exiterror
( ERR_INVALID_EXPRESSION
, 0 );
1805 thisptr
->p
[1] = h
->p
[0];
1812 if
( !IS_EXPRLIST
( thisptr
) )
1815 if
( ( mode
== REDUCE_CALL
) ||
( mode
== REDUCE_RIGHT
) )
1817 if
( IS_EXPRLIST
( thisptr
->p
[0] ) && ( thisptr
->p
[1] == NULL
) )
1819 retval
= thisptr
->p
[0];
1820 RejectNode
( thisptr
);
1826 * mode == REDUCE_EXPR
1828 if
( ( thisptr
->p
[0] != NULL
) && ( thisptr
->p
[1] == NULL
) )
1830 if
( !IS_EXPRLIST
( thisptr
->p
[0] ) )
1832 retval
= thisptr
->p
[0];
1833 RejectNode
( thisptr
);
1841 * optgluelast connect p2 as the ->next element to p1. Every element may be
1843 * If both are non-NULL, the connection is performed using the o.last elements.
1844 * Just the o.last element of p1 remains non-NULL.
1846 * Returns: NULL if p1 and p2 are NULL.
1847 * The non-NULL element if one argumet is NULL.
1850 static nodeptr optgluelast
( nodeptr p1
, nodeptr p2
)
1860 * This is performed very often, so keep the code fast.
1862 * p2last is the "o.last"-element of p2 or just p2 if p2 has no next
1863 * elements. We set p1's o.last further down, but we have to ensure that
1864 * p2->o.last is NULL first. Therefore every element in the ->next chain
1865 * of p1 will have NULL as its o.last field.
1867 if
( ( p2last
= p2
->o.last
) == NULL
)
1872 if
( p1
->o.last
== NULL
)
1875 p1
->o.last
->next
= p2
;
1876 p1
->o.last
= p2last
;
1882 * justlabels returns 1, if n consists of a sequence of labels. The return
1883 * value is 0 otherwise.
1885 static int justlabels
( nodeptr n
)
1889 if
( n
->type
!= X_LABEL
)
1898 * move_labels move the labels from the end of "end" to the end of "front".
1899 * The labels are marked "read_only" if level is nonnull, the read-only flag
1900 * is removed if level is 0.
1901 * NOTE: At least one element of the "end" chain must contain a non-label
1904 static void move_labels
( nodeptr front
, nodeptr end
, int level
)
1909 assert
( front
!= NULL
);
1910 assert
( !justlabels
( end
) );
1912 while
( !justlabels
( end
->next
) )
1915 if
( ( labels
= end
->next
) == NULL
)
1919 * extract the labels.
1921 labels
->o.last
= oend
->o.last
;
1924 oend
->o.last
= NULL
;
1928 if
( labels
->next
== NULL
)
1929 labels
->o.last
= NULL
;
1932 * add the labels to the end of front and then re-mark the labels.
1934 optgluelast
( front
, labels
);
1936 labels
->u.trace_only
= ( level
== 0 ) ?
0 : 1;
1937 labels
= labels
->next
;