Statistics
| Branch: | Revision:

root / src / nedxml / msg2.y @ 68da4f12

History | View | Annotate | Download (21.9 KB)

1
/*===============================================================
2
 * File: msg2.y
3
 *
4
 *  Grammar for OMNeT++ MSG-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
%token NAMESPACE CPLUSPLUS CPLUSPLUSBODY
18
%token MESSAGE PACKET CLASS STRUCT ENUM NONCOBJECT
19
%token EXTENDS FIELDS PROPERTIES ABSTRACT READONLY
20

    
21
%token NAME DOUBLECOLON
22
%token INTCONSTANT REALCONSTANT STRINGCONSTANT CHARCONSTANT
23
%token TRUE_ FALSE_
24
%token BOOLTYPE CHARTYPE SHORTTYPE INTTYPE LONGTYPE DOUBLETYPE UNSIGNED_ STRINGTYPE
25

    
26
%token EQ NE GE LE
27
%token AND OR XOR NOT
28
%token BIN_AND BIN_OR BIN_XOR BIN_COMPL
29
%token SHIFT_LEFT SHIFT_RIGHT
30

    
31
%token INVALID_CHAR   /* just to generate parse error --VA */
32

    
33
/* Operator precedences (low to high) and associativity */
34
%left '?' ':'
35
%left AND OR XOR
36
%left EQ NE '>' GE '<' LE
37
%left BIN_AND BIN_OR BIN_XOR
38
%left SHIFT_LEFT SHIFT_RIGHT
39
%left '+' '-'
40
%left '*' '/' '%'
41
%right '^'
42
%left UMIN NOT BIN_COMPL
43

    
44
%start msgfile
45

    
46
/* requires at least bison 1.50 (tested with bison 2.1); otherwise won't parse "class B extends A;" syntax */
47
%glr-parser
48

    
49
%{
50

    
51
#include <stdio.h>
52
#include <stdlib.h>
53
#include "nedyydefs.h"
54
#include "nederror.h"
55
#include "nedexception.h"
56
#include "commonutil.h"
57

    
58
#define YYDEBUG 1           /* allow debugging */
59
#define YYDEBUGGING_ON 0    /* turn on/off debugging */
60

    
61
#if YYDEBUG != 0
62
#define YYERROR_VERBOSE     /* more detailed error messages */
63
#include <string.h>         /* YYVERBOSE needs it */
64
#endif
65

    
66
#define yylloc msg2yylloc
67
#define yyin msg2yyin
68
#define yyout msg2yyout
69
#define yyrestart msg2yyrestart
70
#define yy_scan_string msg2yy_scan_string
71
#define yy_delete_buffer msg2yy_delete_buffer
72
extern FILE *yyin;
73
extern FILE *yyout;
74
struct yy_buffer_state;
75
struct yy_buffer_state *yy_scan_string(const char *str);
76
void yy_delete_buffer(struct yy_buffer_state *);
77
void yyrestart(FILE *);
78
int yylex();
79
void yyerror (const char *s);
80

    
81
#include "nedparser.h"
82
#include "nedfilebuffer.h"
83
#include "nedelements.h"
84
#include "nedutil.h"
85
#include "nedyylib.h"
86

    
87
USING_NAMESPACE
88

    
89
static struct MSG2ParserState
90
{
91
    /* tmp flags, used with msg fields */
92
    bool isAbstract;
93
    bool isReadonly;
94

    
95
    std::vector<NEDElement *> propvals; // temporarily collects property values
96

    
97
    /* MSG-II: message subclassing */
98
    MsgFileElement *msgfile;
99
    NamespaceElement *namespacedecl;
100
    CplusplusElement *cplusplus;
101
    StructDeclElement *structdecl;
102
    ClassDeclElement *classdecl;
103
    MessageDeclElement *messagedecl;
104
    PacketDeclElement *packetdecl;
105
    EnumDeclElement *enumdecl;
106
    EnumElement *enump;
107
    MessageElement *messagep;
108
    PacketElement *packetp;
109
    ClassElement *classp;
110
    StructElement *structp;
111
    NEDElement *msgclassorstruct;
112
    EnumFieldsElement *enumfields;
113
    EnumFieldElement *enumfield;
114
    FieldElement *field;
115
    PropertyElement *property;
116
    PropertyKeyElement *propkey;
117
} ps;
118

    
119
static void resetParserState()
120
{
121
    static MSG2ParserState cleanps;
122
    ps = cleanps;
123
}
124

    
125
%}
126

    
127
%%
128

    
129
/*
130
 * Top-level components
131
 */
132
msgfile
133
        : definitions
134
        ;
135

    
136
definitions
137
        : definitions definition
138
        |
139
        ;
140

    
141
definition
142
        : namespace_decl
143
        | cplusplus
144
        | struct_decl
145
        | class_decl
146
        | message_decl
147
        | packet_decl
148
        | enum_decl
149

    
150
        | enum
151
                { if (np->getStoreSourceFlag()) ps.enump->setSourceCode(toString(@1)); }
152
        | message
153
                { if (np->getStoreSourceFlag()) ps.messagep->setSourceCode(toString(@1)); }
154
        | packet
155
                { if (np->getStoreSourceFlag()) ps.packetp->setSourceCode(toString(@1)); }
156
        | class
157
                { if (np->getStoreSourceFlag()) ps.classp->setSourceCode(toString(@1)); }
158
        | struct
159
                { if (np->getStoreSourceFlag()) ps.structp->setSourceCode(toString(@1)); }
160
        ;
161

    
162
/*
163
 * namespace declaration
164
 */
165
namespace_decl
166
        : NAMESPACE qname0 ';'
167
                {
168
                  ps.namespacedecl = (NamespaceElement *)createElementWithTag(NED_NAMESPACE, ps.msgfile );
169
                  ps.namespacedecl->setName(toString(@2));
170
                  storeBannerAndRightComments(ps.namespacedecl,@1,@2);
171
                }
172

    
173
qname0
174
        : qname0 DOUBLECOLON NAME
175
        | NAME
176
        ;
177

    
178
qname
179
        : DOUBLECOLON qname0
180
        | qname0
181
        ;
182

    
183
/*
184
 * C++ block
185
 */
186
cplusplus
187
        : CPLUSPLUS CPLUSPLUSBODY opt_semicolon
188
                {
189
                  ps.cplusplus = (CplusplusElement *)createElementWithTag(NED_CPLUSPLUS, ps.msgfile );
190
                  ps.cplusplus->setBody(toString(trimDoubleBraces(@2)));
191
                  storeBannerAndRightComments(ps.cplusplus,@1,@2);
192
                }
193
        ;
194

    
195
/*
196
 * Forward declarations
197
 */
198
struct_decl
199
        : STRUCT qname ';'
200
                {
201
                  ps.structdecl = (StructDeclElement *)createElementWithTag(NED_STRUCT_DECL, ps.msgfile );
202
                  ps.structdecl->setName(toString(@2));
203
                  storeBannerAndRightComments(ps.structdecl,@1,@2);
204
                }
205
        ;
206

    
207
class_decl
208
        : CLASS qname ';'
209
                {
210
                  ps.classdecl = (ClassDeclElement *)createElementWithTag(NED_CLASS_DECL, ps.msgfile );
211
                  ps.classdecl->setName(toString(@2));
212
                  ps.classdecl->setIsCobject(true);
213
                  storeBannerAndRightComments(ps.classdecl,@1,@2);
214
                }
215
        | CLASS NONCOBJECT qname ';'
216
                {
217
                  ps.classdecl = (ClassDeclElement *)createElementWithTag(NED_CLASS_DECL, ps.msgfile );
218
                  ps.classdecl->setIsCobject(false);
219
                  ps.classdecl->setName(toString(@3));
220
                  storeBannerAndRightComments(ps.classdecl,@1,@3);
221
                }
222
        | CLASS qname EXTENDS qname ';'
223
                {
224
                  ps.classdecl = (ClassDeclElement *)createElementWithTag(NED_CLASS_DECL, ps.msgfile );
225
                  ps.classdecl->setIsCobject(true);
226
                  ps.classdecl->setName(toString(@2));
227
                  ps.classdecl->setExtendsName(toString(@4));
228
                  storeBannerAndRightComments(ps.classdecl,@1,@4);
229
                }
230
        ;
231

    
232
message_decl
233
        : MESSAGE qname ';'
234
                {
235
                  ps.messagedecl = (MessageDeclElement *)createElementWithTag(NED_MESSAGE_DECL, ps.msgfile );
236
                  ps.messagedecl->setName(toString(@2));
237
                  storeBannerAndRightComments(ps.messagedecl,@1,@2);
238
                }
239
        ;
240

    
241
packet_decl
242
        : PACKET qname ';'
243
                {
244
                  ps.packetdecl = (PacketDeclElement *)createElementWithTag(NED_PACKET_DECL, ps.msgfile );
245
                  ps.packetdecl->setName(toString(@2));
246
                  storeBannerAndRightComments(ps.packetdecl,@1,@2);
247
                }
248
        ;
249

    
250
enum_decl
251
        : ENUM qname ';'
252
                {
253
                  ps.enumdecl = (EnumDeclElement *)createElementWithTag(NED_ENUM_DECL, ps.msgfile );
254
                  ps.enumdecl->setName(toString(@2));
255
                  storeBannerAndRightComments(ps.enumdecl,@1,@2);
256
                }
257
        ;
258

    
259
/*
260
 * Enum definition
261
 */
262
enum
263
        : ENUM NAME '{'
264
                {
265
                  ps.enump = (EnumElement *)createElementWithTag(NED_ENUM, ps.msgfile );
266
                  ps.enump->setName(toString(@2));
267
                  storeBannerAndRightComments(ps.enump,@1,@2);
268
                  ps.enumfields = (EnumFieldsElement *)createElementWithTag(NED_ENUM_FIELDS, ps.enump);
269
                }
270
          opt_enumfields '}' opt_semicolon
271
                { storeTrailingComment(ps.enump,@$); }
272
        ;
273

    
274
opt_enumfields
275
        : enumfields
276
        |
277
        ;
278

    
279
enumfields
280
        : enumfields enumfield
281
        | enumfield
282
        ;
283

    
284
enumfield
285
        : NAME ';'
286
                {
287
                  ps.enumfield = (EnumFieldElement *)createElementWithTag(NED_ENUM_FIELD, ps.enumfields);
288
                  ps.enumfield->setName(toString(@1));
289
                  storeBannerAndRightComments(ps.enumfield,@1,@1);
290
                }
291
        | NAME '=' enumvalue ';'
292
                {
293
                  ps.enumfield = (EnumFieldElement *)createElementWithTag(NED_ENUM_FIELD, ps.enumfields);
294
                  ps.enumfield->setName(toString(@1));
295
                  ps.enumfield->setValue(toString(@3));
296
                  storeBannerAndRightComments(ps.enumfield,@1,@3);
297
                }
298
        ;
299

    
300
/*
301
 * Message, class and struct definitions
302
 */
303
message
304
        : message_header body
305
                { storeTrailingComment(ps.messagep,@$); }
306
        ;
307

    
308
packet
309
        : packet_header body
310
                { storeTrailingComment(ps.packetp,@$); }
311
        ;
312

    
313
class
314
        : class_header body
315
                { storeTrailingComment(ps.classp,@$); }
316
        ;
317

    
318
struct
319
        : struct_header body
320
                { storeTrailingComment(ps.structp,@$); }
321
        ;
322

    
323
message_header
324
        : MESSAGE NAME '{'
325
                {
326
                  ps.msgclassorstruct = ps.messagep = (MessageElement *)createElementWithTag(NED_MESSAGE, ps.msgfile );
327
                  ps.messagep->setName(toString(@2));
328
                  storeBannerAndRightComments(ps.messagep,@1,@2);
329
                }
330
        | MESSAGE NAME EXTENDS qname '{'
331
                {
332
                  ps.msgclassorstruct = ps.messagep = (MessageElement *)createElementWithTag(NED_MESSAGE, ps.msgfile );
333
                  ps.messagep->setName(toString(@2));
334
                  ps.messagep->setExtendsName(toString(@4));
335
                  storeBannerAndRightComments(ps.messagep,@1,@4);
336
                }
337
        ;
338

    
339
packet_header
340
        : PACKET NAME '{'
341
                {
342
                  ps.msgclassorstruct = ps.packetp = (PacketElement *)createElementWithTag(NED_PACKET, ps.msgfile );
343
                  ps.packetp->setName(toString(@2));
344
                  storeBannerAndRightComments(ps.packetp,@1,@2);
345
                }
346
        | PACKET NAME EXTENDS qname '{'
347
                {
348
                  ps.msgclassorstruct = ps.packetp = (PacketElement *)createElementWithTag(NED_PACKET, ps.msgfile );
349
                  ps.packetp->setName(toString(@2));
350
                  ps.packetp->setExtendsName(toString(@4));
351
                  storeBannerAndRightComments(ps.packetp,@1,@4);
352
                }
353
        ;
354

    
355
class_header
356
        : CLASS NAME '{'
357
                {
358
                  ps.msgclassorstruct = ps.classp = (ClassElement *)createElementWithTag(NED_CLASS, ps.msgfile );
359
                  ps.classp->setName(toString(@2));
360
                  storeBannerAndRightComments(ps.classp,@1,@2);
361
                }
362
        | CLASS NAME EXTENDS qname '{'
363
                {
364
                  ps.msgclassorstruct = ps.classp = (ClassElement *)createElementWithTag(NED_CLASS, ps.msgfile );
365
                  ps.classp->setName(toString(@2));
366
                  ps.classp->setExtendsName(toString(@4));
367
                  storeBannerAndRightComments(ps.classp,@1,@4);
368
                }
369
        ;
370

    
371
struct_header
372
        : STRUCT NAME '{'
373
                {
374
                  ps.msgclassorstruct = ps.structp = (StructElement *)createElementWithTag(NED_STRUCT, ps.msgfile );
375
                  ps.structp->setName(toString(@2));
376
                  storeBannerAndRightComments(ps.structp,@1,@2);
377
                }
378
        | STRUCT NAME EXTENDS qname '{'
379
                {
380
                  ps.msgclassorstruct = ps.structp = (StructElement *)createElementWithTag(NED_STRUCT, ps.msgfile );
381
                  ps.structp->setName(toString(@2));
382
                  ps.structp->setExtendsName(toString(@4));
383
                  storeBannerAndRightComments(ps.structp,@1,@4);
384
                }
385
        ;
386

    
387
body
388
        : opt_fields_and_properties
389
          opt_propertiesblock_old
390
          opt_fieldsblock_old
391
          '}' opt_semicolon
392
        ;
393

    
394
opt_fields_and_properties
395
        : fields_and_properties
396
        |
397
        ;
398

    
399
fields_and_properties
400
        : fields_and_properties field
401
        | fields_and_properties property
402
        | field
403
        | property
404
        ;
405

    
406
/*
407
 * Field
408
 */
409
field
410
        :  fieldtypename opt_fieldvector opt_inline_properties ';'
411
                {
412
                  storeBannerAndRightComments(ps.field,@1,@4);
413
                  ps.field = NULL; // important! see addProperty() calls
414
                }
415
        |  fieldtypename opt_fieldvector opt_inline_properties '=' fieldvalue opt_inline_properties ';'
416
                {
417
                  ps.field->setDefaultValue(toString(@5));
418
                  storeBannerAndRightComments(ps.field,@1,@7);
419
                  ps.field = NULL; // important! see addProperty() calls
420
                }
421
        ;
422

    
423
fieldtypename
424
        : fieldmodifiers fielddatatype NAME
425
                {
426
                  ps.field = (FieldElement *)createElementWithTag(NED_FIELD, ps.msgclassorstruct);
427
                  ps.field->setName(toString(@3));
428
                  ps.field->setDataType(toString(@2));
429
                  ps.field->setIsAbstract(ps.isAbstract);
430
                  ps.field->setIsReadonly(ps.isReadonly);
431
                }
432
        | fieldmodifiers NAME
433
                {
434
                  ps.field = (FieldElement *)createElementWithTag(NED_FIELD, ps.msgclassorstruct);
435
                  ps.field->setName(toString(@2));
436
                  ps.field->setIsAbstract(ps.isAbstract);
437
                  ps.field->setIsReadonly(ps.isReadonly);
438
                }
439
        ;
440

    
441
fieldmodifiers
442
        : ABSTRACT
443
                { ps.isAbstract = true; ps.isReadonly = false; }
444
        | READONLY
445
                { ps.isAbstract = false; ps.isReadonly = true; }
446
        | ABSTRACT READONLY
447
                { ps.isAbstract = true; ps.isReadonly = true; }
448
        | READONLY ABSTRACT
449
                { ps.isAbstract = true; ps.isReadonly = true; }
450
        |
451
                { ps.isAbstract = false; ps.isReadonly = false; }
452
        ;
453

    
454
fielddatatype
455
        : qname
456
        | qname '*'
457

    
458
        | CHARTYPE
459
        | SHORTTYPE
460
        | INTTYPE
461
        | LONGTYPE
462

    
463
        | UNSIGNED_ CHARTYPE
464
        | UNSIGNED_ SHORTTYPE
465
        | UNSIGNED_ INTTYPE
466
        | UNSIGNED_ LONGTYPE
467

    
468
        | DOUBLETYPE
469
        | STRINGTYPE
470
        | BOOLTYPE
471
        ;
472

    
473

    
474
opt_fieldvector
475
        : '[' INTCONSTANT ']'
476
                {
477
                  ps.field->setIsVector(true);
478
                  ps.field->setVectorSize(toString(@2));
479
                }
480
        | '[' qname ']'
481
                {
482
                  ps.field->setIsVector(true);
483
                  ps.field->setVectorSize(toString(@2));
484
                }
485
        | '[' ']'
486
                {
487
                  ps.field->setIsVector(true);
488
                }
489
        |
490
        ;
491

    
492
fieldvalue   /* some arbitrary C++ expression - validation left to C++ compiler */
493
        : fieldvalue fieldvalueitem
494
        | fieldvalueitem
495
        ;
496

    
497
fieldvalueitem
498
        : STRINGCONSTANT
499
        | CHARCONSTANT
500
        | INTCONSTANT
501
        | REALCONSTANT
502
        | TRUE_
503
        | FALSE_
504
        | NAME
505
        | DOUBLECOLON
506
        | '?' | ':' | AND | OR | XOR | EQ | NE | '>' | GE | '<' | LE
507
        | BIN_AND | BIN_OR | BIN_XOR | SHIFT_LEFT | SHIFT_RIGHT
508
        | '+' | '-' | '*' | '/' | '%' | '^' | '&' | UMIN | NOT | BIN_COMPL
509
        | '.' | ',' | '(' | ')' | '[' | ']'
510
        ;
511

    
512
enumvalue
513
        : INTCONSTANT
514
        | '-' INTCONSTANT
515
        | NAME
516
        ;
517

    
518
opt_inline_properties
519
        : inline_properties
520
        |
521
        ;
522

    
523
inline_properties
524
        : inline_properties property_namevalue
525
        | property_namevalue
526
        ;
527

    
528
/*
529
 * Property (code nearly same as in ned2.y)
530
 */
531
property
532
        : property_namevalue ';'
533
                {
534
                  storePos(ps.property, @$);
535
                  storeBannerAndRightComments(ps.property,@$);
536
                }
537
        ;
538

    
539
property_namevalue
540
        : property_name
541
        | property_name '(' opt_property_keys ')'
542
        ;
543

    
544
property_name
545
        : '@' property_name_token
546
                {
547
                  NEDElement *propertyscope = ps.field ? ps.field : ps.msgclassorstruct;
548
                  ps.property = addProperty(propertyscope, toString(@2));
549
                  ps.propvals.clear(); // just to be safe
550
                }
551
        | '@' property_name_token '[' NAME ']'
552
                {
553
                  NEDElement *propertyscope = ps.field ? ps.field : ps.msgclassorstruct;
554
                  ps.property = addProperty(propertyscope, toString(@2));
555
                  ps.property->setIndex(toString(@4));
556
                  ps.propvals.clear(); // just to be safe
557
                }
558
        | ENUM /* legacy syntax */
559
                {
560
                  NEDElement *propertyscope = ps.field ? ps.field : ps.msgclassorstruct;
561
                  ps.property = addProperty(propertyscope, toString(@1));
562
                  ps.propvals.clear(); // just to be safe
563
                }
564
        ;
565

    
566
property_name_token
567
        : NAME
568
        | ENUM  /* unfortunately we have to allow this as property name */
569
        ;
570

    
571
opt_property_keys
572
        : property_keys  /* can't allow epsilon rule here, because @foo() would result in "ambiguous syntax" :( */
573
        ;
574

    
575
property_keys
576
        : property_keys ';' property_key
577
        | property_key
578
        ;
579

    
580
property_key
581
        : NAME '=' property_values
582
                {
583
                  ps.propkey = (PropertyKeyElement *)createElementWithTag(NED_PROPERTY_KEY, ps.property);
584
                  ps.propkey->setName(toString(@1));
585
                  for (int i=0; i<(int)ps.propvals.size(); i++)
586
                      ps.propkey->appendChild(ps.propvals[i]);
587
                  ps.propvals.clear();
588
                  storePos(ps.propkey, @$);
589
                }
590
        | property_values
591
                {
592
                  ps.propkey = (PropertyKeyElement *)createElementWithTag(NED_PROPERTY_KEY, ps.property);
593
                  ps.propkey->appendChild($1);
594
                  for (int i=0; i<(int)ps.propvals.size(); i++)
595
                      ps.propkey->appendChild(ps.propvals[i]);
596
                  ps.propvals.clear();
597
                  storePos(ps.propkey, @$);
598
                }
599
        ;
600

    
601
property_values
602
        : property_values ',' property_value
603
                { ps.propvals.push_back($3); }
604
        | property_value
605
                { ps.propvals.push_back($1); }
606
        ;
607

    
608
property_value
609
        : property_value_tokens
610
                { $$ = createLiteral(NED_CONST_SPEC, @$, @$); }
611
        | STRINGCONSTANT
612
                { $$ = createStringLiteral(@1); }
613
        |  /*empty*/
614
                {
615
                  LiteralElement *node = (LiteralElement *)createElementWithTag(NED_LITERAL);
616
                  node->setType(NED_CONST_SPEC); // and leave both value and text at ""
617
                  $$ = node;
618
                }
619
        ;
620

    
621
property_value_tokens
622
        : property_value_tokens property_value_token
623
        | property_value_token
624
        ;
625

    
626
property_value_token
627
        : NAME | INTCONSTANT | REALCONSTANT | CHARCONSTANT | TRUE_ | FALSE_
628
        | '$' | '@' | ':' | '=' | '[' | ']' | '{' | '}' | '.' | '?'
629
        | '^' | '+' | '-' | '*' | '/' | '%' | '<' | '>' | EQ | NE | LE | GE
630
        | DOUBLECOLON | OR | AND | XOR | NOT
631
        | BIN_AND | BIN_OR | BIN_XOR BIN_COMPL | SHIFT_LEFT | SHIFT_RIGHT
632
        | MESSAGE | PACKET | CLASS | STRUCT | ENUM | NONCOBJECT
633
        | BOOLTYPE | CHARTYPE | SHORTTYPE | INTTYPE | LONGTYPE | DOUBLETYPE | UNSIGNED_ | STRINGTYPE
634
        ;
635

    
636
/*
637
 * Old-style fields block
638
 */
639
opt_fieldsblock_old
640
        : FIELDS ':'
641
          opt_fields_old
642
                { ps.msgfile->setVersion("1"); }
643
        |
644
        ;
645

    
646
opt_fields_old
647
        : fields_old
648
        |
649
        ;
650

    
651
fields_old
652
        : fields_old field
653
        | field
654
        ;
655

    
656
/*
657
 * Old-style properties block
658
 */
659
opt_propertiesblock_old
660
        : PROPERTIES ':'
661
          opt_properties_old
662
                { ps.msgfile->setVersion("1"); }
663
        |
664
        ;
665

    
666
opt_properties_old
667
        : properties_old
668
        |
669
        ;
670

    
671
properties_old
672
        : properties_old property_old
673
        | property_old
674
        ;
675

    
676
property_old
677
        : NAME '=' property_value ';'
678
                {
679
                  ps.property = addProperty(ps.msgclassorstruct, toString(@1));
680
                  ps.propkey = (PropertyKeyElement *)createElementWithTag(NED_PROPERTY_KEY, ps.property);
681
                  ps.propkey->appendChild($3);
682
                  storePos(ps.propkey, @2);
683
                  storePos(ps.property, @$);
684
                  storeBannerAndRightComments(ps.property,@$);
685
                }
686
        ;
687

    
688
opt_semicolon : ';' | ;
689

    
690
%%
691

    
692
//----------------------------------------------------------------------
693
// general bison/flex stuff:
694
//
695

    
696
NEDElement *doParseMSG2(NEDParser *p, const char *nedtext)
697
{
698
#if YYDEBUG != 0      /* #if added --VA */
699
    yydebug = YYDEBUGGING_ON;
700
#endif
701

    
702
    NONREENTRANT_NED_PARSER(p);
703

    
704
    // reset the lexer
705
    pos.co = 0;
706
    pos.li = 1;
707
    prevpos = pos;
708

    
709
    yyin = NULL;
710
    yyout = stderr; // not used anyway
711

    
712
    // alloc buffer
713
    struct yy_buffer_state *handle = yy_scan_string(nedtext);
714
    if (!handle)
715
        {np->getErrors()->addError("", "unable to allocate work memory"); return false;}
716

    
717
    // create parser state and NEDFileElement
718
    resetParserState();
719
    ps.msgfile = new MsgFileElement();
720

    
721
    // store file name with slashes always, even on Windows -- neddoc relies on that
722
    ps.msgfile->setFilename(slashifyFilename(np->getFileName()).c_str());
723

    
724
    // store file comment
725
    storeFileComment(ps.msgfile);
726

    
727
    if (np->getStoreSourceFlag())
728
        storeSourceCode(ps.msgfile, np->getSource()->getFullTextPos());
729

    
730
    // parse
731
    int ret;
732
    try
733
    {
734
        ret = yyparse();
735
    }
736
    catch (NEDException& e)
737
    {
738
        yyerror((std::string("error during parsing: ")+e.what()).c_str());
739
        yy_delete_buffer(handle);
740
        return 0;
741
    }
742

    
743
    yy_delete_buffer(handle);
744

    
745
    //FIXME TODO: fill in @documentation properties from comments
746
    return ps.msgfile;
747
}
748

    
749
void yyerror(const char *s)
750
{
751
    // chop newline
752
    char buf[250];
753
    strcpy(buf, s);
754
    if (buf[strlen(buf)-1] == '\n')
755
        buf[strlen(buf)-1] = '\0';
756

    
757
    np->error(buf, pos.li);
758
}
759