dshellInterpreter 1.2.7.3__tar.gz → 1.2.7.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DISCORD_COMMANDS/utils/utils_type_validation.py +1 -1
  2. dshellinterpreter-1.2.7.4/Dshell/DshellPreProcess/dshell_preprocess.py +73 -0
  3. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DshellTokenizer/dshell_keywords.py +20 -8
  4. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DshellTokenizer/dshell_tokenizer.py +60 -83
  5. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/full_import.py +1 -0
  6. {dshellinterpreter-1.2.7.3/dshellInterpreter.egg-info → dshellinterpreter-1.2.7.4}/PKG-INFO +1 -1
  7. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4/dshellInterpreter.egg-info}/PKG-INFO +1 -1
  8. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/setup.py +1 -1
  9. dshellinterpreter-1.2.7.3/Dshell/DshellPreProcess/dshell_preprocess.py +0 -41
  10. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DISCORD_COMMANDS/__init__.py +0 -0
  11. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DISCORD_COMMANDS/dshell_channel.py +0 -0
  12. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DISCORD_COMMANDS/dshell_embed.py +0 -0
  13. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DISCORD_COMMANDS/dshell_file.py +0 -0
  14. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DISCORD_COMMANDS/dshell_interaction.py +0 -0
  15. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DISCORD_COMMANDS/dshell_member.py +0 -0
  16. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DISCORD_COMMANDS/dshell_message.py +0 -0
  17. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DISCORD_COMMANDS/dshell_pastbin.py +0 -0
  18. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DISCORD_COMMANDS/dshell_role.py +0 -0
  19. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DISCORD_COMMANDS/dshell_ui.py +0 -0
  20. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DISCORD_COMMANDS/utils/__init__.py +0 -0
  21. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DISCORD_COMMANDS/utils/utils_embed.py +0 -0
  22. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DISCORD_COMMANDS/utils/utils_file.py +0 -0
  23. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DISCORD_COMMANDS/utils/utils_global.py +0 -0
  24. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DISCORD_COMMANDS/utils/utils_list.py +0 -0
  25. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DISCORD_COMMANDS/utils/utils_member.py +0 -0
  26. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DISCORD_COMMANDS/utils/utils_message.py +0 -0
  27. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DISCORD_COMMANDS/utils/utils_numbers.py +0 -0
  28. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DISCORD_COMMANDS/utils/utils_permissions.py +0 -0
  29. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DISCORD_COMMANDS/utils/utils_string.py +0 -0
  30. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DISCORD_COMMANDS/utils/utils_thread.py +0 -0
  31. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DshellInterpreteur/__init__.py +0 -0
  32. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DshellInterpreteur/cached_messages.py +0 -0
  33. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DshellInterpreteur/dshell_arguments.py +0 -0
  34. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DshellInterpreteur/dshell_global_variables.py +0 -0
  35. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DshellInterpreteur/dshell_interpreter.py +0 -0
  36. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DshellInterpreteur/dshell_iterators.py +0 -0
  37. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DshellInterpreteur/dshell_scope.py +0 -0
  38. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DshellInterpreteur/errors.py +0 -0
  39. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DshellInterpreteur/utils_interpreter.py +0 -0
  40. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DshellParser/__init__.py +0 -0
  41. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DshellParser/ast_nodes.py +0 -0
  42. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DshellParser/dshell_parser.py +0 -0
  43. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DshellParser/errors.py +0 -0
  44. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DshellPreProcess/__init__.py +0 -0
  45. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DshellTokenizer/__init__.py +0 -0
  46. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/DshellTokenizer/dshell_token_type.py +0 -0
  47. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/Dshell/__init__.py +0 -0
  48. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/LICENSE +0 -0
  49. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/README.md +0 -0
  50. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/dshellInterpreter.egg-info/SOURCES.txt +0 -0
  51. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/dshellInterpreter.egg-info/dependency_links.txt +0 -0
  52. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/dshellInterpreter.egg-info/requires.txt +0 -0
  53. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/dshellInterpreter.egg-info/top_level.txt +0 -0
  54. {dshellinterpreter-1.2.7.3 → dshellinterpreter-1.2.7.4}/setup.cfg +0 -0
@@ -117,7 +117,7 @@ def _validate_optional_permission(value, param_name: StrNode, command_name: StrN
117
117
  :param command_name: The command name for error messages (optional)
118
118
  :raises TypeError: If the value is not None and not a PermissionNode
119
119
  """
120
- if (value is not None or not isinstance(value, _MissingSentinel)) and not isinstance(value, PermissionNode):
120
+ if value is not None and not isinstance(value, _MissingSentinel) and not isinstance(value, PermissionNode):
121
121
  raise TypeError(f"[{command_name}] -> {param_name} must be a PermissionNode or None, not {type(value).__name__}")
122
122
 
123
123
 
@@ -0,0 +1,73 @@
1
+ from ..full_import import sub, MULTILINE, StrEnum, search, compile, DOTALL
2
+
3
+ class PreProcessorInstructions(StrEnum):
4
+ DEFINE = "define"
5
+
6
+ class PreProcessorData:
7
+ def __init__(self, instruction: str, symbol: str, value: str):
8
+ self.instruction = instruction
9
+ self.symbol = symbol
10
+ self.value = value
11
+
12
+ def define(code: str, pre_processor_data: PreProcessorData) -> str:
13
+ """
14
+ Replace all symbol with the current value
15
+ :param code: the code before tokenization
16
+ :param pre_processor_data: all data for the ##define pre-processor
17
+ :return:
18
+ """
19
+ return sub(f"(?<![a-zA-Z]){pre_processor_data.symbol}(?![a-zA-Z])", pre_processor_data.value, code)
20
+
21
+ pre_processor_pattern = compile(r"^\s*## *([a-zA-Z]+) +([a-zA-Z]+)(?: +(.*))?$", flags=MULTILINE|DOTALL)
22
+ def preProcessor(code: list[str]) -> list[str]:
23
+ """
24
+ Execute preprocessor line
25
+ :param code: a list of code line before tokenization
26
+ :return: a new list of string after pre-processor and since pre-processor instructions
27
+ """
28
+ pre_processor_data: list[PreProcessorData] = list()
29
+ new_code: list[str] = []
30
+
31
+ for line in code:
32
+
33
+ line = removeCommentPreProcessor(line)
34
+
35
+ if pre_processor_match := search(pre_processor_pattern, line):
36
+
37
+ instruction: str = pre_processor_match.group(1).lower()
38
+ symbol: str = pre_processor_match.group(2)
39
+ value: str = pre_processor_match.group(3)
40
+ if instruction in PreProcessorInstructions:
41
+ pre_processor_data.append(PreProcessorData(instruction, symbol, value))
42
+
43
+ else:
44
+ # apply pre-processor instructions
45
+ line = applyPreProcessor(line, pre_processor_data)
46
+ new_code.append(line)
47
+
48
+ return new_code
49
+
50
+
51
+
52
+ def applyPreProcessor(code: str, pre_processor_data: list[PreProcessorData]) -> str:
53
+ """
54
+ Apply preprocessor data to code
55
+ :param line: the current line before tokenization
56
+ :param pre_processor_data:
57
+ :return:
58
+ """
59
+ for pre_processor in pre_processor_data:
60
+ match pre_processor.instruction:
61
+ case "define":
62
+ code = define(code, pre_processor)
63
+
64
+ return code
65
+
66
+ def removeCommentPreProcessor(code: str) -> str:
67
+ """
68
+ Remove all comment in the code
69
+ :param code:
70
+ :return:
71
+ """
72
+ # add \ before or in :: like \:: or :\: disable comment. Usable in string to add :: characters sequence.
73
+ return sub(r"(?<!\\):(?<!\\)?:.*", "", code, flags=MULTILINE)
@@ -10,7 +10,7 @@ __all__ = [
10
10
 
11
11
  from ..DISCORD_COMMANDS import *
12
12
 
13
- from ..full_import import Callable
13
+ from ..full_import import Callable, ChainMap
14
14
  from ..DshellInterpreteur.dshell_iterators import IntIterator
15
15
 
16
16
 
@@ -175,7 +175,16 @@ Tuple format: (function, precedence, number of operands min, number of operands
175
175
  Optional[index to translate into value])
176
176
  """
177
177
 
178
- dshell_mathematical_operators: dict[str, tuple[Callable, int, int, int, Optional[int]]] = {
178
+ Operator = tuple[
179
+ Callable,
180
+ int,
181
+ int,
182
+ int,
183
+ Optional[int],
184
+ ]
185
+
186
+
187
+ dshell_mathematical_operators: dict[str, Operator] = {
179
188
 
180
189
  r"++": (lambda a: a + 1, 6, 1, 1, None),
181
190
  r"--": (lambda a: a - 1, 6, 1, 1, None),
@@ -198,14 +207,14 @@ dshell_mathematical_operators: dict[str, tuple[Callable, int, int, int, Optional
198
207
 
199
208
  }
200
209
 
201
- dshell_logical_word_operators: dict[str, tuple[Callable, int, int, int, Optional[int]]] = {
210
+ dshell_logical_word_operators: dict[str, Operator] = {
202
211
  r"and": (lambda a, b: bool(a and b), 2, 2, 2, None),
203
212
  r"or": (lambda a, b: bool(a or b), 1, 2, 2, None),
204
213
  r"not": (lambda a: not a, 3, 1, 1, None),
205
214
  r"in": (lambda a, b: a in b, 4, 2, 2, None),
206
215
  }
207
216
 
208
- dshell_logical_operators: dict[str, tuple[Callable, int, int, int, Optional[int]]] = {
217
+ dshell_logical_operators: dict[str, Operator] = {
209
218
 
210
219
  r"==": (lambda a, b: a == b, 4, 2, 2, None),
211
220
  r"<=": (lambda a, b: a <= b, 4, 2, 2, None),
@@ -223,10 +232,13 @@ dshell_logical_operators: dict[str, tuple[Callable, int, int, int, Optional[int]
223
232
  r">": (lambda a, b: a > b, 4, 2, 2, None),
224
233
  r"!": (lambda a: not a, 3, 1, 1, None),
225
234
  r"?": (lambda condition, first, second: first if condition else second, 1, 3, 3, 1),
226
- #r".": (lambda target, attribute: target.call(attribute) if hasattr(target, attribute) and hasattr(target, 'call') else None, 9, 2, 2), # attribute access operator
227
-
228
235
  }
229
236
 
230
- dshell_operators: dict[str, tuple[Callable, int, int, int, Optional[int]]] = dshell_logical_operators.copy()
237
+ dshell_operators: ChainMap[str, Operator] = ChainMap(
238
+ dshell_logical_operators,
239
+ dshell_logical_word_operators,
240
+ dshell_mathematical_operators)
241
+
242
+ """dshell_operators: dict[str, tuple[Callable, int, int, int, Optional[int]]] = dshell_logical_operators.copy()
231
243
  dshell_operators.update(dshell_logical_word_operators)
232
- dshell_operators.update(dshell_mathematical_operators)
244
+ dshell_operators.update(dshell_mathematical_operators)"""
@@ -12,10 +12,8 @@ from Dshell.full_import import (
12
12
  ASCII,
13
13
  DOTALL,
14
14
  IGNORECASE,
15
- MULTILINE,
16
15
  compile,
17
16
  escape,
18
- findall,
19
17
  finditer,
20
18
  Match,
21
19
  sub)
@@ -27,7 +25,7 @@ from .dshell_keywords import (dshell_keyword,
27
25
  dshell_logical_operators,
28
26
  dshell_logical_word_operators)
29
27
 
30
- from ..DshellPreProcess.dshell_preprocess import preProcessor, applyPreProcessor, PreProcessorData
28
+ from ..DshellPreProcess.dshell_preprocess import preProcessor
31
29
 
32
30
  MASK_CHARACTER = '§'
33
31
 
@@ -37,10 +35,9 @@ def is_line_empty(line: str) -> bool:
37
35
  :param line: The line to check.
38
36
  :return: True if the line is empty, False otherwise.
39
37
  """
40
- return all(c in (MASK_CHARACTER, ' ') for c in line)
38
+ return all(c in (MASK_CHARACTER, ' ', '\n') for c in line)
41
39
 
42
40
  table_regex: dict[DTT, Pattern] = {
43
- DTT.COMMENT: compile(r"::(.*)", flags=MULTILINE),
44
41
  DTT.STR: compile(r'"((?:[^\\"]|\\.)*)"', flags=DOTALL),
45
42
  DTT.EVAL_L_EXPRESSION: compile(r"({)"),
46
43
  DTT.EVAL_R_EXPRESSION: compile(r"(})"),
@@ -54,7 +51,7 @@ table_regex: dict[DTT, Pattern] = {
54
51
  DTT.PARAMETER: compile(rf"--\s*([A-Za-z_]+)\s*", flags=ASCII),
55
52
  DTT.MENTION: compile(r'<(?:@[!&]?|#)([0-9]+)>'),
56
53
  DTT.KEYWORD: compile(rf"(?<!\w)(#?{'|'.join(dshell_keyword)})(?!\w)"),
57
- DTT.DISCORD_KEYWORD: compile(rf"(?<!\w|-)(#?{'|'.join(dshell_discord_keyword)})(?!\w|-)", flags=IGNORECASE),
54
+ DTT.DISCORD_KEYWORD: compile(rf"(?<![\w\-])(#?{'|'.join(dshell_discord_keyword)})(?![\w\-])" , flags=IGNORECASE),
58
55
  DTT.COMMAND: compile(rf"\b({'|'.join(dshell_commands.keys())})\b", flags=IGNORECASE),
59
56
  DTT.FLOAT: compile(r"(\d+\.\d+)"),
60
57
  DTT.HEXA: compile(r"(0[Xx][0-9a-fA-F]+)"),
@@ -66,21 +63,19 @@ table_regex: dict[DTT, Pattern] = {
66
63
  DTT.BOOL: compile(r"(True|False)", flags=IGNORECASE),
67
64
  DTT.NONE: compile(r"(None)", flags=IGNORECASE),
68
65
  DTT.IDENT: compile(rf"([A-Za-z0-9_]+)"),
69
- DTT.ANY_CHARACTER: compile(rf"([^{MASK_CHARACTER}\n]+)"),
70
66
  }
71
67
 
68
+ backslash_pattern = compile(r"\\(.)", flags=DOTALL)
72
69
 
73
70
  class DshellTokenizer:
74
71
 
75
- def __init__(self, code: str, match_any_character: bool = False):
72
+ def __init__(self, code: str):
76
73
  """
77
74
  Initialize the tokenizer.
78
75
  :param code: The code to tokenize
79
76
  :param match_any_character: Whether to match any character
80
77
  """
81
78
  self.code: str = code
82
- self.match_any_character: bool = match_any_character
83
- self.data_pre_processor: list[PreProcessorData] = []
84
79
 
85
80
  def start(self):
86
81
  """
@@ -88,6 +83,7 @@ class DshellTokenizer:
88
83
  Returns an array of tokens per line (normally separated by \\n)
89
84
  """
90
85
  split_commands = self.split(self.code)
86
+ split_commands = preProcessor(split_commands)
91
87
  return self.tokenizer(split_commands)
92
88
 
93
89
  def tokenizer(self, command_lines: list[str]) -> list[list[Token]]:
@@ -96,74 +92,47 @@ class DshellTokenizer:
96
92
  :param command_lines: The code separated into multiple lines by the split method
97
93
  """
98
94
  tokens: list[list[Token]] = []
95
+ ident_tokens = 0
99
96
 
100
- line_number = 1
101
- for line in command_lines: # iterate each line of code
102
- tokens_per_line: list[Token] = []
103
- is_comment: bool = False
97
+ for line_number, line in enumerate(command_lines, start=1):
98
+ line: str = command_lines[line_number-1] # get the current line
104
99
 
100
+ # if the line is empty or already tokenized, pass the line.
105
101
  if is_line_empty(line):
106
- line_number += 1
107
102
  continue
108
103
 
109
- if pre_processor_data := preProcessor(line):
110
- self.data_pre_processor.append(pre_processor_data)
111
- continue
112
- else:
113
- if self.data_pre_processor:
114
- for processor_data in self.data_pre_processor:
115
- line = applyPreProcessor(line, processor_data)
116
-
117
- for token_type, pattern in table_regex.items(): # iterate the regex table to test all patterns on the line
118
-
119
- if is_comment:
120
- is_comment = False
121
- break
122
-
123
- if is_line_empty(line):
124
- break
104
+ tokens.append([])
105
+ tokens_per_line = tokens[ident_tokens]
125
106
 
126
- if not self.match_any_character and token_type == DTT.ANY_CHARACTER:
127
- continue
128
-
129
- for match in finditer(pattern, line): # iterate the match results to get their positions
107
+ for token_type, regex in table_regex.items():
108
+ for match in finditer(regex, line):
130
109
  match: Match
131
110
 
132
- if token_type == DTT.COMMENT: # if we encounter a comment, stop tokenizing the line
133
- if len(match.group(0)) == len(line):
134
- is_comment = True
135
- break
136
- else:
137
- line = line[:match.start()]
138
- continue
139
-
140
- start_match = match.start() # start position of the match
111
+ start_match = match.start()
112
+ end_match = match.end()
141
113
 
142
- token = Token(token_type, match.group(1), (line_number, start_match)) # record its token
114
+ token = Token(token_type, match.group(1), (line_number, start_match))
143
115
  tokens_per_line.append(token)
144
116
 
145
117
  if token_type == DTT.STR:
146
- token.value = token.value.replace(r'\"', '"')
147
-
148
- len_match = len(match.group(0)) # length of the match found
149
- line = line[:start_match] + (MASK_CHARACTER * len_match) + line[
150
- match.end():] # replace the match to avoid matching it a second time
151
-
152
- tokens_per_line.sort(key=lambda
153
- token: token.position[1]) # sort the position based on token match positions to have them in code order
154
- if tokens_per_line:
118
+ token.value = sub(backslash_pattern, lambda m: escape(m.group(1)), token.value)
155
119
 
156
- tokens_per_line = self.parse_group(tokens_per_line,
157
- line_number) # parse list in the current line to regroup them in a single token with all the elements of the list as value
120
+ len_match = len(match.group(0))
121
+ line = line[:start_match] + MASK_CHARACTER * len_match + line[end_match:]
158
122
 
159
- tokens.append(tokens_per_line)
123
+ tokens_per_line.sort(key=lambda t: t.position[1])
160
124
 
161
- line_number += 1 # increment the line number for the next line
125
+ if tokens_per_line:
126
+ tokens[ident_tokens] = self.parse_group(tokens_per_line, line_number)
162
127
 
128
+ ident_tokens += 1
163
129
  return tokens
164
130
 
165
131
  @staticmethod
166
- def split(command: str, global_split='\n', keep_grouping_character=True, grouping_character='"') -> list[
132
+ def split(command: str,
133
+ global_split='\n',
134
+ keep_grouping_character=True,
135
+ grouping_character='"') -> list[
167
136
  str]:
168
137
  """
169
138
  Separate commands into a list while respecting strings between quotes.
@@ -175,31 +144,39 @@ class DshellTokenizer:
175
144
  :return: A list of split commands with restored strings.
176
145
  """
177
146
 
178
- commands: str = command.strip()
179
- temporary_replacement = '[REPLACE]'
180
- pattern_find_regrouped_part = compile(rf'({grouping_character}(?:[^\\{grouping_character}]|\\.)*{grouping_character})', flags=DOTALL)
181
- between_grouping_character = findall(pattern_find_regrouped_part, commands) # find parts between quotes and save them
182
-
183
- res = sub(pattern_find_regrouped_part,
184
- temporary_replacement,
185
- commands,
186
- ) # replace parts between quotes
187
-
188
- res = res.split(global_split) # split commands without quotes
189
-
190
- # restore quotes to their place
191
- result = []
192
- for i in res:
193
- while temporary_replacement in i:
194
- i = i.replace(temporary_replacement,
195
- between_grouping_character[0][1: -1] if not keep_grouping_character else
196
- between_grouping_character[0], 1)
197
- between_grouping_character.pop(0)
198
- result.append(i)
147
+ result: list[str] = []
148
+ in_string: bool = False # True if we are in a string
149
+ backslash: bool = False
150
+ line: list[str] = [] # buffer for each line
151
+
152
+ for char in command:
153
+
154
+ if backslash:
155
+ line.append('\\')
156
+ line.append(char)
157
+ backslash = False
158
+
159
+ elif char == global_split and not in_string:
160
+ result.append(''.join(line))
161
+ line.clear()
162
+
163
+ elif char == grouping_character:
164
+ in_string = not in_string
165
+ if keep_grouping_character:
166
+ line.append(char)
167
+
168
+ elif char == '\\':
169
+ backslash = True
170
+
171
+ else:
172
+ line.append(char)
173
+
174
+ result.append(''.join(line))
175
+
199
176
  return result
200
177
 
201
178
  @staticmethod
202
- def parse_group(line: list[Token],
179
+ def parse_group(tokens_in_line: list[Token],
203
180
  line_position: int):
204
181
  """
205
182
  Parse all list in the current token line and return the modified list line.
@@ -227,8 +204,8 @@ class DshellTokenizer:
227
204
  last_tokens[-1].value.append(token)
228
205
 
229
206
  i = 0
230
- while i < len(line):
231
- token = line[i]
207
+ while i < len(tokens_in_line):
208
+ token = tokens_in_line[i]
232
209
 
233
210
  if token.type == DTT.LIST_L:
234
211
  if last_tokens:
@@ -15,3 +15,4 @@ from contextvars import ContextVar
15
15
  from re import *
16
16
  from random import randint, choice, random
17
17
  from enum import Enum, auto, StrEnum
18
+ from collections import ChainMap
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dshellInterpreter
3
- Version: 1.2.7.3
3
+ Version: 1.2.7.4
4
4
  Summary: A Discord bot interpreter for creating custom commands and automations.
5
5
  Home-page: https://github.com/BOXERRMD/Dshell_Interpreter
6
6
  Author: Chronos
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dshellInterpreter
3
- Version: 1.2.7.3
3
+ Version: 1.2.7.4
4
4
  Summary: A Discord bot interpreter for creating custom commands and automations.
5
5
  Home-page: https://github.com/BOXERRMD/Dshell_Interpreter
6
6
  Author: Chronos
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
5
5
 
6
6
  setup(
7
7
  name="dshellInterpreter",
8
- version="1.2.7.3",
8
+ version="1.2.7.4",
9
9
  author="Chronos",
10
10
  author_email="vagabonwalybi@gmail.com",
11
11
  description="A Discord bot interpreter for creating custom commands and automations.",
@@ -1,41 +0,0 @@
1
- from ..full_import import search, sub, Optional
2
-
3
- class PreProcessorData:
4
- def __init__(self, instruction: str, symbol: str, value: str):
5
- self.instruction = instruction
6
- self.symbol = symbol
7
- self.value = value
8
-
9
- def define(line: str, pre_processor_data: PreProcessorData) -> str:
10
- """
11
- Replace all symbol with the current value
12
- :param line: the current line before tokenization
13
- :param pre_processor_data: all data for the ##define pre-processor
14
- :return:
15
- """
16
- return sub(f"(?<![a-zA-Z]){pre_processor_data.symbol}(?![a-zA-Z])", pre_processor_data.value, line)
17
-
18
-
19
- def preProcessor(line: str) -> Optional[PreProcessorData]:
20
- """
21
- Execute preprocessor line
22
- :param line: the current line before tokenization
23
- :return:
24
- """
25
- pre_process_match = search(r"^\s*##([a-zA-Z]+)\s+([a-zA-Z]+)\s+(.*)$", line)
26
- if pre_process_match:
27
- return PreProcessorData(pre_process_match.group(1).lower(), pre_process_match.group(2), pre_process_match.group(3))
28
- return None
29
-
30
- def applyPreProcessor(line: str, pre_processor_data: PreProcessorData):
31
- """
32
- Apply preprocessor data to code
33
- :param line: the current line before tokenization
34
- :param pre_processor_data:
35
- :return:
36
- """
37
- match pre_processor_data.instruction:
38
- case "define":
39
- return define(line, pre_processor_data)
40
-
41
- return None