/[ascend]/trunk/base/generic/compiler/ascParse.y
ViewVC logotype

Contents of /trunk/base/generic/compiler/ascParse.y

Parent Directory Parent Directory | Revision Log Revision Log


Revision 898 - (show annotations) (download)
Tue Oct 24 13:34:13 2006 UTC (15 years, 8 months ago) by johnpye
File size: 69937 byte(s)
Added 'solver notes' to thermalequilibrium.a4c.
Added 'setup_solver' method in listnotes.py
Added 'getLanguage' to Annotation class
Added 'paramname' to SolverParameters popup in PyGTK
Fixed up some commenting in notate.c
Turned on warning about ignored notes in ascParse.y
1 /*
2 ASCEND modelling environment
3
4 Copyright (C) 1990, 1993, 1994 Thomas Guthrie Epperly
5 Copyright (C) 1997 Benjamin Andrew Allan & Vicente Rico-Ramirez
6 Copyright (C) 1998, 2006 Carnegie Mellon University
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.
22 *//*
23 Ascend Grammar file
24 by Tom Epperly
25 Version: $Revision: 1.23 $
26 Version control file: $RCSfile: ascParse.y,v $
27 Date last modified: $Date: 2000/01/25 02:25:59 $
28 Last modified by: $Author: ballan $
29 */
30 %{
31 #include <stdio.h>
32 #include <stdarg.h>
33 #include <limits.h> /* need DBL_MAX and LONG_MAX */
34 #include <float.h> /* on a NeXT they are in here */
35
36 #include <compiler/parser.h>
37
38 #include <utilities/ascMalloc.h>
39 #include <general/list.h>
40 #include <general/dstring.h>
41 #include <compiler/compiler.h>
42 #include <compiler/scanner.h>
43 #include <compiler/symtab.h> /* the global string/symbol table */
44 #include <compiler/notate.h> /* notes database wrapper */
45 #include <compiler/braced.h>
46 #include <compiler/fractions.h>
47 #include <compiler/dimen.h>
48 #include <compiler/functype.h>
49 #include <compiler/func.h>
50 #include <compiler/expr_types.h>
51 #include <compiler/name.h>
52 #include <compiler/nameio.h>
53 #include <compiler/instance_enum.h>
54 #include <compiler/extfunc.h>
55 #include <compiler/packages.h>
56 #include <compiler/sets.h>
57 #include <compiler/exprs.h>
58 #include <compiler/exprio.h>
59 #include <compiler/vlist.h>
60 #include <compiler/vlistio.h> /* for debugging only */
61 #include <compiler/stattypes.h>
62 #include <compiler/slist.h>
63 #include <compiler/statement.h>
64 #include <compiler/statio.h>
65 #include <compiler/units.h>
66 #include <compiler/when.h>
67 #include <compiler/select.h>
68 #include <compiler/switch.h>
69 #include <compiler/proc.h>
70 #include <compiler/watchpt.h>
71 #include <compiler/module.h>
72 #include <compiler/child.h>
73 #include <compiler/type_desc.h>
74 #include <compiler/type_descio.h>
75 #include <compiler/typedef.h>
76 #include <compiler/library.h>
77 #include <compiler/syntax.h>
78 #include <compiler/lexer.h>
79
80 /* 1 ==> expr can find missing , w/o shift/reduce conflicts */
81 #define COMMAEXPR_NOTBUGGY 0
82 #if COMMAEXPR_NOTBUGGY
83 #include <compiler/exprio.h>
84 #endif /* for CommaExpr if working. */
85
86 #ifndef lint
87 static CONST char ParserID[] = "$Id: ascParse.y,v 1.23 2000/01/25 02:25:59 ballan Exp $";
88 #endif
89
90 int g_compiler_warnings = 1; /* level of whine to allow */
91
92 #include <compiler/redirectFile.h>
93 #ifndef ASCERR
94 # error "ASCERR not defined"
95 #endif
96
97 extern int zz_error(char *);
98 /* provided at the end of this file.
99 * it increments g_untrapped_error, the global defined below
100 */
101
102 static unsigned long g_header_linenum = 0;
103 static unsigned int g_untrapped_error = 0;
104 /* if g_untrapped_error is set to 1, the current definition
105 * should be abandoned even if nothing else detectable by
106 * typedef.c exists. basically any syntax error should cause a type
107 * to be abandoned, but not all cause the parser to barf.
108 */
109
110 /* the last seen method name while processing a method */
111 static symchar *g_proc_name=NULL;
112
113 /* the last seen ATOM/MODEL/constant type and refinement base */
114 static symchar *g_type_name=NULL;
115 static symchar *g_refines_name=NULL;
116 /*********************************************************************\
117 * g_type_name is used by the scanner when closing a module to check if
118 * the parser is in the middle of parsing a MODEL or ATOM type
119 * definition.
120 * g_type_name == NULL implies that the parser is in between
121 * definitions. This depends on proper
122 * resets to NULL at END of type productions.
123 * g_type_name != NULL implies that the parser is in the middle
124 * of a type definition and gives the name
125 * of that type.
126 \*********************************************************************/
127
128 static symchar *g_end_identifier = NULL;
129 /* This variable gets reset every time we see an ``END_TOK''. If the
130 * token after END_TOK is missing (i.e., ``END;'') or if it is recognized
131 * (e.g., FOR_TOK), set this variable to NULL. When we see an
132 * ``END_TOK IDENTIFIER_TOK'', set this variable to the pointer into the
133 * symbol table returned by the scanner.
134 */
135
136 static struct StatementList *g_model_parameters=NULL;
137 /* this is the statementlist of the parameterized type
138 */
139
140 static struct StatementList *g_parameter_wheres=NULL;
141 /* this is the where list of a parameterized type. restrictions on args
142 */
143
144 static struct StatementList *g_parameter_reduction=NULL;
145 /* this is the statementlist of the REFINES clause
146 * at present both might be null, which is bad.
147 */
148
149 static struct Set *g_typeargs=NULL;
150 /* optional args to a typename in part declaration.
151 * it is set in the production type_identifier. in
152 * contexts where args are not allowed, use IDENTIFIER_TOK instead of the
153 * type_identifier production.
154 */
155
156 static struct Set *g_callargs=NULL;
157 /* optional args to a user defined method.
158 * it is set in the production call_identifier. in
159 * contexts where args are not allowed, use IDENTIFIER_TOK instead of the
160 * type_identifier production.
161 */
162
163 static struct gl_list_t *g_notelist = NULL;
164 /*
165 * Notes accumulator until a type commits or destroys it.
166 */
167
168 static int g_defaulted; /* used for atoms,constants */
169
170 static CONST dim_type *g_dim_ptr; /* dim of last units parsed, or so */
171 static CONST dim_type *g_atom_dim_ptr; /* dim of DIMENSION decl */
172 static CONST dim_type *g_default_dim_ptr; /* dim of default value parsed */
173
174 static double g_default_double;
175 static long g_default_long;
176 symchar *g_default_symbol;
177 #define DOUBLECONSTANT 0
178 #define LONGCONSTANT 1
179 #define BOOLEANCONSTANT 2
180 #define SYMBOLCONSTANT 3
181 static int g_constant_type = DOUBLECONSTANT;
182 static CONST struct Units *g_units_ptr;
183
184 int g_parse_relns = 1;
185 /* Should we parse relations?
186 * 0 indicates don't parse relations
187 * 1 indicates process them
188 */
189
190 /* Forward declaration of error message reporting
191 * functions provided at the end of this file.
192 */
193 static void ErrMsg_Generic(CONST char *);
194 static void ErrMsg_CommaName(CONST char *, struct Name *);
195 #if COMMAEXPR_NOTBUGGY
196 static void ErrMsg_CommaExpr(CONST char *, struct Expr *);
197 #endif /* COMMAEXPR_NOTBUGGY */
198 static void ErrMsg_NullDefPointer(CONST char *);
199 static void ErrMsg_ProcTypeMissing(CONST char *, CONST char *);
200 static void ErrMsg_ProcsRejected(CONST char *, CONST char *);
201 static void ErrMsg_DuplicateProc(struct InitProcedure *);
202 static void ErrMsg_ParensBrackets(CONST char *);
203 static void WarnMsg_MismatchEnd(CONST char *, CONST char *,
204 unsigned long, CONST char *);
205 static CONST char *TokenAsString(unsigned long);
206
207 static void error_reporter_current_line(const error_severity_t sev, const char *fmt,...);
208
209 /** @page ascend-notes About 'NOTES' in ASCEND
210 *
211 * The parser will now parse a NOTES block as well as in-lined NOTES. As
212 * a matter of fact, the parser would probably parse FORTRAN now since it
213 * is very lenient. For the in-lined NOTES, I accept any "doubly-quoted"
214 * string after an `fname'. I am currently dropping the NOTE on the
215 * floor. Ideally, we should only accept an inline NOTE when we are
216 * creating a new thing, like in an IS_A statement or a labeled relation.
217 * That means either adding the optional_note to fname and whining at the
218 * user when he/she uses the in-lined notes incorrectly, or coming up
219 * with a fvarnotelist and fnamenote that accepts fnames and
220 * optional_notes in a list or a stand-alone form.
221 *
222 * For the block NOTES statement, the symtax is
223 *
224 * NOTES ( SYMBOL_TOK ( fvarlist BRACEDTEXT_TOK )+ )+ END NOTES ';'
225 *
226 * Here I am using () as part of the meta-language to describe the syntax
227 * to you, they are not part of the formal grammer. An example is
228 *
229 * NOTES
230 * 'text' a,b,c { Here is some text }
231 * d { Here is more text }
232 * 'html' SELF { <bold>html sucks</bold> }
233 * END NOTES;
234 *
235 * Note that the only punctuation is the `,' between the members of the
236 * fvarlist and the closing `;'. Right now, the term `SELF' would be
237 * eaten in the fvarlist production. I'm not sure if this is what we
238 * should do (which requires having the notes processing do something
239 * special when it sees SELF in the fvarlist), or if we should create
240 * a SELF_TOK token. The latter is certainly easier to implement from
241 * the parser's perspective, which is why I did it that way.
242 *
243 * The block NOTES statement doesn't do anything with its stuff either,
244 * the symbols and {bracedText} get dropped on the floor and I destroy
245 * the fvarlist, but that all that happens.
246 *
247 * The `notes_body' and `noteslist' productions return `notes_ptr', which
248 * right now is a `void*' until we can decide what type of data structure
249 * we want to handle NOTES.
250 *
251 * As an amusing side note, the parser will currently eat the following:
252 *
253 * NOTES
254 * 'fun' name "put some text here" {put more text here}
255 * END NOTES;
256 *
257 * Like I said, this is so the parser will eat them; it's not being real
258 * smart about what it does with them.
259 *
260 * For debugging the NOTES stuff, set the DEBUG_NOTES macro to the
261 * following:
262 *
263 * #define DEBUG_NOTES(s) FPRINTF(stderr,"****DISCARDED NOTES:\n%s****\n",(s))
264 *
265 * To completely ignore the NOTES, set DEBUG_NOTES to the following:
266 *
267 * #define DEBUG_NOTES(s) 0
268 *
269 * Note that if you do the latter, you'll get `statement with no effect'
270 * warnings from gcc -Wall.
271 *
272 * -- Mark Thomas Thursday, 13 March 1997
273 */
274 /* #define DEBUG_NOTES(s) 0 */
275 #define DEBUG_NOTES(s) ERROR_REPORTER_NOLINE(ASC_USER_WARNING,"Discarded note: %s", (s))
276
277 /*
278 * Because the ascend types and notes are not tightly bound to each other,
279 * what with notes being stored in a database,
280 * We collect notes locally until the type associated with a batch of notes
281 * is approved by typedef and other error checks. Then we process the
282 * collected notes, commiting them to the database.
283 *
284 * NOTES made via ADD NOTES do not require a type check first and the
285 * type may not even exist yet in the library.
286 *
287 * ProcessNotes(keep); Clear up collected list, commit them if keep != 0.
288 * CollectNote(note); Add a note to the collected list.
289 */
290 static void ProcessNotes(int);
291 static void CollectNote(struct Note *);
292
293 /* For 'inline' notes, note on DQUOTE_TOK from scanner.l:
294 * Remember that DQUOTE_TOK is a string value which is local to the
295 * production that finds it. It must be copied if you want to
296 * keep it.
297 */
298
299 /* MS VC++ won't compiler Bison output unless we switch this */
300 #ifdef _MSC_VER
301 # define __STDC__
302 #endif
303 %}
304
305 %union {
306 double real_value;
307 long int_value;
308 struct fraction frac_value;
309 symchar *id_ptr;
310 CONST char *braced_ptr; /* pointer for units, explanations, tables */
311 symchar *sym_ptr; /* pointer for symbols */
312 CONST char *dquote_ptr; /* for text in "double quotes" */
313 struct Name *nptr;
314 struct Expr *eptr;
315 struct Set *sptr;
316 struct VariableList *lptr;
317 struct Statement *statptr;
318 struct StatementList *slptr;
319 struct SelectList *septr;
320 struct SwitchList *swptr;
321 struct WhenList *wptr;
322 struct NoteTmp *notesptr; /* change this once struct Notes is defined */
323 struct gl_list_t *listp;
324 struct InitProcedure *procptr;
325 CONST dim_type *dimp;
326 struct TypeDescription *tptr;
327 struct UnitDefinition *udefptr;
328 dim_type dimen;
329 enum ForOrder order;
330 enum ForKind fkind;
331 }
332
333 %token ADD_TOK ALIASES_TOK AND_TOK ANY_TOK AREALIKE_TOK ARETHESAME_TOK ARRAY_TOK ASSERT_TOK ATOM_TOK
334 %token BEQ_TOK BNE_TOK BREAK_TOK
335 %token CALL_TOK CARD_TOK CASE_TOK CHOICE_TOK CHECK_TOK CONDITIONAL_TOK CONSTANT_TOK
336 %token CONTINUE_TOK CREATE_TOK
337 %token DATA_TOK DECREASING_TOK DEFAULT_TOK DEFINITION_TOK DIMENSION_TOK
338 %token DIMENSIONLESS_TOK DO_TOK
339 %token ELSE_TOK END_TOK EXPECT_TOK EXTERNAL_TOK
340 %token FALSE_TOK FALLTHRU_TOK FIX_TOK FOR_TOK FREE_TOK FROM_TOK
341 %token GLOBAL_TOK
342 %token IF_TOK IMPORT_TOK IN_TOK INPUT_TOK INCREASING_TOK INTERACTIVE_TOK
343 %token INTERSECTION_TOK ISA_TOK _IS_T ISREFINEDTO_TOK
344 %token MAXIMIZE_TOK MAXINTEGER_TOK MAXREAL_TOK METHODS_TOK METHOD_TOK MINIMIZE_TOK MODEL_TOK
345 %token NOT_TOK NOTES_TOK
346 %token OF_TOK OR_TOK OTHERWISE_TOK OUTPUT_TOK
347 %token PATCH_TOK PROD_TOK PROVIDE_TOK
348 %token REFINES_TOK REPLACE_TOK REQUIRE_TOK RETURN_TOK RUN_TOK
349 %token SATISFIED_TOK SELECT_TOK SIZE_TOK STOP_TOK SUCHTHAT_TOK SUM_TOK SWITCH_TOK
350 %token THEN_TOK TRUE_TOK
351 %token UNION_TOK UNITS_TOK UNIVERSAL_TOK
352 %token WHEN_TOK WHERE_TOK WHILE_TOK WILLBE_TOK WILLBETHESAME_TOK WILLNOTBETHESAME_TOK
353 %token ASSIGN_TOK CASSIGN_TOK DBLCOLON_TOK USE_TOK LEQ_TOK GEQ_TOK NEQ_TOK
354 %token DOTDOT_TOK WITH_TOK VALUE_TOK WITH_VALUE_T
355 %token <real_value> REAL_TOK
356 %token <int_value> INTEGER_TOK
357 %token <id_ptr> IDENTIFIER_TOK
358 %token <braced_ptr> BRACEDTEXT_TOK
359 %token <sym_ptr> SYMBOL_TOK
360 %token <dquote_ptr> DQUOTE_TOK
361
362 /* Set associativities */
363 %left ',' '|' SUCHTHAT_TOK
364 %left BEQ_TOK BNE_TOK
365 %left AND_TOK OR_TOK IN_TOK
366 %left '<' '=' '>' LEQ_TOK GEQ_TOK NEQ_TOK
367 %left '+' '-'
368 %left '/' '*'
369 %left UMINUS_TOK UPLUS_TOK
370 %right '^'
371 %left NOT_TOK
372 %start definitions
373
374 %type <real_value> default_val number realnumber opunits
375 %type <int_value> end optional_sign universal
376 %type <fkind> forexprend
377 %type <frac_value> fraction fractail
378 %type <id_ptr> optional_of optional_method type_identifier call_identifier
379 %type <dquote_ptr> optional_notes
380 %type <braced_ptr> optional_bracedtext
381 %type <nptr> data_args fname name optional_scope
382 %type <eptr> relation expr relop logrelop optional_with_value
383 %type <sptr> set setexprlist optional_set_values
384 %type <lptr> fvarlist input_args output_args varlist
385 %type <statptr> statement isa_statement willbe_statement aliases_statement
386 %type <statptr> is_statement isrefinedto_statement arealike_statement
387 %type <statptr> arethesame_statement willbethesame_statement
388 %type <statptr> willnotbethesame_statement assignment_statement
389 %type <statptr> relation_statement glassbox_statement blackbox_statement
390 %type <statptr> call_statement units_statement
391 %type <statptr> external_statement for_statement run_statement if_statement assert_statement fix_statement free_statement
392 %type <statptr> when_statement use_statement select_statement
393 %type <statptr> conditional_statement notes_statement
394 %type <statptr> flow_statement while_statement
395 %type <statptr> switch_statement
396 %type <slptr> fstatements global_def optional_else
397 %type <slptr> optional_model_parameters optional_parameter_reduction
398 %type <slptr> optional_parameter_wheres
399 %type <septr> selectlist selectlistf
400 %type <swptr> switchlist switchlistf
401 %type <wptr> whenlist whenlistf
402 %type <notesptr> notes_body noteslist
403 %type <listp> methods proclist proclistf statements unitdeflist
404 %type <procptr> procedure
405 %type <dimp> dims dimensions
406 %type <dimen> dimexpr
407 %type <order> optional_direction
408 %type <tptr> add_method_head replace_method_head
409 %type <udefptr> unitdef
410 %type <id_ptr> model_id atom_id procedure_id definition_id
411
412 /* stuff without a particular need for a type */
413
414 %%
415
416 definitions:
417 /* empty */
418 | definitions definition
419 ;
420
421 definition:
422 require_file
423 | provide_module
424 | import
425 | add_method_def
426 | replace_method_def
427 | add_notes_def
428 | constant_def
429 | atom_def
430 | model_def
431 | definition_def
432 | patch_def
433 | units_def
434 | global_def
435 | error
436 {
437 ErrMsg_Generic("Error in definition.");
438 }
439 ;
440
441 global_def:
442 GLOBAL_TOK ';' fstatements end ';'
443 {
444 /* the following steps apply to string buffers only, not files */
445 struct gl_list_t *stats;
446 int dispose;
447 if ($3 != NULL) {
448 stats = gl_create(1L);
449 gl_append_ptr(stats,(void *)$3);
450 if (g_untrapped_error) {
451 ErrMsg_Generic("Because of a syntax error, the following statements are being ignored:");
452 WriteStatementList(ASCERR,$3,4);
453 DestroyStatementList($3);
454 } else {
455 dispose = Asc_ModuleAddStatements(Asc_CurrentModule(),stats);
456 switch (dispose) {
457 case 1: /* appended */
458 if (stats != NULL) {
459 gl_destroy(stats);
460 }
461 break;
462 case 0: /* kept */
463 break;
464 case -1: /* illegal in file */
465 ErrMsg_Generic("GLOBAL statements can only be made interactively. Ignoring:");
466 if (stats != NULL) {
467 WriteStatementList(ASCERR,$3,4);
468 gl_iterate(stats,(DestroyFunc)DestroyStatementList);
469 gl_destroy(stats);
470 }
471 break;
472 default:
473 break;
474 }
475 }
476 }
477 /* don't let any bizarreness in string parsing hang around */
478 g_type_name = g_refines_name = g_proc_name = NULL;
479 g_model_parameters =
480 g_parameter_reduction =
481 g_parameter_wheres = NULL;
482 g_untrapped_error = 0;
483 }
484 ;
485
486 require_file:
487 REQUIRE_TOK DQUOTE_TOK ';'
488 {
489 Asc_ScannerPushBuffer($2);
490 }
491 | REQUIRE_TOK name ';'
492 {
493 DestroyName($2);
494 ErrMsg_Generic("REQUIRE statement syntax is 'REQUIRE \"filename\";'.");
495 }
496 | REQUIRE_TOK name
497 {
498 DestroyName($2);
499 ErrMsg_Generic("REQUIRE statement syntax is 'REQUIRE \"filename\";'.");
500 }
501 ;
502
503 provide_module:
504 PROVIDE_TOK DQUOTE_TOK ';'
505 {
506 Asc_ModuleCreateAlias(Asc_CurrentModule(),$2);
507 }
508 | PROVIDE_TOK name ';'
509 {
510 DestroyName($2);
511 ErrMsg_Generic("PROVIDE statement syntax is 'PROVIDE \"filename\";'.");
512 }
513 | PROVIDE_TOK name
514 {
515 DestroyName($2);
516 ErrMsg_Generic("PROVIDE statement syntax is 'PROVIDE \"filename\";'.");
517 }
518 ;
519
520 import:
521 IMPORT_TOK IDENTIFIER_TOK FROM_TOK DQUOTE_TOK ';'
522 {
523 (void)LoadArchiveLibrary($4,SCP($2));
524 }
525 | IMPORT_TOK DQUOTE_TOK ';'
526 {
527 (void)LoadArchiveLibrary(SCP($2),NULL);
528 }
529 ;
530
531 add_notes_def:
532 add_notes_head notes_body end ';'
533 {
534 /* see comments for notes statement. */
535 if( $3 != NOTES_TOK ) {
536 WarnMsg_MismatchEnd("NOTES", NULL, $3, NULL);
537 }
538 if ($2 != NULL) {
539 struct NoteTmp *nt;
540 symchar *lang=NULL; /* dummy */
541 nt = $2;
542 while (nt != NULL) {
543 if (nt->lang != NULL) {
544 lang = nt->lang;
545 }
546 /* save exploding vardata to simple entries until we keep */
547 CollectNote(CreateNote(g_type_name, lang, NULL, g_proc_name,
548 Asc_ModuleBestName(Asc_CurrentModule()),
549 nt->bt,
550 nt->line, nt->vardata, nd_vlist));
551 nt = nt->next;
552 }
553 /* now keep them */
554 ProcessNotes(1);
555 DestroyNoteTmpList($2);
556 }
557 g_type_name = g_proc_name = NULL;
558 g_untrapped_error = 0;
559 }
560 ;
561
562 add_notes_head:
563 ADD_TOK NOTES_TOK IN_TOK IDENTIFIER_TOK optional_method ';'
564 {
565 g_type_name = $4;
566 g_proc_name = $5;
567 }
568 ;
569
570 add_method_def:
571 add_method_head proclist end ';'
572 {
573 if ($1 == NULL) {
574 DestroyProcedureList($2);
575 } else {
576 if( $3 != METHODS_TOK ) {
577 WarnMsg_MismatchEnd("ADD METHODS", NULL, $3, "METHODS");
578 }
579 if (AddMethods($1,$2,g_untrapped_error) != 0) {
580 if ($1 != ILLEGAL_DEFINITION) {
581 ErrMsg_ProcsRejected("ADD",SCP(GetName($1)));
582 DestroyProcedureList($2);
583 } /* else adding in DEFINITION MODEL may have misgone */
584 }
585 }
586 g_untrapped_error = 0;
587 }
588 ;
589
590 add_method_head:
591 ADD_TOK METHODS_TOK IN_TOK IDENTIFIER_TOK ';'
592 {
593 struct TypeDescription *tmptype;
594 tmptype = FindType($4);
595 if (tmptype == NULL) {
596 ErrMsg_ProcTypeMissing("ADD", SCP($4));
597 }
598 $$ = tmptype; /* parent should check for NULL */
599 g_type_name = $4; /* scope for notes */
600 }
601 | ADD_TOK METHODS_TOK IN_TOK DEFINITION_TOK MODEL_TOK ';'
602 {
603 $$ = ILLEGAL_DEFINITION;
604 /* need a bit of global state here to tag base methods */
605 }
606 ;
607
608 replace_method_def:
609 replace_method_head proclist end ';'
610 {
611 if ($1 == NULL) {
612 DestroyProcedureList($2);
613 } else {
614 if( $3 != METHODS_TOK ) {
615 WarnMsg_MismatchEnd("REPLACE METHODS", NULL, $3, "METHODS");
616 }
617 if (ReplaceMethods($1,$2,g_untrapped_error) != 0) {
618 ErrMsg_ProcsRejected("REPLACE",SCP(GetName($1)));
619 DestroyProcedureList($2);
620 }
621 }
622 g_untrapped_error = 0;
623 }
624 ;
625
626 replace_method_head:
627 REPLACE_TOK METHODS_TOK IN_TOK IDENTIFIER_TOK ';'
628 {
629 struct TypeDescription *tmptype;
630 tmptype = FindType($4);
631 if (tmptype == NULL) {
632 ErrMsg_ProcTypeMissing("REPLACE", SCP($4));
633 }
634 $$ = tmptype; /* parent should check for NULL */
635 }
636 | REPLACE_TOK METHODS_TOK IN_TOK DEFINITION_TOK MODEL_TOK ';'
637 {
638 $$ = ILLEGAL_DEFINITION;
639 /* need a bit of global state here to tag base methods */
640 }
641 ;
642
643 atom_def:
644 universal atom_head fstatements methods end ';'
645 {
646 struct TypeDescription *def_ptr;
647 int keepnotes = 0;
648
649 if(( $5 != IDENTIFIER_TOK ) || ( g_end_identifier != g_type_name )) {
650 /* all identifier_t are from symbol table, so ptr match
651 * is sufficient for equality.
652 */
653 WarnMsg_MismatchEnd("ATOM", SCP(g_type_name),
654 $5, SCP(g_type_name));
655 }
656 g_atom_dim_ptr = CheckDimensionsMatch(g_default_dim_ptr,
657 g_atom_dim_ptr);
658 if (g_atom_dim_ptr != NULL) {
659 def_ptr = CreateAtomTypeDef(g_type_name,
660 g_refines_name,
661 real_type, /* ignored..really */
662 Asc_CurrentModule(),
663 $1,
664 $3,
665 $4,
666 g_defaulted,
667 g_default_double,
668 g_atom_dim_ptr,
669 g_default_long,
670 g_default_symbol,
671 g_untrapped_error);
672 if (def_ptr != NULL) {
673 keepnotes = AddType(def_ptr);
674 } else {
675 /* CreateAtomTypeDef is responsible for freeing (if needed)
676 * all args sent to it event of failure so we don't have to.
677 * In particular $3 $4 should be killed before returning NULL.
678 */
679 ErrMsg_NullDefPointer(SCP(g_type_name));
680 }
681 } else {
682 error_reporter(ASC_USER_ERROR,Asc_ModuleBestName(Asc_CurrentModule()),g_header_linenum,NULL,
683 "Atom dimensions don't match in ATOM %s on line %s:%lu.\n",
684 SCP(g_type_name),
685 Asc_ModuleBestName(Asc_CurrentModule()),
686 g_header_linenum);
687 DestroyStatementList($3);
688 DestroyProcedureList($4);
689 }
690 ProcessNotes(keepnotes);
691 g_type_name = g_refines_name = g_proc_name = NULL;
692 g_untrapped_error = 0;
693 }
694 ;
695
696 atom_head:
697 atom_id REFINES_TOK IDENTIFIER_TOK dims default_val ';'
698 {
699 /* g_type_name = $1; */
700 g_refines_name = $3;
701 g_atom_dim_ptr = $4;
702 g_default_double = $5;
703 g_header_linenum = LineNum();
704 }
705 ;
706
707 atom_id:
708 ATOM_TOK IDENTIFIER_TOK
709 {
710 $$ = $2;
711 g_type_name = $2; /* want this set early so parm lists see it */
712 }
713 ;
714
715 default_val:
716 /* empty */
717 {
718 $$ = 0.0;
719 g_default_dim_ptr = WildDimension();
720 g_defaulted = 0;
721 }
722 | DEFAULT_TOK optional_sign number
723 {
724 $$ = $2 ? -$3 : $3;
725 g_defaulted = 1;
726 }
727 | DEFAULT_TOK FALSE_TOK
728 {
729 $$ = 0.0;
730 g_default_dim_ptr = Dimensionless();
731 g_default_long = 0;
732 g_defaulted = 1;
733 }
734 | DEFAULT_TOK TRUE_TOK
735 {
736 $$ = 0.0;
737 g_default_dim_ptr = Dimensionless();
738 g_default_long = 1;
739 g_defaulted = 1;
740 }
741 | DEFAULT_TOK SYMBOL_TOK
742 {
743 $$ = 0.0;
744 g_default_dim_ptr = Dimensionless();
745 g_default_symbol = $2;
746 g_defaulted = 0;
747 }
748 ;
749
750 constant_def:
751 universal constant_head
752 {
753 struct TypeDescription *def_ptr;
754 int keepnotes = 0;
755 if (g_defaulted) {
756 g_atom_dim_ptr = CheckDimensionsMatch(g_default_dim_ptr,
757 g_atom_dim_ptr);
758 }
759 if (g_atom_dim_ptr != NULL) {
760 def_ptr = CreateConstantTypeDef(g_type_name,
761 g_refines_name,
762 Asc_CurrentModule(),
763 $1,
764 g_defaulted,
765 g_default_double,
766 g_default_long,
767 g_default_symbol,
768 g_atom_dim_ptr,
769 g_untrapped_error);
770 if (def_ptr != NULL) {
771 keepnotes = AddType(def_ptr);
772 } else {
773 ErrMsg_NullDefPointer(SCP(g_type_name));
774 }
775 } else {
776 error_reporter(ASC_USER_ERROR,Asc_ModuleBestName(Asc_CurrentModule()),g_header_linenum,NULL,
777 "Constant dimensions don't match in CONSTANT %s"
778 " on line %s:%lu.\n",
779 SCP(g_type_name),
780 Asc_ModuleBestName(Asc_CurrentModule()),
781 g_header_linenum);
782 }
783 ProcessNotes(keepnotes);
784 g_type_name = g_refines_name = NULL;
785 g_untrapped_error = 0;
786 }
787 ;
788
789 constant_head:
790 CONSTANT_TOK IDENTIFIER_TOK REFINES_TOK IDENTIFIER_TOK dims constant_val
791 optional_notes ';'
792 {
793 g_type_name = $2;
794 g_refines_name = $4;
795 g_atom_dim_ptr = $5;
796 switch (g_constant_type) {
797 case DOUBLECONSTANT:
798 g_default_double = $<real_value>6;
799 break;
800 case LONGCONSTANT:
801 g_default_long = $<real_value>6;
802 break;
803 case BOOLEANCONSTANT:
804 g_default_long = $<int_value>6;
805 break;
806 case SYMBOLCONSTANT:
807 g_default_symbol = $<sym_ptr>6;
808 break;
809 default:
810 ErrMsg_Generic("Wierd constant type assign encountered.");
811 break; /* better not be reached. */
812 }
813 g_header_linenum = LineNum();
814 if ($7 != NULL) {
815 CollectNote(CreateNote(g_type_name,InlineNote(),SelfNote(),NULL,
816 Asc_ModuleBestName(Asc_CurrentModule()),
817 AddBraceChar($7,InlineNote()),
818 g_header_linenum,NULL,nd_empty));
819 }
820 }
821 ;
822
823 constant_val:
824 /* empty */
825 {
826 $<real_value>$ = 0.0;
827 g_default_dim_ptr = WildDimension();
828 g_defaulted = 0;
829 }
830 | CASSIGN_TOK optional_sign number
831 {
832 $<real_value>$ = $2 ? -$3 : $3;
833 g_defaulted = 1;
834 }
835 | CASSIGN_TOK TRUE_TOK
836 {
837 $<int_value>$ = 1;
838 g_defaulted = 1;
839 g_default_dim_ptr = Dimensionless();
840 g_constant_type = BOOLEANCONSTANT;
841 }
842 | CASSIGN_TOK FALSE_TOK
843 {
844 $<int_value>$ = 0;
845 g_defaulted = 1;
846 g_default_dim_ptr = Dimensionless();
847 g_constant_type = BOOLEANCONSTANT;
848 }
849 | CASSIGN_TOK SYMBOL_TOK
850 {
851 $<sym_ptr>$ = $2;
852 g_defaulted = 1;
853 g_default_dim_ptr = Dimensionless();
854 g_constant_type = SYMBOLCONSTANT;
855 }
856 ;
857
858 model_def:
859 universal model_head fstatements methods end ';'
860 {
861 struct TypeDescription *def_ptr;
862 int keepnotes = 0;
863 if(( $5 != IDENTIFIER_TOK ) || ( g_end_identifier != g_type_name )) {
864 /* all identifier_t are from symbol table, so ptr match
865 * is sufficient for equality.
866 */
867 WarnMsg_MismatchEnd("MODEL", SCP(g_type_name),
868 $5, SCP(g_type_name));
869 }
870 def_ptr = CreateModelTypeDef(g_type_name,
871 g_refines_name,
872 Asc_CurrentModule(),
873 $1,
874 $3,
875 $4,
876 g_model_parameters,
877 g_parameter_reduction,
878 g_parameter_wheres,
879 g_untrapped_error);
880 if (def_ptr != NULL) {
881 keepnotes = AddType(def_ptr);
882 } else {
883 /* CreateModelTypeDef is responsible for freeing (if needed)
884 * all args sent to it so we don't have to here.
885 * in particular $3 $4 g_model_parameters, g_parameter_reduction,
886 * and g_parameter_wheres.
887 */
888 ErrMsg_NullDefPointer(SCP(g_type_name));
889 }
890 ProcessNotes(keepnotes);
891 g_type_name = g_refines_name = NULL;
892 g_model_parameters =
893 g_parameter_reduction =
894 g_parameter_wheres = NULL;
895 g_untrapped_error = 0;
896 }
897 ;
898
899 model_head:
900 model_id optional_model_parameters
901 optional_parameter_wheres ';'
902 {
903 /* g_type_name = $1; */
904 g_model_parameters = $2;
905 g_parameter_wheres = $3;
906 g_refines_name = NULL;
907 g_header_linenum = LineNum();
908 }
909 | model_id optional_model_parameters optional_parameter_wheres
910 REFINES_TOK IDENTIFIER_TOK optional_parameter_reduction ';'
911 {
912 /* g_type_name = $1; */
913 g_model_parameters = $2;
914 g_parameter_wheres = $3;
915 g_refines_name = $5;
916 g_parameter_reduction = $6;
917 g_header_linenum = LineNum();
918 }
919 ;
920
921 model_id:
922 MODEL_TOK IDENTIFIER_TOK
923 {
924 $$ = $2;
925 g_type_name = $2; /* want this set early so parm lists see it */
926 }
927 ;
928
929 optional_model_parameters:
930 /* empty */
931 {
932 $$ = NULL;
933 }
934 | '(' fstatements ')'
935 {
936 $$ = $2; /* this could be much more sophisticated */
937 }
938 ;
939
940 optional_parameter_wheres:
941 /* empty */
942 {
943 $$ = NULL;
944 }
945 | WHERE_TOK '(' fstatements ')'
946 {
947 $$ = $3; /* this could be much more sophisticated */
948 }
949 ;
950
951 optional_parameter_reduction:
952 /* empty */
953 {
954 $$ = NULL;
955 }
956 | '(' fstatements ')'
957 {
958 $$ = $2; /* this could be much more sophisticated */
959 }
960 ;
961
962 patch_def:
963 patch_head fstatements methods end ';'
964 {
965 struct TypeDescription *def_ptr;
966 if (($4 != IDENTIFIER_TOK ) || ( g_end_identifier != g_type_name )) {
967 /* all identifier_t are from symbol table, so ptr match
968 * is sufficient for equality.
969 */
970 WarnMsg_MismatchEnd("PATCH", SCP(g_type_name),
971 $4, SCP(g_type_name));
972 }
973 def_ptr = CreatePatchTypeDef(g_type_name,
974 g_refines_name,
975 NULL,
976 Asc_CurrentModule(),
977 $2,
978 $3,
979 g_untrapped_error);
980 g_untrapped_error = 0;
981 if (def_ptr != NULL) {
982 AddType(def_ptr);
983 } else {
984 /* CreatePatchTypeDef is responsible for freeing (if needed)
985 * all args sent to it so we don't have to here.
986 * in particular $2 $3
987 */
988 ErrMsg_NullDefPointer(SCP(g_type_name));
989 }
990 g_type_name = g_refines_name = g_proc_name = NULL;
991 }
992 ;
993
994 patch_head:
995 PATCH_TOK IDENTIFIER_TOK FOR_TOK IDENTIFIER_TOK ';'
996 {
997 /*
998 * A patch definition looks just like a model def.
999 * with the original name <=> refine name.
1000 */
1001 g_type_name = $2;
1002 g_refines_name = $4;
1003 g_header_linenum = LineNum();
1004 }
1005 ;
1006
1007 universal:
1008 /* empty */
1009 {
1010 $$ = 0;
1011 }
1012 | UNIVERSAL_TOK
1013 {
1014 $$ = 1;
1015 }
1016 ;
1017
1018 definition_def:
1019 definition_id fstatements methods end ';'
1020 {
1021 struct TypeDescription *def_ptr;
1022 int keepnotes = 0;
1023
1024 if(( $4 != IDENTIFIER_TOK ) || ( g_end_identifier != $1 )) {
1025 WarnMsg_MismatchEnd("DEFINITION", SCP($1), $4, SCP($1));
1026 }
1027 if( $1 == GetBaseTypeName(relation_type)) {
1028 def_ptr = CreateRelationTypeDef(Asc_CurrentModule(),$1,$2,$3);
1029 }
1030 else if( $1 == GetBaseTypeName(logrel_type) ) {
1031 def_ptr = CreateLogRelTypeDef(Asc_CurrentModule(),$1,$2,$3);
1032 }
1033 else {
1034 ErrMsg_Generic("Bad type passed to DEFINITION statement.");
1035 def_ptr = NULL;
1036 }
1037 if ( def_ptr != NULL ) {
1038 keepnotes = AddType(def_ptr);
1039 } else {
1040 ErrMsg_NullDefPointer(SCP($1));
1041 }
1042 ProcessNotes(keepnotes);
1043 g_type_name = NULL;
1044 g_untrapped_error = 0;
1045 }
1046 ;
1047
1048 definition_id:
1049 DEFINITION_TOK IDENTIFIER_TOK
1050 {
1051 $$ = $2;
1052 g_type_name = $2; /* want this set early so parm lists see it */
1053 }
1054 ;
1055
1056
1057 units_def:
1058 units_statement ';'
1059 { /* nothing to do. just cruft to fix ; problem */ }
1060 ;
1061
1062 units_statement:
1063 UNITS_TOK unitdeflist end
1064 {
1065 struct UnitDefinition *ud;
1066 unsigned long c,len;
1067
1068 if( $3 != UNITS_TOK ) {
1069 WarnMsg_MismatchEnd("UNITS", NULL, $3, NULL);
1070 }
1071 len = gl_length($2);
1072 for (c=1; c <= len; c++) {
1073 ud = (struct UnitDefinition *)gl_fetch($2,c);
1074 ProcessUnitDef(ud);
1075 DestroyUnitDef(ud);
1076 }
1077 gl_destroy($2);
1078 $$ = NULL;
1079 }
1080 ;
1081
1082 unitdeflist:
1083 {
1084 $$ = gl_create(100L);
1085 }
1086 | unitdeflist unitdef
1087 {
1088 gl_append_ptr($1,(char *)$2);
1089 $$ = $1;
1090 }
1091 ;
1092
1093 unitdef:
1094 IDENTIFIER_TOK '=' BRACEDTEXT_TOK ';'
1095 {
1096 $$ = CreateUnitDef($1,$3,Asc_ModuleBestName(Asc_CurrentModule()),
1097 LineNum());
1098 }
1099 ;
1100
1101
1102 methods:
1103 /* empty */
1104 {
1105 $$ = NULL;
1106 }
1107 | METHODS_TOK
1108 { /* To get rid of this, we will need a global proclist
1109 * that accumulates procs until a MODEL production is
1110 * completed. If any other sort of production is started,
1111 * and proclist is not NULL, it should be discarded.
1112 */
1113 }
1114 proclist
1115 {
1116 $$ = $3;
1117 }
1118 ;
1119
1120 proclist:
1121 proclistf
1122 {
1123 $$ = $1;
1124 gl_sort($$,(CmpFunc)CmpProcs);
1125 }
1126 ;
1127
1128 proclistf:
1129 {
1130 $$ = gl_create(7L);
1131 }
1132 | proclistf procedure
1133 {
1134 unsigned long c;
1135 struct InitProcedure *oldproc;
1136 c = gl_length($1);
1137 while (c > 0) {
1138 oldproc = (struct InitProcedure *)gl_fetch($1,c);
1139 if (ProcName($2) == ProcName(oldproc)) {
1140 ErrMsg_DuplicateProc($2);
1141 break;
1142 }
1143 c--;
1144 }
1145 if (c) { /* broke early */
1146 DestroyProcedure($2);
1147 } else {
1148 gl_append_ptr($1,(char *)$2);
1149 }
1150 $$ = $1;
1151 }
1152 ;
1153
1154 procedure:
1155 procedure_id ';' fstatements end ';'
1156 {
1157 if (($4 != IDENTIFIER_TOK) || ($1 != g_end_identifier)) {
1158 /* all identifier_t are from symbol table, so ptr match
1159 * is sufficient for equality.
1160 */
1161 WarnMsg_MismatchEnd("METHOD", SCP($1), $4, SCP($1));
1162 }
1163 $$ = CreateProcedure($1,$3);
1164 g_proc_name = NULL;
1165 }
1166 ;
1167
1168 procedure_id:
1169 METHOD_TOK IDENTIFIER_TOK
1170 {
1171 $$ = $2;
1172 g_proc_name = $2;
1173 }
1174 ;
1175
1176
1177 fstatements:
1178 statements
1179 {
1180 $$ = CreateStatementList($1);
1181 }
1182 ;
1183
1184 statements:
1185 /* empty */
1186 {
1187 $$ = gl_create(7L);
1188 }
1189 | statements statement ';'
1190 {
1191 /* this is appending to a gllist of statements, not yet slist. */
1192 if ($2 != NULL) {
1193 gl_append_ptr($1,(char *)$2);
1194 }
1195 $$ = $1;
1196 }
1197 | statements error ';'
1198 {
1199 ErrMsg_Generic("Error in statement input.");
1200 $$ = $1;
1201 }
1202 ;
1203
1204 statement:
1205 isa_statement
1206 | willbe_statement
1207 | aliases_statement
1208 | is_statement
1209 | isrefinedto_statement
1210 | arealike_statement
1211 | arethesame_statement
1212 | willbethesame_statement
1213 | willnotbethesame_statement
1214 | assignment_statement
1215 | relation_statement
1216 | glassbox_statement
1217 | blackbox_statement
1218 | call_statement
1219 | external_statement
1220 | for_statement
1221 | run_statement
1222 | fix_statement
1223 | free_statement
1224 | assert_statement
1225 | if_statement
1226 | while_statement
1227 | when_statement
1228 | use_statement
1229 | flow_statement
1230 | select_statement
1231 | switch_statement
1232 | conditional_statement
1233 | notes_statement
1234 | units_statement
1235 ;
1236
1237 isa_statement:
1238 fvarlist ISA_TOK type_identifier optional_of optional_with_value
1239 {
1240 struct TypeDescription *tmptype;
1241 tmptype = FindType($3);
1242 if ($5 != NULL) {
1243 ErrMsg_Generic("WITH VALUE clause not allowed in IS_A.");
1244 g_untrapped_error++;
1245 DestroyVariableList($1);
1246 DestroySetList(g_typeargs);
1247 DestroyExprList($5);
1248 $$ = NULL;
1249 } else {
1250 if (tmptype != NULL) {
1251 if ((GetBaseType(tmptype) != model_type) &&
1252 (g_typeargs != NULL)) {
1253 error_reporter_current_line(ASC_USER_ERROR,
1254 "IS_A has arguments to the nonmodel type %s.\n",
1255 SCP($3));
1256 DestroyVariableList($1);
1257 DestroySetList(g_typeargs);
1258 DestroyExprList($5);
1259 g_untrapped_error++;
1260 $$ = NULL;
1261 } else {
1262 $$ = CreateISA($1,$3,g_typeargs,$4);
1263 }
1264 } else {
1265 error_reporter_current_line(ASC_USER_ERROR,"IS_A uses the undefined type %s.", SCP($3));
1266 DestroyVariableList($1);
1267 DestroySetList(g_typeargs);
1268 DestroyExprList($5);
1269 g_untrapped_error++;
1270 $$ = NULL;
1271 }
1272 }
1273 g_typeargs = NULL;
1274
1275 }
1276 ;
1277
1278 willbe_statement:
1279 fvarlist WILLBE_TOK type_identifier optional_of optional_with_value
1280 {
1281 struct TypeDescription *tmptype;
1282 tmptype = FindType($3);
1283 if (tmptype != NULL) {
1284 if ((GetBaseType(tmptype) != model_type) &&
1285 (g_typeargs != NULL)) {
1286 error_reporter_current_line(ASC_USER_ERROR,"WILL_BE has arguments to the nonmodel type '%s'",SCP($3));
1287 DestroyVariableList($1);
1288 DestroySetList(g_typeargs);
1289 DestroyExprList($5);
1290 g_untrapped_error++;
1291 $$ = NULL;
1292 } else {
1293 $$ = CreateWILLBE($1,$3,g_typeargs,$4,$5);
1294 }
1295 } else {
1296 DestroyVariableList($1);
1297 DestroySetList(g_typeargs);
1298 DestroyExprList($5);
1299 g_untrapped_error++;
1300 $$ = NULL;
1301 error_reporter_current_line(ASC_USER_ERROR,"WILL_BE uses the undefined type %s.",SCP($3));
1302 }
1303 g_typeargs = NULL;
1304 }
1305 ;
1306
1307 aliases_statement:
1308 fvarlist ALIASES_TOK fname
1309 {
1310 $$ = CreateALIASES($1,$3);
1311 }
1312 | fvarlist ALIASES_TOK '(' fvarlist ')' WHERE_TOK fvarlist ISA_TOK
1313 IDENTIFIER_TOK OF_TOK IDENTIFIER_TOK optional_set_values
1314 {
1315 int carray_err;
1316 carray_err = 0;
1317 if (VariableListLength($1) != 1L) {
1318 carray_err = 1;
1319 error_reporter_current_line(ASC_USER_ERROR,
1320 "Compound ALIASES allows only 1 LHS name. Found:");
1321 WriteVariableList(ASCERR,$1);
1322 }
1323 if (VariableListLength($7) != 1L) {
1324 carray_err = 1;
1325 error_reporter_current_line(ASC_USER_ERROR,
1326 "Compound ALIASES/IS_A allows only one LHS name. Found:");
1327 WriteVariableList(ASCERR,$7);
1328 }
1329 /* verify $9 == "set" */
1330 if (!carray_err && $9 != GetBaseTypeName(set_type)) {
1331 carray_err = 1;
1332 error_reporter_current_line(ASC_USER_ERROR,"Compound ALIASES statement requires IS_A %s. ",SCP(GetBaseTypeName(set_type)));
1333 FPRINTF(ASCERR," Found %s.\n",SCP($9));
1334 }
1335 /* verify set type */
1336 if ((!carray_err) &&
1337 ($11 != GetBaseTypeName(symbol_constant_type)) &&
1338 ($11 != GetBaseTypeName(integer_constant_type))) {
1339 carray_err = 1;
1340 error_reporter_current_line(ASC_USER_ERROR,
1341 "Compound ALIASES IS_A statement requires %s or %s.\n",
1342 SCP(GetBaseTypeName(integer_constant_type)),
1343 SCP(GetBaseTypeName(symbol_constant_type)));
1344 FPRINTF(ASCERR," Found %s.\n",SCP($11));
1345 }
1346 if (carray_err) {
1347 DestroyVariableList($1);
1348 DestroyVariableList($4);
1349 DestroyVariableList($7);
1350 DestroySetList($12);
1351 g_untrapped_error++;
1352 $$ = NULL;
1353 } else {
1354 int intset;
1355 intset = ($11 == GetBaseTypeName(integer_constant_type));
1356 $$ = CreateARR($1,$4,$7,intset,$12);
1357 }
1358 }
1359 ;
1360
1361 optional_set_values:
1362 /* empty */
1363 {
1364 $$ = NULL;
1365 }
1366 | WITH_VALUE_T '(' set ')'
1367 {
1368 $$ = $3;
1369 }
1370 ;
1371
1372 is_statement:
1373 fvarlist _IS_T IDENTIFIER_TOK optional_of
1374 {
1375 if (FindType($3)) {
1376 $$ = CreateREF($1,$3,$4,1);
1377 } else {
1378 $$ = CreateREF($1,$3,$4,1);
1379 error_reporter_current_line(ASC_USER_WARNING,"_IS_ uses the unbuilt prototype %s.\n",SCP($3));
1380 }
1381 }
1382 ;
1383
1384 isrefinedto_statement:
1385 fvarlist ISREFINEDTO_TOK type_identifier
1386 {
1387 struct TypeDescription *tmptype;
1388 tmptype = FindType($3);
1389 if (tmptype != NULL) {
1390 if ((GetBaseType(tmptype) != model_type) &&
1391 (g_typeargs != NULL)) {
1392 error_reporter_current_line(ASC_USER_ERROR,"IS_REFINED_TO has arguments to the nonmodel type %s.",SCP($3));
1393 DestroyVariableList($1);
1394 DestroySetList(g_typeargs);
1395 g_untrapped_error++;
1396 $$ = NULL;
1397 } else {
1398 $$ = CreateIRT($1,$3,g_typeargs);
1399 }
1400 } else {
1401 error_reporter_current_line(ASC_USER_ERROR,"The IS_REFINED_TO uses the undefined type %s.\n",SCP($3));
1402 DestroyVariableList($1);
1403 DestroySetList(g_typeargs);
1404 g_untrapped_error++;
1405 $$ = NULL;
1406 }
1407 g_typeargs = NULL;
1408 }
1409 ;
1410
1411 call_identifier:
1412 IDENTIFIER_TOK
1413 {
1414 $$ = $1;
1415 g_callargs = NULL;
1416 }
1417 | IDENTIFIER_TOK '(' set ')'
1418 {
1419 $$ = $1;
1420 g_callargs = $3;
1421 }
1422 ;
1423
1424 type_identifier:
1425 IDENTIFIER_TOK
1426 {
1427 $$ = $1;
1428 g_typeargs = NULL;
1429 }
1430 | IDENTIFIER_TOK '(' set ')'
1431 {
1432 $$ = $1;
1433 g_typeargs = $3;
1434 }
1435 ;
1436
1437 optional_method:
1438 /* empty */
1439 {
1440 $$ = NULL;
1441 }
1442 | METHOD_TOK IDENTIFIER_TOK
1443 {
1444 $$ = $2;
1445 }
1446 ;
1447
1448 optional_of:
1449 /* empty */
1450 {
1451 $$ = NULL;
1452 }
1453 | OF_TOK IDENTIFIER_TOK
1454 {
1455 $$ = $2;
1456 }
1457 ;
1458
1459 optional_with_value:
1460 /* empty */
1461 {
1462 $$ = NULL;
1463 }
1464 | WITH_VALUE_T expr
1465 {
1466 $$ = $2;
1467 }
1468 ;
1469
1470 arealike_statement:
1471 fvarlist AREALIKE_TOK
1472 {
1473 $$ = CreateAA($1);
1474 }
1475 ;
1476
1477 arethesame_statement:
1478 fvarlist ARETHESAME_TOK
1479 {
1480 $$ = CreateATS($1);
1481 }
1482 ;
1483
1484 willbethesame_statement:
1485 fvarlist WILLBETHESAME_TOK
1486 {
1487 $$ = CreateWBTS($1);
1488 }
1489 ;
1490
1491 willnotbethesame_statement:
1492 fvarlist WILLNOTBETHESAME_TOK
1493 {
1494 $$ = CreateWNBTS($1);
1495 }
1496 ;
1497
1498 assignment_statement:
1499 fname ASSIGN_TOK expr
1500 {
1501 $$ = CreateASSIGN($1,$3);
1502 }
1503 | fname CASSIGN_TOK expr
1504 {
1505 $$ = CreateCASSIGN($1,$3);
1506 }
1507 ;
1508
1509 relation_statement:
1510 relation
1511 {
1512 if (IsRelation($1)) {
1513 if (g_parse_relns == 0) {
1514 DestroyExprList($1);
1515 $$ = NULL;
1516 } else {
1517 $$ = CreateREL(NULL,$1);
1518 }
1519 } else {
1520 $$ = CreateLOGREL(NULL,$1);
1521 }
1522 }
1523 | fname ':' relation
1524 {
1525 if (IsRelation($3)) {
1526 if (g_parse_relns == 0) {
1527 DestroyExprList($3);
1528 DestroyName($1);
1529 $$ = NULL;
1530 } else {
1531 $$ = CreateREL($1,$3);
1532 }
1533 } else {
1534 $$ = CreateLOGREL($1,$3);
1535 }
1536 }
1537 ;
1538
1539 relation:
1540 expr
1541 {
1542 $$ = $1;
1543 if (NumberOfRelOps($1) < 1) {
1544 /* want at least 1. restriction to exactly 1 is in typelint */
1545 ErrMsg_Generic("Missing punctuation (,;:) or else expression contains the \
1546 wrong number of relation operators (=, ==, <, >, <=, >=, !=) preceeding or.");
1547 g_untrapped_error++;
1548 }
1549 }
1550 | MINIMIZE_TOK expr
1551 {
1552 $$ = JoinExprLists($2,CreateOpExpr(e_minimize));
1553 if (NumberOfRelOps($2) > 0) {
1554 ErrMsg_Generic("Objective function contains relation operators (=, ==, <, >, <=, >=, !=).");
1555 g_untrapped_error++;
1556 }
1557 }
1558 | MAXIMIZE_TOK expr
1559 {
1560 $$ = JoinExprLists($2,CreateOpExpr(e_maximize));
1561 if (NumberOfRelOps($2)>0) {
1562 ErrMsg_Generic("Objective function contains relation operators (=, ==, <, >, <=, >=, !=).");
1563 g_untrapped_error++;
1564 }
1565 }
1566 ;
1567
1568 blackbox_statement:
1569 fname ':' IDENTIFIER_TOK '(' input_args ';' output_args data_args ')'
1570 {
1571 /*
1572 * This is the blackbox declarative external relation.
1573 */
1574 struct VariableList *vl;
1575 vl = JoinVariableLists($5,$7);
1576 /* $$ = CreateEXTERN(2,$1,SCP($3),vl,$8,NULL); */
1577 $$ = CreateEXTERNBlackBox($1,SCP($3),vl,$8);
1578 }
1579 ;
1580
1581 input_args:
1582 fvarlist ':' INPUT_TOK
1583 {
1584 $$ = $1;
1585 }
1586 ;
1587
1588 output_args:
1589 fvarlist ':' OUTPUT_TOK
1590 {
1591 $$ = $1;
1592 }
1593 ;
1594
1595 data_args:
1596 /* empty */
1597 {
1598 $$ = NULL;
1599 }
1600 | ';' fname ':' DATA_TOK
1601 {
1602 $$ = $2;
1603 }
1604 ;
1605
1606 glassbox_statement:
1607 fname ':' IDENTIFIER_TOK '(' fvarlist ';' INTEGER_TOK ')' optional_scope
1608 {
1609 /*
1610 * This is the glassbox declarative external relation.
1611 * This now allows a scope for placement of the relations
1612 */
1613 struct VariableList *vl = $5;
1614 struct Name *nptr;
1615 char tmp[32];
1616 symchar *str;
1617
1618 sprintf(tmp,"%ld",$7);
1619 str = AddSymbol(tmp);
1620 nptr = CreateIdName(str);
1621 /* $$ = CreateEXTERN(1,$1,SCP($3),vl,nptr,$9); */
1622 $$ = CreateEXTERNGlassBox($1,SCP($3),vl,nptr,$9);
1623 }
1624 ;
1625
1626 optional_scope:
1627 /* empty */
1628 {
1629 $$ = NULL;
1630 }
1631 | IN_TOK fname
1632 {
1633 $$ = $2;
1634 }
1635 ;
1636
1637 for_statement:
1638 FOR_TOK IDENTIFIER_TOK IN_TOK expr optional_direction forexprend
1639 fstatements end
1640 {
1641 if( $8 != FOR_TOK ) {
1642 WarnMsg_MismatchEnd("FOR", SCP($2), $8, NULL);
1643 }
1644 if ($6 == fk_create && $5 != f_random) {
1645 /* create cannot have an order in declarative FOR */
1646 ErrMsg_Generic("FOR loops only accept DECREASING or INCREASING in the method section.");
1647 g_untrapped_error++;
1648 }
1649 if ($6 == fk_do && $5 == f_random) {
1650 /* all FOR/DO default to increasing */
1651 $$ = CreateFOR($2,$4,$7,f_increasing,$6);
1652 } else {
1653 $$ = CreateFOR($2,$4,$7,$5,$6);
1654 }
1655 }
1656 ;
1657
1658 optional_direction:
1659 /* empty */
1660 {
1661 $$ = f_random;
1662 }
1663 | INCREASING_TOK
1664 {
1665 $$ = f_increasing;
1666 }
1667 | DECREASING_TOK
1668 {
1669 $$ = f_decreasing;
1670 }
1671 ;
1672
1673 forexprend:
1674 CREATE_TOK
1675 {
1676 $$ = fk_create; /* declarative FOR */
1677 }
1678 | EXPECT_TOK
1679 {
1680 $$ = fk_expect; /* parameter FOR */
1681 }
1682 | CHECK_TOK
1683 {
1684 $$ = fk_check; /* WHERE FOR */
1685 }
1686 | DO_TOK
1687 {
1688 $$ = fk_do; /* method FOR */
1689 }
1690 ;
1691
1692 run_statement:
1693 RUN_TOK fname
1694 {
1695 $$ = CreateRUN($2,NULL);
1696 }
1697 | RUN_TOK fname DBLCOLON_TOK fname
1698 {
1699 $$ = CreateRUN($4,$2); /* type :: name */
1700 }
1701 ;
1702
1703 fix_statement:
1704 FIX_TOK fvarlist
1705 {
1706 $$ = CreateFIX($2);
1707 }
1708 ;
1709
1710 free_statement:
1711 FREE_TOK fvarlist
1712 {
1713 $$ = CreateFREE($2);
1714 }
1715 ;
1716
1717 external_statement:
1718 EXTERNAL_TOK IDENTIFIER_TOK '(' fvarlist ')'
1719 {
1720 /*
1721 * This is procedural external code. Was:
1722 $$ = CreateEXTERN(0,NULL,SCP($2),$4,NULL,NULL);
1723 */
1724 $$ = CreateEXTERNMethod(SCP($2),$4);
1725 }
1726 ;
1727
1728 call_statement:
1729 CALL_TOK call_identifier
1730 {
1731 /*
1732 * This is proper procedural external method code.
1733 */
1734 $$ = CreateCALL($2,g_callargs);
1735 g_callargs = NULL;
1736 }
1737 ;
1738
1739 assert_statement:
1740 ASSERT_TOK expr
1741 {
1742 $$ = CreateASSERT($2);
1743 }
1744
1745 if_statement:
1746 IF_TOK expr THEN_TOK fstatements optional_else end
1747 {
1748 if( $6 != IF_TOK ) {
1749 WarnMsg_MismatchEnd("IF", NULL, $6, NULL);
1750 }
1751 $$ = CreateIF($2,$4,$5);
1752 }
1753 ;
1754
1755 while_statement:
1756 WHILE_TOK expr DO_TOK fstatements end
1757 {
1758 if( $5 != WHILE_TOK ) {
1759 WarnMsg_MismatchEnd("WHILE", NULL, $5, NULL);
1760 }
1761 $$ = CreateWhile($2,$4);
1762 }
1763 ;
1764
1765 optional_else:
1766 {
1767 $$ = NULL;
1768 }
1769 | ELSE_TOK fstatements
1770 {
1771 $$ = $2;
1772 }
1773 ;
1774
1775 when_statement:
1776 WHEN_TOK fvarlist whenlist end
1777 {
1778 if( $4 != WHEN_TOK ) {
1779 WarnMsg_MismatchEnd("WHEN", NULL, $4, NULL);
1780 }
1781 ErrMsg_Generic("() missing in WHEN statement.");
1782 DestroyWhenList($3);
1783 DestroyVariableList($2);
1784 g_untrapped_error++;
1785 $$ = NULL;
1786 }
1787 | fname ':' WHEN_TOK fvarlist whenlist end
1788 {
1789 if( $6 != WHEN_TOK ) {
1790 WarnMsg_MismatchEnd("WHEN", NULL, $6, NULL);
1791 }
1792 ErrMsg_Generic("() missing in WHEN statement.");
1793 DestroyWhenList($5);
1794 DestroyVariableList($4);
1795 DestroyName($1);
1796 g_untrapped_error++;
1797 $$ = NULL;
1798 }
1799 | WHEN_TOK '(' fvarlist ')' whenlist end
1800 {
1801 if( $6 != WHEN_TOK ) {
1802 WarnMsg_MismatchEnd("WHEN", NULL, $6, NULL);
1803 }
1804 $$ = CreateWHEN(NULL,$3,$5);
1805 }
1806 | fname ':' WHEN_TOK '(' fvarlist ')' whenlist end
1807 {
1808 if( $8 != WHEN_TOK ) {
1809 WarnMsg_MismatchEnd("WHEN", NULL, $8, NULL);
1810 }
1811 $$ = CreateWHEN($1,$5,$7);
1812 }
1813 ;
1814
1815 whenlist:
1816 whenlistf
1817 {
1818 $$ = ReverseWhenCases($1);
1819 }
1820 ;
1821
1822 whenlistf:
1823 CASE_TOK set ':' fstatements
1824 {
1825 $$ = CreateWhen($2,$4);
1826 }
1827 | OTHERWISE_TOK ':' fstatements
1828 {
1829 $$ = CreateWhen(NULL,$3);
1830 }
1831 | whenlistf CASE_TOK set ':' fstatements
1832 {
1833 $$ = LinkWhenCases(CreateWhen($3,$5),$1);
1834 }
1835 | whenlistf OTHERWISE_TOK ':' fstatements
1836 {
1837 $$ = LinkWhenCases(CreateWhen(NULL,$4),$1);
1838 }
1839 ;
1840
1841 flow_statement:
1842 BREAK_TOK
1843 {
1844 $$ = CreateFlow(fc_break,NULL);
1845 }
1846 | CONTINUE_TOK
1847 {
1848 $$ = CreateFlow(fc_continue,NULL);
1849 }
1850 | FALLTHRU_TOK
1851 {
1852 $$ = CreateFlow(fc_fallthru,NULL);
1853 }
1854 | RETURN_TOK
1855 {
1856 $$ = CreateFlow(fc_return,NULL);
1857 }
1858 | STOP_TOK optional_bracedtext
1859 {
1860 $$ = CreateFlow(fc_stop,$2);
1861 }
1862 ;
1863
1864 use_statement:
1865 USE_TOK fname
1866 {
1867 $$ = CreateFNAME($2);
1868 }
1869 ;
1870
1871 select_statement:
1872 SELECT_TOK fvarlist selectlist end
1873 {
1874 if( $4 != SELECT_TOK ) {
1875 WarnMsg_MismatchEnd("SELECT", NULL, $4, NULL);
1876 }
1877 ErrMsg_Generic("() missing in SELECT statement.");
1878 DestroySelectList($3);
1879 DestroyVariableList($2);
1880 g_untrapped_error++;
1881 $$ = NULL;
1882 }
1883 | SELECT_TOK '(' fvarlist ')' selectlist end
1884 {
1885 if( $6 != SELECT_TOK ) {
1886 WarnMsg_MismatchEnd("SELECT", NULL, $6, NULL);
1887 }
1888 $$ = CreateSELECT($3,$5);
1889 }
1890 ;
1891
1892 selectlist:
1893 selectlistf
1894 {
1895 $$ = ReverseSelectCases($1);
1896 }
1897 ;
1898
1899 selectlistf:
1900 CASE_TOK set ':' fstatements
1901 {
1902 $$ = CreateSelect($2,$4);
1903 }
1904 | OTHERWISE_TOK ':' fstatements
1905 {
1906 $$ = CreateSelect(NULL,$3);
1907 }
1908 | selectlistf CASE_TOK set ':' fstatements
1909 {
1910 $$ = LinkSelectCases(CreateSelect($3,$5),$1);
1911 }
1912 | selectlistf OTHERWISE_TOK ':' fstatements
1913 {
1914 $$ = LinkSelectCases(CreateSelect(NULL,$4),$1);
1915 }
1916 ;
1917
1918 switch_statement:
1919 SWITCH_TOK fvarlist switchlist end
1920 {
1921 if( $4 != SWITCH_TOK ) {
1922 WarnMsg_MismatchEnd("SWITCH", NULL, $4, NULL);
1923 }
1924 ErrMsg_Generic("() missing in SWITCH statement.");
1925 DestroySwitchList($3);
1926 DestroyVariableList($2);
1927 g_untrapped_error++;
1928 $$ = NULL;
1929 }
1930 | SWITCH_TOK '(' fvarlist ')' switchlist end
1931 {
1932 if( $6 != SWITCH_TOK ) {
1933 WarnMsg_MismatchEnd("SWITCH", NULL, $6, NULL);
1934 }
1935 $$ = CreateSWITCH($3,$5);
1936 }
1937 ;
1938
1939 switchlist:
1940 switchlistf
1941 {
1942 $$ = ReverseSwitchCases($1);
1943 }
1944 ;
1945
1946 switchlistf:
1947 CASE_TOK set ':' fstatements
1948 {
1949 $$ = CreateSwitch($2,$4);
1950 }
1951 | OTHERWISE_TOK ':' fstatements
1952 {
1953 $$ = CreateSwitch(NULL,$3);
1954 }
1955 | switchlistf CASE_TOK set ':' fstatements
1956 {
1957 $$ = LinkSwitchCases(CreateSwitch($3,$5),$1);
1958 }
1959 | switchlistf OTHERWISE_TOK ':' fstatements
1960 {
1961 $$ = LinkSwitchCases(CreateSwitch(NULL,$4),$1);
1962 }
1963 ;
1964
1965 conditional_statement:
1966 CONDITIONAL_TOK fstatements end
1967 {
1968 if( $3 != CONDITIONAL_TOK ) {
1969 WarnMsg_MismatchEnd("CONDITIONAL", NULL, $3, NULL);
1970 }
1971 $$ = CreateCOND($2);
1972 }
1973 ;
1974
1975 notes_statement:
1976 NOTES_TOK notes_body end
1977 {
1978 /* All processing of notes takes place on the notes_body here.
1979 * Notes should NOT be added to the statement list.
1980 * Here we know the current type and method names.
1981 */
1982 if( $3 != NOTES_TOK ) {
1983 WarnMsg_MismatchEnd("NOTES", NULL, $3, NULL);
1984 }
1985 if ($2 != NULL) {
1986 struct NoteTmp *nt;
1987 symchar *lang=NULL; /* dummy */
1988 nt = $2;
1989 while (nt != NULL) {
1990 if (nt->lang != NULL) {
1991 /* this logic works because of the reverse sort that
1992 * yacc does via noteslist and the forward sort that
1993 * we do via notesbody. lang recorded last appears
1994 * before other entries that need it.
1995 */
1996 lang = nt->lang;
1997 }
1998
1999 /* save exploding vardata to simple entries until we keep */
2000 CollectNote(CreateNote(g_type_name, lang, NULL, g_proc_name,
2001 Asc_ModuleBestName(Asc_CurrentModule()),
2002 nt->bt,
2003 nt->line, nt->vardata, nd_vlist));
2004 nt = nt->next;
2005 }
2006 DestroyNoteTmpList($2);
2007 }
2008 $$ = NULL;
2009 }
2010 ;
2011
2012 notes_body:
2013 SYMBOL_TOK noteslist
2014 {
2015 /* At this point we have the "language", the names of the
2016 * objects we are explaining, and the explanation/notes itself.
2017 */
2018 $$ = $2;
2019 assert($$->lang == NULL);
2020 $$->lang = $1;
2021 }
2022 | notes_body SYMBOL_TOK noteslist
2023 {
2024 struct NoteTmp *nt;
2025 $$ = $1;
2026 assert($3->lang == NULL);
2027 $3->lang = $2;
2028 nt = $$;
2029 while (nt->next != NULL) {
2030 nt = nt->next;
2031 }
2032 LinkNoteTmp(nt,$3);
2033 }
2034 ;
2035
2036 noteslist:
2037 fvarlist BRACEDTEXT_TOK
2038 {
2039 $$ = CreateNoteTmp(NULL, AddBraceChar($2,NULL),
2040 (void *)$1, LineNum());
2041 }
2042 | noteslist fvarlist BRACEDTEXT_TOK
2043 {
2044 $$ = CreateNoteTmp(NULL, AddBraceChar($3,NULL),
2045 (void *)$2, LineNum());
2046 LinkNoteTmp($$,$1);
2047 }
2048 ;
2049
2050 fvarlist:
2051 varlist
2052 {
2053 /*
2054 * Reversing the variable list is now essential to deal with
2055 * external procedures and other things where order is important.
2056 */
2057 $$ = ReverseVariableList($1);
2058 }
2059 ;
2060
2061 varlist:
2062 fname
2063 {
2064 $$ = CreateVariableNode($1);
2065 }
2066 | varlist ',' fname
2067 {
2068 $$ = CreateVariableNode($3);
2069 LinkVariableNodes($$,$1);
2070 }
2071 | varlist fname
2072 {
2073 ErrMsg_CommaName("name",$2);
2074 $$ = CreateVariableNode($2);
2075 LinkVariableNodes($$,$1);
2076 /* trash the definition. keep the loose fname around because
2077 * destroying here is inconvenient
2078 */
2079 g_untrapped_error++;
2080 }
2081 ;
2082
2083 fname:
2084 name optional_notes
2085 {
2086 symchar *simple;
2087 void *data;
2088 enum NoteData nd;
2089 $$ = ReverseName($1);
2090 if ($2 != NULL && $1 != NULL) {
2091 simple = SimpleNameIdPtr($$);
2092 data = (simple == NULL ? (void *)$$ : NULL);
2093 nd = (data == NULL ? nd_empty : nd_name);
2094 CollectNote(CreateNote(g_type_name, InlineNote(), simple,
2095 g_proc_name,
2096 Asc_ModuleBestName(Asc_CurrentModule()),
2097 AddBraceChar($2,InlineNote()),
2098 LineNum(), data, nd));
2099 }
2100 }
2101 ;
2102
2103 name:
2104 IDENTIFIER_TOK
2105 {
2106 $$ = CreateIdName($1);
2107 }
2108 | name '.' IDENTIFIER_TOK
2109 {
2110 $$ = CreateIdName($3);
2111 LinkNames($$,$1);
2112 }
2113 | name '[' set ']'
2114 {
2115 if ($3 == NULL) {
2116 error_reporter_current_line(ASC_USER_ERROR,"syntax error: Empty set in name definition, name:");
2117 WriteName(ASCERR,$1);
2118 FPRINTF(ASCERR,"[]\n");
2119 g_untrapped_error++;
2120 } else {
2121 $$ = CreateSetName($3);
2122 LinkNames($$,$1);
2123 }
2124 }
2125 ;
2126
2127 end:
2128 END_TOK CONDITIONAL_TOK
2129 {
2130 g_end_identifier = NULL;
2131 $$ = CONDITIONAL_TOK;
2132 }
2133 | END_TOK FOR_TOK
2134 {
2135 g_end_identifier = NULL;
2136 $$ = FOR_TOK;
2137 }
2138 | END_TOK IF_TOK
2139 {
2140 g_end_identifier = NULL;
2141 $$ = IF_TOK;
2142 }
2143 | END_TOK INTERACTIVE_TOK
2144 {
2145 g_end_identifier = NULL;
2146 $$ = INTERACTIVE_TOK;
2147 }
2148 | END_TOK METHODS_TOK
2149 {
2150 g_end_identifier = NULL;
2151 $$ = METHODS_TOK;
2152 }
2153 | END_TOK NOTES_TOK
2154 {
2155 g_end_identifier = NULL;
2156 $$ = NOTES_TOK;
2157 }
2158 | END_TOK SELECT_TOK
2159 {
2160 g_end_identifier = NULL;
2161 $$ = SELECT_TOK;
2162 }
2163 | END_TOK SWITCH_TOK
2164 {
2165 g_end_identifier = NULL;
2166 $$ = SWITCH_TOK;
2167 }
2168 | END_TOK UNITS_TOK
2169 {
2170 g_end_identifier = NULL;
2171 $$ = UNITS_TOK;
2172 }
2173 | END_TOK GLOBAL_TOK
2174 {
2175 g_end_identifier = NULL;
2176 $$ = GLOBAL_TOK;
2177 }
2178 | END_TOK WHEN_TOK
2179 {
2180 g_end_identifier = NULL;
2181 $$ = WHEN_TOK;
2182 }
2183 | END_TOK WHILE_TOK
2184 {
2185 g_end_identifier = NULL;
2186 $$ = WHILE_TOK;
2187 }
2188 | END_TOK IDENTIFIER_TOK
2189 {
2190 g_end_identifier = $2;
2191 $$ = IDENTIFIER_TOK;
2192 }
2193 | END_TOK /* empty */
2194 {
2195 g_end_identifier = NULL;
2196 $$ = END_TOK;
2197 }
2198 ;
2199
2200 optional_bracedtext:
2201 /* empty */
2202 {
2203 $$ = NULL;
2204 }
2205 | BRACEDTEXT_TOK
2206 {
2207 $$ = $1;
2208 }
2209 ;
2210
2211 optional_notes:
2212 /* empty */
2213 {
2214 $$ = NULL;
2215 }
2216 | DQUOTE_TOK
2217 {
2218 $$ = $1;
2219 }
2220 ;
2221
2222 set:
2223 setexprlist
2224 {
2225 $$ = ReverseSetList($1);
2226 }
2227 | /* empty */
2228 {
2229 $$ = NULL;
2230 }
2231 ;
2232
2233 setexprlist:
2234 expr
2235 {
2236 $$ = CreateSingleSet($1);
2237 }
2238 | expr DOTDOT_TOK expr
2239 {
2240 $$ = CreateRangeSet($1,$3);
2241 }
2242 | setexprlist ',' expr
2243 {
2244 $$ = CreateSingleSet($3);
2245 LinkSets($$,$1);
2246 }
2247 | setexprlist ',' expr DOTDOT_TOK expr
2248 {
2249 $$ = CreateRangeSet($3,$5);
2250 LinkSets($$,$1);
2251 }
2252 ;
2253
2254 number:
2255 INTEGER_TOK
2256 {
2257 $$ = $1;
2258 g_constant_type = LONGCONSTANT;
2259 g_default_dim_ptr = Dimensionless();
2260 }
2261 | realnumber
2262 {
2263 $$ = $1;
2264 g_constant_type = DOUBLECONSTANT;
2265 g_default_dim_ptr = g_dim_ptr;
2266 }
2267 ;
2268
2269 realnumber:
2270 REAL_TOK opunits
2271 {
2272 $$ = $1*$2;
2273 }
2274 | INTEGER_TOK BRACEDTEXT_TOK
2275 {
2276 unsigned long pos;
2277 int error_code;
2278 g_units_ptr = FindOrDefineUnits($2,&pos,&error_code);
2279 if (g_units_ptr != NULL) {
2280 $$ = (double)$1*UnitsConvFactor(g_units_ptr);
2281 g_dim_ptr = UnitsDimensions(g_units_ptr);
2282 } else {
2283 char **errv;
2284 $$ = (double)$1;
2285 g_dim_ptr = WildDimension();
2286 error_reporter_current_line(ASC_USER_ERROR,"Undefined units '%s'", $2);
2287 errv = UnitsExplainError($2,error_code,pos);
2288 error_reporter_current_line(ASC_USER_ERROR," %s\n %s\n %s\n",errv[0],errv[1],errv[2]);
2289 g_untrapped_error++;
2290 }
2291 }
2292 ;
2293
2294 opunits:
2295 /* empty */
2296 {
2297 g_dim_ptr = Dimensionless();
2298 $$ = 1.0;
2299 }
2300 | BRACEDTEXT_TOK
2301 {
2302 unsigned long pos;
2303 int error_code;
2304 g_units_ptr = FindOrDefineUnits($1,&pos,&error_code);
2305 if (g_units_ptr != NULL) {
2306 $$ = UnitsConvFactor(g_units_ptr);
2307 g_dim_ptr = UnitsDimensions(g_units_ptr);
2308 } else {
2309 char **errv;
2310 $$ = 1.0;
2311 g_dim_ptr = WildDimension();
2312 error_reporter_current_line(ASC_USER_ERROR,"Undefined units '%s'",$1);
2313 errv = UnitsExplainError($1,error_code,pos);
2314 error_reporter_current_line(ASC_USER_ERROR," %s\n %s\n %s\n",errv[0],errv[1],errv[2]);
2315 g_untrapped_error++;
2316 }
2317 }
2318 ;
2319
2320 dims:
2321 DIMENSION_TOK dimensions
2322 {
2323 $$ = $2;
2324 }
2325 | DIMENSIONLESS_TOK
2326 {
2327 $$ = Dimensionless();
2328 }
2329 | /* empty */
2330 {
2331 $$ = WildDimension();
2332 }
2333 ;
2334
2335 dimensions:
2336 '*'
2337 {
2338 $$ = WildDimension();
2339 }
2340 | dimexpr
2341 {
2342 $$ = FindOrAddDimen(&($1));
2343 }
2344 ;
2345
2346 dimexpr:
2347 IDENTIFIER_TOK
2348 {
2349 ParseDim(&($$),SCP($1));
2350 }
2351 | INTEGER_TOK
2352 {
2353 ClearDimensions(&($$));
2354 }
2355 | dimexpr '/' dimexpr
2356 {
2357 $$ = SubDimensions(&($1),&($3));
2358 }
2359 | dimexpr '*' dimexpr
2360 {
2361 $$ = AddDimensions(&($1),&($3));
2362 }
2363 | dimexpr '^' fraction
2364 {
2365 $$ = ScaleDimensions(&($1),$3);
2366 }
2367 | '(' dimexpr ')'
2368 {
2369 CopyDimensions(&($2),&($$));
2370 }
2371 ;
2372
2373 fraction:
2374 optional_sign fractail
2375 {
2376 $$ = $1 ? NegateF($2) : $2;
2377 }
2378 ;
2379
2380 fractail:
2381 INTEGER_TOK
2382 {
2383 $$ = CreateFraction((short)$1,(short)1);
2384 }
2385 | '(' INTEGER_TOK '/' INTEGER_TOK ')'
2386 {
2387 $$ = CreateFraction((short)$2,(short)$4);
2388 }
2389 ;
2390
2391 optional_sign:
2392 /* empty */
2393 {
2394 $$ = 0;
2395 }
2396 | '+'
2397 {
2398 $$ = 0;
2399 }
2400 | '-'
2401 {
2402 $$ = 1;
2403 }
2404 ;
2405
2406 expr:
2407 INTEGER_TOK
2408 {
2409 $$ = CreateIntExpr($1);
2410 }
2411 | MAXINTEGER_TOK
2412 {
2413 $$ = CreateIntExpr(LONG_MAX-1);
2414 }
2415 | realnumber
2416 {
2417 $$ = CreateRealExpr($1,g_dim_ptr);
2418 }
2419 | MAXREAL_TOK
2420 {
2421 $$ = CreateRealExpr(DBL_MAX/(1+1e-15),Dimensionless());
2422 }
2423 | TRUE_TOK
2424 {
2425 $$ = CreateTrueExpr();
2426 }
2427 | FALSE_TOK
2428 {
2429 $$ = CreateFalseExpr();
2430 }
2431 | ANY_TOK
2432 {
2433 $$ = CreateAnyExpr();
2434 }
2435 | SYMBOL_TOK
2436 {
2437 $$ = CreateSymbolExpr($1);
2438 }
2439 | fname
2440 {
2441 $$ = CreateVarExpr($1);
2442 }
2443 | '[' set ']'
2444 {
2445 $$ = CreateSetExpr($2);
2446 }
2447 | expr '+' expr
2448 {
2449 $3 = JoinExprLists($3,CreateOpExpr(e_plus));
2450 $$ = JoinExprLists($1,$3);
2451 }
2452 | expr '-' expr
2453 {
2454 $3 = JoinExprLists($3,CreateOpExpr(e_minus));
2455 $$ = JoinExprLists($1,$3);
2456 }
2457 | expr '*' expr
2458 {
2459 $3 = JoinExprLists($3,CreateOpExpr(e_times));
2460 $$ = JoinExprLists($1,$3);
2461 }
2462 | expr '/' expr
2463 {
2464 $3 = JoinExprLists($3,CreateOpExpr(e_divide));
2465 $$ = JoinExprLists($1,$3);
2466 }
2467 | expr '^' expr
2468 {
2469 $3 = JoinExprLists($3,CreateOpExpr(e_power));
2470 $$ = JoinExprLists($1,$3);
2471 }
2472 | expr AND_TOK expr
2473 {
2474 $3 = JoinExprLists($3,CreateOpExpr(e_and));
2475 $$ = JoinExprLists($1,$3);
2476 }
2477 | expr OR_TOK expr
2478 {
2479 $3 = JoinExprLists($3,CreateOpExpr(e_or));
2480 $$ = JoinExprLists($1,$3);
2481 }
2482 | NOT_TOK expr
2483 {
2484 $$ = JoinExprLists($2,CreateOpExpr(e_not));
2485 }
2486 | expr relop expr %prec NEQ_TOK
2487 {
2488 $3 = JoinExprLists($3,$2);
2489 $$ = JoinExprLists($1,$3);
2490 }
2491 | expr logrelop expr %prec BEQ_TOK
2492 {
2493 $3 = JoinExprLists($3,$2);
2494 $$ = JoinExprLists($1,$3);
2495 }
2496 | expr IN_TOK expr
2497 {
2498 $3 = JoinExprLists($3,CreateOpExpr(e_in));
2499 $$ = JoinExprLists($1,$3);
2500 }
2501 | expr '|' expr
2502 {
2503 $3 = JoinExprLists($3,CreateOpExpr(e_st));
2504 $$ = JoinExprLists($1,$3);
2505 }
2506 | expr SUCHTHAT_TOK expr
2507 {
2508 $3 = JoinExprLists($3,CreateOpExpr(e_st));
2509 $$ = JoinExprLists($1,$3);
2510 }
2511 | '+' expr %prec UPLUS_TOK
2512 {
2513 $$ = $2;
2514 }
2515 | '-' expr %prec UMINUS_TOK
2516 {
2517 $$ = JoinExprLists($2,CreateOpExpr(e_uminus));
2518 }
2519 | SATISFIED_TOK '(' fname ',' realnumber ')'
2520 {
2521 $$ = CreateSatisfiedExpr($3,$5,g_dim_ptr);
2522 }
2523 | SATISFIED_TOK '(' fname ')'
2524 {
2525 $$ = CreateSatisfiedExpr($3,DBL_MAX,NULL);
2526 }
2527 | SUM_TOK '(' set ')'
2528 {
2529 DestroySetList($3);
2530 $$ = NULL;
2531 ErrMsg_ParensBrackets("SUM");
2532 g_untrapped_error++;
2533 }
2534 | SUM_TOK '[' set ']'
2535 {
2536 $$ = CreateBuiltin(e_sum,$3);
2537 }
2538 | PROD_TOK '(' set ')'
2539 {
2540 DestroySetList($3);
2541 $$ = NULL;
2542 ErrMsg_ParensBrackets("PROD");
2543 g_untrapped_error++;
2544 }
2545 | PROD_TOK '[' set ']'
2546 {
2547 $$ = CreateBuiltin(e_prod,$3);
2548 }
2549 | UNION_TOK '(' set ')'
2550 {
2551 DestroySetList($3);
2552 $$ = NULL;
2553 ErrMsg_ParensBrackets("UNION");
2554 g_untrapped_error++;
2555 }
2556 | UNION_TOK '[' set ']'
2557 {
2558 $$ = CreateBuiltin(e_union,$3);
2559 }
2560 | INTERSECTION_TOK '(' set ')'
2561 {
2562 DestroySetList($3);
2563 $$ = NULL;
2564 ErrMsg_ParensBrackets("INTERSECTION");
2565 g_untrapped_error++;
2566 }
2567 | INTERSECTION_TOK '[' set ']'
2568 {
2569 $$ = CreateBuiltin(e_inter,$3);
2570 }
2571 | CARD_TOK '(' set ')'
2572 {
2573 DestroySetList($3);
2574 $$ = NULL;
2575 ErrMsg_ParensBrackets("CARD");
2576 g_untrapped_error++;
2577 }
2578 | CARD_TOK '[' set ']'
2579 {
2580 $$ = CreateBuiltin(e_card,$3);
2581 }
2582 | CHOICE_TOK '(' set ')'
2583 {
2584 DestroySetList($3);
2585 $$ = NULL;
2586 ErrMsg_ParensBrackets("CHOICE");
2587 g_untrapped_error++;
2588 }
2589 | CHOICE_TOK '[' set ']'
2590 {
2591 $$ = CreateBuiltin(e_choice,$3);
2592 }
2593 | IDENTIFIER_TOK '(' expr ')'
2594 {
2595 CONST struct Func *fptr;
2596 if ((fptr = LookupFunc(SCP($1)))!=NULL) {
2597 $$ = JoinExprLists($3,CreateFuncExpr(fptr));
2598 } else {
2599 $$ = NULL;
2600 error_reporter_current_line(ASC_USER_ERROR,"Function '%s' is not defined.",SCP($1));
2601 g_untrapped_error++;
2602 }
2603 }
2604 | '(' expr ')'
2605 {
2606 $$ = $2;
2607 }
2608 ;
2609
2610 relop:
2611 '='
2612 {
2613 $$ = CreateOpExpr(e_equal);
2614 }
2615 | '<'
2616 {
2617 $$ = CreateOpExpr(e_less);
2618 }
2619 | '>'
2620 {
2621 $$ = CreateOpExpr(e_greater);
2622 }
2623 | LEQ_TOK /* less than or equal written "<=" */
2624 {
2625 $$ = CreateOpExpr(e_lesseq);
2626 }
2627 | GEQ_TOK /* greater than or equal written ">=" */
2628 {
2629 $$ = CreateOpExpr(e_greatereq);
2630 }
2631 | NEQ_TOK /* not equal written "<>" */
2632 {
2633 $$ = CreateOpExpr(e_notequal);
2634 }
2635 ;
2636
2637 logrelop:
2638 BEQ_TOK /* equality in boolean relations */
2639 {
2640 $$ = CreateOpExpr(e_boolean_eq);
2641 }
2642 | BNE_TOK /* non equality in boolean relations */
2643 {
2644 $$ = CreateOpExpr(e_boolean_neq);
2645 }
2646 ;
2647 %%
2648 /*
2649 * We really need to do something about freeing up the productions
2650 * that invoke this so we don't leak memory like a seive.
2651 * for example z[i IN [1..2]][j IN [process[i]] IS_A mass; eats a ton.
2652 */
2653 int
2654 yyerror(char *s)
2655 {
2656 g_untrapped_error++;
2657 if (Asc_CurrentModule() != NULL) {
2658 error_reporter_current_line(ASC_USER_ERROR,"%s",s);
2659 } else {
2660 error_reporter(ASC_USER_ERROR,NULL,0,"%s at end of input.\n",s);
2661 }
2662 return 0;
2663 }
2664
2665 /*
2666 * See the header file scanner.h for a description of this function.
2667 */
2668 void
2669 Asc_ErrMsgTypeDefnEOF(void)
2670 {
2671 /* Check g_type_name to see if we're in the middle of a type
2672 * definition. If NULL no, otherwise yes.
2673 */
2674 if ( g_type_name ) {
2675 error_reporter_current_line(ASC_USER_ERROR,
2676 "End of file reached in a type definition. Incomplete definition for '%s'.",
2677 SCP(g_type_name));
2678 }
2679 }
2680
2681 #define ERRCOUNT_PARSERGENERIC 30
2682 /*
2683 * void ErrMsg_*(void)
2684 *
2685 * The following print error and warning messages to the filehandles
2686 * ASCERR and ASCWARN, respectively.
2687 * The type of error/warning that will be printed is indicated by the
2688 * functions name and the arguments to fprintf.
2689 */
2690 static void ErrMsg_Generic(CONST char *string){
2691 static int errcount=0;
2692 if(errcount<30){
2693 /* the module may have be already closed, Asc_CurrentModule will be null */
2694 error_reporter_current_line(ASC_USER_ERROR,"%s",string);
2695
2696 if (g_type_name != NULL) {
2697 error_reporter_current_line(ASC_USER_ERROR," type %s\n",SCP(g_type_name));
2698 }
2699 if (g_proc_name != NULL) {
2700 error_reporter_current_line(ASC_USER_ERROR," METHOD %s\n",SCP(g_proc_name));
2701 }
2702
2703 errcount++;
2704 if(errcount==30){
2705 ERROR_REPORTER_HERE(ASC_PROG_NOTE
2706 ,"Further reports of this error will be suppressed.\n"
2707 );
2708 }
2709 }
2710 }
2711
2712 static void ErrMsg_CommaName(CONST char *what, struct Name *name)
2713 {
2714 struct module_t *mod;
2715
2716 /* the module may have be already closed */
2717 mod = Asc_CurrentModule();
2718
2719 error_reporter_current_line(ASC_USER_ERROR, "ASC-Error: Missing comma or operator before %s ",what);
2720 WriteName(ASCERR,name);
2721 }
2722
2723 #if COMMAEXPR_NOTBUGGY
2724 static void ErrMsg_CommaExpr(CONST char *what, struct Expr *eptr)
2725 {
2726 struct module_t *mod;
2727
2728 /* the module may have be already closed */
2729 error_reporter_current_line(ASC_USER_ERROR, "ASC-Error: Missing comma before %s ",what);
2730 WriteExpr(ASCERR,eptr);
2731 }
2732 #endif /* COMMAEXPR_NOTBUGGY. delete if can't fix */
2733
2734 static void
2735 ErrMsg_NullDefPointer(CONST char *object)
2736 {
2737 error_reporter_current_line(ASC_USER_ERROR,"Rejected '%s'", object);
2738 }
2739
2740 static void
2741 ErrMsg_ProcTypeMissing(CONST char *AorR, CONST char *type)
2742 {
2743 error_reporter_current_line(ASC_USER_ERROR,
2744 "%s METHODS called with undefined type (%s)", AorR, type);
2745 }
2746
2747 static void
2748 ErrMsg_ProcsRejected(CONST char *AorR, CONST char *type)
2749 {
2750 error_reporter_current_line(ASC_USER_ERROR,
2751 "%s METHODS failed for type %s", AorR, type);
2752 }
2753
2754 static void
2755 ErrMsg_DuplicateProc(struct InitProcedure *p)
2756 {
2757 error_reporter_current_line(ASC_USER_WARNING,
2758 "Duplicate METHOD %s rejected", SCP(ProcName(p)));
2759 }
2760
2761 static void
2762 ErrMsg_ParensBrackets(CONST char *operation)
2763 {
2764 error_reporter_current_line(ASC_USER_ERROR,
2765 " You should be using %s[] not %s()",
2766 operation,
2767 operation);
2768 }
2769
2770
2771 /*
2772 * WarnMsg_MismatchEnd(statement, opt_name, end_token, expecting);
2773 * const char *statement;
2774 * const char *opt_name;
2775 * unsigned long end_token;
2776 * const char *expecting;
2777 *
2778 * Print a warning message that the token after the END keyword did not
2779 * match what we were expecting for the current statement.
2780 * Arguments:
2781 * statement --the current statement, e.g. ATOM, METHOD, FOR, IF, CASE
2782 * opt_name --the name of the thing we were defining for ATOMs, METHODs,
2783 * etc, or NULL anonymous statements (FOR, IF, CASE, etc)
2784 * end_token --the TOKEN_TOK that we were received instead. We use the
2785 * TokenAsString to produce a string given a TOKEN_TOK
2786 * expecting --the keyword we were expecting to see after the END; if
2787 * NULL, we were expecting the string given in statement
2788 */
2789 static void
2790 WarnMsg_MismatchEnd(CONST char *statement, CONST char *opt_name,
2791 unsigned long end_token, CONST char *expecting)
2792 {
2793 error_reporter_current_line(ASC_USER_WARNING,
2794 "%s %s terminated with 'END %s;', expecting 'END %s;'"
2795 ,statement
2796 ,((opt_name != NULL) ? opt_name : "statement")
2797 ,TokenAsString(end_token)
2798 ,((expecting != NULL) ? expecting : statement));
2799 }
2800
2801
2802 /*
2803 * CONST char *TokenAsString(token);
2804 * unsigned long token;
2805 *
2806 * Takes a TOKEN_TOK (e.g., FOR_TOK, MODEL_TOK, END_TOK, IDENTIFIER_TOK) and returns
2807 * a string representation of it:
2808 * e.g.: TokenAsString(FOR_TOK) ==> "FOR"
2809 *
2810 * Since this function is only used inside WarnMsg_MismatchEnd, we do a
2811 * couple of things specific to that function: If token is END_TOK, we
2812 * return an empty string, and if it is IDENTIFIER_TOK, we return the
2813 * current value of g_end_identifier, or UNKNOWN if g_end_identifier is
2814 * NULL.
2815 */
2816 static CONST char *
2817 TokenAsString(unsigned long token)
2818 {
2819 switch( token ) {
2820 case ATOM_TOK:
2821 return "ATOM";
2822 case CONDITIONAL_TOK:
2823 return "CONDITIONAL";
2824 case FOR_TOK:
2825 return "FOR";
2826 case ASSERT_TOK:
2827 return "ASSERT";
2828 case IF_TOK:
2829 return "IF";
2830 case INTERACTIVE_TOK:
2831 return "INTERACTIVE";
2832 case METHOD_TOK:
2833 return "METHOD";
2834 case METHODS_TOK:
2835 return "METHODS";
2836 case MODEL_TOK:
2837 return "MODEL";
2838 case NOTES_TOK:
2839 return "NOTES";
2840 case PATCH_TOK:
2841 return "PATCH";
2842 case SELECT_TOK:
2843 return "SELECT";
2844 case SWITCH_TOK:
2845 return "SWITCH";
2846 case UNITS_TOK:
2847 return "UNITS";
2848 case WHEN_TOK:
2849 return "WHEN";
2850 case END_TOK:
2851 return "";
2852 case IDENTIFIER_TOK:
2853 default:
2854 if( g_end_identifier != NULL ) {
2855 return SCP(g_end_identifier);
2856 } else {
2857 return "UNKNOWN";
2858 }
2859 }
2860 }
2861
2862 /* need a refcount game on the text field of the note. must keep
2863 * original note to avoid losing the varlist.
2864 */
2865 static void ProcessNotes(int keep)
2866 {
2867 int c,len;
2868 if (g_notelist == NULL) {
2869 return;
2870 }
2871 if (keep) {
2872 len = gl_length(g_notelist);
2873 for (c=1;c <= len;c++) {
2874 CommitNote(LibraryNote(),gl_fetch(g_notelist,c));
2875 }
2876 } else {
2877 gl_iterate(g_notelist,(void (*) (VOIDPTR))DestroyNote);
2878 }
2879 gl_destroy(g_notelist);
2880 g_notelist = NULL;
2881 }
2882
2883 static void CollectNote(struct Note *n)
2884 {
2885 if (g_notelist == NULL) {
2886 g_notelist = gl_create(50L);
2887 }
2888 if (g_notelist == NULL) {
2889 DestroyNote(n);
2890 return;
2891 }
2892 gl_append_ptr(g_notelist,(VOIDPTR)n);
2893 }
2894
2895 /*
2896 This can be called as error_reporter_current_line(ASC_USER_ERROR,...);
2897 or error_reporter_current_line(ASC_USER_WARNING,...), or with any of the other
2898 severity flags.
2899 */
2900 static void error_reporter_current_line(const error_severity_t sev, const char *fmt,...){
2901 va_list args;
2902 va_start(args,fmt);
2903 va_error_reporter(sev,Asc_ModuleBestName(Asc_CurrentModule()),(int)LineNum(),NULL,fmt,args);
2904 va_end(args);
2905 }

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22