Project

General

Profile

Statistics
| Branch: | Revision:

root / src / nedxml / ned1.y @ 79bb12dc

History | View | Annotate | Download (44.9 KB)

1
/*===============================================================
2
 * File: ned.y
3
 *
4
 *  Grammar for OMNeT++ NED.
5
 *
6
 *  Author: Andras Varga
7
 *
8
 *  Based on code from nedc.
9
 *
10
 *  nedc credits:
11
 *     original code:
12
 *       Jan Heijmans, Alex Paalvast, Robert van der Leij, 1996
13
 *       (nedc was originally named jar, for Jan+Alex+Robert)
14
 *     modifications
15
 *       Gabor Lencse 1998
16
 *     restructuring, maintenance, new features, etc:
17
 *       Andras Varga 1996-2001
18
 *
19
 *=============================================================*/
20

    
21
/*--------------------------------------------------------------*
22
  Copyright (C) 1992,2006 Andras Varga
23

    
24
  This file is distributed WITHOUT ANY WARRANTY. See the file
25
  `license' for details on this and other legal matters.
26
*--------------------------------------------------------------*/
27

    
28
%token INCLUDE SIMPLE
29
%token CHANNEL
30
%token MODULE PARAMETERS GATES GATESIZES SUBMODULES CONNECTIONS DISPLAY
31
%token IN OUT
32
%token NOCHECK LEFT_ARROW RIGHT_ARROW
33
%token FOR TO DO IF LIKE
34
%token NETWORK
35
%token ENDSIMPLE ENDMODULE ENDCHANNEL
36
%token ENDNETWORK ENDFOR
37
%token MACHINES ON
38
%token CHANATTRNAME
39

    
40
%token INTCONSTANT REALCONSTANT NAME STRINGCONSTANT CHARCONSTANT
41
%token TRUE_ FALSE_
42
%token INPUT_ XMLDOC
43
%token REF ANCESTOR
44
%token CONSTDECL NUMERICTYPE STRINGTYPE BOOLTYPE XMLTYPE ANYTYPE
45

    
46
%token CPLUSPLUS CPLUSPLUSBODY
47
%token MESSAGE CLASS STRUCT ENUM NONCOBJECT
48
%token EXTENDS FIELDS PROPERTIES ABSTRACT READONLY
49
%token CHARTYPE SHORTTYPE INTTYPE LONGTYPE DOUBLETYPE UNSIGNED_
50

    
51
%token SIZEOF SUBMODINDEX PLUSPLUS
52
%token EQ NE GT GE LS LE
53
%token AND OR XOR NOT
54
%token BIN_AND BIN_OR BIN_XOR BIN_COMPL
55
%token SHIFT_LEFT SHIFT_RIGHT
56

    
57
%token INVALID_CHAR   /* just to generate parse error --VA */
58

    
59
/* Operator precedences (low to high) and associativity */
60
%right '?' ':'
61
%left OR
62
%left XOR
63
%left AND
64
%left EQ NE GT GE LS LE
65
%left BIN_OR
66
%left BIN_XOR
67
%left BIN_AND
68
%left SHIFT_LEFT SHIFT_RIGHT
69
%left '+' '-'
70
%left '*' '/' '%'
71
%right '^'
72
%left UMIN NOT BIN_COMPL
73

    
74
%start networkdescription
75

    
76

    
77
%{
78

    
79
/*
80
 * Note:
81
 * This file contains about 5 shift-reduce conflicts, 3 of them around 'expression'.
82
 *
83
 * Plus one (real) ambiguity exists between submodule display string
84
 * and compound module display string if no connections are present.
85
 */
86

    
87

    
88
#include <stdio.h>
89
#include <stdlib.h>
90
#include <assert.h>
91
#include "nedyydefs.h"
92
#include "nedutil.h"
93
#include "nederror.h"
94
#include "nedexception.h"
95
#include "stringutil.h"
96
#include "commonutil.h"
97

    
98
#define YYDEBUG 1           /* allow debugging */
99
#define YYDEBUGGING_ON 0    /* turn on/off debugging */
100

    
101
#if YYDEBUG != 0
102
#define YYERROR_VERBOSE     /* more detailed error messages */
103
#include <string.h>         /* YYVERBOSE needs it */
104
#endif
105

    
106
#define yylloc ned1yylloc
107
#define yyin ned1yyin
108
#define yyout ned1yyout
109
#define yyrestart ned1yyrestart
110
#define yy_scan_string ned1yy_scan_string
111
#define yy_delete_buffer ned1yy_delete_buffer
112
extern FILE *yyin;
113
extern FILE *yyout;
114
struct yy_buffer_state;
115
struct yy_buffer_state *yy_scan_string(const char *str);
116
void yy_delete_buffer(struct yy_buffer_state *);
117
void yyrestart(FILE *);
118
int yylex();
119
void yyerror (const char *s);
120

    
121
#include "nedparser.h"
122
#include "nedfilebuffer.h"
123
#include "nedelements.h"
124
#include "nedutil.h"
125
#include "nedyylib.h"
126

    
127
USING_NAMESPACE
128

    
129
static struct NED1ParserState
130
{
131
    bool inLoop;
132
    bool inNetwork;
133
    bool inGroup;
134

    
135
    /* tmp flags, used with msg fields */
136
    bool isAbstract;
137
    bool isReadonly;
138

    
139
    /* NED-I: modules, channels, networks */
140
    NedFileElement *nedfile;
141
    CommentElement *comment;
142
    ImportElement *import;
143
    ExtendsElement *extends;
144
    ChannelElement *channel;
145
    NEDElement *module;  // in fact, CompoundModuleElement* or SimpleModule*
146
    ParametersElement *params;
147
    ParamElement *param;
148
    ParametersElement *substparams;
149
    ParamElement *substparam;
150
    PropertyElement *property;
151
    PropertyKeyElement *propkey;
152
    GatesElement *gates;
153
    GateElement *gate;
154
    GatesElement *gatesizes;
155
    GateElement *gatesize;
156
    SubmodulesElement *submods;
157
    SubmoduleElement *submod;
158
    ConnectionsElement *conns;
159
    ConnectionGroupElement *conngroup;
160
    ConnectionElement *conn;
161
    ChannelSpecElement *chanspec;
162
    LoopElement *loop;
163
    ConditionElement *condition;
164
} ps;
165

    
166
static void resetParserState()
167
{
168
    static NED1ParserState cleanps;
169
    ps = cleanps;
170
}
171

    
172
ChannelSpecElement *createChannelSpec(NEDElement *conn);
173
void removeRedundantChanSpecParams();
174
void createSubstparamsElementIfNotExists();
175
void createGatesizesElementIfNotExists();
176

    
177
%}
178

    
179
%%
180

    
181
/*
182
 * Top-level components (no shift-reduce conflict here)
183
 */
184
networkdescription
185
        : somedefinitions
186
        ;
187

    
188
somedefinitions
189
        : somedefinitions definition
190
        |
191
        ;
192

    
193
definition
194
        : import
195

    
196
        | channeldefinition
197
                { if (np->getStoreSourceFlag()) storeComponentSourceCode(ps.channel, @1); }
198
        | simpledefinition
199
                { if (np->getStoreSourceFlag()) storeComponentSourceCode(ps.module, @1); }
200
        | moduledefinition
201
                { if (np->getStoreSourceFlag()) storeComponentSourceCode(ps.module, @1); }
202
        | networkdefinition
203
                { if (np->getStoreSourceFlag()) storeComponentSourceCode(ps.module, @1); }
204
        ;
205

    
206
/*
207
 * Imports (no shift-reduce conflict here)
208
 */
209
import
210
        : INCLUDE
211
          filenames ';'
212
        ;
213

    
214
filenames
215
        : filenames ',' filename
216
        | filename
217
        ;
218

    
219
filename
220
        : STRINGCONSTANT
221
                {
222
                  ps.import = (ImportElement *)createElementWithTag(NED_IMPORT, ps.nedfile );
223
                  ps.import->setImportSpec(toString(trimQuotes(@1)));
224
                  storeBannerAndRightComments(ps.import,@1);
225
                  storePos(ps.import, @$);
226
                }
227
        ;
228

    
229
/*
230
 * Channel - old syntax
231
 */
232
channeldefinition
233
        : channelheader opt_channelattrblock endchannel
234
                {
235
                  storePos(ps.channel, @$);
236
                  storeTrailingComment(ps.channel,@$);
237
                }
238
        ;
239

    
240
channelheader
241
        : CHANNEL NAME
242
                {
243
                  ps.channel = (ChannelElement *)createElementWithTag(NED_CHANNEL, ps.nedfile);
244
                  ps.channel->setName(toString(@2));
245
                  ps.extends = (ExtendsElement *)createElementWithTag(NED_EXTENDS, ps.channel);
246
                  ps.extends->setName("ned.DatarateChannel");  // NED-1 channels are implicitly DatarateChannels
247
                  ps.params = (ParametersElement *)createElementWithTag(NED_PARAMETERS, ps.channel);
248
                  ps.params->setIsImplicit(true);
249
                  storeBannerAndRightComments(ps.channel,@1,@2);
250
                }
251
        ;
252

    
253
opt_channelattrblock
254
        :
255
        | channelattrblock
256
                { storePos(ps.params, @$); }
257
        ;
258

    
259
channelattrblock
260
        : channelattrblock CHANATTRNAME expression opt_semicolon
261
                {
262
                  const char *name = toString(@2);
263
                  if (strcmp(name,"error")==0) name = "ber";  // "error" got renamed to "ber" in 4.0
264
                  ps.params->setIsImplicit(false);
265
                  ps.param = addParameter(ps.params, name, @2);
266
                  addExpression(ps.param, "value",@3,$3);
267
                  storeBannerAndRightComments(ps.param,@2,@3);
268
                  storePos(ps.param, @2,@4);
269
                }
270
        | CHANATTRNAME expression opt_semicolon
271
                {
272
                  const char *name = toString(@1);
273
                  if (strcmp(name,"error")==0) name = "ber"; // "error" got renamed to "ber" in 4.0
274
                  ps.params->setIsImplicit(false);
275
                  ps.param = addParameter(ps.params, name, @1);
276
                  addExpression(ps.param, "value",@2,$2);
277
                  storeBannerAndRightComments(ps.param,@1,@2);
278
                  storePos(ps.param, @$);
279
                }
280
        ;
281

    
282
endchannel
283
        : ENDCHANNEL NAME opt_semicolon
284
        | ENDCHANNEL opt_semicolon
285
        ;
286

    
287
/*
288
 * Simple module - old syntax
289
 */
290
simpledefinition
291
        : simpleheader
292
            opt_paramblock
293
            opt_gateblock
294
          endsimple
295
                {
296
                  storePos(ps.module, @$);
297
                  storeTrailingComment(ps.module,@$);
298
                }
299
        ;
300

    
301
simpleheader
302
        : SIMPLE NAME
303
                {
304
                  ps.module = (SimpleModuleElement *)createElementWithTag(NED_SIMPLE_MODULE, ps.nedfile );
305
                  ((SimpleModuleElement *)ps.module)->setName(toString(@2));
306
                  storeBannerAndRightComments(ps.module,@1,@2);
307
                }
308
        ;
309

    
310
endsimple
311
        : ENDSIMPLE NAME opt_semicolon
312
        | ENDSIMPLE opt_semicolon
313
        ;
314

    
315
/*
316
 * Module - old syntax
317
 */
318
moduledefinition
319
        : moduleheader
320
            opt_paramblock
321
            opt_gateblock
322
            opt_submodblock
323
            opt_connblock
324
            opt_displayblock
325
          endmodule
326
                {
327
                  storePos(ps.module, @$);
328
                  storeTrailingComment(ps.module,@$);
329
                }
330
        ;
331

    
332
moduleheader
333
        : MODULE NAME
334
                {
335
                  ps.module = (CompoundModuleElement *)createElementWithTag(NED_COMPOUND_MODULE, ps.nedfile );
336
                  ((CompoundModuleElement *)ps.module)->setName(toString(@2));
337
                  storeBannerAndRightComments(ps.module,@1,@2);
338
                }
339
        ;
340

    
341
endmodule
342
        : ENDMODULE NAME opt_semicolon
343
        | ENDMODULE opt_semicolon
344
        ;
345

    
346
/*
347
 * Display block - old syntax
348
 */
349
opt_displayblock
350
        : displayblock
351
        |
352
        ;
353

    
354
displayblock
355
        : DISPLAY ':' STRINGCONSTANT ';'
356
                {
357
                  ps.property = addComponentProperty(ps.module, "display");
358
                  ps.params = (ParametersElement *)ps.module->getFirstChildWithTag(NED_PARAMETERS); // previous line doesn't set it
359
                  ps.propkey = (PropertyKeyElement *)createElementWithTag(NED_PROPERTY_KEY, ps.property);
360
                  LiteralElement *literal = (LiteralElement *)createElementWithTag(NED_LITERAL);
361
                  literal->setType(NED_CONST_STRING);
362
                  try {
363
                      std::string displaystring = DisplayStringUtil::upgradeBackgroundDisplayString(opp_parsequotedstr(toString(@3)).c_str());
364
                      literal->setValue(displaystring.c_str());
365
                      // NOTE: no setText(): it would cause the OLD form to be exported into NED2 too
366
                  }
367
                  catch (std::exception& e) {
368
                      np->getErrors()->addError(ps.property, e.what());
369
                  }
370
                  ps.propkey->appendChild(literal);
371
                  storePos(ps.propkey, @$);
372
                  storePos(literal, @3);
373
                  storePos(ps.property, @$);
374
                  storeBannerAndRightComments(ps.property,@$);
375
                }
376
        ;
377

    
378
/*
379
 * Parameters - old syntax
380
 */
381
opt_paramblock
382
        : paramblock
383
        |
384
        ;
385

    
386
paramblock
387
        : PARAMETERS ':'
388
                {
389
                  ps.params = (ParametersElement *)getOrCreateElementWithTag(NED_PARAMETERS, ps.module); // network header may have created it for @isNetwork
390
                  storeBannerAndRightComments(ps.params,@1,@2);
391
                }
392
          opt_parameters
393
                {
394
                  storePos(ps.params, @$);
395
                }
396
        ;
397

    
398
opt_parameters
399
        : parameters ';'
400
        |
401
        ;
402

    
403
parameters
404
        : parameters ',' parameter  /* comma as separator */
405
                {
406
                  storePos(ps.param, @3);
407
                  storeBannerAndRightComments(ps.param,@3);
408
                }
409
        | parameter
410
                {
411
                  storePos(ps.param, @1);
412
                  storeBannerAndRightComments(ps.param,@1);
413
                }
414
        ;
415

    
416
/*
417
 * Parameter
418
 */
419
parameter
420
        : NAME
421
                {
422
                  ps.param = addParameter(ps.params, @1);
423
                  ps.param->setType(NED_PARTYPE_DOUBLE);
424
                  ps.param->setIsVolatile(true); // because CONST is missing
425
                }
426
        | NAME ':' NUMERICTYPE
427
                {
428
                  ps.param = addParameter(ps.params, @1);
429
                  ps.param->setType(NED_PARTYPE_DOUBLE);
430
                  ps.param->setIsVolatile(true); // because CONST is missing
431
                }
432
        | CONSTDECL NAME /* for compatibility */
433
                {
434
                  ps.param = addParameter(ps.params, @2);
435
                  ps.param->setType(NED_PARTYPE_DOUBLE);
436
                }
437
        | NAME ':' CONSTDECL
438
                {
439
                  ps.param = addParameter(ps.params, @1);
440
                  ps.param->setType(NED_PARTYPE_DOUBLE);
441
                }
442
        | NAME ':' CONSTDECL NUMERICTYPE
443
                {
444
                  ps.param = addParameter(ps.params, @1);
445
                  ps.param->setType(NED_PARTYPE_DOUBLE);
446
                }
447
        | NAME ':' NUMERICTYPE CONSTDECL
448
                {
449
                  ps.param = addParameter(ps.params, @1);
450
                  ps.param->setType(NED_PARTYPE_DOUBLE);
451
                }
452
        | NAME ':' STRINGTYPE
453
                {
454
                  ps.param = addParameter(ps.params, @1);
455
                  ps.param->setType(NED_PARTYPE_STRING);
456
                }
457
        | NAME ':' BOOLTYPE
458
                {
459
                  ps.param = addParameter(ps.params, @1);
460
                  ps.param->setType(NED_PARTYPE_BOOL);
461
                }
462
        | NAME ':' XMLTYPE
463
                {
464
                  ps.param = addParameter(ps.params, @1);
465
                  ps.param->setType(NED_PARTYPE_XML);
466
                }
467
        | NAME ':' ANYTYPE
468
                {
469
                  np->getErrors()->addError(ps.params,"type 'anytype' no longer supported");
470
                  ps.param = addParameter(ps.params, @1); // add anyway to prevent crash
471
                }
472
        ;
473

    
474
/*
475
 * Gates - old syntax
476
 */
477
opt_gateblock
478
        : gateblock
479
        |
480
        ;
481

    
482
gateblock
483
        : GATES ':'
484
                {
485
                  ps.gates = (GatesElement *)createElementWithTag(NED_GATES, ps.module );
486
                  storeBannerAndRightComments(ps.gates,@1,@2);
487
                }
488
          opt_gates
489
                {
490
                  storePos(ps.gates, @$);
491
                }
492
        ;
493

    
494
opt_gates
495
        : gates
496
        |
497
        ;
498

    
499
gates
500
        : gates IN gatesI ';'
501
        | IN  gatesI ';'
502
        | gates OUT gatesO ';'
503
        | OUT gatesO ';'
504
        ;
505

    
506
gatesI
507
        : gatesI ',' gateI
508
        | gateI
509
        ;
510

    
511
gateI
512
        : NAME '[' ']'
513
                {
514
                  ps.gate = addGate(ps.gates, @1);
515
                  ps.gate->setType(NED_GATETYPE_INPUT);
516
                  ps.gate->setIsVector(true);
517
                  storeBannerAndRightComments(ps.gate,@1,@3);
518
                  storePos(ps.gate, @$);
519
                }
520
        | NAME
521
                {
522
                  ps.gate = addGate(ps.gates, @1);
523
                  ps.gate->setType(NED_GATETYPE_INPUT);
524
                  storeBannerAndRightComments(ps.gate,@1);
525
                  storePos(ps.gate, @$);
526
                }
527
        ;
528

    
529
gatesO
530
        : gatesO ',' gateO
531
        | gateO
532
        ;
533

    
534
gateO
535
        : NAME '[' ']'
536
                {
537
                  ps.gate = addGate(ps.gates, @1);
538
                  ps.gate->setType(NED_GATETYPE_OUTPUT);
539
                  ps.gate->setIsVector(true);
540
                  storeBannerAndRightComments(ps.gate,@1,@3);
541
                  storePos(ps.gate, @$);
542
                }
543
        | NAME
544
                {
545
                  ps.gate = addGate(ps.gates, @1);
546
                  ps.gate->setType(NED_GATETYPE_OUTPUT);
547
                  storeBannerAndRightComments(ps.gate,@1,@1);
548
                  storePos(ps.gate, @$);
549
                }
550
        ;
551

    
552
/*
553
 * Submodules - old syntax
554
 */
555
opt_submodblock
556
        : submodblock
557
        |
558
        ;
559

    
560
submodblock
561
        : SUBMODULES ':'
562
                {
563
                  ps.submods = (SubmodulesElement *)createElementWithTag(NED_SUBMODULES, ps.module );
564
                  storeBannerAndRightComments(ps.submods,@1,@2);
565
                }
566
          opt_submodules
567
                {
568
                  storePos(ps.submods, @$);
569
                }
570
        ;
571

    
572
opt_submodules
573
        : submodules
574
        |
575
        ;
576

    
577
submodules
578
        : submodules submodule
579
        | submodule
580
        ;
581

    
582
submodule
583
        : NAME ':' NAME opt_semicolon
584
                {
585
                  ps.submod = (SubmoduleElement *)createElementWithTag(NED_SUBMODULE, ps.submods);
586
                  ps.submod->setName(toString(@1));
587
                  ps.submod->setType(toString(@3));
588
                  storeBannerAndRightComments(ps.submod,@1,@4);
589
                }
590
          submodule_body
591
                {
592
                  storePos(ps.submod, @$);
593
                }
594
        | NAME ':' NAME vector opt_semicolon
595
                {
596
                  ps.submod = (SubmoduleElement *)createElementWithTag(NED_SUBMODULE, ps.submods);
597
                  ps.submod->setName(toString(@1));
598
                  ps.submod->setType(toString(@3));
599
                  addVector(ps.submod, "vector-size",@4,$4);
600
                  storeBannerAndRightComments(ps.submod,@1,@5);
601
                }
602
          submodule_body
603
                {
604
                  storePos(ps.submod, @$);
605
                }
606
        | NAME ':' NAME LIKE NAME opt_semicolon
607
                {
608
                  ps.submod = (SubmoduleElement *)createElementWithTag(NED_SUBMODULE, ps.submods);
609
                  ps.submod->setName(toString(@1));
610
                  ps.submod->setLikeType(toString(@5));
611
                  ps.submod->setLikeParam(toString(@3)); //FIXME store as expression!!!
612
                  storeBannerAndRightComments(ps.submod,@1,@6);
613
                }
614
          submodule_body
615
                {
616
                  storePos(ps.submod, @$);
617
                }
618
        | NAME ':' NAME vector LIKE NAME opt_semicolon
619
                {
620
                  ps.submod = (SubmoduleElement *)createElementWithTag(NED_SUBMODULE, ps.submods);
621
                  ps.submod->setName(toString(@1));
622
                  ps.submod->setLikeType(toString(@6));
623
                  ps.submod->setLikeParam(toString(@3)); //FIXME store as expression!!!
624
                  addVector(ps.submod, "vector-size",@4,$4);
625
                  storeBannerAndRightComments(ps.submod,@1,@7);
626
                }
627
          submodule_body
628
                {
629
                  storePos(ps.submod, @$);
630
                }
631
        ;
632

    
633
submodule_body
634
        : opt_substparamblocks
635
          opt_gatesizeblocks
636
          opt_submod_displayblock
637
        ;
638

    
639
/*
640
 * Substparameters - old syntax
641
 */
642
opt_substparamblocks
643
        : substparamblocks
644
                { storePos(ps.substparams, @$); /*must do it here because there might be multiple (conditional) gatesizes/parameters sections */ }
645
        |
646
        ;
647

    
648
substparamblocks
649
        : substparamblocks substparamblock
650
        | substparamblock
651
        ;
652

    
653
substparamblock
654
        : PARAMETERS ':' /*FIXME empty "parameters:" in submodule doesn't get accepted! WFT??? */
655
                {
656
                  createSubstparamsElementIfNotExists();
657
                  storeBannerAndRightComments(ps.substparams,@1,@2);
658
                }
659
          opt_substparameters
660
        | PARAMETERS IF expression ':'
661
                {
662
                  createSubstparamsElementIfNotExists();
663
                  delete $3;
664
                  np->getErrors()->addError(ps.substparams,
665
                                    "conditional parameters no longer supported -- "
666
                                    "please rewrite parameter assignments to use "
667
                                    "conditional expression syntax (cond ? a : b)");
668
                }
669
          opt_substparameters
670
        ;
671

    
672
opt_substparameters
673
        : substparameters ';'
674
        |
675
        ;
676

    
677
substparameters
678
        : substparameters ',' substparameter   /* comma as separator */
679
        | substparameter
680
        ;
681

    
682
substparameter
683
        : NAME '=' expression
684
                {
685
                  ps.substparam = addParameter(ps.substparams,@1);
686
                  addExpression(ps.substparam, "value",@3,$3);
687
                  storeBannerAndRightComments(ps.substparam,@1,@3);
688
                  storePos(ps.substparam, @$);
689
                }
690
        | NAME '=' INPUT_
691
                {
692
                  ps.substparam = addParameter(ps.substparams,@1);
693
                  ps.substparam->setIsDefault(true);
694
                }
695
          inputvalue
696
                {
697
                  storeBannerAndRightComments(ps.substparam,@1,@5);
698
                  storePos(ps.substparam, @$);
699
                }
700
        ;
701

    
702
inputvalue
703
        : '(' expression ',' STRINGCONSTANT ')'
704
                {
705
                  addExpression(ps.substparam, "value",@2,$2);
706

    
707
                  PropertyElement *prop = addProperty(ps.substparam, "prompt");
708
                  PropertyKeyElement *propkey = (PropertyKeyElement *)createElementWithTag(NED_PROPERTY_KEY, prop);
709
                  propkey->appendChild(createStringLiteral(@4));
710
                }
711
        | '(' expression ')'
712
                {
713
                  addExpression(ps.substparam, "value",@2,$2);
714
                }
715
        | '(' ')'
716
        |
717
        ;
718

    
719
/*
720
 * Gatesizes - old syntax
721
 */
722
opt_gatesizeblocks
723
        : gatesizeblocks
724
                { storePos(ps.gatesizes, @$); /*must do it here because there might be multiple (conditional) gatesizes/parameters sections */ }
725
        |
726
        ;
727

    
728
gatesizeblocks
729
        : gatesizeblocks gatesizeblock
730
        | gatesizeblock
731
        ;
732

    
733
gatesizeblock
734
        : GATESIZES ':'
735
                {
736
                  createGatesizesElementIfNotExists();
737
                  storeBannerAndRightComments(ps.gatesizes,@1,@2);
738
                }
739
          opt_gatesizes
740
        | GATESIZES IF expression ':'
741
                {
742
                  createSubstparamsElementIfNotExists();
743
                  delete $3;
744
                  np->getErrors()->addError(ps.substparams,
745
                                    "conditional gatesizes no longer supported -- "
746
                                    "please rewrite gatesize assignments to use "
747
                                    "conditional expression syntax (cond ? a : b)");
748
                }
749
          opt_gatesizes
750
        ;
751

    
752
opt_gatesizes
753
        : gatesizes ';'
754
        |
755
        ;
756

    
757
gatesizes
758
        : gatesizes ',' gatesize
759
        | gatesize
760
        ;
761

    
762
gatesize
763
        : NAME vector
764
                {
765
                  ps.gatesize = addGate(ps.gatesizes,@1);
766
                  ps.gatesize->setIsVector(true);
767
                  addVector(ps.gatesize, "vector-size",@2,$2);
768
                  storeBannerAndRightComments(ps.gatesize,@1,@2);
769
                  storePos(ps.gatesize, @$);
770
                }
771
        ;
772

    
773
/*
774
 * Submodule-displayblock - old syntax
775
 */
776
opt_submod_displayblock
777
        : DISPLAY ':' STRINGCONSTANT ';'
778
                {
779
                  ps.property = addComponentProperty(ps.submod, "display");
780
                  ps.substparams = (ParametersElement *)ps.submod->getFirstChildWithTag(NED_PARAMETERS); // previous line doesn't set it
781
                  ps.propkey = (PropertyKeyElement *)createElementWithTag(NED_PROPERTY_KEY, ps.property);
782
                  LiteralElement *literal = (LiteralElement *)createElementWithTag(NED_LITERAL);
783
                  literal->setType(NED_CONST_STRING);
784
                  try {
785
                      std::string displaystring = DisplayStringUtil::upgradeSubmoduleDisplayString(opp_parsequotedstr(toString(@3)).c_str());
786
                      literal->setValue(displaystring.c_str());
787
                      // NOTE: no setText(): it would cause the OLD form to be exported into NED2 too
788
                  }
789
                  catch (std::exception& e) {
790
                      np->getErrors()->addError(ps.property, e.what());
791
                  }
792
                  ps.propkey->appendChild(literal);
793
                  storePos(ps.propkey, @$);
794
                  storePos(literal, @3);
795
                  storePos(ps.property, @$);
796
                  storeBannerAndRightComments(ps.property,@$);
797
                }
798
        |
799
        ;
800

    
801
/*
802
 * Connections - old syntax  (about 7 shift/reduce)
803
 */
804
opt_connblock
805
        : connblock
806
        |
807
        ;
808

    
809
connblock
810
        : CONNECTIONS NOCHECK ':'
811
                {
812
                  ps.conns = (ConnectionsElement *)createElementWithTag(NED_CONNECTIONS, ps.module );
813
                  ps.conns->setAllowUnconnected(true);
814
                  storeBannerAndRightComments(ps.conns,@1,@3);
815
                }
816
          opt_connections
817
                {
818
                  storePos(ps.conns, @$);
819
                }
820
        | CONNECTIONS ':'
821
                {
822
                  ps.conns = (ConnectionsElement *)createElementWithTag(NED_CONNECTIONS, ps.module );
823
                  ps.conns->setAllowUnconnected(false);
824
                  storeBannerAndRightComments(ps.conns,@1,@2);
825
                }
826
          opt_connections
827
                {
828
                  storePos(ps.conns, @$);
829
                }
830
        ;
831

    
832
opt_connections
833
        : connections
834
        |
835
        ;
836

    
837
connections
838
        : connections connection
839
        | connection
840
        ;
841

    
842
connection
843
        : loopconnection
844
        | notloopconnection
845
        ;
846

    
847
loopconnection
848
        : FOR
849
                {
850
                  ps.conngroup = (ConnectionGroupElement *)createElementWithTag(NED_CONNECTION_GROUP, ps.conns);
851
                  ps.inLoop=1;
852
                }
853
          loopvarlist DO notloopconnections ENDFOR opt_semicolon
854
                {
855
                  ps.inLoop=0;
856
                  storePos(ps.conngroup, @$);
857
                  storeBannerAndRightComments(ps.conngroup,@1,@4); // "for..do"
858
                  storeTrailingComment(ps.conngroup,@$);
859
                }
860
        ;
861

    
862
loopvarlist
863
        : loopvar ',' loopvarlist
864
        | loopvar
865
        ;
866

    
867
loopvar
868
        : NAME '=' expression TO expression
869
                {
870
                  ps.loop = (LoopElement *)createElementWithTag(NED_LOOP, ps.conngroup);
871
                  ps.loop->setParamName( toString(@1) );
872
                  addExpression(ps.loop, "from-value",@3,$3);
873
                  addExpression(ps.loop, "to-value",@5,$5);
874
                  storePos(ps.loop, @$);
875
                }
876
        ;
877

    
878
opt_conncondition
879
        : IF expression
880
                {
881
                  // add condition to conn
882
                  ps.condition = (ConditionElement *)createElementWithTag(NED_CONDITION, ps.conn);
883
                  addExpression(ps.condition, "condition",@2,$2);
884
                  storePos(ps.condition, @$);
885
                }
886
        |
887
        ;
888

    
889
opt_conn_displaystr
890
        : DISPLAY STRINGCONSTANT
891
                {
892
                  bool hadChanSpec = ps.chanspec!=NULL;
893
                  if (!ps.chanspec)
894
                      ps.chanspec = createChannelSpec(ps.conn);
895
                  ps.property = addComponentProperty(ps.chanspec, "display");
896
                  ps.propkey = (PropertyKeyElement *)createElementWithTag(NED_PROPERTY_KEY, ps.property);
897
                  LiteralElement *literal = (LiteralElement *)createElementWithTag(NED_LITERAL);
898
                  literal->setType(NED_CONST_STRING);
899
                  try {
900
                      std::string displaystring = DisplayStringUtil::upgradeConnectionDisplayString(opp_parsequotedstr(toString(@2)).c_str());
901
                      literal->setValue(displaystring.c_str());
902
                  }
903
                  catch (std::exception& e) {
904
                      np->getErrors()->addError(ps.property, e.what());
905
                  }
906
                  // NOTE: no setText(): it would cause the OLD form to be exported into NED2 too
907
                  ps.propkey->appendChild(literal);
908
                  storePos(ps.propkey, @$);
909
                  storePos(literal, @2);
910
                  storePos(ps.property, @$);
911
                  if (!hadChanSpec)
912
                      storePos(ps.chanspec, @$);
913
                }
914
        |
915
        ;
916

    
917
notloopconnections
918
        : notloopconnections notloopconnection
919
        | notloopconnection
920
        ;
921

    
922
notloopconnection
923
        : leftgatespec RIGHT_ARROW rightgatespec opt_conncondition opt_conn_displaystr comma_or_semicolon
924
                {
925
                  ps.conn->setArrowDirection(NED_ARROWDIR_L2R);
926
                  storeBannerAndRightComments(ps.conn,@$);
927
                  storePos(ps.conn, @$);
928
                }
929
        | leftgatespec RIGHT_ARROW channeldescr RIGHT_ARROW rightgatespec opt_conncondition opt_conn_displaystr comma_or_semicolon
930
                {
931
                  ps.conn->setArrowDirection(NED_ARROWDIR_L2R);
932
                  removeRedundantChanSpecParams();
933
                  storeBannerAndRightComments(ps.conn,@$);
934
                  storePos(ps.conn, @$);
935
                }
936
        | leftgatespec LEFT_ARROW rightgatespec opt_conncondition opt_conn_displaystr comma_or_semicolon
937
                {
938
                  swapConnection(ps.conn);
939
                  ps.conn->setArrowDirection(NED_ARROWDIR_R2L);
940
                  storeBannerAndRightComments(ps.conn,@$);
941
                  storePos(ps.conn, @$);
942
                }
943
        | leftgatespec LEFT_ARROW channeldescr LEFT_ARROW rightgatespec opt_conncondition opt_conn_displaystr comma_or_semicolon
944
                {
945
                  swapConnection(ps.conn);
946
                  ps.conn->setArrowDirection(NED_ARROWDIR_R2L);
947
                  removeRedundantChanSpecParams();
948
                  storeBannerAndRightComments(ps.conn,@$);
949
                  storePos(ps.conn, @$);
950
                }
951
        ;
952

    
953
leftgatespec
954
        : leftmod '.' leftgate
955
        | parentleftgate
956
        ;
957

    
958
leftmod
959
        : NAME vector
960
                {
961
                  ps.conn = (ConnectionElement *)createElementWithTag(NED_CONNECTION, ps.inLoop ? (NEDElement *)ps.conngroup : (NEDElement*)ps.conns );
962
                  ps.conn->setSrcModule( toString(@1) );
963
                  addVector(ps.conn, "src-module-index",@2,$2);
964
                  ps.chanspec = NULL;   // signal that there's no chanspec for this conn yet
965
                }
966
        | NAME
967
                {
968
                  ps.conn = (ConnectionElement *)createElementWithTag(NED_CONNECTION, ps.inLoop ? (NEDElement *)ps.conngroup : (NEDElement*)ps.conns );
969
                  ps.conn->setSrcModule( toString(@1) );
970
                  ps.chanspec = NULL;   // signal that there's no chanspec for this conn yet
971
                }
972
        ;
973

    
974
leftgate
975
        : NAME vector
976
                {
977
                  ps.conn->setSrcGate( toString( @1) );
978
                  addVector(ps.conn, "src-gate-index",@2,$2);
979
                }
980
        | NAME
981
                {
982
                  ps.conn->setSrcGate( toString( @1) );
983
                }
984
        | NAME PLUSPLUS
985
                {
986
                  ps.conn->setSrcGate( toString( @1) );
987
                  ps.conn->setSrcGatePlusplus(true);
988
                }
989
        ;
990

    
991
parentleftgate
992
        : NAME vector
993
                {
994
                  ps.conn = (ConnectionElement *)createElementWithTag(NED_CONNECTION, ps.inLoop ? (NEDElement *)ps.conngroup : (NEDElement*)ps.conns );
995
                  ps.conn->setSrcModule("");
996
                  ps.conn->setSrcGate(toString(@1));
997
                  addVector(ps.conn, "src-gate-index",@2,$2);
998
                  ps.chanspec = NULL;   // signal that there's no chanspec for this conn yet
999
                }
1000
        | NAME
1001
                {
1002
                  ps.conn = (ConnectionElement *)createElementWithTag(NED_CONNECTION, ps.inLoop ? (NEDElement *)ps.conngroup : (NEDElement*)ps.conns );
1003
                  ps.conn->setSrcModule("");
1004
                  ps.conn->setSrcGate(toString(@1));
1005
                  ps.chanspec = NULL;   // signal that there's no chanspec for this conn yet
1006
                }
1007
        | NAME PLUSPLUS
1008
                {
1009
                  ps.conn = (ConnectionElement *)createElementWithTag(NED_CONNECTION, ps.inLoop ? (NEDElement *)ps.conngroup : (NEDElement*)ps.conns );
1010
                  ps.conn->setSrcModule("");
1011
                  ps.conn->setSrcGate(toString(@1));
1012
                  ps.conn->setSrcGatePlusplus(true);
1013
                  ps.chanspec = NULL;   // signal that there's no chanspec for this conn yet
1014
                }
1015
        ;
1016

    
1017
rightgatespec
1018
        : rightmod '.' rightgate
1019
        | parentrightgate
1020
        ;
1021

    
1022
rightmod
1023
        : NAME vector
1024
                {
1025
                  ps.conn->setDestModule( toString(@1) );
1026
                  addVector(ps.conn, "dest-module-index",@2,$2);
1027
                }
1028
        | NAME
1029
                {
1030
                  ps.conn->setDestModule( toString(@1) );
1031
                }
1032
        ;
1033

    
1034
rightgate
1035
        : NAME vector
1036
                {
1037
                  ps.conn->setDestGate( toString( @1) );
1038
                  addVector(ps.conn, "dest-gate-index",@2,$2);
1039
                }
1040
        | NAME
1041
                {
1042
                  ps.conn->setDestGate( toString( @1) );
1043
                }
1044
        | NAME PLUSPLUS
1045
                {
1046
                  ps.conn->setDestGate( toString( @1) );
1047
                  ps.conn->setDestGatePlusplus(true);
1048
                }
1049
        ;
1050

    
1051
parentrightgate
1052
        : NAME vector
1053
                {
1054
                  ps.conn->setDestGate( toString( @1) );
1055
                  addVector(ps.conn, "dest-gate-index",@2,$2);
1056
                }
1057
        | NAME
1058
                {
1059
                  ps.conn->setDestGate( toString( @1) );
1060
                }
1061
        | NAME PLUSPLUS
1062
                {
1063
                  ps.conn->setDestGate( toString( @1) );
1064
                  ps.conn->setDestGatePlusplus(true);
1065
                }
1066
        ;
1067

    
1068

    
1069
channeldescr
1070
        : channelattrs
1071
                {
1072
                  storePos(ps.chanspec, @$);
1073
                  if (ps.chanspec->getFirstChildWithTag(NED_PARAMETERS)!=NULL)
1074
                      storePos(ps.params, @$);
1075
                }
1076
        ;
1077

    
1078
channelattrs
1079
        : NAME
1080
                {
1081
                  if (!ps.chanspec)
1082
                      ps.chanspec = createChannelSpec(ps.conn);
1083
                  ps.chanspec->setType(toString(@1));
1084
                }
1085
        | chanattr
1086
        | channelattrs chanattr
1087
        ;
1088

    
1089
chanattr
1090
        : CHANATTRNAME expression
1091
                {
1092
                  if (!ps.chanspec)
1093
                      ps.chanspec = createChannelSpec(ps.conn);
1094
                  ps.param = addParameter(ps.params, @1);
1095
                  addExpression(ps.param, "value",@2,$2);
1096
                  storePos(ps.param, @$);
1097
                }
1098
        ;
1099

    
1100
/*
1101
 * Network - old syntax
1102
 */
1103
networkdefinition
1104
        : networkheader
1105
            opt_substparamblocks
1106
          endnetwork
1107
                {
1108
                  storePos(ps.module, @$);
1109
                  storeTrailingComment(ps.module,@$);
1110
                }
1111
        ;
1112

    
1113
networkheader
1114
        : NETWORK NAME ':' NAME opt_semicolon
1115
                {
1116
                  ps.module = (CompoundModuleElement *)createElementWithTag(NED_COMPOUND_MODULE, ps.nedfile );
1117
                  ((CompoundModuleElement *)ps.module)->setName(toString(@2));
1118
                  ps.extends = (ExtendsElement *)createElementWithTag(NED_EXTENDS, ps.module);
1119
                  ps.extends->setName(toString(@4));
1120
                  storeBannerAndRightComments(ps.module,@1,@5);
1121
                  storePos(ps.extends, @4);
1122
                  setIsNetworkProperty(ps.module);
1123
                  ps.inNetwork=1;
1124
                }
1125
        ;
1126

    
1127
endnetwork
1128
        : ENDNETWORK opt_semicolon
1129
                {
1130
                  ps.inNetwork=0;
1131
                }
1132
        ;
1133

    
1134
/*
1135
 * Common part
1136
 */
1137
vector
1138
        : '[' expression ']'
1139
                { $$ = $2; }
1140
        ;
1141

    
1142
expression
1143
        :
1144
          expr
1145
                {
1146
                  if (np->getParseExpressionsFlag()) $$ = createExpression($1);
1147
                }
1148
        | xmldocvalue
1149
                {
1150
                  if (np->getParseExpressionsFlag()) $$ = createExpression($1);
1151
                }
1152
        ;
1153

    
1154
/*
1155
 * Expressions (3 shift-reduce conflicts here)
1156
 */
1157

    
1158
xmldocvalue
1159
        : XMLDOC '(' stringliteral ',' stringliteral ')'
1160
                { if (np->getParseExpressionsFlag()) $$ = createFunction("xmldoc", $3, $5); }
1161
        | XMLDOC '(' stringliteral ')'
1162
                { if (np->getParseExpressionsFlag()) $$ = createFunction("xmldoc", $3); }
1163
        ;
1164

    
1165
expr
1166
        : simple_expr
1167
        | '(' expr ')'
1168
                { $$ = $2; }
1169

    
1170
        | expr '+' expr
1171
                { if (np->getParseExpressionsFlag()) $$ = createOperator("+", $1, $3); }
1172
        | expr '-' expr
1173
                { if (np->getParseExpressionsFlag()) $$ = createOperator("-", $1, $3); }
1174
        | expr '*' expr
1175
                { if (np->getParseExpressionsFlag()) $$ = createOperator("*", $1, $3); }
1176
        | expr '/' expr
1177
                { if (np->getParseExpressionsFlag()) $$ = createOperator("/", $1, $3); }
1178
        | expr '%' expr
1179
                { if (np->getParseExpressionsFlag()) $$ = createOperator("%", $1, $3); }
1180
        | expr '^' expr
1181
                { if (np->getParseExpressionsFlag()) $$ = createOperator("^", $1, $3); }
1182

    
1183
        | '-' expr
1184
                %prec UMIN
1185
                { if (np->getParseExpressionsFlag()) $$ = unaryMinus($2); }
1186

    
1187
        | expr EQ expr
1188
                { if (np->getParseExpressionsFlag()) $$ = createOperator("==", $1, $3); }
1189
        | expr NE expr
1190
                { if (np->getParseExpressionsFlag()) $$ = createOperator("!=", $1, $3); }
1191
        | expr GT expr
1192
                { if (np->getParseExpressionsFlag()) $$ = createOperator(">", $1, $3); }
1193
        | expr GE expr
1194
                { if (np->getParseExpressionsFlag()) $$ = createOperator(">=", $1, $3); }
1195
        | expr LS expr
1196
                { if (np->getParseExpressionsFlag()) $$ = createOperator("<", $1, $3); }
1197
        | expr LE expr
1198
                { if (np->getParseExpressionsFlag()) $$ = createOperator("<=", $1, $3); }
1199

    
1200
        | expr AND expr
1201
                { if (np->getParseExpressionsFlag()) $$ = createOperator("&&", $1, $3); }
1202
        | expr OR expr
1203
                { if (np->getParseExpressionsFlag()) $$ = createOperator("||", $1, $3); }
1204
        | expr XOR expr
1205
                { if (np->getParseExpressionsFlag()) $$ = createOperator("##", $1, $3); }
1206

    
1207
        | NOT expr
1208
                %prec UMIN
1209
                { if (np->getParseExpressionsFlag()) $$ = createOperator("!", $2); }
1210

    
1211
        | expr BIN_AND expr
1212
                { if (np->getParseExpressionsFlag()) $$ = createOperator("&", $1, $3); }
1213
        | expr BIN_OR expr
1214
                { if (np->getParseExpressionsFlag()) $$ = createOperator("|", $1, $3); }
1215
        | expr BIN_XOR expr
1216
                { if (np->getParseExpressionsFlag()) $$ = createOperator("#", $1, $3); }
1217

    
1218
        | BIN_COMPL expr
1219
                %prec UMIN
1220
                { if (np->getParseExpressionsFlag()) $$ = createOperator("~", $2); }
1221
        | expr SHIFT_LEFT expr
1222
                { if (np->getParseExpressionsFlag()) $$ = createOperator("<<", $1, $3); }
1223
        | expr SHIFT_RIGHT expr
1224
                { if (np->getParseExpressionsFlag()) $$ = createOperator(">>", $1, $3); }
1225
        | expr '?' expr ':' expr
1226
                { if (np->getParseExpressionsFlag()) $$ = createOperator("?:", $1, $3, $5); }
1227

    
1228
        | INTTYPE '(' expr ')'
1229
                { if (np->getParseExpressionsFlag()) $$ = createFunction(toString(@1), $3); }
1230
        | DOUBLETYPE '(' expr ')'
1231
                { if (np->getParseExpressionsFlag()) $$ = createFunction(toString(@1), $3); }
1232
        | STRINGTYPE '(' expr ')'
1233
                { if (np->getParseExpressionsFlag()) $$ = createFunction(toString(@1), $3); }
1234

    
1235
        | NAME '(' ')'
1236
                { if (np->getParseExpressionsFlag()) $$ = createFunction(toString(@1)); }
1237
        | NAME '(' expr ')'
1238
                { if (np->getParseExpressionsFlag()) $$ = createFunction(toString(@1), $3); }
1239
        | NAME '(' expr ',' expr ')'
1240
                { if (np->getParseExpressionsFlag()) $$ = createFunction(toString(@1), $3, $5); }
1241
        | NAME '(' expr ',' expr ',' expr ')'
1242
                { if (np->getParseExpressionsFlag()) $$ = createFunction(toString(@1), $3, $5, $7); }
1243
        | NAME '(' expr ',' expr ',' expr ',' expr ')'
1244
                { if (np->getParseExpressionsFlag()) $$ = createFunction(toString(@1), $3, $5, $7, $9); }
1245
         ;
1246

    
1247
simple_expr
1248
        : parameter_expr
1249
        | special_expr
1250
        | literal
1251
        ;
1252

    
1253
parameter_expr
1254
        : NAME
1255
                {
1256
                  // if there's no modifier, might be a loop variable too
1257
                  if (np->getParseExpressionsFlag()) $$ = createIdent(@1);
1258
                }
1259
        | REF NAME
1260
                {
1261
                  if (np->getParseExpressionsFlag()) $$ = createIdent(@2);
1262
                  np->getErrors()->addError(ps.substparams,"`ref' modifier no longer supported (add `volatile' modifier to destination parameter instead)");
1263
                }
1264
        | REF ANCESTOR NAME
1265
                {
1266
                  if (np->getParseExpressionsFlag()) $$ = createIdent(@3);
1267
                  np->getErrors()->addError(ps.substparams,"`ancestor' and `ref' modifiers no longer supported");
1268
                }
1269
        | ANCESTOR REF NAME
1270
                {
1271
                  if (np->getParseExpressionsFlag()) $$ = createIdent(@3);
1272
                  np->getErrors()->addError(ps.substparams,"`ancestor' and `ref' modifiers no longer supported");
1273
                }
1274
        | ANCESTOR NAME
1275
                {
1276
                  if (np->getParseExpressionsFlag()) $$ = createIdent(@2);
1277
                  np->getErrors()->addError(ps.substparams,"`ancestor' modifier no longer supported");
1278
                }
1279
        ;
1280

    
1281
special_expr
1282
        : SUBMODINDEX
1283
                { if (np->getParseExpressionsFlag()) $$ = createFunction("index"); }
1284
        | SUBMODINDEX '(' ')'
1285
                { if (np->getParseExpressionsFlag()) $$ = createFunction("index"); }
1286
        | SIZEOF '(' NAME ')'
1287
                { if (np->getParseExpressionsFlag()) $$ = createFunction("sizeof", createIdent(@3)); }
1288
        ;
1289

    
1290
literal
1291
        : stringliteral
1292
        | boolliteral
1293
        | numliteral
1294
        ;
1295

    
1296
stringliteral
1297
        : STRINGCONSTANT
1298
                { if (np->getParseExpressionsFlag()) $$ = createStringLiteral(@1); }
1299
        ;
1300

    
1301
boolliteral
1302
        : TRUE_
1303
                { if (np->getParseExpressionsFlag()) $$ = createLiteral(NED_CONST_BOOL, @1, @1); }
1304
        | FALSE_
1305
                { if (np->getParseExpressionsFlag()) $$ = createLiteral(NED_CONST_BOOL, @1, @1); }
1306
        ;
1307

    
1308
numliteral
1309
        : INTCONSTANT
1310
                { if (np->getParseExpressionsFlag()) $$ = createLiteral(NED_CONST_INT, @1, @1); }
1311
        | REALCONSTANT
1312
                { if (np->getParseExpressionsFlag()) $$ = createLiteral(NED_CONST_DOUBLE, @1, @1); }
1313
        | quantity
1314
                { if (np->getParseExpressionsFlag()) $$ = createQuantityLiteral(@1); }
1315
        ;
1316

    
1317
quantity
1318
        : quantity INTCONSTANT NAME
1319
        | quantity REALCONSTANT NAME
1320
        | INTCONSTANT NAME
1321
        | REALCONSTANT NAME
1322
        ;
1323

    
1324
opt_semicolon : ';' | ;
1325

    
1326
comma_or_semicolon : ',' | ';' ;
1327

    
1328
%%
1329

    
1330
//----------------------------------------------------------------------
1331
// general bison/flex stuff:
1332
//
1333

    
1334
NEDElement *doParseNED1(NEDParser *p, const char *nedtext)
1335
{
1336
#if YYDEBUG != 0      /* #if added --VA */
1337
    yydebug = YYDEBUGGING_ON;
1338
#endif
1339

    
1340
    NONREENTRANT_NED_PARSER(p);
1341

    
1342
    // reset the lexer
1343
    pos.co = 0;
1344
    pos.li = 1;
1345
    prevpos = pos;
1346

    
1347
    yyin = NULL;
1348
    yyout = stderr; // not used anyway
1349

    
1350
    // alloc buffer
1351
    struct yy_buffer_state *handle = yy_scan_string(nedtext);
1352
    if (!handle)
1353
        {np->getErrors()->addError("", "unable to allocate work memory"); return false;}
1354

    
1355
    // create parser state and NEDFileElement
1356
    resetParserState();
1357
    ps.nedfile = new NedFileElement();
1358

    
1359
    // store file name with slashes always, even on Windows -- neddoc relies on that
1360
    ps.nedfile->setFilename(slashifyFilename(np->getFileName()).c_str());
1361
    ps.nedfile->setVersion("1");
1362

    
1363
    // store file comment
1364
    storeFileComment(ps.nedfile);
1365

    
1366
    if (np->getStoreSourceFlag())
1367
        storeSourceCode(ps.nedfile, np->getSource()->getFullTextPos());
1368

    
1369
    // parse
1370
    int ret;
1371
    try
1372
    {
1373
        ret = yyparse();
1374
    }
1375
    catch (NEDException& e)
1376
    {
1377
        yyerror((std::string("error during parsing: ")+e.what()).c_str());
1378
        yy_delete_buffer(handle);
1379
        return 0;
1380
    }
1381

    
1382
    yy_delete_buffer(handle);
1383

    
1384
    //FIXME TODO: fill in @documentation properties from comments
1385
    return ps.nedfile;
1386
}
1387

    
1388
void yyerror(const char *s)
1389
{
1390
    // chop newline
1391
    char buf[250];
1392
    strcpy(buf, s);
1393
    if (buf[strlen(buf)-1] == '\n')
1394
        buf[strlen(buf)-1] = '\0';
1395

    
1396
    np->error(buf, pos.li);
1397
}
1398

    
1399
// this function depends too much on ps, cannot be put into nedyylib.cc
1400
ChannelSpecElement *createChannelSpec(NEDElement *conn)
1401
{
1402
   ChannelSpecElement *chanspec = (ChannelSpecElement *)createElementWithTag(NED_CHANNEL_SPEC, ps.conn);
1403
   ps.params = (ParametersElement *)createElementWithTag(NED_PARAMETERS, chanspec);
1404
   ps.params->setIsImplicit(true);
1405
   return chanspec;
1406
}
1407

    
1408
void createSubstparamsElementIfNotExists()
1409
{
1410
   // check if already exists (multiple blocks must be merged)
1411
   NEDElement *parent = ps.inNetwork ? (NEDElement *)ps.module : (NEDElement *)ps.submod;
1412
   ps.substparams = (ParametersElement *)parent->getFirstChildWithTag(NED_PARAMETERS);
1413
   if (!ps.substparams)
1414
       ps.substparams = (ParametersElement *)createElementWithTag(NED_PARAMETERS, parent);
1415
}
1416

    
1417
void createGatesizesElementIfNotExists()
1418
{
1419
   // check if already exists (multiple blocks must be merged)
1420
   ps.gatesizes = (GatesElement *)ps.submod->getFirstChildWithTag(NED_GATES);
1421
   if (!ps.gatesizes)
1422
       ps.gatesizes = (GatesElement *)createElementWithTag(NED_GATES, ps.submod);
1423
}
1424

    
1425
void removeRedundantChanSpecParams()
1426
{
1427
    if (ps.chanspec && !ps.params->getFirstChild())
1428
        delete ps.chanspec->removeChild(ps.params);
1429
}
1430