lizard 1.17.21__tar.gz → 1.17.23__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 (100) hide show
  1. {lizard-1.17.21 → lizard-1.17.23}/PKG-INFO +1 -1
  2. {lizard-1.17.21 → lizard-1.17.23}/lizard.egg-info/PKG-INFO +1 -1
  3. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/version.py +1 -1
  4. lizard-1.17.23/lizard_languages/perl.py +330 -0
  5. lizard-1.17.21/lizard_languages/perl.py +0 -103
  6. {lizard-1.17.21 → lizard-1.17.23}/LICENSE.txt +0 -0
  7. {lizard-1.17.21 → lizard-1.17.23}/README.rst +0 -0
  8. {lizard-1.17.21 → lizard-1.17.23}/lizard.egg-info/SOURCES.txt +0 -0
  9. {lizard-1.17.21 → lizard-1.17.23}/lizard.egg-info/dependency_links.txt +0 -0
  10. {lizard-1.17.21 → lizard-1.17.23}/lizard.egg-info/entry_points.txt +0 -0
  11. {lizard-1.17.21 → lizard-1.17.23}/lizard.egg-info/requires.txt +0 -0
  12. {lizard-1.17.21 → lizard-1.17.23}/lizard.egg-info/top_level.txt +0 -0
  13. {lizard-1.17.21 → lizard-1.17.23}/lizard.py +0 -0
  14. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/__init__.py +0 -0
  15. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/auto_open.py +0 -0
  16. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/csvoutput.py +0 -0
  17. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/default_ordered_dict.py +0 -0
  18. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/extension_base.py +0 -0
  19. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/htmloutput.py +0 -0
  20. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/keywords.py +0 -0
  21. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/lizardboolcount.py +0 -0
  22. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/lizardcomplextags.py +0 -0
  23. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/lizardcpre.py +0 -0
  24. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/lizarddependencycount.py +0 -0
  25. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/lizarddumpcomments.py +0 -0
  26. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/lizardduplicate.py +0 -0
  27. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/lizardduplicated_param_list.py +0 -0
  28. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/lizardexitcount.py +0 -0
  29. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/lizardgotocount.py +0 -0
  30. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/lizardignoreassert.py +0 -0
  31. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/lizardio.py +0 -0
  32. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/lizardmccabe.py +0 -0
  33. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/lizardmodified.py +0 -0
  34. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/lizardnd.py +0 -0
  35. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/lizardnonstrict.py +0 -0
  36. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/lizardns.py +0 -0
  37. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/lizardoutside.py +0 -0
  38. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/lizardstatementcount.py +0 -0
  39. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/lizardwordcount.py +0 -0
  40. {lizard-1.17.21 → lizard-1.17.23}/lizard_ext/xmloutput.py +0 -0
  41. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/__init__.py +0 -0
  42. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/clike.py +0 -0
  43. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/code_reader.py +0 -0
  44. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/csharp.py +0 -0
  45. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/erlang.py +0 -0
  46. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/fortran.py +0 -0
  47. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/gdscript.py +0 -0
  48. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/go.py +0 -0
  49. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/golike.py +0 -0
  50. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/java.py +0 -0
  51. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/javascript.py +0 -0
  52. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/js_style_language_states.py +0 -0
  53. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/js_style_regex_expression.py +0 -0
  54. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/jsx.py +0 -0
  55. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/kotlin.py +0 -0
  56. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/lua.py +0 -0
  57. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/objc.py +0 -0
  58. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/php.py +0 -0
  59. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/python.py +0 -0
  60. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/ruby.py +0 -0
  61. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/rubylike.py +0 -0
  62. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/rust.py +0 -0
  63. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/scala.py +0 -0
  64. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/script_language.py +0 -0
  65. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/solidity.py +0 -0
  66. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/swift.py +0 -0
  67. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/tnsdl.py +0 -0
  68. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/tsx.py +0 -0
  69. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/ttcn.py +0 -0
  70. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/typescript.py +0 -0
  71. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/vue.py +0 -0
  72. {lizard-1.17.21 → lizard-1.17.23}/lizard_languages/zig.py +0 -0
  73. {lizard-1.17.21 → lizard-1.17.23}/setup.cfg +0 -0
  74. {lizard-1.17.21 → lizard-1.17.23}/setup.py +0 -0
  75. {lizard-1.17.21 → lizard-1.17.23}/test/testApplication.py +0 -0
  76. {lizard-1.17.21 → lizard-1.17.23}/test/testAssertionExtension.py +0 -0
  77. {lizard-1.17.21 → lizard-1.17.23}/test/testBasicFunctionInfo.py +0 -0
  78. {lizard-1.17.21 → lizard-1.17.23}/test/testCOutsideComplexity.py +0 -0
  79. {lizard-1.17.21 → lizard-1.17.23}/test/testCPreprocessorExtension.py +0 -0
  80. {lizard-1.17.21 → lizard-1.17.23}/test/testCommentOptions.py +0 -0
  81. {lizard-1.17.21 → lizard-1.17.23}/test/testCyclomaticComplexity.py +0 -0
  82. {lizard-1.17.21 → lizard-1.17.23}/test/testExtension.py +0 -0
  83. {lizard-1.17.21 → lizard-1.17.23}/test/testFilesFilter.py +0 -0
  84. {lizard-1.17.21 → lizard-1.17.23}/test/testFunctionDependencyCount.py +0 -0
  85. {lizard-1.17.21 → lizard-1.17.23}/test/testFunctionExitCount.py +0 -0
  86. {lizard-1.17.21 → lizard-1.17.23}/test/testFunctionGotoCount.py +0 -0
  87. {lizard-1.17.21 → lizard-1.17.23}/test/testFunctionStatementCount.py +0 -0
  88. {lizard-1.17.21 → lizard-1.17.23}/test/testHelpers.py +0 -0
  89. {lizard-1.17.21 → lizard-1.17.23}/test/testLanguages.py +0 -0
  90. {lizard-1.17.21 → lizard-1.17.23}/test/testMcCabe.py +0 -0
  91. {lizard-1.17.21 → lizard-1.17.23}/test/testNestedStructures.py +0 -0
  92. {lizard-1.17.21 → lizard-1.17.23}/test/testNestingDepth.py +0 -0
  93. {lizard-1.17.21 → lizard-1.17.23}/test/testOutput.py +0 -0
  94. {lizard-1.17.21 → lizard-1.17.23}/test/testOutputCSV.py +0 -0
  95. {lizard-1.17.21 → lizard-1.17.23}/test/testOutputFile.py +0 -0
  96. {lizard-1.17.21 → lizard-1.17.23}/test/testOutputHTML.py +0 -0
  97. {lizard-1.17.21 → lizard-1.17.23}/test/testTokenizer.py +0 -0
  98. {lizard-1.17.21 → lizard-1.17.23}/test/test_analyzer.py +0 -0
  99. {lizard-1.17.21 → lizard-1.17.23}/test/test_auto_open.py +0 -0
  100. {lizard-1.17.21 → lizard-1.17.23}/test/test_options.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lizard
3
- Version: 1.17.21
3
+ Version: 1.17.23
4
4
  Summary: A code analyzer without caring the C/C++ header files. It works with Java, C/C++, JavaScript, Python, Ruby, Swift, Objective C. Metrics includes cyclomatic complexity number etc.
5
5
  Home-page: http://www.lizard.ws
6
6
  Download-URL: https://pypi.python.org/lizard/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lizard
3
- Version: 1.17.21
3
+ Version: 1.17.23
4
4
  Summary: A code analyzer without caring the C/C++ header files. It works with Java, C/C++, JavaScript, Python, Ruby, Swift, Objective C. Metrics includes cyclomatic complexity number etc.
5
5
  Home-page: http://www.lizard.ws
6
6
  Download-URL: https://pypi.python.org/lizard/
@@ -3,4 +3,4 @@
3
3
  #
4
4
  # pylint: disable=missing-docstring,invalid-name
5
5
 
6
- version = "1.17.21"
6
+ version = "1.17.23"
@@ -0,0 +1,330 @@
1
+ '''
2
+ Language parser for Perl
3
+ '''
4
+
5
+ from .code_reader import CodeReader, CodeStateMachine
6
+ from .script_language import ScriptLanguageMixIn
7
+
8
+
9
+ class PerlCommentsMixin(object):
10
+ @staticmethod
11
+ def get_comment_from_token(token):
12
+ if token.startswith('#'):
13
+ return token # Return the entire comment including #
14
+ return None
15
+
16
+
17
+ class PerlReader(CodeReader, ScriptLanguageMixIn):
18
+ # pylint: disable=R0903
19
+
20
+ ext = ['pl', 'pm']
21
+ language_names = ['perl']
22
+ _conditions = set(['if', 'elsif', 'unless', 'while', 'until', 'for', 'foreach', '&&', '||', '?', ':', 'when', 'given', 'default', 'do'])
23
+
24
+ def __init__(self, context):
25
+ super(PerlReader, self).__init__(context)
26
+ self.parallel_states = [PerlStates(context)]
27
+
28
+ def preprocess(self, tokens):
29
+ comment = None
30
+ for token in tokens:
31
+ if comment is not None:
32
+ if token == '\n':
33
+ yield comment
34
+ comment = None
35
+ yield token
36
+ else:
37
+ comment += token
38
+ elif token == '#':
39
+ comment = token
40
+ else:
41
+ yield token
42
+ if comment is not None:
43
+ yield comment
44
+
45
+ def _state(self, token):
46
+ current_state = self.parallel_states[-1]
47
+ if token == '\n':
48
+ return
49
+ return current_state.state(token)
50
+
51
+ @staticmethod
52
+ def get_comment_from_token(token):
53
+ if token.startswith('#'):
54
+ # For forgiveness comments, return the entire comment
55
+ stripped = token.lstrip('#').strip()
56
+ if stripped.startswith('lizard forgives') or stripped.startswith('#lizard forgives'):
57
+ return '#lizard forgives' # Return standardized forgiveness comment
58
+ return stripped # Return the stripped comment for other cases
59
+ return None
60
+
61
+ @staticmethod
62
+ def generate_tokens(source_code, addition='', token_class=None):
63
+ return ScriptLanguageMixIn.generate_common_tokens(source_code, addition, token_class)
64
+
65
+
66
+ class PerlStates(CodeStateMachine):
67
+ _conditions = set(['if', 'elsif', 'unless', 'while', 'until', 'for', 'foreach', '&&', '||', '?', ':', 'when', 'given', 'default', 'do'])
68
+
69
+ def __init__(self, context):
70
+ super(PerlStates, self).__init__(context)
71
+ self.function_name = ''
72
+ self.package_name = ''
73
+ self.variable_name = ''
74
+ self.brace_count = 0
75
+ self.paren_count = 0
76
+ self.in_attribute = False
77
+ self.anonymous_count = 0
78
+ self._state = self._state_global
79
+
80
+ def _state_global(self, token):
81
+ if token == 'package':
82
+ self.next(self._state_package_dec)
83
+ elif token == 'sub':
84
+ self.function_name = ''
85
+ self.next(self._state_function_dec)
86
+ elif token == '{':
87
+ self.brace_count += 1
88
+ elif token == '}':
89
+ self.brace_count -= 1
90
+ elif token == '(':
91
+ self.paren_count += 1
92
+ self.next(self._state_function_call)
93
+ elif token == '$' or token == 'my' or token == 'our' or token == 'local':
94
+ self.variable_name = ''
95
+ self.next(self._state_variable)
96
+
97
+ def _state_package_dec(self, token):
98
+ if not token.isspace():
99
+ self.package_name = token
100
+ self.next(self._state_global)
101
+
102
+ def _state_variable(self, token):
103
+ if token == '$':
104
+ # Skip the $ in variable names
105
+ pass
106
+ elif token == '=':
107
+ self.next(self._state_assignment)
108
+ elif token == ';':
109
+ self.variable_name = ''
110
+ self.next(self._state_global)
111
+ elif not token.isspace() and self.variable_name == '':
112
+ self.variable_name = token
113
+
114
+ def _state_assignment(self, token):
115
+ if token == 'sub':
116
+ self.next(self._state_anon_sub)
117
+ elif token == ';':
118
+ self.variable_name = ''
119
+ self.next(self._state_global)
120
+
121
+ def _state_function_call(self, token):
122
+ if token == 'sub':
123
+ # Inline anonymous subroutine as argument
124
+ self.anonymous_count += 1
125
+ full_name = f"<anonymous>"
126
+ if self.package_name:
127
+ full_name = f"{self.package_name}::{full_name}"
128
+
129
+ self.context.try_new_function(full_name)
130
+ self.context.confirm_new_function()
131
+ self.next(self._state_anon_brace_search)
132
+ elif token == ')':
133
+ self.paren_count -= 1
134
+ if self.paren_count == 0:
135
+ self.next(self._state_global)
136
+ elif token == '(':
137
+ self.paren_count += 1
138
+
139
+ def _state_anon_sub(self, token):
140
+ if token == '{':
141
+ self.brace_count = 1
142
+ full_name = '<anonymous>'
143
+ # Use variable name if available for more readable function names
144
+ if self.variable_name:
145
+ full_name = '$' + self.variable_name
146
+
147
+ if self.package_name:
148
+ full_name = f"{self.package_name}::{full_name}"
149
+
150
+ self.context.try_new_function(full_name)
151
+ self.context.confirm_new_function()
152
+ self.next(self._state_function_body)
153
+
154
+ def _state_function_dec(self, token):
155
+ if token == '{':
156
+ self.brace_count = 1
157
+ if self.function_name:
158
+ full_name = self.function_name
159
+ if self.package_name:
160
+ full_name = f"{self.package_name}::{self.function_name}"
161
+ self.context.try_new_function(full_name)
162
+ self.context.confirm_new_function()
163
+ self.next(self._state_function_body)
164
+ elif token == ':':
165
+ self.in_attribute = True
166
+ elif token == ';':
167
+ # Forward declaration like "sub func_name;"
168
+ if self.function_name:
169
+ full_name = self.function_name
170
+ if self.package_name:
171
+ full_name = f"{self.package_name}::{self.function_name}"
172
+ self.context.try_new_function(full_name)
173
+ self.context.confirm_new_function()
174
+ # Empty function body
175
+ self.context.end_of_function()
176
+ self.next(self._state_global)
177
+ elif token == '(':
178
+ # Function with parameter prototype like "sub fetch($)"
179
+ # Save the current function name and look for closing paren
180
+ self.paren_count = 1
181
+ self.next(self._state_function_prototype)
182
+ elif token == 'sub':
183
+ # Handle anonymous subroutine like 'callback(sub { ... })'
184
+ self.anonymous_count += 1
185
+ full_name = f"<anonymous>"
186
+ if self.package_name:
187
+ full_name = f"{self.package_name}::{full_name}"
188
+ self.context.try_new_function(full_name)
189
+ self.context.confirm_new_function()
190
+ self.next(self._state_anon_brace_search)
191
+ elif not token.isspace():
192
+ if not self.in_attribute:
193
+ self.function_name = token
194
+ else:
195
+ # Skip attribute name
196
+ self.in_attribute = False
197
+
198
+ def _state_function_prototype(self, token):
199
+ # Handle parameter prototypes after function name: sub fetch($) { ... }
200
+ if token == ')':
201
+ self.paren_count -= 1
202
+ if self.paren_count == 0:
203
+ # Return to function declaration state to handle the opening brace
204
+ self.next(self._state_function_dec)
205
+ elif token == '(':
206
+ self.paren_count += 1
207
+
208
+ def _state_anon_brace_search(self, token):
209
+ if token == '{':
210
+ self.brace_count = 1
211
+ self.next(self._state_function_body)
212
+ elif token == '(':
213
+ self.paren_count += 1
214
+ elif token == ')':
215
+ self.paren_count -= 1
216
+ if self.paren_count == 0:
217
+ self.next(self._state_global)
218
+
219
+ def _state_function_body(self, token):
220
+ if token == '{':
221
+ self.brace_count += 1
222
+ elif token == '}':
223
+ self.brace_count -= 1
224
+ if self.brace_count == 0:
225
+ self.context.end_of_function()
226
+ self.next(self._state_global)
227
+ elif token == '?':
228
+ # Ternary operator increases complexity
229
+ self.context.add_condition()
230
+ elif token == ':':
231
+ # Colon part of ternary operator also increases complexity
232
+ self.context.add_condition()
233
+ elif token == 'sub':
234
+ # Check if it's a nested named subroutine or anonymous
235
+ self.next(self._state_nested_sub_dec)
236
+ elif token == '(':
237
+ # Track function calls inside function body
238
+ self.paren_count += 1
239
+ self.next(self._state_nested_call)
240
+
241
+ def _state_nested_sub_dec(self, token):
242
+ if token.isspace():
243
+ return
244
+ elif token == '{':
245
+ # Anonymous sub
246
+ self.brace_count += 1
247
+ self.anonymous_count += 1
248
+ anon_name = f"<anonymous>"
249
+ if self.package_name:
250
+ anon_name = f"{self.package_name}::{anon_name}"
251
+ self.context.add_condition() # Count sub as a condition
252
+ self.next(self._state_function_body)
253
+ else:
254
+ # Named nested sub
255
+ nested_func_name = token
256
+ full_name = nested_func_name
257
+ if self.package_name:
258
+ full_name = f"{self.package_name}::{nested_func_name}"
259
+
260
+ # Save current function state
261
+ saved_func_context = self.context
262
+
263
+ # Create a new function for the nested sub
264
+ self.context.try_new_function(full_name)
265
+ self.context.confirm_new_function()
266
+ self.next(self._state_nested_named_sub_brace_search)
267
+
268
+ def _state_nested_named_sub_brace_search(self, token):
269
+ if token == '{':
270
+ self.brace_count = 1
271
+ self.next(self._state_nested_sub_body)
272
+ elif token.isspace():
273
+ return
274
+ elif token == ':':
275
+ # Handle attributes in nested sub
276
+ self.in_attribute = True
277
+ return
278
+ elif token == ';':
279
+ # Forward declaration
280
+ self.context.end_of_function()
281
+ self.next(self._state_function_body)
282
+
283
+ def _state_nested_sub_body(self, token):
284
+ if token == '{':
285
+ self.brace_count += 1
286
+ elif token == '}':
287
+ self.brace_count -= 1
288
+ if self.brace_count == 0:
289
+ # End the nested function
290
+ self.context.end_of_function()
291
+ # Return to parent function
292
+ self.next(self._state_function_body)
293
+
294
+ def _state_nested_call(self, token):
295
+ if token == 'sub':
296
+ # Inline anonymous subroutine as argument
297
+ self.anonymous_count += 1
298
+ full_name = f"<anonymous>"
299
+ if self.package_name:
300
+ full_name = f"{self.package_name}::{full_name}"
301
+
302
+ self.context.try_new_function(full_name)
303
+ self.context.confirm_new_function()
304
+ self.next(self._state_nested_anon_search)
305
+ elif token == ')':
306
+ self.paren_count -= 1
307
+ if self.paren_count == 0:
308
+ self.next(self._state_function_body)
309
+ elif token == '(':
310
+ self.paren_count += 1
311
+
312
+ def _state_nested_anon_search(self, token):
313
+ if token == '{':
314
+ self.brace_count += 1
315
+ self.next(self._state_nested_anon_body)
316
+ elif token == '(':
317
+ self.paren_count += 1
318
+ elif token == ')':
319
+ self.paren_count -= 1
320
+ if self.paren_count == 0:
321
+ self.next(self._state_function_body)
322
+
323
+ def _state_nested_anon_body(self, token):
324
+ if token == '{':
325
+ self.brace_count += 1
326
+ elif token == '}':
327
+ self.brace_count -= 1
328
+ if self.brace_count == 1: # Back to outer function level
329
+ self.context.end_of_function()
330
+ self.next(self._state_function_body)
@@ -1,103 +0,0 @@
1
- '''
2
- Language parser for Perl
3
- '''
4
-
5
- from .code_reader import CodeReader, CodeStateMachine
6
- from .script_language import ScriptLanguageMixIn
7
-
8
-
9
- class PerlCommentsMixin(object):
10
- @staticmethod
11
- def get_comment_from_token(token):
12
- if token.startswith('#'):
13
- return token # Return the entire comment including #
14
- return None
15
-
16
-
17
- class PerlReader(CodeReader, ScriptLanguageMixIn):
18
- # pylint: disable=R0903
19
-
20
- ext = ['pl', 'pm']
21
- language_names = ['perl']
22
- _conditions = set(['if', 'elsif', 'unless', 'while', 'until', 'for', 'foreach', '&&', '||', '?', 'when'])
23
-
24
- def __init__(self, context):
25
- super(PerlReader, self).__init__(context)
26
- self.parallel_states = [PerlStates(context)]
27
-
28
- def preprocess(self, tokens):
29
- comment = None
30
- for token in tokens:
31
- if comment is not None:
32
- if token == '\n':
33
- yield comment
34
- comment = None
35
- yield token
36
- else:
37
- comment += token
38
- elif token == '#':
39
- comment = token
40
- else:
41
- yield token
42
- if comment is not None:
43
- yield comment
44
-
45
- def _state(self, token):
46
- current_state = self.parallel_states[-1]
47
- if token == '\n':
48
- return
49
- return current_state.state(token)
50
-
51
- @staticmethod
52
- def get_comment_from_token(token):
53
- if token.startswith('#'):
54
- # For forgiveness comments, return the entire comment
55
- stripped = token.lstrip('#').strip()
56
- if stripped.startswith('lizard forgives') or stripped.startswith('#lizard forgives'):
57
- return '#lizard forgives' # Return standardized forgiveness comment
58
- return stripped # Return the stripped comment for other cases
59
- return None
60
-
61
- @staticmethod
62
- def generate_tokens(source_code, addition='', token_class=None):
63
- return ScriptLanguageMixIn.generate_common_tokens(source_code, addition, token_class)
64
-
65
-
66
- class PerlStates(CodeStateMachine):
67
- _conditions = set(['if', 'elsif', 'unless', 'while', 'until', 'for', 'foreach'])
68
-
69
- def __init__(self, context):
70
- super(PerlStates, self).__init__(context)
71
- self.function_name = ''
72
- self.brace_count = 0
73
- self._state = self._state_global
74
-
75
- def _state_global(self, token):
76
- if token == 'sub':
77
- self.function_name = ''
78
- self.next(self._state_function_dec)
79
- elif token == '{':
80
- self.brace_count += 1
81
- elif token == '}':
82
- self.brace_count -= 1
83
-
84
- def _state_function_dec(self, token):
85
- if token == '{':
86
- self.brace_count = 1
87
- if self.function_name:
88
- self.context.try_new_function(self.function_name)
89
- self.context.confirm_new_function()
90
- self.next(self._state_function_body)
91
- elif token == ';':
92
- self.next(self._state_global)
93
- elif not token.isspace():
94
- self.function_name = token
95
-
96
- def _state_function_body(self, token):
97
- if token == '{':
98
- self.brace_count += 1
99
- elif token == '}':
100
- self.brace_count -= 1
101
- if self.brace_count == 0:
102
- self.context.end_of_function()
103
- self.next(self._state_global)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes