Passed
Branch master (0442a2)
by P.R.
02:00
created

SDoc2Visitor._get_options()   C

Complexity

Conditions 7

Size

Total Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 28
rs 5.5
cc 7
1
"""
2
SDoc
3
4
Copyright 2016 Set Based IT Consultancy
5
6
Licence MIT
7
"""
8
# ----------------------------------------------------------------------------------------------------------------------
9
import re
10
11
from sdoc import sdoc2
12
from sdoc.antlr.sdoc2ParserVisitor import sdoc2ParserVisitor
13
from sdoc.sdoc.SDocVisitor import SDocVisitor
14
from sdoc.sdoc2.Position import Position
15
16
17
class SDoc2Visitor(sdoc2ParserVisitor, SDocVisitor):
18
    """
19
    Visitor for SDoc level 2.
20
    """
21
22
    # ------------------------------------------------------------------------------------------------------------------
23
    def __init__(self):
24
        """
25
        Object constructor.
26
        """
27
        SDocVisitor.__init__(self)
28
29
        self._output = None
30
        """
31
        Object for streaming the generated output. This object MUST implement the write method.
32
        """
33
34
        self._sdoc1_file_name = ''
35
        """
36
        The original file name at SDoc1 level.
37
38
        :type: str
39
        """
40
41
        self._sdoc1_line = 0
42
        """
43
        The offset of for computing the current line at SDoc1 level.
44
45
        :type: int
46
        """
47
48
        self._sdoc1_column = 0
49
        """
50
        The offset of for computing the current column at SDoc1 level.
51
52
        :type: int
53
        """
54
55
        self._sdoc2_line = 0
56
        """
57
        The line position of the last position command.
58
59
        :type: int
60
        """
61
62
        self._sdoc2_column = 0
63
        """
64
        The last column position of the last position command.
65
66
        :type: int
67
        """
68
69
    # ------------------------------------------------------------------------------------------------------------------
70
    @staticmethod
71
    def _get_options(ctx):
72
        """
73
        Returns the option of an command.
74
75
        :param ParserRuleContext ctx: The parse tree with the options.
76
77
        :rtype: dict[str,str]
78
        """
79
        options = {}
80
        i = 0
81
        while True:
82
            name_token = ctx.OPT_ARG_NAME(i)
83
            value_token = ctx.OPT_ARG_VALUE(i)
84
            if not name_token:
85
                break
86
87
            option_name = name_token.getText()
88
            option_value = value_token.getText()
89
            # Trim leading and trailing (double)quotes from string. (Is there a way to do this in ANTLR?)
90
            if (option_value[0] == '"' and option_value[-1] == '"') or \
91
                    (option_value[0] == "'" and option_value[-1] == "'"):
92
                option_value = option_value[1:-1]
93
94
            options[option_name] = option_value
95
            i += 1
96
97
        return options
98
99
    # ------------------------------------------------------------------------------------------------------------------
100
    def get_position(self, token):
101
        """
102
        Returns the position of the token in the original SDoc1 source file.
103
104
        :param token:
105
106
        :rtype: sdoc.sdoc2.Position.Position
107
        """
108
        line_number = token.line
109
        column = token.column
110
111
        if self._sdoc2_line == line_number:
112
            column = self._sdoc1_column + (column - self._sdoc2_column)
113
114
        line_number = self._sdoc1_line + (line_number - self._sdoc2_line)
115
116
        return Position(self._sdoc1_file_name, line_number, column, -1, -1)
117
118
    # ------------------------------------------------------------------------------------------------------------------
119
    def set_output(self, output):
120
        """
121
        Sets the object for streaming the generated output.
122
123
        :param output: This object MUST implement the write method.
124
        """
125
        self._output = output
126
127
    # ------------------------------------------------------------------------------------------------------------------
128
    def stream(self, snippet):
129
        """
130
        Puts an output snippet on the output stream.
131
132
        :param str snippet: The snippet to be appended to the output stream of this parser.
133
        """
134
        if snippet is not None:
135
            self._output.write(snippet)
136
137
    # ------------------------------------------------------------------------------------------------------------------
138
    def visitCmd_begin(self, ctx):
139
        """
140
        Visit a parse tree produced by a begin command.
141
142
        :param sdoc.antlr.sdoc2Parser.sdoc2Parser.Cmd_beginContext ctx: The parse tree.
143
        """
144
        command = ctx.BLOCK_ARG_ARG().getText()
145
146
        sdoc2.node_store.append_block_node(command, self._get_options(ctx), self.get_position(ctx.start))
147
148
    # ------------------------------------------------------------------------------------------------------------------
149
    def visitCmd_end(self, ctx):
150
        """
151
        Visit a parse tree produced by an end command.
152
153
        :param sdoc.antlr.sdoc2Parser.sdoc2Parser.Cmd_endContext ctx: The parse tree.
154
        """
155
        command = ctx.BLOCK_ARG_ARG().getText().rstrip()
156
157
        sdoc2.node_store.end_block_node(command)
158
159
    # ------------------------------------------------------------------------------------------------------------------
160
    def visitCmd_position(self, ctx):
161
        """
162
        Visit a parse tree produced by a position command.
163
164
        :param sdoc.antlr.sdoc2Parser.sdoc2Parser.Cmd_positionContext ctx: The parse tree.
165
        """
166
        argument = ctx.INLINE_ARG_ARG()
167
        parts = re.match(r'(.+):([0-9]+)\.([0-9]+)', str(argument))
168
        if not parts:
169
            self._error('{0!s} is not a valid position'.format(argument))
0 ignored issues
show
Bug introduced by
It seems like a value for argument token is missing in the method call.
Loading history...
170
            return
171
172
        self._sdoc1_file_name = parts.group(1)
173
        self._sdoc1_line = int(parts.group(2))
174
        self._sdoc1_column = int(parts.group(3))
175
176
        token = ctx.stop
177
        self._sdoc2_line = token.line
178
        self._sdoc2_column = token.column + len(token.text)
179
180
    # ------------------------------------------------------------------------------------------------------------------
181
    def visitCmd_sdoc2(self, ctx):
182
        """
183
        Visit a parse tree produced by a inline command.
184
185
        :param sdoc.antlr.sdoc2Parser.sdoc2Parser.Cmd_sdoc2Context ctx: The parse tree.
186
        """
187
        command = ctx.SDOC2_COMMAND().getText()
188
        argument = ctx.INLINE_ARG_ARG()
189
190
        sdoc2.node_store.append_inline_node(command[1:],
191
                                            self._get_options(ctx),
192
                                            argument.getText() if argument else '',
193
                                            self.get_position(ctx.start))
194
195
    # ------------------------------------------------------------------------------------------------------------------
196
    def visitText(self, ctx):
197
        """
198
        Visit a parse tree produced by TEXT.
199
200
        :param sdoc.antlr.sdoc2Parser.sdoc2Parser.TextContext ctx: The parse tree.
201
        """
202
        sdoc2.node_store.append_inline_node('TEXT', {}, ctx.TEXT().getText(), self.get_position(ctx.start))
203
204
# ----------------------------------------------------------------------------------------------------------------------
205