GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Parser.parse_structured_comment()   F
last analyzed

Complexity

Conditions 10

Size

Total Lines 35

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 10

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 10
c 1
b 0
f 0
dl 0
loc 35
ccs 23
cts 23
cp 1
crap 10
rs 3.1304

How to fix   Complexity   

Complexity

Complex classes like Parser.parse_structured_comment() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
"""
2
Franca parser.
3
"""
4
5 1
from collections import OrderedDict
6 1
from abc import ABCMeta
7 1
import ply.yacc as yacc
0 ignored issues
show
Configuration introduced by
The import ply.yacc could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
8 1
from pyfranca import franca_lexer
9 1
from pyfranca import ast
10 1
import re
11
12
13 1
class ArgumentGroup(object):
14
15 1
    __metaclass__ = ABCMeta
16
17 1
    def __init__(self, arguments=None):
18 1
        self.arguments = arguments if arguments else OrderedDict()
19
20
21 1
class InArgumentGroup(ArgumentGroup):
22 1
    pass
23
24
25 1
class OutArgumentGroup(ArgumentGroup):
26 1
    pass
27
28
29 1
class ErrorArgumentGroup(ArgumentGroup):
30 1
    pass
31
32
33 1
class ParserException(Exception):
34
35 1
    def __init__(self, message):
36 1
        super(ParserException, self).__init__()
37 1
        self.message = message
38
39 1
    def __str__(self):
40 1
        return self.message
41
42
43 1
class Parser(object):
44
    """
45
    Franca IDL PLY parser.
46
    """
47
48 1
    @staticmethod
49
    def _package_def(members):
50 1
        imports = []
51 1
        interfaces = OrderedDict()
52 1
        typecollections = OrderedDict()
53 1
        if members:
54 1
            for member in members:
55 1
                if isinstance(member, ast.Import):
56 1
                    imports.append(member)
57 1
                elif isinstance(member, ast.Interface):
58 1
                    interfaces[member.name] = member
59 1
                elif isinstance(member, ast.TypeCollection):
60 1
                    typecollections[member.name] = member
61
                else:
62
                    raise ParserException("Unexpected package member type.")
63 1
        return imports, interfaces, typecollections
64
65 1
    @staticmethod
66
    def parse_structured_comment(comment):
67
        """
68
        Parse a structured comment.
69
70
        :param comment: Structured comment of an Franca-IDL symbol to parse.
71
        :return: OrderedDict of all comments. Key is Franca-IDL keyword, e.g. @description, value conatins the text.
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (116/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
72
        """
73 1
        keys = ['@description', '@author', '@deprecated', '@source_uri', '@source_alias', '@see', '@experimental']
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (114/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
74
75 1
        strings = re.split('(' + '|'.join(keys) + ')', comment)
76
77
        # remove optional spaces, ':' and finally empty strings
78 1
        strings = [item.strip() for item in strings]
79 1
        strings = [item.lstrip(':') for item in strings]
80 1
        strings = [item.strip() for item in strings]
81 1
        for item in strings:
82 1
            if item == "":
83 1
                strings.remove(item)
84
85 1
        comments = OrderedDict()
86 1
        length = len(strings)
87 1
        i = 0
88 1
        while i < length:
89 1
            key = strings[i]
90 1
            if key in keys:
91 1
                comments[key] = ""
92
93 1
                if i < (length - 1):
94 1
                    item = strings[i + 1]
95 1
                    if item not in keys:
96 1
                        comments[key] = item
97 1
                        i += 1
98 1
            i += 1
99 1
        return comments
100
101
    # noinspection PyIncorrectDocstring
102 1
    @staticmethod
103
    def p_package_def(p):
104
        """
105
        package_def : structured_comment PACKAGE fqn defs
106
        """
107 1
        imports, interfaces, typecollections = Parser._package_def(p[4])
108 1
        p[0] = ast.Package(name=p[3], file_name=None, imports=imports,
109
                           interfaces=interfaces,
110
                           typecollections=typecollections,
111
                           comments=p[1])
112
113
    # noinspection PyIncorrectDocstring
114 1
    @staticmethod
115
    def p_structured_comment_1(p):
116
        """
117
        structured_comment : STRUCTURED_COMMENT
118
        """
119 1
        p[0] = Parser.parse_structured_comment(p[1])
120
121
    # noinspection PyIncorrectDocstring
122 1
    @staticmethod
123
    def p_structured_comment_2(p):
124
        """
125
        structured_comment : empty
126
        """
127 1
        p[0] = None
128
129
    # noinspection PyIncorrectDocstring
130 1
    @staticmethod
131
    def p_defs_1(p):
132
        """
133
        defs : defs def
134
        """
135 1
        p[0] = p[1]
136 1
        p[0].append(p[2])
137
138
    # noinspection PyIncorrectDocstring
139 1
    @staticmethod
140
    def p_defs_2(p):
141
        """
142
        defs : def
143
        """
144 1
        p[0] = [p[1]]
145
146
    # noinspection PyIncorrectDocstring
147 1
    @staticmethod
148
    def p_defs_3(p):
149
        """
150
        defs : empty
151
        """
152
153
    # noinspection PyIncorrectDocstring
154 1
    @staticmethod
155
    def p_fqn_1(p):
156
        """
157
        fqn : ID '.' fqn
158
        """
159 1
        p[0] = "{}.{}".format(p[1], p[3])
160
161
    # noinspection PyIncorrectDocstring
162 1
    @staticmethod
163
    def p_fqn_2(p):
164
        """
165
        fqn : ID
166
        """
167 1
        p[0] = p[1]
168
169
    # noinspection PyIncorrectDocstring
170 1
    @staticmethod
171
    def p_fqn_3(p):
172
        """
173
        fqn : '*'
174
        """
175 1
        p[0] = p[1]
176
177
    # noinspection PyIncorrectDocstring
178 1
    @staticmethod
179
    def p_import_def_1(p):
180
        """
181
        def : IMPORT fqn FROM STRING_VAL
182
        """
183 1
        p[0] = ast.Import(file_name=p[4], namespace=p[2])
184
185
    # noinspection PyIncorrectDocstring
186 1
    @staticmethod
187
    def p_import_def_2(p):
188
        """
189
        def : IMPORT MODEL STRING_VAL
190
        """
191 1
        p[0] = ast.Import(file_name=p[3])
192
193
    # noinspection PyIncorrectDocstring
194 1
    @staticmethod
195
    def p_typecollection(p):
196
        """
197
        def : structured_comment TYPECOLLECTION ID '{' typecollection_members '}'
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (81/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
198
        """
199 1
        try:
200 1
            p[0] = ast.TypeCollection(name=p[3], flags=None, members=p[5], comments=p[1])
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (89/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
201 1
        except ast.ASTException as e:
202 1
            raise ParserException(e.message)
203
204
    # noinspection PyIncorrectDocstring
205 1
    @staticmethod
206
    def p_typecollection_members_1(p):
207
        """
208
        typecollection_members : typecollection_members typecollection_member
209
        """
210 1
        p[0] = p[1]
211 1
        p[0].append(p[2])
212
213
    # noinspection PyIncorrectDocstring
214 1
    @staticmethod
215
    def p_typecollection_members_2(p):
216
        """
217
        typecollection_members : typecollection_member
218
        """
219 1
        p[0] = [p[1]]
220
221
    # noinspection PyUnusedLocal, PyIncorrectDocstring
222 1
    @staticmethod
223
    def p_typecollection_members_3(p):
224
        """
225
        typecollection_members : empty
226
        """
227 1
        pass
228
229
    # noinspection PyIncorrectDocstring
230 1
    @staticmethod
231
    def p_typecollection_member(p):
232
        """
233
        typecollection_member : version_def
234
                              | type_def
235
                              | enumeration_def
236
                              | struct_def
237
                              | array_def
238
                              | map_def
239
                              | constant_def
240
        """
241 1
        p[0] = p[1]
242
243
    # noinspection PyIncorrectDocstring
244 1
    @staticmethod
245
    def p_version_def(p):
246
        """
247
        version_def : VERSION '{' MAJOR INTEGER_VAL MINOR INTEGER_VAL '}'
248
        """
249 1
        p[0] = ast.Version(major=p[4], minor=p[6])
250
251
    # noinspection PyIncorrectDocstring
252 1
    @staticmethod
253
    def p_type_def(p):
254
        """
255
        type_def : structured_comment TYPEDEF ID IS type
256
        """
257 1
        p[0] = ast.Typedef(name=p[3], base_type=p[5], comments=p[1])
258
259
    # noinspection PyIncorrectDocstring
260 1
    @staticmethod
261
    def p_interface_1(p):
262
        """
263
        def : structured_comment INTERFACE ID '{' interface_members '}'
264
        """
265 1
        try:
266 1
            p[0] = ast.Interface(name=p[3], flags=None, members=p[5],
267
                                 extends=None, comments=p[1])
268 1
        except ast.ASTException as e:
269 1
            raise ParserException(e.message)
270
271
    # noinspection PyIncorrectDocstring
272 1
    @staticmethod
273
    def p_interface_2(p):
274
        """
275
        def : structured_comment INTERFACE ID EXTENDS fqn '{' interface_members '}'
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (83/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
276
        """
277 1
        try:
278 1
            p[0] = ast.Interface(name=p[3], flags=None, members=p[7],
279
                                 extends=p[5], comments=p[1])
280
        except ast.ASTException as e:
281
            raise ParserException(e.message)
282
283
    # noinspection PyIncorrectDocstring
284 1
    @staticmethod
285
    def p_interface_members_1(p):
286
        """
287
        interface_members : interface_members interface_member
288
        """
289 1
        p[0] = p[1]
290 1
        p[0].append(p[2])
291
292
    # noinspection PyIncorrectDocstring
293 1
    @staticmethod
294
    def p_interface_members_2(p):
295
        """
296
        interface_members : interface_member
297
        """
298 1
        p[0] = [p[1]]
299
300
    # noinspection PyUnusedLocal, PyIncorrectDocstring
301 1
    @staticmethod
302
    def p_interface_members_3(p):
303
        """
304
        interface_members : empty
305
        """
306 1
        pass
307
308
    # noinspection PyIncorrectDocstring
309 1
    @staticmethod
310
    def p_interface_member(p):
311
        """
312
        interface_member : version_def
313
                         | attribute_def
314
                         | method_def
315
                         | broadcast_def
316
                         | type_def
317
                         | enumeration_def
318
                         | struct_def
319
                         | array_def
320
                         | map_def
321
                         | constant_def
322
        """
323 1
        p[0] = p[1]
324
325
    # noinspection PyIncorrectDocstring
326 1
    @staticmethod
327
    def p_attribute_def(p):
328
        """
329
        attribute_def : structured_comment ATTRIBUTE type ID flag_defs
330
        """
331 1
        p[0] = ast.Attribute(name=p[4], attr_type=p[3], flags=p[5], comments=p[1])
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (82/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
332
333 1
    @staticmethod
334
    def _method_def(arg_groups):
335 1
        in_args = None
336 1
        out_args = None
337 1
        errors = None
338 1
        if arg_groups:
339 1
            for arg_group in arg_groups:
340 1
                if isinstance(arg_group, InArgumentGroup):
341 1
                    if not in_args:
342 1
                        in_args = arg_group.arguments
343
                    else:
344
                        raise ParserException("Multiple in argument "
345
                                              "definitions for a method.")
346 1
                elif isinstance(arg_group, OutArgumentGroup):
347 1
                    if not out_args:
348 1
                        out_args = arg_group.arguments
349
                    else:
350
                        raise ParserException("Multiple out argument "
351
                                              "definitions for a method.")
352 1
                elif isinstance(arg_group, ErrorArgumentGroup):
353 1
                    if not errors:
354 1
                        errors = arg_group.arguments
355
                    else:
356
                        raise ParserException("Multiple error definitions "
357
                                              "for a method.")
358
                else:
359
                    raise ParserException("Unexpected method definition "
360
                                          "member.")
361 1
        return in_args, out_args, errors
362
363
    # noinspection PyIncorrectDocstring
364 1
    @staticmethod
365
    def p_method_def(p):
366
        """
367
        method_def : structured_comment METHOD ID flag_defs '{' arg_group_defs '}'
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (82/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
368
        """
369 1
        in_args, out_args, errors = Parser._method_def(p[6])
370 1
        p[0] = ast.Method(name=p[3], flags=p[4],
371
                          in_args=in_args, out_args=out_args, errors=errors, comments=p[1])
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (91/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
372
373
    # noinspection PyIncorrectDocstring
374 1
    @staticmethod
375
    def p_flag_defs_1(p):
376
        """
377
        flag_defs : flag_defs flag_def
378
        """
379 1
        p[0] = p[1]
380 1
        p[0].append(p[2])
381
382
    # noinspection PyIncorrectDocstring
383 1
    @staticmethod
384
    def p_flag_defs_2(p):
385
        """
386
        flag_defs : flag_def
387
        """
388 1
        p[0] = [p[1]]
389
390
    # noinspection PyIncorrectDocstring
391 1
    @staticmethod
392
    def p_flag_defs_3(p):
393
        """
394
        flag_defs : empty
395
        """
396 1
        pass
397
398
    # noinspection PyIncorrectDocstring
399 1
    @staticmethod
400
    def p_flag_def(p):
401
        """
402
        flag_def : SELECTIVE
403
                 | FIREANDFORGET
404
                 | POLYMORPHIC
405
                 | NOSUBSCRIPTIONS
406
                 | READONLY
407
        """
408 1
        p[0] = p[1]
409
410
    # noinspection PyIncorrectDocstring
411 1
    @staticmethod
412
    def p_arg_group_defs_1(p):
413
        """
414
        arg_group_defs : arg_group_defs arg_group_def
415
        """
416 1
        p[0] = p[1]
417 1
        p[0].append(p[2])
418
419
    # noinspection PyIncorrectDocstring
420 1
    @staticmethod
421
    def p_arg_group_defs_2(p):
422
        """
423
        arg_group_defs : arg_group_def
424
        """
425 1
        p[0] = [p[1]]
426
427
    # noinspection PyIncorrectDocstring
428 1
    @staticmethod
429
    def p_arg_group_defs_3(p):
430
        """
431
        arg_group_defs : empty
432
        """
433 1
        pass
434
435
    # noinspection PyIncorrectDocstring
436 1
    @staticmethod
437
    def p_arg_group_def_1(p):
438
        """
439
        arg_group_def : IN '{' arg_defs '}'
440
        """
441 1
        p[0] = InArgumentGroup(p[3])
442
443
    # noinspection PyIncorrectDocstring
444 1
    @staticmethod
445
    def p_arg_group_def_2(p):
446
        """
447
        arg_group_def : OUT '{' arg_defs '}'
448
        """
449 1
        p[0] = OutArgumentGroup(p[3])
450
451
    # noinspection PyIncorrectDocstring
452 1
    @staticmethod
453
    def p_arg_group_def_3(p):
454
        """
455
        arg_group_def : ERROR '{' enumerators '}'
456
        """
457 1
        p[0] = ErrorArgumentGroup(p[3])
458
459
    # noinspection PyIncorrectDocstring
460 1
    @staticmethod
461
    def p_arg_group_def_4(p):
462
        """
463
        arg_group_def : ERROR type
464
        """
465 1
        p[0] = ErrorArgumentGroup(p[2])
466
467
    # noinspection PyIncorrectDocstring
468 1
    @staticmethod
469
    def p_broadcast_def(p):
470
        """
471
        broadcast_def : structured_comment BROADCAST ID flag_defs '{' arg_group_defs '}'
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (88/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
472
        """
473 1
        in_args, out_args, errors = Parser._method_def(p[6])
474 1
        if in_args or errors:
475
            raise ParserException("In arguments and errors cannot be part "
476
                                  "of a broadcast definition.")
477 1
        p[0] = ast.Broadcast(name=p[3], flags=p[4], out_args=out_args, comments=p[1])
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (85/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
478
479
    # noinspection PyIncorrectDocstring
480 1
    @staticmethod
481
    def p_arg_defs_1(p):
482
        """
483
        arg_defs : arg_defs arg_def
484
        """
485 1
        p[0] = p[1]
486 1
        if p[2].name not in p[0]:
487 1
            p[0][p[2].name] = p[2]
488
        else:
489 1
            raise ParserException("Duplicate argument '{}'.".format(p[2].name))
490
491
    # noinspection PyIncorrectDocstring
492 1
    @staticmethod
493
    def p_arg_defs_2(p):
494
        """
495
        arg_defs : arg_def
496
        """
497 1
        p[0] = OrderedDict()
498 1
        p[0][p[1].name] = p[1]
499
500
    # noinspection PyIncorrectDocstring
501 1
    @staticmethod
502
    def p_arg_def(p):
503
        """
504
        arg_def : structured_comment type ID
505
        """
506 1
        p[0] = ast.Argument(name=p[3], arg_type=p[2], comments=p[1])
507
508
    # noinspection PyIncorrectDocstring
509 1
    @staticmethod
510
    def p_enumeration_def_1(p):
511
        """
512
        enumeration_def : structured_comment ENUMERATION ID '{' enumerators '}'
513
        """
514 1
        p[0] = ast.Enumeration(name=p[3], enumerators=p[5], comments=p[1])
515
516
    # noinspection PyIncorrectDocstring
517 1
    @staticmethod
518
    def p_enumeration_def_2(p):
519
        """
520
        enumeration_def : structured_comment ENUMERATION ID EXTENDS fqn '{' enumerators '}'
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (91/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
521
        """
522 1
        p[0] = ast.Enumeration(name=p[3], enumerators=p[7], extends=p[5], comments=p[1])
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (88/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
523
524
    # noinspection PyIncorrectDocstring
525 1
    @staticmethod
526
    def p_enumerators_1(p):
527
        """
528
        enumerators : enumerators enumerator
529
        """
530 1
        p[0] = p[1]
531 1
        if p[2].name not in p[0]:
532 1
            p[0][p[2].name] = p[2]
533
        else:
534 1
            raise ParserException(
535
                "Duplicate enumerator '{}'.".format(p[2].name))
536
537
    # noinspection PyIncorrectDocstring
538 1
    @staticmethod
539
    def p_enumerators_2(p):
540
        """
541
        enumerators : enumerator
542
        """
543 1
        p[0] = OrderedDict()
544 1
        p[0][p[1].name] = p[1]
545
546
    # noinspection PyUnusedLocal, PyIncorrectDocstring
547 1
    @staticmethod
548
    def p_enumerators_3(p):
549
        """
550
        enumerators : empty
551
        """
552 1
        pass
553
554
    # noinspection PyIncorrectDocstring
555 1
    @staticmethod
556
    def p_enumerator_1(p):
557
        """
558
        enumerator : structured_comment ID
559
        """
560 1
        p[0] = ast.Enumerator(name=p[2], comments=p[1])
561
562
    # noinspection PyIncorrectDocstring
563 1
    @staticmethod
564
    def p_enumerator_2(p):
565
        """
566
        enumerator : structured_comment ID '=' integer_val
567
        """
568 1
        p[0] = ast.Enumerator(name=p[2], value=p[4], comments=p[1])
569
570
    # noinspection PyIncorrectDocstring
571 1
    @staticmethod
572
    def p_struct_def_1(p):
573
        """
574
        struct_def : structured_comment STRUCT ID flag_defs '{' struct_fields '}'
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (81/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
575
        """
576 1
        p[0] = ast.Struct(name=p[3], fields=p[6], flags=p[4], comments=p[1])
577
578
    # noinspection PyIncorrectDocstring
579 1
    @staticmethod
580
    def p_struct_def_2(p):
581
        """
582
        struct_def : structured_comment STRUCT ID EXTENDS fqn '{' struct_fields '}'
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (83/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
583
        """
584 1
        p[0] = ast.Struct(name=p[3], fields=p[7], extends=p[5], comments=p[1])
585
586
    # noinspection PyIncorrectDocstring
587 1
    @staticmethod
588
    def p_struct_fields_1(p):
589
        """
590
        struct_fields : struct_fields struct_field
591
        """
592 1
        p[0] = p[1]
593 1
        if p[2].name not in p[0]:
594 1
            p[0][p[2].name] = p[2]
595
        else:
596 1
            raise ParserException(
597
                "Duplicate structure field '{}'.".format(p[2].name))
598
599
    # noinspection PyIncorrectDocstring
600 1
    @staticmethod
601
    def p_struct_fields_2(p):
602
        """
603
        struct_fields : struct_field
604
        """
605 1
        p[0] = OrderedDict()
606 1
        p[0][p[1].name] = p[1]
607
608
    # noinspection PyUnusedLocal, PyIncorrectDocstring
609 1
    @staticmethod
610
    def p_struct_fields_3(p):
611
        """
612
        struct_fields : empty
613
        """
614 1
        pass
615
616
    # noinspection PyIncorrectDocstring
617 1
    @staticmethod
618
    def p_struct_field(p):
619
        """
620
        struct_field : structured_comment type ID
621
        """
622 1
        p[0] = ast.StructField(name=p[3], field_type=p[2], comments=p[1])
623
624
    # noinspection PyIncorrectDocstring
625 1
    @staticmethod
626
    def p_array_def(p):
627
        """
628
        array_def : structured_comment ARRAY ID OF type
629
        """
630 1
        p[0] = ast.Array(name=p[3], element_type=p[5], comments=p[1])
631
632
    # noinspection PyIncorrectDocstring
633 1
    @staticmethod
634
    def p_map_def(p):
635
        """
636
        map_def : structured_comment MAP ID '{' type TO type '}'
637
        """
638 1
        p[0] = ast.Map(name=p[3], key_type=p[5], value_type=p[7], comments=p[1])
639
640
    # noinspection PyIncorrectDocstring
641 1
    @staticmethod
642
    def p_constant_def_1(p):
643
        """
644
        constant_def : structured_comment CONST INT8 ID '=' integer_val
645
                     | structured_comment CONST INT16 ID '=' integer_val
646
                     | structured_comment CONST INT32 ID '=' integer_val
647
                     | structured_comment CONST INT64 ID '=' integer_val
648
                     | structured_comment CONST UINT8 ID '=' integer_val
649
                     | structured_comment CONST UINT16 ID '=' integer_val
650
                     | structured_comment CONST UINT32 ID '=' integer_val
651
                     | structured_comment CONST UINT64 ID '=' integer_val
652
        """
653 1
        type_class = getattr(ast, p[3])
654 1
        value = ast.IntegerValue(p[6].value, p[6].base)
655 1
        p[0] = ast.Constant(name=p[4], element_type=type_class(), element_value=value, comments=p[1])
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (101/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
656
657
    # noinspection PyIncorrectDocstring
658 1
    @staticmethod
659
    def p_constant_def_2(p):
660
        """
661
        constant_def : structured_comment CONST INT8 ID '=' boolean_val
662
                     | structured_comment CONST INT16 ID '=' boolean_val
663
                     | structured_comment CONST INT32 ID '=' boolean_val
664
                     | structured_comment CONST INT64 ID '=' boolean_val
665
                     | structured_comment CONST UINT8 ID '=' boolean_val
666
                     | structured_comment CONST UINT16 ID '=' boolean_val
667
                     | structured_comment CONST UINT32 ID '=' boolean_val
668
                     | structured_comment CONST UINT64 ID '=' boolean_val
669
                     | structured_comment CONST INT8 ID '=' real_val
670
                     | structured_comment CONST INT16 ID '=' real_val
671
                     | structured_comment CONST INT32 ID '=' real_val
672
                     | structured_comment CONST INT64 ID '=' real_val
673
                     | structured_comment CONST UINT8 ID '=' real_val
674
                     | structured_comment CONST UINT16 ID '=' real_val
675
                     | structured_comment CONST UINT32 ID '=' real_val
676
                     | structured_comment CONST UINT64 ID '=' real_val
677
        """
678
        type_class = getattr(ast, p[3])
679
        value = ast.IntegerValue(int(p[6].value))
680
        p[0] = ast.Constant(name=p[4], element_type=type_class(), element_value=value, comments=p[1])
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (101/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
681
682
    # noinspection PyIncorrectDocstring
683 1
    @staticmethod
684
    def p_constant_def_3(p):
685
        """
686
        constant_def : structured_comment CONST FLOAT ID '=' integer_val
687
                     | structured_comment CONST FLOAT ID '=' boolean_val
688
                     | structured_comment CONST FLOAT ID '=' real_val
689
        """
690 1
        type_class = getattr(ast, p[3])
691 1
        value = ast.FloatValue(float(p[6].value))
692 1
        p[0] = ast.Constant(name=p[4], element_type=type_class(), element_value=value, comments=p[1])
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (101/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
693
694
    # noinspection PyIncorrectDocstring
695 1
    @staticmethod
696
    def p_constant_def_4(p):
697
        """
698
        constant_def : structured_comment CONST DOUBLE ID '=' integer_val
699
                     | structured_comment CONST DOUBLE ID '=' boolean_val
700
                     | structured_comment CONST DOUBLE ID '=' real_val
701
        """
702 1
        type_class = getattr(ast, p[3])
703 1
        value = ast.DoubleValue(float(p[6].value))
704 1
        p[0] = ast.Constant(name=p[4], element_type=type_class(), element_value=value, comments=p[1])
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (101/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
705
706
    # noinspection PyIncorrectDocstring
707 1
    @staticmethod
708
    def p_constant_def_5(p):
709
        """
710
        constant_def : structured_comment CONST BOOLEAN ID '=' value
711
        """
712 1
        type_class = getattr(ast, p[3])
713 1
        value = ast.BooleanValue(bool(p[6].value))
714 1
        p[0] = ast.Constant(name=p[4], element_type=type_class(), element_value=value, comments=p[1])
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (101/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
715
716
    # noinspection PyIncorrectDocstring
717 1
    @staticmethod
718
    def p_constant_def_6(p):
719
        """
720
        constant_def : structured_comment CONST STRING ID '=' value
721
        """
722 1
        type_class = getattr(ast, p[3])
723 1
        value = ast.StringValue(str(p[6].value))
724 1
        p[0] = ast.Constant(name=p[4], element_type=type_class(), element_value=value, comments=p[1])
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (101/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
725
726
    # noinspection PyIncorrectDocstring
727 1
    @staticmethod
728
    def p_boolean_val(p):
729
        """
730
        boolean_val : BOOLEAN_VAL
731
        """
732 1
        p[0] = ast.BooleanValue(p[1])
733
734
    # noinspection PyIncorrectDocstring
735 1
    @staticmethod
736
    def p_integer_val(p):
737
        """
738
        integer_val : INTEGER_VAL
739
        """
740 1
        p[0] = ast.IntegerValue(p[1])
741
742
    # noinspection PyIncorrectDocstring
743 1
    @staticmethod
744
    def p_integer_val_2(p):
745
        """
746
        integer_val : HEXADECIMAL_VAL
747
        """
748 1
        p[0] = ast.IntegerValue(p[1], ast.IntegerValue.HEXADECIMAL)
749
750
    # noinspection PyIncorrectDocstring
751 1
    @staticmethod
752
    def p_integer_val_3(p):
753
        """
754
        integer_val : BINARY_VAL
755
        """
756 1
        p[0] = ast.IntegerValue(p[1], ast.IntegerValue.BINARY)
757
758
    # noinspection PyIncorrectDocstring
759 1
    @staticmethod
760
    def p_real_val(p):
761
        """
762
        real_val : REAL_VAL
763
        """
764 1
        if re.match(r".*[dD]", p[1]):
765 1
            p[0] = ast.DoubleValue(float(p[1][:-1]))
766 1
        elif re.match(r".*[fF]", p[1]):
767 1
            p[0] = ast.FloatValue(float(p[1][:-1]))
768
        else:
769
            p[0] = ast.DoubleValue(float(p[1]))
770
771
    # noinspection PyIncorrectDocstring
772 1
    @staticmethod
773
    def p_string_val(p):
774
        """
775
        string_val : STRING_VAL
776
        """
777 1
        p[0] = ast.StringValue(p[1])
778
779
    # noinspection PyIncorrectDocstring
780 1
    @staticmethod
781
    def p_value(p):
782
        """
783
        value : boolean_val
784
              | string_val
785
              | real_val
786
              | integer_val
787
        """
788 1
        p[0] = p[1]
789
790
    # noinspection PyIncorrectDocstring
791 1
    @staticmethod
792
    def p_type_1(p):
793
        """
794
        type : INT8
795
             | INT16
796
             | INT32
797
             | INT64
798
             | UINT8
799
             | UINT16
800
             | UINT32
801
             | UINT64
802
             | BOOLEAN
803
             | FLOAT
804
             | DOUBLE
805
             | STRING
806
             | BYTEBUFFER
807
        """
808 1
        type_class = getattr(ast, p[1])
809 1
        p[0] = type_class()
810
811
    # noinspection PyIncorrectDocstring
812 1
    @staticmethod
813
    def p_type_2(p):
814
        """
815
        type : INT8 '[' ']'
816
             | INT16 '[' ']'
817
             | INT32 '[' ']'
818
             | INT64 '[' ']'
819
             | UINT8 '[' ']'
820
             | UINT16 '[' ']'
821
             | UINT32 '[' ']'
822
             | UINT64 '[' ']'
823
             | BOOLEAN '[' ']'
824
             | FLOAT '[' ']'
825
             | DOUBLE '[' ']'
826
             | STRING '[' ']'
827
             | BYTEBUFFER '[' ']'
828
        """
829 1
        type_class = getattr(ast, p[1])
830 1
        p[0] = ast.Array(name=None, element_type=type_class())
831
832
    # noinspection PyIncorrectDocstring
833 1
    @staticmethod
834
    def p_type_3(p):
835
        """
836
        type : fqn
837
        """
838 1
        p[0] = ast.Reference(name=p[1])
839
840
    # noinspection PyIncorrectDocstring
841 1
    @staticmethod
842
    def p_type_4(p):
843
        """
844
        type : fqn '[' ']'
845
        """
846 1
        element_type = ast.Reference(name=p[1])
847 1
        p[0] = ast.Array(name=None, element_type=element_type)
848
849
    # noinspection PyUnusedLocal, PyIncorrectDocstring
850 1
    @staticmethod
851
    def p_empty(p):
852
        """
853
        empty :
854
        """
855 1
        pass
856
857
    # noinspection PyIncorrectDocstring
858 1
    @staticmethod
859
    def p_error(p):
860 1
        if p:
861 1
            raise ParserException("Syntax error at line {} near '{}'.".format(
862
                                  p.lineno, p.value))
863
        else:
864 1
            raise ParserException("Reached unexpected end of file.")
865
866 1
    def __init__(self, the_lexer=None, **kwargs):
867
        """
868
        Constructor.
869
870
        :param lexer: a lexer object to use.
871
        """
872 1
        if not the_lexer:
873 1
            the_lexer = franca_lexer.Lexer()
874 1
        self._lexer = the_lexer
875 1
        self.tokens = self._lexer.tokens
876
        # Disable debugging, by default.
877 1
        if "debug" not in kwargs:
878 1
            kwargs["debug"] = False
879 1
        if "write_tables" not in kwargs:
880 1
            kwargs["write_tables"] = False
881 1
        self._parser = yacc.yacc(module=self, **kwargs)
882
883 1
    def parse(self, fidl):
884
        """
885
        Parse input text
886
887
        :param fidl: Input text to parse.
888
        :return: AST representation of the input.
889
        """
890 1
        package = self._parser.parse(fidl)
891 1
        return package
892
893 1
    def parse_file(self, fspec):
894
        """
895
        Parse input file
896
897
        :param fspec: Specification of a fidl to parse.
898
        :return: AST representation of the input.
899
        """
900 1
        with open(fspec, "r") as f:
901 1
            fidl = f.read()
902 1
        package = self.parse(fidl)
903 1
        if package:
904 1
            package.files = [fspec]
905
        return package
906