SDoc2Visitor._get_options()   B
last analyzed

Complexity

Conditions 7

Size

Total Lines 26
Code Lines 17

Duplication

Lines 26
Ratio 100 %

Code Coverage

Tests 15
CRAP Score 7

Importance

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