Project

General

Profile

Statistics
| Branch: | Revision:

root / src / nedxml / ned2.y-RECOVERY @ 79bb12dc

History | View | Annotate | Download (51.7 KB)

1 01873262 Georg Kunz
/*===============================================================
2
 * File: ned2.y
3
 *
4
 *  Grammar for OMNeT++ NED-2.
5
 *
6
 *  Author: Andras Varga
7
 *
8
 *=============================================================*/
9
10
/*--------------------------------------------------------------*
11
  Copyright (C) 1992,2005 Andras Varga
12
13
  This file is distributed WITHOUT ANY WARRANTY. See the file
14
  `license' for details on this and other legal matters.
15
*--------------------------------------------------------------*/
16
17
/* Reserved words */
18
%token IMPORT PACKAGE PROPERTY
19
%token MODULE SIMPLE NETWORK CHANNEL INTERFACE CHANNELINTERFACE
20
%token EXTENDS LIKE WITHCPPCLASS
21
%token TYPES PARAMETERS GATES SUBMODULES CONNECTIONS ALLOWUNCONNECTED
22
%token DOUBLETYPE INTTYPE STRINGTYPE BOOLTYPE XMLTYPE FUNCTION TYPENAME
23
%token INPUT_ OUTPUT_ INOUT_
24
%token IF WHERE
25
%token RIGHTARROW LEFTARROW DBLARROW TO
26
%token TRUE_ FALSE_ THIS_ DEFAULT CONST_ SIZEOF INDEX_ XMLDOC
27
28
/* Other tokens: identifiers, numeric literals, operators etc */
29
%token NAME INTCONSTANT REALCONSTANT STRINGCONSTANT CHARCONSTANT
30
%token PLUSPLUS DOUBLEASTERISK
31
%token EQ NE GE LE
32
%token AND OR XOR NOT
33
%token BIN_AND BIN_OR BIN_XOR BIN_COMPL
34
%token SHIFT_LEFT SHIFT_RIGHT
35
36
%token INVALID_CHAR   /* just to generate parse error --VA */
37
38
/* Operator precedences (low to high) and associativity */
39
%left '?' ':'
40
%left AND OR XOR
41
%left EQ NE '>' GE '<' LE
42
%left BIN_AND BIN_OR BIN_XOR
43
%left SHIFT_LEFT SHIFT_RIGHT
44
%left '+' '-'
45
%left '*' '/' '%'
46
%right '^'
47
%left UMIN NOT BIN_COMPL
48
49
%start nedfile
50
51
/* requires at least bison 1.50 (tested with bison 2.1) */
52
%glr-parser
53
54
%{
55
56
#include <stdio.h>
57
#include <stdlib.h>
58
#include <stack>
59
#include "nedyydefs.h"
60
#include "nederror.h"
61
62
#define YYDEBUG 1           /* allow debugging */
63
#define YYDEBUGGING_ON 0    /* turn on/off debugging */
64
65
#if YYDEBUG != 0
66
#define YYERROR_VERBOSE     /* more detailed error messages */
67
#include <string.h>         /* YYVERBOSE needs it */
68
#endif
69
70
#define yylloc ned2yylloc
71
#define yyin ned2yyin
72
#define yyout ned2yyout
73
#define yyrestart ned2yyrestart
74
#define yy_scan_string ned2yy_scan_string
75
#define yy_delete_buffer ned2yy_delete_buffer
76
extern FILE *yyin;
77
extern FILE *yyout;
78
struct yy_buffer_state;
79
struct yy_buffer_state *yy_scan_string(const char *str);
80
void yy_delete_buffer(struct yy_buffer_state *);
81
void yyrestart(FILE *);
82
int yylex();
83
void yyerror (const char *s);
84
85
#include "nedparser.h"
86
#include "nedfilebuffer.h"
87
#include "nedelements.h"
88
#include "nedutil.h"
89
#include "nedyylib.h"
90
91
static struct NED2ParserState
92
{
93
    bool inTypes;
94
    bool inGroup;
95
    std::stack<NEDElement *> propertyscope; // top(): where to insert properties as we parse them
96
    std::stack<NEDElement *> blockscope;    // top(): where to insert parameters, gates, etc
97
    std::stack<NEDElement *> typescope;     // top(): as blockscope, but ignore submodules and connection channels
98
99
    /* tmp flags, used with param, gate and conn */
100
    int paramType;
101
    int gateType;
102
    bool isFunction;
103
    bool isDefault;
104
    int subgate;
105
106
    /* tmp flags, used with msg fields */
107
    bool isAbstract;
108
    bool isReadonly;
109
110
    /* NED-II: modules, channels */
111
    NedFileNode *nedfile;
112
    WhitespaceNode *whitespace;
113
    ImportNode *import;
114
    PropertyDeclNode *propertydecl;
115
    ExtendsNode *extends;
116
    InterfaceNameNode *interfacename;
117
    NEDElement *component;  // compound/simple module, module interface, channel or channel interface
118
    ParametersNode *parameters;
119
    ParamGroupNode *paramgroup;
120
    ParamNode *param;
121
    PatternNode *pattern;
122
    PropertyNode *property;
123
    PropertyKeyNode *propkey;
124
    TypesNode *types;
125
    GatesNode *gates;
126
    GateGroupNode *gategroup;
127
    GateNode *gate;
128
    SubmodulesNode *submods;
129
    SubmoduleNode *submod;
130
    ConnectionsNode *conns;
131
    ConnectionGroupNode *conngroup;
132
    ConnectionNode *conn;
133
    ChannelSpecNode *chanspec;
134
    WhereNode *where;
135
    LoopNode *loop;
136
    ConditionNode *condition;
137
} ps;
138
139
static void resetParserState()
140
{
141
    static NED2ParserState cleanps;
142
    ps = cleanps;
143
}
144
145
static NED2ParserState globalps;  // for error recovery
146
147
static void restoreGlobalParserState()  // for error recovery
148
{
149
    ps = globalps;
150
}
151
152
static void assertNonEmpty(std::stack<NEDElement *>& somescope) {
153
    // for error recovery: STL stack::top() crashes if stack is empty
154
    if (somescope.empty())
155
    {
156
        INTERNAL_ERROR0(NULL, "error during parsing: scope stack empty");
157
        somescope.push(NULL);
158
    }
159
}
160
161
%}
162
163
%%
164
165
/*
166
 * Top-level components
167
 */
168
nedfile
169
        : packagedeclaration somedefinitions
170
        | somedefinitions
171
        ;
172
173
somedefinitions
174
        : somedefinitions definition
175
        |
176
        ;
177
178
definition
179
        : import
180
        | propertydecl
181
        | fileproperty
182
        | channeldefinition
183
        | channelinterfacedefinition
184
        | simplemoduledefinition
185
        | compoundmoduledefinition
186
        | networkdefinition
187
        | moduleinterfacedefinition
188
        ;
189
190
packagedeclaration         /* TBD package is currently not supported */
191
        : PACKAGE packagename ';'
192
        | PACKAGE error ';' /* error recovery rule */
193
        ;
194
195
packagename                /* TBD package is currently not supported */
196
        : packagename '.' NAME
197
        | NAME
198
        ;
199
200
201
/*
202
 * Import
203
 */
204
import
205
        : IMPORT STRINGCONSTANT ';'
206
                {
207
                  ps.import = (ImportNode *)createNodeWithTag(NED_IMPORT, ps.nedfile);
208
                  ps.import->setFilename(toString(trimQuotes(@2)));
209
                  //setComments(ps.import,@1);
210
                }
211
        | IMPORT error ';' /* error recovery rule */
212
        ;
213
214
/*
215
 * Property declaration
216
 */
217
propertydecl
218
        : propertydecl_header opt_inline_properties ';'
219
        | propertydecl_header '(' opt_propertydecl_keys ')' opt_inline_properties ';'
220
        | propertydecl_header error ';'
221
        | PROPERTY error ';' /* error recovery rule */
222
        ;
223
224
propertydecl_header
225
        : PROPERTY '@' NAME
226
                {
227
                  ps.propertydecl = (PropertyDeclNode *)createNodeWithTag(NED_PROPERTY_DECL, ps.nedfile);
228
                  ps.propertydecl->setName(toString(@3));
229
                  //setComments(ps.propertydecl,@1);
230
                }
231
        ;
232
233
opt_propertydecl_keys
234
        : propertydecl_keys
235
        |
236
        ;
237
238
propertydecl_keys
239
        : propertydecl_keys ',' propertydecl_key
240
        | propertydecl_key
241
        ;
242
243
propertydecl_key
244
        : NAME
245
                {
246
                  ps.propkey = (PropertyKeyNode *)createNodeWithTag(NED_PROPERTY_KEY, ps.propertydecl);
247
                  ps.propkey->setKey(toString(@1));
248
                }
249
        ;
250
251
/*
252
 * File Property
253
 */
254
fileproperty
255
        : property_namevalue ';'
256
        ;
257
258
/*
259
 * Channel
260
 */
261
channeldefinition
262
        : channelheader '{'
263
                {
264
                  ps.typescope.push(ps.component);
265
                  ps.blockscope.push(ps.component);
266
                  ps.parameters = (ParametersNode *)createNodeWithTag(NED_PARAMETERS, ps.component);
267
                  ps.parameters->setIsImplicit(true);
268
                  ps.propertyscope.push(ps.parameters);
269
                }
270
            opt_paramblock
271
          '}' opt_semicolon
272
                {
273
                  ps.propertyscope.pop();
274
                  ps.blockscope.pop();
275
                  ps.typescope.pop();
276
                  setTrailingComment(ps.component,@4);
277
                  if (np->getStoreSourceFlag())
278
                      storeComponentSourceCode(ps.component, @$);
279
                }
280
        | channelheader error '}' /* error recovery rule */
281
                {restoreGlobalParserState();}
282
        | CHANNEL error '}' /* error recovery rule */
283
                {restoreGlobalParserState();}
284
        ;
285
286
channelheader
287
        : CHANNEL NAME
288
                {
289
                  ps.component = (ChannelNode *)createNodeWithTag(NED_CHANNEL, ps.inTypes ? (NEDElement *)ps.types : (NEDElement *)ps.nedfile);
290
                  ((ChannelNode *)ps.component)->setName(toString(@2));
291
                  //setComments(ps.component,@1,@2);
292
                }
293
           opt_inheritance
294
        | CHANNEL WITHCPPCLASS NAME
295
                {
296
                  ps.component = (ChannelNode *)createNodeWithTag(NED_CHANNEL, ps.inTypes ? (NEDElement *)ps.types : (NEDElement *)ps.nedfile);
297
                  ((ChannelNode *)ps.component)->setName(toString(@3));
298
                  ((ChannelNode *)ps.component)->setIsWithcppclass(true);
299
                  //setComments(ps.component,@1,@2);
300
                }
301
           opt_inheritance
302
        ;
303
304
opt_inheritance
305
        :
306
        | EXTENDS extendsname
307
        | LIKE likenames
308
        | EXTENDS extendsname LIKE likenames
309
        ;
310
311
extendsname
312
        : NAME
313
                {
314
                  ps.extends = (ExtendsNode *)createNodeWithTag(NED_EXTENDS, ps.component);
315
                  ps.extends->setName(toString(@1));
316
                }
317
        ;
318
319
likenames
320
        : likenames ',' likename
321
        | likename
322
        ;
323
324
likename
325
        : NAME
326
                {
327
                  ps.interfacename = (InterfaceNameNode *)createNodeWithTag(NED_INTERFACE_NAME, ps.component);
328
                  ps.interfacename->setName(toString(@1));
329
                }
330
        ;
331
332
/*
333
 * Channel Interface
334
 */
335
channelinterfacedefinition
336
        : channelinterfaceheader '{'
337
                {
338
                  ps.typescope.push(ps.component);
339
                  ps.blockscope.push(ps.component);
340
                  ps.parameters = (ParametersNode *)createNodeWithTag(NED_PARAMETERS, ps.component);
341
                  ps.parameters->setIsImplicit(true);
342
                  ps.propertyscope.push(ps.parameters);
343
                }
344
            opt_paramblock
345
          '}' opt_semicolon
346
                {
347
                  ps.propertyscope.pop();
348
                  ps.blockscope.pop();
349
                  ps.typescope.pop();
350
                  setTrailingComment(ps.component,@4);
351
                  if (np->getStoreSourceFlag())
352
                      storeComponentSourceCode(ps.component, @$);
353
                }
354
        | channelinterfaceheader error '}' /* error recovery rule */
355
                {restoreGlobalParserState();}
356
        | CHANNELINTERFACE error '}' /* error recovery rule */
357
                {restoreGlobalParserState();}
358
        ;
359
360
channelinterfaceheader
361
        : CHANNELINTERFACE NAME
362
                {
363
                  ps.component = (ChannelInterfaceNode *)createNodeWithTag(NED_CHANNEL_INTERFACE, ps.inTypes ? (NEDElement *)ps.types : (NEDElement *)ps.nedfile);
364
                  ((ChannelInterfaceNode *)ps.component)->setName(toString(@2));
365
                  //setComments(ps.component,@1,@2);
366
                }
367
           opt_interfaceinheritance
368
        ;
369
370
opt_interfaceinheritance
371
        : EXTENDS extendsnames
372
        |
373
        ;
374
375
extendsnames
376
        : extendsnames ',' extendsname
377
        | extendsname
378
        ;
379
380
/*
381
 * Simple module
382
 */
383
simplemoduledefinition
384
        : simplemoduleheader '{'
385
                {
386
                  ps.typescope.push(ps.component);
387
                  ps.blockscope.push(ps.component);
388
                  ps.parameters = (ParametersNode *)createNodeWithTag(NED_PARAMETERS, ps.component);
389
                  ps.parameters->setIsImplicit(true);
390
                  ps.propertyscope.push(ps.parameters);
391
                }
392
            opt_paramblock
393
            opt_gateblock
394
          '}' opt_semicolon
395
                {
396
                  ps.propertyscope.pop();
397
                  ps.blockscope.pop();
398
                  ps.typescope.pop();
399
                  setTrailingComment(ps.component,@6);
400
                  if (np->getStoreSourceFlag())
401
                      storeComponentSourceCode(ps.component, @$);
402
                }
403
        | simplemoduleheader error '}' /* error recovery rule */
404
                {restoreGlobalParserState();}
405
        | SIMPLE error '}' /* error recovery rule */
406
                {restoreGlobalParserState();}
407
        ;
408
409
simplemoduleheader
410
        : SIMPLE NAME
411
                {
412
                  ps.component = (SimpleModuleNode *)createNodeWithTag(NED_SIMPLE_MODULE, ps.inTypes ? (NEDElement *)ps.types : (NEDElement *)ps.nedfile );
413
                  ((SimpleModuleNode *)ps.component)->setName(toString(@2));
414
                  //setComments(ps.component,@1,@2);
415
                }
416
          opt_inheritance
417
        ;
418
419
/*
420
 * Module
421
 */
422
compoundmoduledefinition
423
        : compoundmoduleheader '{'
424
                {
425
                  ps.typescope.push(ps.component);
426
                  ps.blockscope.push(ps.component);
427
                  ps.parameters = (ParametersNode *)createNodeWithTag(NED_PARAMETERS, ps.component);
428
                  ps.parameters->setIsImplicit(true);
429
                  ps.propertyscope.push(ps.parameters);
430
                }
431
            opt_paramblock
432
            opt_gateblock
433
            opt_typeblock
434
            opt_submodblock
435
            opt_connblock
436
          '}' opt_semicolon
437
                {
438
                  ps.propertyscope.pop();
439
                  ps.blockscope.pop();
440
                  ps.typescope.pop();
441
                  setTrailingComment(ps.component,@9);
442
                  if (np->getStoreSourceFlag())
443
                      storeComponentSourceCode(ps.component, @$);
444
                }
445
        | compoundmoduleheader error '}' /* error recovery rule */
446
                {restoreGlobalParserState();}
447
        | MODULE error '}' /* error recovery rule */
448
                {restoreGlobalParserState();}
449
        ;
450
451
compoundmoduleheader
452
        : MODULE NAME
453
                {
454
                  ps.component = (CompoundModuleNode *)createNodeWithTag(NED_COMPOUND_MODULE, ps.inTypes ? (NEDElement *)ps.types : (NEDElement *)ps.nedfile );
455
                  ((CompoundModuleNode *)ps.component)->setName(toString(@2));
456
                  //setComments(ps.component,@1,@2);
457
                }
458
          opt_inheritance
459
        ;
460
461
/*
462
 * Network
463
 */
464
networkdefinition
465
        : networkheader '{'
466
                {
467
                  ps.typescope.push(ps.component);
468
                  ps.blockscope.push(ps.component);
469
                  ps.parameters = (ParametersNode *)createNodeWithTag(NED_PARAMETERS, ps.component);
470
                  ps.parameters->setIsImplicit(true);
471
                  ps.propertyscope.push(ps.parameters);
472
                }
473
            opt_paramblock
474
            opt_gateblock
475
            opt_typeblock
476
            opt_submodblock
477
            opt_connblock
478
          '}' opt_semicolon
479
                {
480
                  ps.propertyscope.pop();
481
                  ps.blockscope.pop();
482
                  ps.typescope.pop();
483
                  setTrailingComment(ps.component,@5);
484
                  if (np->getStoreSourceFlag())
485
                      storeComponentSourceCode(ps.component, @$);
486
                }
487
        | networkheader error '}' /* error recovery rule */
488
                {restoreGlobalParserState();}
489
        | NETWORK error '}' /* error recovery rule */
490
                {restoreGlobalParserState();}
491
        ;
492
493
networkheader
494
        : NETWORK NAME
495
                {
496
                  ps.component = (CompoundModuleNode *)createNodeWithTag(NED_COMPOUND_MODULE, ps.inTypes ? (NEDElement *)ps.types : (NEDElement *)ps.nedfile );
497
                  ((CompoundModuleNode *)ps.component)->setName(toString(@2));
498
                  ((CompoundModuleNode *)ps.component)->setIsNetwork(true);
499
                  //setComments(ps.component,@1,@2);
500
                }
501
          opt_inheritance
502
        ;
503
504
/*
505
 * Module Interface
506
 */
507
moduleinterfacedefinition
508
        : moduleinterfaceheader '{'
509
                {
510
                  ps.typescope.push(ps.component);
511
                  ps.blockscope.push(ps.component);
512
                  ps.parameters = (ParametersNode *)createNodeWithTag(NED_PARAMETERS, ps.component);
513
                  ps.parameters->setIsImplicit(true);
514
                  ps.propertyscope.push(ps.parameters);
515
                }
516
            opt_paramblock
517
            opt_gateblock
518
          '}' opt_semicolon
519
                {
520
                  ps.propertyscope.pop();
521
                  ps.blockscope.pop();
522
                  ps.typescope.pop();
523
                  setTrailingComment(ps.component,@6);
524
                  if (np->getStoreSourceFlag())
525
                      storeComponentSourceCode(ps.component, @$);
526
                }
527
        | moduleinterfaceheader error '}' /* error recovery rule */
528
                {restoreGlobalParserState();}
529
        | INTERFACE error '}' /* error recovery rule */
530
                {restoreGlobalParserState();}
531
        ;
532
533
moduleinterfaceheader
534
        : INTERFACE NAME
535
                {
536
                  ps.component = (ModuleInterfaceNode *)createNodeWithTag(NED_MODULE_INTERFACE, ps.inTypes ? (NEDElement *)ps.types : (NEDElement *)ps.nedfile);
537
                  ((ModuleInterfaceNode *)ps.component)->setName(toString(@2));
538
                  //setComments(ps.component,@1,@2);
539
                }
540
           opt_interfaceinheritance
541
        ;
542
543
/*
544
 * Parameters
545
 */
546
opt_paramblock
547
        : opt_params   /* "parameters" keyword is optional */
548
        | PARAMETERS ':'
549
                {
550
                  ps.parameters->setIsImplicit(false);
551
                }
552
          opt_params
553
        ;
554
555
opt_params
556
        : params
557
        |
558
        ;
559
560
params
561
        : params paramsitem
562
                {
563
                  //setComments(ps.param,@2);
564
                }
565
        | paramsitem
566
                {
567
                  //setComments(ps.param,@1);
568
                }
569
        ;
570
571
paramsitem
572
        : param
573
        | paramgroup
574
        | property
575
        ;
576
577
paramgroup
578
        : opt_condition '{'
579
                {
580
                    ps.paramgroup = (ParamGroupNode *)createNodeWithTag(NED_PARAM_GROUP, ps.parameters);
581
                    if (ps.inGroup)
582
                       np->getErrors()->add(ps.paramgroup,"nested parameter groups are not allowed");
583
                    ps.inGroup = true;
584
                }
585
          params '}'
586
                {
587
                    ps.inGroup = false;
588
                    if ($1)
589
                        ps.paramgroup->appendChild($1); // append optional condition
590
                }
591
        ;
592
593
param
594
        : param_typenamevalue
595
                {
596
                  ps.propertyscope.push(ps.param);
597
                }
598
          opt_inline_properties opt_condition ';'
599
                {
600
                  ps.propertyscope.pop();
601
                  if (ps.inGroup && $4)
602
                       np->getErrors()->add(ps.param,"conditional parameters inside parameter/property groups are not allowed");
603
                  if ($4)
604
                      ps.param->appendChild($4); // append optional condition
605
                      // FIXME typename and "if" cannot occur together!!!
606
                }
607
        | param_typenamevalue error ';' /* error recovery rule */
608
        | paramtype error ';' /* error recovery rule */
609
        | TYPENAME error ';' /* error recovery rule */
610
        | '/' error ';' /* error recovery rule */
611
        | error ';' /* error recovery rule */
612
        ;
613
614
/*
615
 * Parameter
616
 */
617
param_typenamevalue
618
        : paramtype opt_function NAME
619
                {
620
                  ps.param = addParameter(ps.inGroup ? (NEDElement *)ps.paramgroup : (NEDElement *)ps.parameters, @3);
621
                  ps.param->setType(ps.paramType);
622
                  ps.param->setIsFunction(ps.isFunction);
623
                }
624
        | paramtype opt_function NAME '=' paramvalue
625
                {
626
                  ps.param = addParameter(ps.inGroup ? (NEDElement *)ps.paramgroup : (NEDElement *)ps.parameters, @3);
627
                  ps.param->setType(ps.paramType);
628
                  ps.param->setIsFunction(ps.isFunction);
629
                  addExpression(ps.param, "value",@5,$5);
630
                  ps.param->setIsDefault(ps.isDefault);
631
                }
632
        | NAME '=' paramvalue
633
                {
634
                  ps.param = addParameter(ps.inGroup ? (NEDElement *)ps.paramgroup : (NEDElement *)ps.parameters, @1);
635
                  addExpression(ps.param, "value",@3,$3);
636
                  ps.param->setIsDefault(ps.isDefault);
637
                }
638
        | NAME
639
                {
640
                  ps.param = addParameter(ps.inGroup ? (NEDElement *)ps.paramgroup : (NEDElement *)ps.parameters, @1);
641
                }
642
        | TYPENAME '=' paramvalue  /* this is to assign module type with the "<> like Foo" syntax */
643
                {
644
                  ps.param = addParameter(ps.inGroup ? (NEDElement *)ps.paramgroup : (NEDElement *)ps.parameters, @1);
645
                  addExpression(ps.param, "value",@3,$3);
646
                  ps.param->setIsDefault(ps.isDefault);
647
                }
648
        | '/' pattern '/' '=' paramvalue
649
                {
650
                  ps.pattern = (PatternNode *)createNodeWithTag(NED_PATTERN, ps.inGroup ? (NEDElement *)ps.paramgroup : (NEDElement *)ps.parameters);
651
                  ps.pattern->setPattern(toString(@2));
652
                  addExpression(ps.pattern, "value",@5,$5);
653
                  ps.pattern->setIsDefault(ps.isDefault);
654
                }
655
656
paramtype
657
        : DOUBLETYPE
658
                { ps.paramType = NED_PARTYPE_DOUBLE; }
659
        | INTTYPE
660
                { ps.paramType = NED_PARTYPE_INT; }
661
        | STRINGTYPE
662
                { ps.paramType = NED_PARTYPE_STRING; }
663
        | BOOLTYPE
664
                { ps.paramType = NED_PARTYPE_BOOL; }
665
        | XMLTYPE
666
                { ps.paramType = NED_PARTYPE_XML; }
667
        ;
668
669
opt_function
670
        : FUNCTION
671
                { ps.isFunction = true; }
672
        |
673
                { ps.isFunction = false; }
674
        ;
675
676
paramvalue
677
        : expression
678
                { $$ = $1; ps.isDefault = false; }
679
        | DEFAULT '(' expression ')'
680
                { $$ = $3; ps.isDefault = true; }
681
        ;
682
683
opt_inline_properties
684
        : inline_properties
685
        |
686
        ;
687
688
inline_properties
689
        : inline_properties property_namevalue
690
        | property_namevalue
691
        ;
692
693
pattern /* this attempts to capture inifile-like patterns */
694
        : pattern pattern_elem
695
        | pattern_elem
696
        ;
697
698
pattern_elem
699
        : '.'
700
        | '*'
701
        | '?'
702
        | DOUBLEASTERISK
703
        | NAME
704
        | INTCONSTANT
705
        | TO
706
        | '[' pattern ']'
707
        | '{' pattern '}'
708
        /* allow reserved words in patterns as well */
709
        | IMPORT | PACKAGE | PROPERTY
710
        | MODULE | SIMPLE | NETWORK | CHANNEL | INTERFACE | CHANNELINTERFACE
711
        | EXTENDS | LIKE | WITHCPPCLASS
712
        | DOUBLETYPE | INTTYPE | STRINGTYPE | BOOLTYPE | XMLTYPE | FUNCTION | TYPENAME
713
        | INPUT_ | OUTPUT_ | INOUT_ | IF | WHERE
714
        | TYPES | PARAMETERS | GATES | SUBMODULES | CONNECTIONS | ALLOWUNCONNECTED
715
        | TRUE_ | FALSE_ | THIS_ | DEFAULT | CONST_ | SIZEOF | INDEX_ | XMLDOC
716
        ;
717
718
/*
719
 * Property
720
 */
721
property
722
        : property_namevalue opt_condition ';'
723
                {
724
                  if (ps.inGroup && $2)
725
                       np->getErrors()->add(ps.param,"conditional properties inside parameter/property groups are not allowed");
726
                  if ($2)
727
                      ps.property->appendChild($2); // append optional condition
728
                }
729
        | property_namevalue error ';' /* error recovery rule */
730
        | property_name error ';' /* error recovery rule; causes shift-reduce, but still necessary for missing-")" errors */
731
        | '@' error ';' /* error recovery rule */
732
        ;
733
734
property_namevalue
735
        : property_name
736
        | property_name '(' opt_property_keys ')'
737
        ;
738
739
property_name
740
        : '@' NAME
741
                {
742
                  assertNonEmpty(ps.propertyscope);
743
                  ps.property = addProperty(ps.propertyscope.top(), toString(@2));
744
                }
745
        ;
746
747
opt_property_keys
748
        : property_keys
749
        |
750
        ;
751
752
property_keys
753
        : property_keys ',' property_key
754
        | property_key
755
        ;
756
757
property_key
758
        : NAME '=' property_value
759
                {
760
                  ps.propkey = (PropertyKeyNode *)createNodeWithTag(NED_PROPERTY_KEY, ps.property);
761
                  ps.propkey->setKey(toString(@1));
762
                  ps.propkey->appendChild($3);
763
                }
764
        | property_value
765
                {
766
                  ps.propkey = (PropertyKeyNode *)createNodeWithTag(NED_PROPERTY_KEY, ps.property);
767
                  ps.propkey->appendChild($1);
768
                }
769
        ;
770
771
property_value
772
        : NAME
773
                { $$ = createLiteral(NED_CONST_STRING, @1, @1); }
774
        | STRINGCONSTANT
775
                { $$ = createLiteral(NED_CONST_STRING, trimQuotes(@1), @1); }
776
        | TRUE_
777
                { $$ = createLiteral(NED_CONST_BOOL, @1, @1); }
778
        | FALSE_
779
                { $$ = createLiteral(NED_CONST_BOOL, @1, @1); }
780
        | INTCONSTANT
781
                { $$ = createLiteral(NED_CONST_INT, @1, @1); }
782
        | REALCONSTANT
783
                { $$ = createLiteral(NED_CONST_DOUBLE, @1, @1); }
784
        | quantity
785
                { $$ = createQuantity(toString(@1)); }
786
        ;
787
788
/*
789
 * Gates
790
 */
791
opt_gateblock
792
        : gateblock
793
        |
794
        ;
795
796
gateblock
797
        : GATES ':'
798
                {
799
                  assertNonEmpty(ps.blockscope);
800
                  ps.gates = (GatesNode *)createNodeWithTag(NED_GATES, ps.blockscope.top());
801
                  //setComments(ps.gates,@1,@2);
802
                }
803
          opt_gates
804
                {
805
                }
806
        ;
807
808
opt_gates
809
        : gates
810
        |
811
        ;
812
813
gates
814
        : gates gatesitem
815
                {
816
                  //setComments(ps.gate,@2);
817
                }
818
        | gatesitem
819
                {
820
                  //setComments(ps.gate,@1);
821
                }
822
        ;
823
824
gatesitem
825
        : gategroup
826
        | gate
827
        ;
828
829
gategroup
830
        : opt_condition '{'
831
                {
832
                    ps.gategroup = (GateGroupNode *)createNodeWithTag(NED_GATE_GROUP, ps.gates);
833
                    if (ps.inGroup)
834
                       np->getErrors()->add(ps.gategroup,"nested gate groups are not allowed");
835
                    ps.inGroup = true;
836
                }
837
          gates '}'
838
                {
839
                    ps.inGroup = false;
840
                    if ($1)
841
                        ps.gategroup->appendChild($1); // append optional condition
842
                }
843
        ;
844
845
/*
846
 * Gate
847
 */
848
gate
849
        : gate_typenamesize
850
                {
851
                  ps.propertyscope.push(ps.gate);
852
                }
853
          opt_inline_properties opt_condition ';'
854
                {
855
                  ps.propertyscope.pop();
856
                  if (ps.inGroup && $4)
857
                       np->getErrors()->add(ps.param,"conditional gates inside gate groups are not allowed");
858
                  if ($4)
859
                      ps.gate->appendChild($4); // append optional condition
860
                      // FIXME typename and "if" cannot occur together!!!
861
                }
862
        | gate_typenamesize error ';' /* error recovery rule */
863
        | gatetype error ';' /* error recovery rule */
864
        | error ';' /* error recovery rule */
865
        ;
866
867
gate_typenamesize
868
        : gatetype NAME
869
                {
870
                  ps.gate = addGate(ps.inGroup ? (NEDElement *)ps.gategroup : (NEDElement *)ps.gates, @2);
871
                  ps.gate->setType(ps.gateType);
872
                }
873
        | gatetype NAME '[' ']'
874
                {
875
                  ps.gate = addGate(ps.inGroup ? (NEDElement *)ps.gategroup : (NEDElement *)ps.gates, @2);
876
                  ps.gate->setType(ps.gateType);
877
                  ps.gate->setIsVector(true);
878
                }
879
        | gatetype NAME vector
880
                {
881
                  ps.gate = addGate(ps.inGroup ? (NEDElement *)ps.gategroup : (NEDElement *)ps.gates, @2);
882
                  ps.gate->setType(ps.gateType);
883
                  addVector(ps.gate, "vector-size",@3,$3);
884
                }
885
        | NAME
886
                {
887
                  ps.gate = addGate(ps.inGroup ? (NEDElement *)ps.gategroup : (NEDElement *)ps.gates, @1);
888
                }
889
        | NAME '[' ']'
890
                {
891
                  ps.gate = addGate(ps.inGroup ? (NEDElement *)ps.gategroup : (NEDElement *)ps.gates, @1);
892
                  ps.gate->setIsVector(true);
893
                }
894
        | NAME vector
895
                {
896
                  ps.gate = addGate(ps.inGroup ? (NEDElement *)ps.gategroup : (NEDElement *)ps.gates, @1);
897
                  addVector(ps.gate, "vector-size",@2,$2);
898
                }
899
        ;
900
901
gatetype
902
        : INPUT_
903
                { ps.gateType = NED_GATETYPE_INPUT; }
904
        | OUTPUT_
905
                { ps.gateType = NED_GATETYPE_OUTPUT; }
906
        | INOUT_
907
                { ps.gateType = NED_GATETYPE_INOUT; }
908
        ;
909
910
/*
911
 * Local Types
912
 */
913
opt_typeblock
914
        : typeblock
915
        |
916
        ;
917
918
typeblock
919
        : TYPES ':'
920
                {
921
                  assertNonEmpty(ps.blockscope);
922
                  ps.types = (TypesNode *)createNodeWithTag(NED_TYPES, ps.blockscope.top());
923
                  //setComments(ps.types,@1,@2);
924
                  if (ps.inTypes)
925
                     np->getErrors()->add(ps.paramgroup,"more than one level of type nesting is not allowed");
926
                  ps.inTypes = true;
927
                }
928
           opt_localtypes
929
                {
930
                  ps.inTypes = false;
931
                }
932
        ;
933
934
opt_localtypes
935
        : localtypes
936
        |
937
        ;
938
939
localtypes
940
        : localtypes localtype
941
        | localtype
942
        ;
943
944
localtype
945
        : propertydecl
946
        | channeldefinition
947
        | channelinterfacedefinition
948
        | simplemoduledefinition
949
        | compoundmoduledefinition
950
        | networkdefinition
951
        | moduleinterfacedefinition
952
        ;
953
954
/*
955
 * Submodules
956
 */
957
opt_submodblock
958
        : submodblock
959
        |
960
        ;
961
962
submodblock
963
        : SUBMODULES ':'
964
                {
965
                  assertNonEmpty(ps.blockscope);
966
                  ps.submods = (SubmodulesNode *)createNodeWithTag(NED_SUBMODULES, ps.blockscope.top());
967
                  //setComments(ps.submods,@1,@2);
968
                }
969
          opt_submodules
970
                {
971
                }
972
        ;
973
974
opt_submodules
975
        : submodules
976
        |
977
        ;
978
979
submodules
980
        : submodules submodule
981
        | submodule
982
        ;
983
984
submodule
985
        : submoduleheader ';'
986
                {
987
                  //setComments(ps.submod,@1,@2);
988
                }
989
        | submoduleheader '{'
990
                {
991
                  ps.blockscope.push(ps.submod);
992
                  ps.parameters = (ParametersNode *)createNodeWithTag(NED_PARAMETERS, ps.submod);
993
                  ps.parameters->setIsImplicit(true);
994
                  ps.propertyscope.push(ps.parameters);
995
                  //setComments(ps.submod,@1,@2);
996
                }
997
          opt_paramblock
998
          opt_gateblock
999
          '}' opt_semicolon
1000
                {
1001
                  ps.blockscope.pop();
1002
                  ps.propertyscope.pop();
1003
                }
1004
        | submoduleheader error '}' /* error recovery rule */
1005
        | submoduleheader error ';' /* error recovery rule */
1006
        | submodulename error '}' /* error recovery rule */
1007
        | submodulename error ';' /* error recovery rule */
1008
        ;
1009
1010
submoduleheader
1011
        : submodulename ':' NAME
1012
                {
1013
                  ps.submod->setType(toString(@3));
1014
                }
1015
        | submodulename ':' likeparam LIKE NAME
1016
                {
1017
                  addLikeParam(ps.submod, "like-param", @3, $3);
1018
                  ps.submod->setLikeType(toString(@5));
1019
                }
1020
        | submodulename ':' likeparam LIKE '*'
1021
                {
1022
                  addLikeParam(ps.submod, "like-param", @3, $3);
1023
                  ps.submod->setLikeAny(true);
1024
                }
1025
        ;
1026
1027
submodulename
1028
        : NAME
1029
                {
1030
                  ps.submod = (SubmoduleNode *)createNodeWithTag(NED_SUBMODULE, ps.submods);
1031
                  ps.submod->setName(toString(@1));
1032
                }
1033
        |  NAME vector
1034
                {
1035
                  ps.submod = (SubmoduleNode *)createNodeWithTag(NED_SUBMODULE, ps.submods);
1036
                  ps.submod->setName(toString(@1));
1037
                  addVector(ps.submod, "vector-size",@2,$2);
1038
                }
1039
        ;
1040
1041
likeparam
1042
        : '<' '>'
1043
                { $$ = NULL; }
1044
        | '<' '@' NAME '>'
1045
                { $$ = NULL; }
1046
        | '<' thisqualifier '.' '@' NAME '>'
1047
                { $$ = NULL; }
1048
        | '<' expression '>' /* XXX this expression is the source of one shift-reduce conflict because it may contain '>' */
1049
                { $$ = $2; }
1050
        ;
1051
1052
thisqualifier
1053
        : THIS_
1054
        | NAME
1055
                { np->getErrors()->add(NULL,"invalid property qualifier `%s', only `this' is allowed here", toString(@1)); }
1056
        | NAME vector
1057
                { np->getErrors()->add(NULL,"invalid property qualifier `%s', only `this' is allowed here", toString(@1)); }
1058
        ;
1059
1060
1061
/*
1062
 * Connections
1063
 */
1064
opt_connblock
1065
        : connblock
1066
        |
1067
        ;
1068
1069
connblock
1070
        : CONNECTIONS ALLOWUNCONNECTED ':'
1071
                {
1072
                  assertNonEmpty(ps.blockscope);
1073
                  ps.conns = (ConnectionsNode *)createNodeWithTag(NED_CONNECTIONS, ps.blockscope.top());
1074
                  ps.conns->setAllowUnconnected(true);
1075
                  //setComments(ps.conns,@1,@3);
1076
                }
1077
          opt_connections
1078
                {
1079
                }
1080
        | CONNECTIONS ':'
1081
                {
1082
                  assertNonEmpty(ps.blockscope);
1083
                  ps.conns = (ConnectionsNode *)createNodeWithTag(NED_CONNECTIONS, ps.blockscope.top());
1084
                  //setComments(ps.conns,@1,@2);
1085
                }
1086
          opt_connections
1087
                {
1088
                }
1089
        ;
1090
1091
opt_connections
1092
        : connections
1093
        |
1094
        ;
1095
1096
connections
1097
        : connections connectionsitem
1098
        | connectionsitem
1099
        ;
1100
1101
connectionsitem
1102
        : connectiongroup
1103
        | connection opt_whereclause ';'
1104
                {
1105
                  ps.chanspec = (ChannelSpecNode *)ps.conn->getFirstChildWithTag(NED_CHANNEL_SPEC);
1106
                  if (ps.chanspec)
1107
                      ps.conn->appendChild(ps.conn->removeChild(ps.chanspec)); // move channelspec to conform DTD
1108
                  if (ps.inGroup && $2)
1109
                       np->getErrors()->add(ps.param,"conditional connections inside connection groups are not allowed");
1110
                  if ($2)
1111
                      ps.conn->appendChild($2);
1112
                }
1113
        | connection error ';' /* error recovery rule */
1114
        | leftgatespec error ';' /* error recovery rule */
1115
        | NAME error ';' /* error recovery rule */
1116
        ;
1117
1118
connectiongroup  /* note: semicolon at end is mandatory (cannot be opt_semicolon because it'd be ambiguous where "where" clause in "{a-->b;} where i>0 {c-->d;}" belongs) */
1119
        : whereclause '{'
1120
                {
1121
                  ps.conngroup = (ConnectionGroupNode *)createNodeWithTag(NED_CONNECTION_GROUP, ps.conns);
1122
                  if (ps.inGroup)
1123
                     np->getErrors()->add(ps.conngroup,"nested connection groups are not allowed");
1124
                  ps.inGroup = true;
1125
                }
1126
          connections '}' ';'
1127
                {
1128
                  ps.inGroup = false;
1129
                  ps.conngroup->appendChild(ps.where);  // XXX appendChild($1) crashes, $1 being NULL (???)
1130
                  ps.where->setAtFront(true);
1131
                }
1132
        | '{'
1133
                {
1134
                  ps.conngroup = (ConnectionGroupNode *)createNodeWithTag(NED_CONNECTION_GROUP, ps.conns);
1135
                  if (ps.inGroup)
1136
                     np->getErrors()->add(ps.conngroup,"nested connection groups are not allowed");
1137
                  ps.inGroup = true;
1138
                }
1139
          connections '}' opt_whereclause ';'
1140
                {
1141
                  ps.inGroup = false;
1142
                  if ($5)
1143
                      ps.conngroup->appendChild($5);
1144
                }
1145
        ;
1146
1147
opt_whereclause
1148
        : whereclause
1149
            { $$ = ps.where; }
1150
        |
1151
            { $$ = NULL; }
1152
        ;
1153
1154
whereclause
1155
        : WHERE
1156
                {
1157
                  ps.where = (WhereNode *)createNodeWithTag(NED_WHERE);
1158
                  ps.where->setAtFront(false); // by default
1159
                }
1160
          whereitems
1161
        ;
1162
1163
whereitems
1164
        : whereitems ',' whereitem
1165
        | whereitem
1166
        ;
1167
1168
whereitem
1169
        : expression   /* that is, a condition */
1170
                {
1171
                  ps.condition = (ConditionNode *)createNodeWithTag(NED_CONDITION, ps.where);
1172
                  addExpression(ps.condition, "condition",@1,$1);
1173
                }
1174
        | loop
1175
        ;
1176
1177
loop
1178
        : NAME '=' expression TO expression
1179
                {
1180
                  ps.loop = addLoop(ps.where, @1);
1181
                  addExpression(ps.loop, "from-value",@3,$3);
1182
                  addExpression(ps.loop, "to-value",@5,$5);
1183
                  //setComments(ps.loop,@1,@5);
1184
                }
1185
        ;
1186
1187
/*
1188
 * Connection
1189
 */
1190
connection
1191
        : leftgatespec RIGHTARROW rightgatespec
1192
                {
1193
                  ps.conn->setArrowDirection(NED_ARROWDIR_L2R);
1194
                  //setComments(ps.conn,@1,@3);
1195
                }
1196
        | leftgatespec RIGHTARROW channelspec RIGHTARROW rightgatespec
1197
                {
1198
                  ps.conn->setArrowDirection(NED_ARROWDIR_L2R);
1199
                  //setComments(ps.conn,@1,@5);
1200
                }
1201
        | leftgatespec LEFTARROW rightgatespec
1202
                {
1203
                  swapConnection(ps.conn);
1204
                  ps.conn->setArrowDirection(NED_ARROWDIR_R2L);
1205
                  //setComments(ps.conn,@1,@3);
1206
                }
1207
        | leftgatespec LEFTARROW channelspec LEFTARROW rightgatespec
1208
                {
1209
                  swapConnection(ps.conn);
1210
                  ps.conn->setArrowDirection(NED_ARROWDIR_R2L);
1211
                  //setComments(ps.conn,@1,@5);
1212
                }
1213
        | leftgatespec DBLARROW rightgatespec
1214
                {
1215
                  ps.conn->setArrowDirection(NED_ARROWDIR_BIDIR);
1216
                  //setComments(ps.conn,@1,@3);
1217
                }
1218
        | leftgatespec DBLARROW channelspec DBLARROW rightgatespec
1219
                {
1220
                  ps.conn->setArrowDirection(NED_ARROWDIR_BIDIR);
1221
                  //setComments(ps.conn,@1,@5);
1222
                }
1223
        ;
1224
1225
leftgatespec
1226
        : leftmod '.' leftgate opt_subgate
1227
                { ps.conn->setSrcGateSubg(ps.subgate); }
1228
        | parentleftgate opt_subgate
1229
                { ps.conn->setSrcGateSubg(ps.subgate); }
1230
        ;
1231
1232
leftmod
1233
        : NAME vector
1234
                {
1235
                  ps.conn = (ConnectionNode *)createNodeWithTag(NED_CONNECTION, ps.inGroup ? (NEDElement*)ps.conngroup : (NEDElement*)ps.conns );
1236
                  ps.conn->setSrcModule( toString(@1) );
1237
                  addVector(ps.conn, "src-module-index",@2,$2);
1238
                }
1239
        | NAME
1240
                {
1241
                  ps.conn = (ConnectionNode *)createNodeWithTag(NED_CONNECTION, ps.inGroup ? (NEDElement*)ps.conngroup : (NEDElement*)ps.conns );
1242
                  ps.conn->setSrcModule( toString(@1) );
1243
                }
1244
        ;
1245
1246
leftgate
1247
        : NAME
1248
                {
1249
                  ps.conn->setSrcGate( toString( @1) );
1250
                }
1251
        | NAME vector
1252
                {
1253
                  ps.conn->setSrcGate( toString( @1) );
1254
                  addVector(ps.conn, "src-gate-index",@2,$2);
1255
                }
1256
        | NAME PLUSPLUS
1257
                {
1258
                  ps.conn->setSrcGate( toString( @1) );
1259
                  ps.conn->setSrcGatePlusplus(true);
1260
                }
1261
        ;
1262
1263
parentleftgate
1264
        : NAME
1265
                {
1266
                  ps.conn = (ConnectionNode *)createNodeWithTag(NED_CONNECTION, ps.inGroup ? (NEDElement*)ps.conngroup : (NEDElement*)ps.conns );
1267
                  ps.conn->setSrcModule("");
1268
                  ps.conn->setSrcGate(toString(@1));
1269
                }
1270
        | NAME vector
1271
                {
1272
                  ps.conn = (ConnectionNode *)createNodeWithTag(NED_CONNECTION, ps.inGroup ? (NEDElement*)ps.conngroup : (NEDElement*)ps.conns );
1273
                  ps.conn->setSrcModule("");
1274
                  ps.conn->setSrcGate(toString(@1));
1275
                  addVector(ps.conn, "src-gate-index",@2,$2);
1276
                }
1277
        | NAME PLUSPLUS
1278
                {
1279
                  ps.conn = (ConnectionNode *)createNodeWithTag(NED_CONNECTION, ps.inGroup ? (NEDElement*)ps.conngroup : (NEDElement*)ps.conns );
1280
                  ps.conn->setSrcModule("");
1281
                  ps.conn->setSrcGate(toString(@1));
1282
                  ps.conn->setSrcGatePlusplus(true);
1283
                }
1284
        ;
1285
1286
rightgatespec
1287
        : rightmod '.' rightgate opt_subgate
1288
                { ps.conn->setDestGateSubg(ps.subgate); }
1289
        | parentrightgate opt_subgate
1290
                { ps.conn->setDestGateSubg(ps.subgate); }
1291
        ;
1292
1293
rightmod
1294
        : NAME
1295
                {
1296
                  ps.conn->setDestModule( toString(@1) );
1297
                }
1298
        | NAME vector
1299
                {
1300
                  ps.conn->setDestModule( toString(@1) );
1301
                  addVector(ps.conn, "dest-module-index",@2,$2);
1302
                }
1303
        ;
1304
1305
rightgate
1306
        : NAME
1307
                {
1308
                  ps.conn->setDestGate( toString( @1) );
1309
                }
1310
        | NAME vector
1311
                {
1312
                  ps.conn->setDestGate( toString( @1) );
1313
                  addVector(ps.conn, "dest-gate-index",@2,$2);
1314
                }
1315
        | NAME PLUSPLUS
1316
                {
1317
                  ps.conn->setDestGate( toString( @1) );
1318
                  ps.conn->setDestGatePlusplus(true);
1319
                }
1320
        ;
1321
1322
parentrightgate
1323
        : NAME
1324
                {
1325
                  ps.conn->setDestGate( toString( @1) );
1326
                }
1327
        | NAME vector
1328
                {
1329
                  ps.conn->setDestGate( toString( @1) );
1330
                  addVector(ps.conn, "dest-gate-index",@2,$2);
1331
                }
1332
        | NAME PLUSPLUS
1333
                {
1334
                  ps.conn->setDestGate( toString( @1) );
1335
                  ps.conn->setDestGatePlusplus(true);
1336
                }
1337
        ;
1338
1339
opt_subgate
1340
        : '$' NAME
1341
                {
1342
                  const char *s = toString(@2);
1343
                  if (!strcmp(s,"i"))
1344
                      ps.subgate = NED_SUBGATE_I;
1345
                  else if (!strcmp(s,"o"))
1346
                      ps.subgate = NED_SUBGATE_O;
1347
                  else
1348
                       np->getErrors()->add(NULL,"invalid subgate spec `%s', must be `i' or `o'", toString(@2));
1349
                }
1350
        |
1351
                {  ps.subgate = NED_SUBGATE_NONE; }
1352
        ;
1353
1354
channelspec
1355
        : channelspec_header
1356
        | channelspec_header '{'
1357
                {
1358
                  ps.parameters = (ParametersNode *)createNodeWithTag(NED_PARAMETERS, ps.chanspec);
1359
                  ps.parameters->setIsImplicit(true);
1360
                  ps.propertyscope.push(ps.parameters);
1361
                }
1362
            opt_paramblock
1363
          '}'
1364
                {
1365
                  ps.propertyscope.pop();
1366
                }
1367
        ;
1368
1369
1370
channelspec_header
1371
        :
1372
                {
1373
                  ps.chanspec = (ChannelSpecNode *)createNodeWithTag(NED_CHANNEL_SPEC, ps.conn);
1374
                }
1375
        | NAME
1376
                {
1377
                  ps.chanspec = (ChannelSpecNode *)createNodeWithTag(NED_CHANNEL_SPEC, ps.conn);
1378
                  ps.chanspec->setType(toString(@1));
1379
                }
1380
        | likeparam LIKE NAME
1381
                {
1382
                  ps.chanspec = (ChannelSpecNode *)createNodeWithTag(NED_CHANNEL_SPEC, ps.conn);
1383
                  addLikeParam(ps.chanspec, "like-param", @1, $1);
1384
                  ps.chanspec->setLikeType(toString(@3));
1385
                }
1386
        | likeparam LIKE '*'
1387
                {
1388
                  ps.chanspec = (ChannelSpecNode *)createNodeWithTag(NED_CHANNEL_SPEC, ps.conn);
1389
                  addLikeParam(ps.chanspec, "like-param", @1, $1);
1390
                  ps.chanspec->setLikeAny(true);
1391
                }
1392
        ;
1393
1394
/*
1395
 * Condition
1396
 */
1397
opt_condition
1398
        : condition
1399
           { $$ = $1; }
1400
        |
1401
           { $$ = NULL; }
1402
        ;
1403
1404
condition
1405
        : IF expression
1406
                {
1407
                  ps.condition = (ConditionNode *)createNodeWithTag(NED_CONDITION);
1408
                  addExpression(ps.condition, "condition",@2,$2);
1409
                  $$ = ps.condition;
1410
                }
1411
        ;
1412
1413
/*
1414
 * Common part
1415
 */
1416
vector
1417
        : '[' expression ']'
1418
                { $$ = $2; }
1419
        ;
1420
1421
expression
1422
        :
1423
          expr
1424
                {
1425
                  if (np->getParseExpressionsFlag()) $$ = createExpression($1);
1426
                }
1427
        | xmldocvalue
1428
                {
1429
                  if (np->getParseExpressionsFlag()) $$ = createExpression($1);
1430
                }
1431
        ;
1432
1433
/*
1434
 * Expressions
1435
 */
1436
xmldocvalue
1437
        : XMLDOC '(' stringliteral ',' stringliteral ')'
1438
                { if (np->getParseExpressionsFlag()) $$ = createFunction("xmldoc", $3, $5); }
1439
        | XMLDOC '(' stringliteral ')'
1440
                { if (np->getParseExpressionsFlag()) $$ = createFunction("xmldoc", $3); }
1441
        ;
1442
1443
expr
1444
        : simple_expr
1445
        | '(' expr ')'
1446
                { $$ = $2; }
1447
        | CONST_ '(' expr ')'
1448
                { if (np->getParseExpressionsFlag()) $$ = createFunction("const", $3); }
1449
1450
        | expr '+' expr
1451
                { if (np->getParseExpressionsFlag()) $$ = createOperator("+", $1, $3); }
1452
        | expr '-' expr
1453
                { if (np->getParseExpressionsFlag()) $$ = createOperator("-", $1, $3); }
1454
        | expr '*' expr
1455
                { if (np->getParseExpressionsFlag()) $$ = createOperator("*", $1, $3); }
1456
        | expr '/' expr
1457
                { if (np->getParseExpressionsFlag()) $$ = createOperator("/", $1, $3); }
1458
        | expr '%' expr
1459
                { if (np->getParseExpressionsFlag()) $$ = createOperator("%", $1, $3); }
1460
        | expr '^' expr
1461
                { if (np->getParseExpressionsFlag()) $$ = createOperator("^", $1, $3); }
1462
1463
        | '-' expr
1464
                %prec UMIN
1465
                { if (np->getParseExpressionsFlag()) $$ = unaryMinus($2); }
1466
1467
        | expr EQ expr
1468
                { if (np->getParseExpressionsFlag()) $$ = createOperator("==", $1, $3); }
1469
        | expr NE expr
1470
                { if (np->getParseExpressionsFlag()) $$ = createOperator("!=", $1, $3); }
1471
        | expr '>' expr
1472
                { if (np->getParseExpressionsFlag()) $$ = createOperator(">", $1, $3); }
1473
        | expr GE expr
1474
                { if (np->getParseExpressionsFlag()) $$ = createOperator(">=", $1, $3); }
1475
        | expr '<' expr
1476
                { if (np->getParseExpressionsFlag()) $$ = createOperator("<", $1, $3); }
1477
        | expr LE expr
1478
                { if (np->getParseExpressionsFlag()) $$ = createOperator("<=", $1, $3); }
1479
1480
        | expr AND expr
1481
                { if (np->getParseExpressionsFlag()) $$ = createOperator("&&", $1, $3); }
1482
        | expr OR expr
1483
                { if (np->getParseExpressionsFlag()) $$ = createOperator("||", $1, $3); }
1484
        | expr XOR expr
1485
                { if (np->getParseExpressionsFlag()) $$ = createOperator("##", $1, $3); }
1486
1487
        | NOT expr
1488
                %prec UMIN
1489
                { if (np->getParseExpressionsFlag()) $$ = createOperator("!", $2); }
1490
1491
        | expr BIN_AND expr
1492
                { if (np->getParseExpressionsFlag()) $$ = createOperator("&", $1, $3); }
1493
        | expr BIN_OR expr
1494
                { if (np->getParseExpressionsFlag()) $$ = createOperator("|", $1, $3); }
1495
        | expr BIN_XOR expr
1496
                { if (np->getParseExpressionsFlag()) $$ = createOperator("#", $1, $3); }
1497
1498
        | BIN_COMPL expr
1499
                %prec UMIN
1500
                { if (np->getParseExpressionsFlag()) $$ = createOperator("~", $2); }
1501
        | expr SHIFT_LEFT expr
1502
                { if (np->getParseExpressionsFlag()) $$ = createOperator("<<", $1, $3); }
1503
        | expr SHIFT_RIGHT expr
1504
                { if (np->getParseExpressionsFlag()) $$ = createOperator(">>", $1, $3); }
1505
        | expr '?' expr ':' expr
1506
                { if (np->getParseExpressionsFlag()) $$ = createOperator("?:", $1, $3, $5); }
1507
1508
        | NAME '(' ')'
1509
                { if (np->getParseExpressionsFlag()) $$ = createFunction(toString(@1)); }
1510
        | NAME '(' expr ')'
1511
                { if (np->getParseExpressionsFlag()) $$ = createFunction(toString(@1), $3); }
1512
        | NAME '(' expr ',' expr ')'
1513
                { if (np->getParseExpressionsFlag()) $$ = createFunction(toString(@1), $3, $5); }
1514
        | NAME '(' expr ',' expr ',' expr ')'
1515
                { if (np->getParseExpressionsFlag()) $$ = createFunction(toString(@1), $3, $5, $7); }
1516
        | NAME '(' expr ',' expr ',' expr ',' expr ')'
1517
                { if (np->getParseExpressionsFlag()) $$ = createFunction(toString(@1), $3, $5, $7, $9); }
1518
         ;
1519
1520
simple_expr
1521
        : identifier
1522
        | special_expr
1523
        | literal
1524
        ;
1525
1526
identifier
1527
        : NAME
1528
                { if (np->getParseExpressionsFlag()) $$ = createIdent(@1); }
1529
        | THIS_ '.' NAME
1530
                { if (np->getParseExpressionsFlag()) $$ = createIdent(@3, @1); }
1531
        | NAME '.' NAME
1532
                { if (np->getParseExpressionsFlag()) $$ = createIdent(@3, @1); }
1533
        | NAME vector '.' NAME
1534
                { if (np->getParseExpressionsFlag()) $$ = createIdent(@4, @1, $2); }
1535
        ;
1536
1537
special_expr
1538
        : INDEX_
1539
                { if (np->getParseExpressionsFlag()) $$ = createFunction("index"); }
1540
        | INDEX_ '(' ')'
1541
                { if (np->getParseExpressionsFlag()) $$ = createFunction("index"); }
1542
        | SIZEOF '(' identifier ')'
1543
                { if (np->getParseExpressionsFlag()) $$ = createFunction("sizeof", $3); }
1544
        ;
1545
1546
literal
1547
        : stringliteral
1548
        | boolliteral
1549
        | numliteral
1550
        ;
1551
1552
stringliteral
1553
        : STRINGCONSTANT
1554
                { if (np->getParseExpressionsFlag()) $$ = createLiteral(NED_CONST_STRING, trimQuotes(@1), @1); }
1555
        ;
1556
1557
boolliteral
1558
        : TRUE_
1559
                { if (np->getParseExpressionsFlag()) $$ = createLiteral(NED_CONST_BOOL, @1, @1); }
1560
        | FALSE_
1561
                { if (np->getParseExpressionsFlag()) $$ = createLiteral(NED_CONST_BOOL, @1, @1); }
1562
        ;
1563
1564
numliteral
1565
        : INTCONSTANT
1566
                { if (np->getParseExpressionsFlag()) $$ = createLiteral(NED_CONST_INT, @1, @1); }
1567
        | REALCONSTANT
1568
                { if (np->getParseExpressionsFlag()) $$ = createLiteral(NED_CONST_DOUBLE, @1, @1); }
1569
        | quantity
1570
                { if (np->getParseExpressionsFlag()) $$ = createQuantity(toString(@1)); }
1571
        ;
1572
1573
quantity
1574
        : quantity INTCONSTANT NAME
1575
        | quantity REALCONSTANT NAME
1576
        | INTCONSTANT NAME
1577
        | REALCONSTANT NAME
1578
        ;
1579
1580
opt_semicolon : ';' | ;
1581
1582
%%
1583
1584
//----------------------------------------------------------------------
1585
// general bison/flex stuff:
1586
//
1587
1588
NEDElement *doParseNED2(NEDParser *p, const char *nedtext)
1589
{
1590
#if YYDEBUG != 0      /* #if added --VA */
1591
    yydebug = YYDEBUGGING_ON;
1592
#endif
1593
1594
    // reset the lexer
1595
    pos.co = 0;
1596
    pos.li = 1;
1597
    prevpos = pos;
1598
1599
    yyin = NULL;
1600
    yyout = stderr; // not used anyway
1601
1602
    // alloc buffer
1603
    struct yy_buffer_state *handle = yy_scan_string(nedtext);
1604
    if (!handle)
1605
        {np->getErrors()->add(NULL, "unable to allocate work memory"); return false;}
1606
1607
    // create parser state and NEDFileNode
1608
    np = p;
1609
    resetParserState();
1610
    ps.nedfile = new NedFileNode();
1611
1612
    // store file name with slashes always, even on Windows -- neddoc relies on that
1613
    ps.nedfile->setFilename(slashifyFilename(np->getFileName()).c_str());
1614
    ps.nedfile->setVersion("2");
1615
1616
    // store file comment
1617
    //FIXME ps.nedfile->setBannerComment(nedsource->getFileComment());
1618
1619
    ps.propertyscope.push(ps.nedfile);
1620
1621
    globalps = ps; // remember this for error recovery
1622
1623
    if (np->getStoreSourceFlag())
1624
        storeSourceCode(ps.nedfile, np->getSource()->getFullTextPos());
1625
1626
    // parse
1627
    int ret;
1628
    try
1629
    {
1630
        ret = yyparse();
1631
    }
1632
    catch (NEDException *e)
1633
    {
1634
        INTERNAL_ERROR1(NULL, "error during parsing: %s", e->errorMessage());
1635
        yy_delete_buffer(handle);
1636
        delete e;
1637
        return 0;
1638
    }
1639
1640
    if (np->getErrors()->empty())
1641
    {
1642
        // more sanity checks
1643
        if (ps.propertyscope.size()!=1 || ps.propertyscope.top()!=ps.nedfile)
1644
            INTERNAL_ERROR0(NULL, "error during parsing: imbalanced propertyscope");
1645
        if (!ps.blockscope.empty() || !ps.typescope.empty())
1646
            INTERNAL_ERROR0(NULL, "error during parsing: imbalanced blockscope or typescope");
1647
    }
1648
    yy_delete_buffer(handle);
1649
    return ps.nedfile;
1650
}
1651
1652
void yyerror(const char *s)
1653
{
1654
    // chop newline
1655
    char buf[250];
1656
    strcpy(buf, s);
1657
    if (buf[strlen(buf)-1] == '\n')
1658
        buf[strlen(buf)-1] = '\0';
1659
1660
    np->error(buf, pos.li);
1661
}