Coverage for trlc/nested.py: 100%
26 statements
« prev ^ index » next coverage.py v7.7.1, created at 2025-03-27 00:52 +0000
« prev ^ index » next coverage.py v7.7.1, created at 2025-03-27 00:52 +0000
1#!/usr/bin/env python3
2#
3# TRLC - Treat Requirements Like Code
4# Copyright (C) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
5#
6# This file is part of the TRLC Python Reference Implementation.
7#
8# TRLC is free software: you can redistribute it and/or modify it
9# under the terms of the GNU General Public License as published by
10# the Free Software Foundation, either version 3 of the License, or
11# (at your option) any later version.
12#
13# TRLC is distributed in the hope that it will be useful, but WITHOUT
14# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16# License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with TRLC. If not, see <https://www.gnu.org/licenses/>.
21from abc import abstractmethod
23from trlc.ast import String_Literal
24from trlc.lexer import Lexer_Base, Source_Reference
27class Nested_Lexer(Lexer_Base):
28 def __init__(self, mh, literal):
29 assert isinstance(literal, String_Literal)
31 origin_full_text = literal.location.text()
32 self.origin_multi_string = origin_full_text.startswith(('"""', "'''"))
33 if self.origin_multi_string:
34 self.base_offset = 3
35 text = origin_full_text[3:-3]
36 else:
37 self.base_offset = 1
38 text = origin_full_text[1:-1].replace('\\"', '"')
40 self.origin_location = literal.location
42 super().__init__(mh, text)
44 def source_location(self, start_line, start_col, begin, end):
45 assert 0 <= begin <= end < self.length
46 assert start_line >= 1
47 assert start_col >= 1
49 if self.origin_multi_string:
50 loc = Source_Reference(
51 lexer = self.origin_location.lexer,
52 start_line = self.origin_location.line_no + (start_line - 1),
53 start_col = (self.origin_location.col_no + self.base_offset
54 if start_line == 1
55 else start_col),
56 start_pos = (self.origin_location.start_pos +
57 self.base_offset +
58 begin),
59 end_pos = (self.origin_location.start_pos +
60 self.base_offset +
61 end))
63 else:
64 escapes_to_start = self.content[0:begin].count('"')
65 escapes_to_end = escapes_to_start + \
66 self.content[begin:end + 1].count('"')
67 assert start_line == 1
68 loc = Source_Reference(
69 lexer = self.origin_location.lexer,
70 start_line = self.origin_location.line_no,
71 start_col = (self.origin_location.col_no +
72 self.base_offset +
73 begin + escapes_to_start),
74 start_pos = (self.origin_location.start_pos +
75 self.base_offset +
76 begin + escapes_to_start),
77 end_pos = (self.origin_location.start_pos +
78 self.base_offset +
79 end + escapes_to_end))
81 return loc
83 @abstractmethod
84 def file_location(self):
85 pass
87 @abstractmethod
88 def token(self):
89 pass