Statistics
| Branch: | Revision:

root / src / nedxml / nedyylib.cc @ 68da4f12

History | View | Annotate | Download (15.1 KB)

1 01873262 Georg Kunz
//==========================================================================
2
// nedyylib.cc  -
3
//
4
//                     OMNeT++/OMNEST
5
//            Discrete System Simulation in C++
6
//
7
//==========================================================================
8
9
/*--------------------------------------------------------------*
10
  Copyright (C) 2002-2008 Andras Varga
11
  Copyright (C) 2006-2008 OpenSim Ltd.
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
18
#include <assert.h>
19
#include "opp_ctype.h"
20
#include "nedyylib.h"
21
#include "nedfilebuffer.h"
22
#include "nedyydefs.h"
23
#include "stringutil.h"
24
#include "unitconversion.h"
25
26
NAMESPACE_BEGIN
27
28
// this global var is shared by all lexers
29
LineColumn pos, prevpos;
30
31
std::string slashifyFilename(const char *fname)
32
{
33
    std::string fnamewithslash = np->getFileName();
34
    for (char *s=const_cast<char *>(fnamewithslash.data()); *s; s++)
35
        if (*s=='\\')
36
            *s='/';
37
    return fnamewithslash;
38
}
39
40
const char *toString(YYLTYPE pos)
41
{
42
    return np->getSource()->get(pos);
43
}
44
45
const char *toString(long l)
46
{
47
    static char buf[32];
48
    sprintf(buf,"%ld", l);
49
    return buf;
50
}
51
52
std::string removeSpaces(YYLTYPE pos)
53
{
54
    const char *s = np->getSource()->get(pos);
55
    std::string result;
56
    for (; *s; s++)
57
        if (!opp_isspace(*s))
58
            result += *s;
59
    return result;
60
}
61
62
const char *currentLocation()
63
{
64
    static char buf[200];
65
    sprintf(buf,"%s:%d", np->getFileName(), pos.li);
66
    return buf;
67
}
68
69
NEDElement *createElementWithTag(int tagcode, NEDElement *parent)
70
{
71
    // create via a factory
72
    NEDElement *e = NEDElementFactory::getInstance()->createElementWithTag(tagcode);
73
    e->setSourceLocation(currentLocation());
74
75
    // add to parent
76
    if (parent)
77
       parent->appendChild(e);
78
79
    return e;
80
}
81
82
NEDElement *getOrCreateElementWithTag(int tagcode, NEDElement *parent)
83
{
84
    assert(parent);
85
    NEDElement *e = parent->getFirstChildWithTag(tagcode);
86
    return e!=NULL ? e : createElementWithTag(tagcode, parent);
87
}
88
89
void storePos(NEDElement *node, YYLTYPE pos)
90
{
91
    np->getSource()->trimSpaceAndComments(pos);
92
93
    assert(node);
94
    NEDSourceRegion region;
95
    region.startLine = pos.first_line;
96
    region.startColumn = pos.first_column;
97
    region.endLine = pos.last_line;
98
    region.endColumn = pos.last_column;
99
    node->setSourceRegion(region);
100
}
101
102
void storePos(NEDElement *node, YYLTYPE firstpos, YYLTYPE lastpos)
103
{
104
    YYLTYPE pos = firstpos;
105
    pos.last_line = lastpos.last_line;
106
    pos.last_column = lastpos.last_column;
107
    storePos(node, pos);
108
}
109
110
//
111
// Properties
112
//
113
114
PropertyElement *addProperty(NEDElement *node, const char *name)
115
{
116
    PropertyElement *prop = (PropertyElement *)createElementWithTag(NED_PROPERTY, node);
117
    prop->setName(name);
118
    return prop;
119
}
120
121
PropertyElement *addComponentProperty(NEDElement *node, const char *name)
122
{
123
    // add propery under the ParametersElement; create that if not yet exists
124
    NEDElement *params = node->getFirstChildWithTag(NED_PARAMETERS);
125
    if (!params)
126
    {
127
        params = createElementWithTag(NED_PARAMETERS, node);
128
129
        // move parameters section in front of potential gates, types, etc sections
130
        NEDElement *prev;
131
        while ((prev=params->getPrevSibling())!=NULL &&
132
                 (prev->getTagCode()==NED_GATES || prev->getTagCode()==NED_TYPES ||
133
                  prev->getTagCode()==NED_SUBMODULES || prev->getTagCode()==NED_CONNECTIONS))
134
        {
135
            node->removeChild(params);
136
            node->insertChildBefore(prev, params);
137
        }
138
    }
139
    PropertyElement *prop = (PropertyElement *)createElementWithTag(NED_PROPERTY, params);
140
    prop->setName(name);
141
    return prop;
142
}
143
144
//
145
// Spec Properties: source code, display string
146
//
147
148
PropertyElement *storeSourceCode(NEDElement *node, YYLTYPE tokenpos)
149
{
150
    PropertyElement *prop = addProperty(node, "sourcecode");
151
    prop->setIsImplicit(true);
152
    PropertyKeyElement *propkey = (PropertyKeyElement *)createElementWithTag(NED_PROPERTY_KEY, prop);
153
    propkey->appendChild(createLiteral(NED_CONST_STRING, tokenpos, makeEmptyYYLTYPE()));  // don't store it twice
154
    return prop;
155
}
156
157
PropertyElement *storeComponentSourceCode(NEDElement *node, YYLTYPE tokenpos)
158
{
159
    PropertyElement *prop = addComponentProperty(node, "sourcecode");
160
    prop->setIsImplicit(true);
161
    PropertyKeyElement *propkey = (PropertyKeyElement *)createElementWithTag(NED_PROPERTY_KEY, prop);
162
    propkey->appendChild(createLiteral(NED_CONST_STRING, tokenpos, makeEmptyYYLTYPE()));  // don't store it twice
163
    return prop;
164
}
165
166
PropertyElement *setIsNetworkProperty(NEDElement *node)
167
{
168
    PropertyElement *prop = addComponentProperty(node, "isNetwork");
169
    prop->setIsImplicit(true);
170
    // Note: the following is not needed, because @isNetwork already means @isNetwork(true)
171
    // PropertyKeyElement *propkey = (PropertyKeyElement *)createElementWithTag(NED_PROPERTY_KEY, prop);
172
    // propkey->appendChild(createLiteral(NED_CONST_BOOL, "true", ""));
173
    return prop;
174
}
175
176
//
177
// Comments
178
//
179
void addComment(NEDElement *node, const char *locId, const char *text, const char *defaultValue)
180
{
181
    // don't store empty string or the default
182
    if (!text[0] || strcmp(text,defaultValue)==0)
183
        return;
184
185
    CommentElement *comment = (CommentElement *)createElementWithTag(NED_COMMENT);
186
    comment->setLocid(locId);
187
    comment->setContent(text);
188
    node->insertChildBefore(node->getFirstChild(), comment);
189
}
190
191
void storeFileComment(NEDElement *node)
192
{
193
    addComment(node, "banner", np->getSource()->getFileComment(), "");
194
}
195
196
void storeBannerComment(NEDElement *node, YYLTYPE tokenpos)
197
{
198
    addComment(node, "banner", np->getSource()->getBannerComment(tokenpos), "");
199
}
200
201
void storeRightComment(NEDElement *node, YYLTYPE tokenpos)
202
{
203
    addComment(node, "right", np->getSource()->getTrailingComment(tokenpos), "\n");
204
}
205
206
void storeTrailingComment(NEDElement *node, YYLTYPE tokenpos)
207
{
208
    addComment(node, "trailing", np->getSource()->getTrailingComment(tokenpos), "\n");
209
}
210
211
void storeBannerAndRightComments(NEDElement *node, YYLTYPE pos)
212
{
213
    np->getSource()->trimSpaceAndComments(pos);
214
    storeBannerComment(node, pos);
215
    storeRightComment(node, pos);
216
    storeInnerComments(node, pos);
217
}
218
219
void storeBannerAndRightComments(NEDElement *node, YYLTYPE firstpos, YYLTYPE lastpos)
220
{
221
    YYLTYPE pos = firstpos;
222
    pos.last_line = lastpos.last_line;
223
    pos.last_column = lastpos.last_column;
224
225
    np->getSource()->trimSpaceAndComments(pos);
226
    storeBannerComment(node, pos);
227
    storeRightComment(node, pos);
228
}
229
230
void storeInnerComments(NEDElement *node, YYLTYPE pos)
231
{
232
    for (;;)
233
    {
234
        const char *comment = np->getSource()->getNextInnerComment(pos); // updates "pos"
235
        if (!comment)
236
            break;
237
        addComment(node, "inner", comment, "");
238
    }
239
}
240
241
ParamElement *addParameter(NEDElement *params, YYLTYPE namepos)
242
{
243
    ParamElement *param = (ParamElement *)createElementWithTag(NED_PARAM,params);
244
    param->setName( toString( namepos) );
245
    return param;
246
}
247
248
ParamElement *addParameter(NEDElement *params, const char *name, YYLTYPE namepos)
249
{
250
    ParamElement *param = (ParamElement *)createElementWithTag(NED_PARAM,params);
251
    param->setName(name);
252
    return param;
253
}
254
255
GateElement *addGate(NEDElement *gates, YYLTYPE namepos)
256
{
257
    GateElement *gate = (GateElement *)createElementWithTag(NED_GATE,gates);
258
    gate->setName( toString( namepos) );
259
    return gate;
260
}
261
262
YYLTYPE trimBrackets(YYLTYPE vectorpos)
263
{
264
    // should check it's really brackets that get chopped off
265
    vectorpos.first_column++;
266
    vectorpos.last_column--;
267
    return vectorpos;
268
}
269
270
YYLTYPE trimAngleBrackets(YYLTYPE vectorpos)
271
{
272
    // should check it's really angle brackets that get chopped off
273
    vectorpos.first_column++;
274
    vectorpos.last_column--;
275
    return vectorpos;
276
}
277
278
YYLTYPE trimQuotes(YYLTYPE vectorpos)
279
{
280
    // should check it's really quotes that get chopped off
281
    vectorpos.first_column++;
282
    vectorpos.last_column--;
283
    return vectorpos;
284
}
285
286
YYLTYPE trimDoubleBraces(YYLTYPE vectorpos)
287
{
288
    // should check it's really '{{' and '}}' that get chopped off
289
    vectorpos.first_column+=2;
290
    vectorpos.last_column-=2;
291
    return vectorpos;
292
}
293
294
void addVector(NEDElement *elem, const char *attrname, YYLTYPE exprpos, NEDElement *expr)
295
{
296
    addExpression(elem, attrname, trimBrackets(exprpos), expr);
297
}
298
299
void addLikeParam(NEDElement *elem, const char *attrname, YYLTYPE exprpos, NEDElement *expr)
300
{
301
    if (np->getParseExpressionsFlag() && !expr)
302
        elem->setAttribute(attrname, toString(trimAngleBrackets(exprpos)));
303
    else
304
        addExpression(elem, attrname, trimAngleBrackets(exprpos), expr);
305
}
306
307
void addExpression(NEDElement *elem, const char *attrname, YYLTYPE exprpos, NEDElement *expr)
308
{
309
    if (np->getParseExpressionsFlag()) {
310
        ((ExpressionElement *)expr)->setTarget(attrname);
311
312
        // in the DTD, whilespaces and expressions are at front, insert there
313
        NEDElement *insertPos = elem->getFirstChild();
314
        while (insertPos && (insertPos->getTagCode()==NED_COMMENT || insertPos->getTagCode()==NED_EXPRESSION))
315
            insertPos = insertPos->getNextSibling();
316
        if (!insertPos)
317
            elem->appendChild(expr);
318
        else
319
            elem->insertChildBefore(insertPos, expr);
320
321
    } else {
322
        elem->setAttribute(attrname, toString(exprpos));
323
    }
324
}
325
326
void swapConnection(NEDElement *conn)
327
{
328
    swapAttributes(conn, "src-module", "dest-module");
329
    swapAttributes(conn, "src-module-index", "dest-module-index");
330
    swapAttributes(conn, "src-gate", "dest-gate");
331
    swapAttributes(conn, "src-gate-index", "dest-gate-index");
332
    swapAttributes(conn, "src-gate-plusplus", "dest-gate-plusplus");
333
    swapAttributes(conn, "src-gate-subg", "dest-gate-subg");
334
335
    swapExpressionChildren(conn, "src-module-index", "dest-module-index");
336
    swapExpressionChildren(conn, "src-gate-index", "dest-gate-index");
337
}
338
339
void swapAttributes(NEDElement *node, const char *attr1, const char *attr2)
340
{
341
    std::string oldv1(node->getAttribute(attr1));
342
    node->setAttribute(attr1,node->getAttribute(attr2));
343
    node->setAttribute(attr2,oldv1.c_str());
344
}
345
346
void swapExpressionChildren(NEDElement *node, const char *attr1, const char *attr2)
347
{
348
    ExpressionElement *expr1, *expr2;
349
    for (expr1=(ExpressionElement *)node->getFirstChildWithTag(NED_EXPRESSION); expr1; expr1=expr1->getNextExpressionSibling())
350
        if (!strcmp(expr1->getTarget(),attr1))
351
            break;
352
    for (expr2=(ExpressionElement *)node->getFirstChildWithTag(NED_EXPRESSION); expr2; expr2=expr2->getNextExpressionSibling())
353
        if (!strcmp(expr2->getTarget(),attr2))
354
            break;
355
356
    if (expr1) expr1->setTarget(attr2);
357
    if (expr2) expr2->setTarget(attr1);
358
}
359
360
void transferChildren(NEDElement *from, NEDElement *to)
361
{
362
    while (from->getFirstChild())
363
        to->appendChild(from->removeChild(from->getFirstChild()));
364
}
365
366
OperatorElement *createOperator(const char *op, NEDElement *operand1, NEDElement *operand2, NEDElement *operand3)
367
{
368
    OperatorElement *opnode = (OperatorElement *)createElementWithTag(NED_OPERATOR);
369
    opnode->setName(op);
370
    opnode->appendChild(operand1);
371
    if (operand2) opnode->appendChild(operand2);
372
    if (operand3) opnode->appendChild(operand3);
373
    return opnode;
374
}
375
376
FunctionElement *createFunction(const char *funcname, NEDElement *arg1, NEDElement *arg2, NEDElement *arg3, NEDElement *arg4, NEDElement *arg5, NEDElement *arg6, NEDElement *arg7, NEDElement *arg8, NEDElement *arg9, NEDElement *arg10)
377
{
378
    FunctionElement *funcnode = (FunctionElement *)createElementWithTag(NED_FUNCTION);
379
    funcnode->setName(funcname);
380
    if (arg1) funcnode->appendChild(arg1);
381
    if (arg2) funcnode->appendChild(arg2);
382
    if (arg3) funcnode->appendChild(arg3);
383
    if (arg4) funcnode->appendChild(arg4);
384
    if (arg5) funcnode->appendChild(arg5);
385
    if (arg6) funcnode->appendChild(arg6);
386
    if (arg7) funcnode->appendChild(arg7);
387
    if (arg8) funcnode->appendChild(arg8);
388
    if (arg9) funcnode->appendChild(arg9);
389
    if (arg10) funcnode->appendChild(arg10);
390
    return funcnode;
391
}
392
393
ExpressionElement *createExpression(NEDElement *expr)
394
{
395
    ExpressionElement *expression = (ExpressionElement *)createElementWithTag(NED_EXPRESSION);
396
    expression->appendChild(expr);
397
    return expression;
398
}
399
400
IdentElement *createIdent(YYLTYPE parampos)
401
{
402
    IdentElement *ident = (IdentElement *)createElementWithTag(NED_IDENT);
403
    ident->setName(toString(parampos));
404
    return ident;
405
}
406
407
IdentElement *createIdent(YYLTYPE parampos, YYLTYPE modulepos, NEDElement *moduleindexoperand)
408
{
409
    IdentElement *ident = (IdentElement *)createElementWithTag(NED_IDENT);
410
    ident->setName(toString(parampos));
411
    ident->setModule(toString(modulepos));
412
    if (moduleindexoperand)
413
        ident->appendChild(moduleindexoperand);
414
    return ident;
415
}
416
417
LiteralElement *createLiteral(int type, YYLTYPE valuepos, YYLTYPE textpos)
418
{
419
    LiteralElement *c = (LiteralElement *)createElementWithTag(NED_LITERAL);
420
    c->setType(type);
421
    c->setValue(toString(valuepos));
422
    c->setText(toString(textpos));
423
    return c;
424
}
425
426
LiteralElement *createLiteral(int type, const char *value, const char *text)
427
{
428
    LiteralElement *c = (LiteralElement *)createElementWithTag(NED_LITERAL);
429
    c->setType(type);
430
    c->setValue(value);
431
    c->setText(text);
432
    return c;
433
}
434
435
LiteralElement *createStringLiteral(YYLTYPE textpos)
436
{
437
    LiteralElement *c = (LiteralElement *)createElementWithTag(NED_LITERAL);
438
    c->setType(NED_CONST_STRING);
439
440
    const char *text = toString(textpos);
441
    c->setText(text);
442
443
    try {
444
        std::string value = opp_parsequotedstr(text);
445
        c->setValue(value.c_str());
446
    }
447
    catch (std::exception& e) {
448
        np->error(e.what(), pos.li);
449
    }
450
    return c;
451
}
452
453
LiteralElement *createQuantityLiteral(YYLTYPE textpos)
454
{
455
    LiteralElement *c = (LiteralElement *)createElementWithTag(NED_LITERAL);
456
    c->setType(NED_CONST_DOUBLE);
457
458
    const char *text = toString(textpos);
459
    c->setText(text);
460
461
    double d = 0;
462
    std::string unit;
463
464
    try {
465
        // evaluate quantities like "5s 230ms"
466
        d = UnitConversion::parseQuantity(text, unit);
467
    }
468
    catch (std::exception& e) {
469
        np->error(e.what(), pos.li);
470
    }
471
472
    // convert value back to string
473
    char buf[32];
474
    sprintf(buf,"%g",d);
475
    c->setValue(buf);
476
477
    if (!unit.empty())
478
        c->setUnit(unit.c_str());
479
    return c;
480
}
481
482
NEDElement *unaryMinus(NEDElement *node)
483
{
484
    // if not a constant, must apply unary minus operator
485
    if (node->getTagCode()!=NED_LITERAL)
486
        return createOperator("-", node);
487
488
    LiteralElement *constNode = (LiteralElement *)node;
489
490
    // only int and real constants can be negative, string, bool, etc cannot
491
    if (constNode->getType()!=NED_CONST_INT && constNode->getType()!=NED_CONST_DOUBLE)
492
    {
493
       char msg[140];
494
       sprintf(msg,"unary minus not accepted before '%.100s'",constNode->getValue());
495
       np->error(msg, pos.li);
496
       return node;
497
    }
498
499
    // prepend the constant with a '-'
500
    char *buf = new char[strlen(constNode->getValue())+2];
501
    buf[0] = '-';
502
    strcpy(buf+1, constNode->getValue());
503
    constNode->setValue(buf);
504
    constNode->setText(buf); // for int and double literals, text and value are the same string
505
    delete [] buf;
506
507
    return node;
508
}
509
510
NAMESPACE_END
511