Project

General

Profile

Statistics
| Branch: | Revision:

root / src / nedxml / nedsyntaxvalidator.cc @ 79bb12dc

History | View | Annotate | Download (23.3 KB)

1 01873262 Georg Kunz
//==========================================================================
2
// nedsyntaxvalidator.cc
3
//
4
//                     OMNeT++/OMNEST
5
//            Discrete System Simulation in C++
6
//
7
// Contents:
8
//   class NEDSyntaxValidator
9
//
10
//==========================================================================
11
12
/*--------------------------------------------------------------*
13
  Copyright (C) 2002-2008 Andras Varga
14
  Copyright (C) 2006-2008 OpenSim Ltd.
15

16
  This file is distributed WITHOUT ANY WARRANTY. See the file
17
  `license' for details on this and other legal matters.
18
*--------------------------------------------------------------*/
19
20
#include <stdio.h>
21
#include <string.h>
22
#include <stdlib.h>
23
#include <assert.h>
24
#include <locale.h>
25
#include "opp_ctype.h"
26
#include "nederror.h"
27
#include "nedsyntaxvalidator.h"
28
#include "stringutil.h"
29
30
USING_NAMESPACE
31
32
33
// FIXME TODO: assert types begin with capital letters, and submods/gates/params with lowercase! warning if not!
34
35
36
static struct { const char *fname; int args; } known_funcs[] =
37
{
38
   /* <math.h> */
39
   {"fabs", 1},    {"fmod", 2},
40
   {"acos", 1},    {"asin", 1},    {"atan", 1},   {"atan2", 1},
41
   {"sin", 1},     {"cos", 1},     {"tan", 1},    {"hypot", 2},
42
   {"ceil", 1},    {"floor", 1},
43
   {"exp", 1},     {"pow", 2},     {"sqrt", 1},
44
   {"log",  1},    {"log10", 1},
45
46
   /* OMNeT++ general */
47
   {"min", 2},
48
   {"max", 2},
49
50
   /* OMNeT++: distributions without rng-id arg */
51
   {"uniform",2},
52
   {"exponential",1},
53
   {"normal",2},
54
   {"truncnormal",2},
55
   {"gamma_d",2},
56
   {"beta",2},
57
   {"erlang_k",2},
58
   {"chi_square",1},
59
   {"student_t",1},
60
   {"cauchy",2},
61
   {"triang",3},
62
   {"lognormal",2},
63
   {"weibull",2},
64
   {"pareto_shifted",3},
65
   {"intuniform",2},
66
   {"bernoulli",1},
67
   {"binomial",2},
68
   {"geometric",1},
69
   {"negbinomial",2},
70
   {"hypergeometric",3},
71
   {"poisson",1},
72
73
   /* OMNeT++: distributions with rng-id arg */
74
   {"uniform",3},
75
   {"exponential",2},
76
   {"normal",3},
77
   {"truncnormal",3},
78
   {"gamma_d",3},
79
   {"beta",3},
80
   {"erlang_k",3},
81
   {"chi_square",2},
82
   {"student_t",2},
83
   {"cauchy",3},
84
   {"triang",4},
85
   {"lognormal",3},
86
   {"weibull",3},
87
   {"pareto_shifted",4},
88
   {"intuniform",3},
89
   {"bernoulli",2},
90
   {"binomial",3},
91
   {"geometric",2},
92
   {"negbinomial",3},
93
   {"hypergeometric",4},
94
   {"poisson",2},
95
96
   /* END */
97
   {NULL,0}
98
};
99
100
void NEDSyntaxValidator::checkExpressionAttributes(NEDElement *node, const char *attrs[], bool optional[], int n)
101
{
102
    if (parsedExpressions)
103
    {
104
        // allow attribute values to be present, but check there are no
105
        // Expression children that are not in the list
106
        for (NEDElement *child=node->getFirstChildWithTag(NED_EXPRESSION); child; child=child->getNextSiblingWithTag(NED_EXPRESSION))
107
        {
108
            ExpressionElement *expr = (ExpressionElement *) child;
109
            const char *target = expr->getTarget();
110
            int i;
111
            for (i=0; i<n; i++)
112
                if (!strcmp(target, attrs[i]))
113
                    break;
114
            if (i==n)
115
                errors->addError(child, "'expression' element with invalid target attribute '%s'",target);
116
        }
117
    }
118
    else
119
    {
120
        // check: should be no Expression children at all
121
        if (node->getFirstChildWithTag(NED_EXPRESSION))
122
            errors->addError(node, "'expression' element found while using non-parsed expressions\n");
123
    }
124
125
    // check mandatory expressions are there
126
    for (int i=0; i<n; i++)
127
    {
128
       if (!optional[i])
129
       {
130
           if (parsedExpressions)
131
           {
132
               // check: Expression element must be there
133
               ExpressionElement *expr;
134
               for (expr=(ExpressionElement *)node->getFirstChildWithTag(NED_EXPRESSION); expr; expr=expr->getNextExpressionSibling())
135
                   if (!opp_isempty(expr->getTarget()) && !strcmp(expr->getTarget(),attrs[i]))
136
                       break;
137
               if (!expr)
138
                   errors->addError(node, "expression-valued attribute '%s' not present in parsed form (missing 'expression' element)", attrs[i]);
139
           }
140
           else
141
           {
142
               // attribute must be there
143
               if (!node->getAttribute(attrs[i]) || !(node->getAttribute(attrs[i]))[0])
144
                   errors->addError(node, "missing attribute '%s'", attrs[i]);
145
           }
146
       }
147
    }
148
}
149
150
void NEDSyntaxValidator::checkDottedNameAttribute(NEDElement *node, const char *attr, bool wildcardsAllowed)
151
{
152
    const char *s = node->getAttribute(attr);
153
    assert(s);
154
    if (!*s)
155
        return;
156
    for (; *s; s++)
157
        if (!opp_isalpha(*s) && !opp_isdigit(*s) && *s!='_' && *s!='.' && (wildcardsAllowed ? *s!='*' : true))
158
            {errors->addError(node,"validation error: attribute %s='%s' contains invalid character", attr, node->getAttribute(attr)); return;}
159
}
160
161
bool NEDSyntaxValidator::isWithinSubcomponent(NEDElement *node)
162
{
163
    // only returns true if node is within the BODY of a submodule or a channelspec
164
    // (i.e. returns *false* for a submodule vector size)
165
    for (; node!=NULL; node = node->getParent())
166
    {
167
        if (node->getTagCode() == NED_PARAMETERS || node->getTagCode() == NED_GATES) {
168
            int sectionOwnerType = node->getParent()->getTagCode();
169
            return sectionOwnerType==NED_SUBMODULE || sectionOwnerType==NED_CHANNEL_SPEC || sectionOwnerType==NED_CONNECTION;
170
        }
171
    }
172
    return false;
173
}
174
175
bool NEDSyntaxValidator::isWithinInnerType(NEDElement *node)
176
{
177
    for (; node!=NULL; node = node->getParent())
178
        if (node->getTagCode() == NED_TYPES)
179
            return true;
180
    return false;
181
}
182
183
void NEDSyntaxValidator::validateElement(FilesElement *node)
184
{
185
}
186
187
void NEDSyntaxValidator::validateElement(NedFileElement *node)
188
{
189
}
190
191
void NEDSyntaxValidator::validateElement(CommentElement *node)
192
{
193
    //FIXME revise
194
}
195
196
void NEDSyntaxValidator::validateElement(PackageElement *node)
197
{
198
    checkDottedNameAttribute(node, "name", false);
199
}
200
201
void NEDSyntaxValidator::validateElement(ImportElement *node)
202
{
203
    checkDottedNameAttribute(node, "import-spec", true);
204
}
205
206
void NEDSyntaxValidator::validateElement(PropertyDeclElement *node)
207
{
208
    //FIXME revise
209
}
210
211
void NEDSyntaxValidator::validateElement(ExtendsElement *node)
212
{
213
    checkDottedNameAttribute(node, "name", false);
214
}
215
216
void NEDSyntaxValidator::validateElement(InterfaceNameElement *node)
217
{
218
    checkDottedNameAttribute(node, "name", false);
219
}
220
221
void NEDSyntaxValidator::validateElement(SimpleModuleElement *node)
222
{
223
    //FIXME revise
224
}
225
226
void NEDSyntaxValidator::validateElement(ModuleInterfaceElement *node)
227
{
228
    //FIXME revise
229
}
230
231
void NEDSyntaxValidator::validateElement(CompoundModuleElement *node)
232
{
233
    //FIXME revise
234
}
235
236
void NEDSyntaxValidator::validateElement(ParametersElement *node)
237
{
238
    //FIXME revise
239
}
240
241
void NEDSyntaxValidator::validateElement(ParamElement *node)
242
{
243
    NEDElement *parent = node->getParent();
244
    if (parent)
245
        parent = parent->getParent();
246
247
    // param declarations cannot occur in submodules
248
    if (parent->getTagCode() == NED_SUBMODULE)
249
    {
250
        if (node->getType() != NED_PARTYPE_NONE)
251
            errors->addError(node, "cannot define new parameters within a submodule");
252
    }
253
254
    // check isPattern flag is consistent with 'name' attribute
255
    bool containsDot = strchr(node->getName(), '.')!=NULL;
256
    if (!node->getIsPattern() && containsDot)
257
        errors->addError(node, "parameter names must not contain a dot");
258
    if (node->getIsPattern() && !containsDot)
259
        errors->addError(node, "parameter name patterns must contain a dot");
260
261
    // type+pattern are not compatible
262
    if (node->getIsPattern() && node->getType() != NED_PARTYPE_NONE)
263
        errors->addError(node, "name must be an identifier when defining a new parameter");
264
265
    // in module or channel interfaces, one cannot specify parameter values
266
    if (parent->getTagCode() == NED_MODULE_INTERFACE || parent->getTagCode() == NED_CHANNEL_INTERFACE)
267
    {
268
        if (parsedExpressions)
269
        {
270
            if (node->getFirstChildWithTag(NED_EXPRESSION)) // && expr->getTarget()=="value"
271
                errors->addError(node, "cannot specify parameter values within a module interface or or channel interface");
272
        }
273
        else
274
        {
275
            if (!opp_isempty(node->getValue()))
276
                errors->addError(node, "cannot specify parameter values within a module interface or or channel interface");
277
        }
278
    }
279
}
280
281
void NEDSyntaxValidator::validateElement(PropertyElement *node)
282
{
283
    // properties cannot occur on submodule or channelspec parameters and gates.
284
    // structure: submodule>parameters>parameter>property
285
    NEDElement *parent = node->getParent();
286
    if (parent && (parent->getTagCode()==NED_PARAM || parent->getTagCode()==NED_GATE))
287
    {
288
        NEDElement *container = parent->getParent()->getParent();
289
        if (container && (container->getTagCode()==NED_SUBMODULE || container->getTagCode()==NED_CHANNEL_SPEC))
290
            errors->addError(node, "cannot modify parameter or gate properties with a submodule or connection");
291
    }
292
}
293
294
void NEDSyntaxValidator::validateElement(PropertyKeyElement *node)
295
{
296
    //FIXME revise
297
}
298
299
void NEDSyntaxValidator::validateElement(GatesElement *node)
300
{
301
    //FIXME revise
302
}
303
304
void NEDSyntaxValidator::validateElement(TypesElement *node)
305
{
306
    // make sure type names are unique
307
}
308
309
void NEDSyntaxValidator::validateElement(GateElement *node)
310
{
311
    // param declarations cannot occur in submodules
312
    if (node->getType() != NED_GATETYPE_NONE)
313
    {
314
        NEDElement *parent = node->getParent();
315
        if (parent)
316
            parent = parent->getParent();
317
        if (parent->getTagCode() == NED_SUBMODULE)
318
            errors->addError(node, "cannot define new gates within a submodule");
319
    }
320
}
321
322
void NEDSyntaxValidator::validateElement(SubmodulesElement *node)
323
{
324
    //FIXME revise
325
}
326
327
void NEDSyntaxValidator::validateElement(SubmoduleElement *node)
328
{
329
    //FIXME revise
330
    const char *expr[] = {"like-param", "vector-size"};
331
    bool opt[] = {true, true};
332
    checkExpressionAttributes(node, expr, opt, 2);
333
334
    checkDottedNameAttribute(node, "type", false);
335
    checkDottedNameAttribute(node, "like-type", false);
336
337
338
//    // if there's a "like", name should be an existing module parameter name
339
//    if (!opp_isempty(node->getLikeParam()))
340
//    {
341
//        const char *paramName = node->getLikeParam();
342
//        NEDElement *compound = node->getParentWithTag(NED_COMPOUND_MODULE);
343
//        if (!compound)
344
//            INTERNAL_ERROR0(node,"occurs outside a compound-module");
345
//        NEDElement *params = compound->getFirstChildWithTag(NED_PARAMETERS);
346
//        if (!params || params->getFirstChildWithAttribute(NED_PARAM, "name", paramName)==NULL)
347
//            {errors->addError(node, "compound module has no parameter named '%s'", paramName);return;}
348
//    }
349
}
350
351
//void NEDSyntaxValidator::validateElement(SubstparamsElement *node)
352
//{
353
//    const char *expr[] = {"condition"};
354
//    bool opt[] = {true};
355
//    checkExpressionAttributes(node, expr, opt, 1);
356
//
357
//    // make sure parameter names are unique
358
//    checkUniqueness(node, NED_SUBSTPARAM, "name");
359
//}
360
361
// TODO merge into 'parameters'
362
//void NEDSyntaxValidator::validateElement(SubstparamElement *node)
363
//{
364
//    const char *expr[] = {"value"};
365
//    bool opt[] = {false};
366
//    checkExpressionAttributes(node, expr, opt, 1);
367
//}
368
369
// TODO merge into 'gates'
370
//void NEDSyntaxValidator::validateElement(GatesizesElement *node)
371
//{
372
//    const char *expr[] = {"condition"};
373
//    bool opt[] = {true};
374
//    checkExpressionAttributes(node, expr, opt, 1);
375
//
376
//    // make sure gate names are unique
377
//    checkUniqueness(node, NED_GATESIZE, "name");
378
//}
379
380
// TODO merge into 'gates'
381
//void NEDSyntaxValidator::validateElement(GatesizeElement *node)
382
//{
383
//    const char *expr[] = {"vector-size"};
384
//    bool opt[] = {true};
385
//    checkExpressionAttributes(node, expr, opt, 1);
386
//}
387
388
void NEDSyntaxValidator::validateElement(ConnectionsElement *node)
389
{
390
    //FIXME revise
391
    // TBD if check=true, make sure all gates are connected
392
}
393
394
void NEDSyntaxValidator::validateElement(ConnectionElement *node)
395
{
396
    //FIXME revise
397
    const char *expr[] = {"condition", "src-module-index", "src-gate-index", "dest-module-index", "dest-gate-index"};
398
    bool opt[] = {true, true, true, true, true};
399
    checkExpressionAttributes(node, expr, opt, 5);
400
401
    // plusplus and gate index expression cannot be both there
402
    bool srcGateIx =  node->getFirstChildWithAttribute(NED_EXPRESSION, "target", "src-gate-index")!=NULL;
403
    bool destGateIx = node->getFirstChildWithAttribute(NED_EXPRESSION, "target", "dest-gate-index")!=NULL;
404
    if (srcGateIx && node->getSrcGatePlusplus())
405
        errors->addError(node, "wrong source gate: cannot have both gate index and '++' operator specified");
406
    if (destGateIx && node->getDestGatePlusplus())
407
        errors->addError(node, "wrong destination gate: cannot have both gate index and '++' operator specified");
408
}
409
410
void NEDSyntaxValidator::validateElement(ChannelSpecElement *node)
411
{
412
    checkDottedNameAttribute(node, "type", false);
413
    checkDottedNameAttribute(node, "like-type", false);
414
    //FIXME revise
415
}
416
417
void NEDSyntaxValidator::validateElement(ChannelInterfaceElement *node)
418
{
419
    //FIXME revise
420
}
421
422
void NEDSyntaxValidator::validateElement(ChannelElement *node)
423
{
424
    //FIXME revise
425
}
426
427
void NEDSyntaxValidator::validateElement(ConnectionGroupElement *node)
428
{
429
    //FIXME revise
430
    // TODO check loop vars are unique etc
431
}
432
433
void NEDSyntaxValidator::validateElement(LoopElement *node)
434
{
435
    //TODO adapt
436
    //const char *expr[] = {"from-value", "to-value"};
437
    //bool opt[] = {false, false};
438
    //checkExpressionAttributes(node, expr, opt, 2);
439
}
440
441
void NEDSyntaxValidator::validateElement(ConditionElement *node)
442
{
443
    //FIXME revise
444
}
445
446
void NEDSyntaxValidator::validateElement(ExpressionElement *node)
447
{
448
    //FIXME revise
449
}
450
451
void NEDSyntaxValidator::validateElement(OperatorElement *node)
452
{
453
    //FIXME revise
454
    // check operator name is valid and argument count matches
455
    const char *op = node->getName();
456
457
    // next list uses space as separator, so make sure op does not contain space
458
    if (strchr(op, ' '))
459
    {
460
        errors->addError(node, "invalid operator '%s' (contains space)",op);
461
        return;
462
    }
463
464
    // count arguments
465
    int args = 0;
466
    for (NEDElement *child=node->getFirstChild(); child; child=child->getNextSibling())
467
       args++;
468
469
    // unary?
470
    if (strstr("! ~",op))
471
    {
472
         if (args!=1)
473
            errors->addError(node, "operator '%s' should have 1 operand, not %d", op, args);
474
    }
475
    // unary or binary?
476
    else if (strstr("-",op))
477
    {
478
         if (args!=1 && args!=2)
479
            errors->addError(node, "operator '%s' should have 1 or 2 operands, not %d", op, args);
480
    }
481
    // binary?
482
    else if (strstr("+ * / % ^ == != > >= < <= && || ## & | # << >>",op))
483
    {
484
         if (args!=2)
485
            errors->addError(node, "operator '%s' should have 2 operands, not %d", op, args);
486
    }
487
    // tertiary?
488
    else if (strstr("?:",op))
489
    {
490
         if (args!=3)
491
            errors->addError(node, "operator '%s' should have 3 operands, not %d", op, args);
492
    }
493
    else
494
    {
495
        errors->addError(node, "invalid operator '%s'",op);
496
    }
497
}
498
499
void NEDSyntaxValidator::validateElement(FunctionElement *node)
500
{
501
    //FIXME revise
502
    // if we know the function, check argument count
503
    const char *func = node->getName();
504
    int args = node->getNumChildren();
505
506
    // if it's an operator, treat specially
507
    if (!strcmp(func,"index"))
508
    {
509
         if (args!=0)
510
             errors->addError(node, "operator 'index' does not take arguments");
511
512
         // find expression and submodule node we're under
513
         NEDElement *parent = node->getParent();
514
         while (parent && parent->getTagCode()!=NED_EXPRESSION)
515
             parent = parent->getParent();
516
         NEDElement *expr = parent;
517
518
         while (parent && parent->getTagCode()!=NED_SUBMODULE)
519
             parent = parent->getParent();
520
         NEDElement *submod = parent;
521
522
         if (!submod || submod->getFirstChildWithAttribute(NED_EXPRESSION, "target", "vector-size")==NULL)
523
             errors->addError(node, "'index' may only occur in a submodule vector's definition");
524
         if (expr->getParent()==submod)
525
             errors->addError(node, "'index' is not allowed here");
526
         return;
527
    }
528
    else if (!strcmp(func,"sizeof"))
529
    {
530
         if (args!=1)
531
             errors->addError(node, "operator 'sizeof' takes one argument");
532
         //else if (node->getFirstChild()->getTagCode()!=NED_IDENT)
533
         //    errors->addError(node, "argument of operator 'sizeof' should be an identifier");
534
         else
535
         {
536
             // TBD further check it's an existing parent module gate or submodule name
537
         }
538
         return;
539
    }
540
    else if (!strcmp(func,"input"))
541
    {
542
         if (args>2)
543
             errors->addError(node, "operator 'input' takes 0, 1 or 2 arguments");
544
         NEDElement *op1 = node->getFirstChild();
545
         NEDElement *op2 = op1 ? op1->getNextSibling() : NULL;
546
         if (args==2)
547
             if (op2->getTagCode()!=NED_LITERAL || ((LiteralElement *)op2)->getType()!=NED_CONST_STRING)
548
                 errors->addError(node, "second argument to 'input()' must be a string literal (prompt text)");
549
         NEDElement *parent = node->getParent();
550
         if (parent->getTagCode()!=NED_EXPRESSION)
551
             errors->addError(node, "'input()' occurs in wrong place");
552
         return;
553
    }
554
    else if (!strcmp(func,"xmldoc"))
555
    {
556
         if (args!=1 && args!=2)
557
             {errors->addError(node, "'xmldoc()' takes 1 or 2 arguments");return;}
558
         NEDElement *op1 = node->getFirstChild();
559
         NEDElement *op2 = op1 ? op1->getNextSibling() : NULL;
560
         if (op1->getTagCode()!=NED_LITERAL || ((LiteralElement *)op1)->getType()!=NED_CONST_STRING ||
561
             (op2 && (op2->getTagCode()!=NED_LITERAL || ((LiteralElement *)op2)->getType()!=NED_CONST_STRING)))
562
             errors->addError(node, "'xmldoc()' arguments must be string literals");
563
         return;
564
    }
565
566
    // check if we know about it
567
    bool name_found = false;
568
    bool argc_matches = false;
569
    for (int i=0; known_funcs[i].fname!=NULL;i++)
570
    {
571
        if (!strcmp(func,known_funcs[i].fname))
572
        {
573
            name_found = true;
574
            if (known_funcs[i].args == args)
575
            {
576
                argc_matches = true;
577
                break;
578
            }
579
        }
580
    }
581
    if (name_found && !argc_matches)
582
    {
583
        errors->addError(node, "function '%s' cannot take %d operands", func, args);
584
    }
585
}
586
587
void NEDSyntaxValidator::validateElement(IdentElement *node)
588
{
589
    const char *expr[] = {"module-index", "param-index"};
590
    bool opt[] = {true, true};
591
    checkExpressionAttributes(node, expr, opt, 2);
592
593
/*TODO:
594
    bool withinSubcomponent = isWithinSubcomponent(node);
595
    bool withinInnerType = isWithinInnerType(node);
596

597
    const char *modulename = node->getModule();
598
    if (opp_isempty(modulename) || strcmp(modulename, "this")==0)
599
    {
600
        // OK -- "identifier" and "this.identifier" are allowed in expressions anywhere
601
    }
602
    else
603
    {
604
        // TODO module.ident is not legal at certain places
605
    }
606
*/
607
}
608
609
void NEDSyntaxValidator::validateElement(LiteralElement *node)
610
{
611
    // verify syntax of constant
612
    int type = node->getType();
613
    const char *value = node->getValue();
614
    //const char *text = node->getText();
615
616
    // Note: null value is valid as well, because that represents the "" string literal!
617
    if (opp_isempty(value)) value="";
618
619
    if (type==NED_CONST_BOOL)
620
    {
621
        // check bool
622
        if (strcmp(value,"true") && strcmp(value,"false"))
623
            errors->addError(node, "bool constant should be 'true' or 'false'");
624
        if (!opp_isempty(node->getUnit()))
625
            errors->addError(node, "bool constant cannot have a unit");
626
        // TBD check that if text is present, it's the same as value
627
    }
628
    else if (type==NED_CONST_INT)
629
    {
630
        // check int
631
        char *s;
632
        (void) strtol(value, &s, 0);
633
        if (s && *s)
634
            errors->addError(node, "invalid integer constant '%s'", value);
635
        if (!opp_isempty(node->getUnit()))
636
            errors->addError(node, "integer constant cannot have a unit");
637
        // TBD check that if text is present, it's the same as value
638
    }
639
    else if (type==NED_CONST_DOUBLE)
640
    {
641
        // check real
642
        char *s;
643
        setlocale(LC_NUMERIC, "C");
644
        (void) strtod(value, &s);
645
        if (s && *s)
646
            errors->addError(node, "invalid real constant '%s'", value);
647
        // TBD check that if text and/or unit is present, they're consistent
648
    }
649
    else if (type==NED_CONST_STRING)
650
    {
651
        // string: no restriction on value
652
        if (!opp_isempty(node->getUnit()))
653
            errors->addError(node, "string constant cannot have a unit");
654
        // TBD check that if text is present, it's the same as value
655
    }
656
}
657
658
void NEDSyntaxValidator::validateElement(MsgFileElement *node)
659
{
660
}
661
662
void NEDSyntaxValidator::validateElement(NamespaceElement *node)
663
{
664
}
665
666
void NEDSyntaxValidator::validateElement(CplusplusElement *node)
667
{
668
}
669
670
void NEDSyntaxValidator::validateElement(StructDeclElement *node)
671
{
672
}
673
674
void NEDSyntaxValidator::validateElement(ClassDeclElement *node)
675
{
676
}
677
678
void NEDSyntaxValidator::validateElement(MessageDeclElement *node)
679
{
680
}
681
682
void NEDSyntaxValidator::validateElement(PacketDeclElement *node)
683
{
684
}
685
686
void NEDSyntaxValidator::validateElement(EnumDeclElement *node)
687
{
688
}
689
690
void NEDSyntaxValidator::validateElement(EnumElement *node)
691
{
692
}
693
694
void NEDSyntaxValidator::validateElement(EnumFieldsElement *node)
695
{
696
}
697
698
void NEDSyntaxValidator::validateElement(EnumFieldElement *node)
699
{
700
}
701
702
void NEDSyntaxValidator::validateElement(MessageElement *node)
703
{
704
}
705
706
void NEDSyntaxValidator::validateElement(PacketElement *node)
707
{
708
}
709
710
void NEDSyntaxValidator::validateElement(ClassElement *node)
711
{
712
}
713
714
void NEDSyntaxValidator::validateElement(StructElement *node)
715
{
716
}
717
718
void NEDSyntaxValidator::validateElement(FieldElement *node)
719
{
720
    NEDElement *classNode = node->getParent()->getParent();
721
    bool isStruct = !strcmp(classNode->getTagName(), "struct");
722
723
    if (node->getIsAbstract() && isStruct)
724
          errors->addError(node, "a struct cannot have abstract fields");
725
726
    if (node->getIsAbstract() && !opp_isempty(node->getDefaultValue()))
727
         errors->addError(node, "an abstract field cannot be assigned a default value");
728
729
    if (node->getIsVector() && opp_isempty(node->getVectorSize()) && isStruct)
730
         errors->addError(node, "a struct cannot have dynamic array fields");
731
732
    // if (!opp_isempty(node->getDataType())) // type is there
733
    // {
734
    //      if (defined in base class too)
735
    //      {
736
    //          if (!node->getIsReadonly())
737
    //              errors->addError(node, "field is already declared in a base class (only readonly fields can be overridden)");
738
    //          if (node->getIsReadonly() && type is not the same)
739
    //              errors->addError(node, "field is already declared in a base class with a different type");
740
    //      }
741
    // }
742
743
    if (opp_isempty(node->getDataType())) // type is missing
744
    {
745
         if (node->getIsAbstract())
746
             errors->addError(node, "an abstract field needs a type");
747
         if (node->getIsVector())
748
             errors->addError(node, "cannot set array field of the base class");
749
         if (opp_isempty(node->getDefaultValue()))
750
             errors->addError(node, "missing field type");
751
    }
752
753
    // TBD check syntax of default value, and that its type agrees with field type
754
755
}
756
757
void NEDSyntaxValidator::validateElement(UnknownElement *node)
758
{
759
}