Skip to content

Commit 9b24242

Browse files
authored
Merge pull request #2 from dxworks/victorc/update-kt
Victorc/update kt
2 parents d2a40dc + fa4b2af commit 9b24242

File tree

6 files changed

+347
-20
lines changed

6 files changed

+347
-20
lines changed

README.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ A list of supported languages:
3434
- Lua
3535
- Rust
3636
- Fortran
37+
- Kotlin
3738

3839
By default lizard will search for any source code that it knows and mix
3940
all the results together. This might not be what you want. You can use

lizard.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -563,10 +563,13 @@ def analyze_source_code(self, filename, code):
563563
context = FileInfoBuilder(filename)
564564
reader = (get_reader_for(filename) or CLikeReader)(context)
565565
tokens = reader.generate_tokens(code)
566-
for processor in self.processors:
567-
tokens = processor(tokens, reader)
568-
for _ in reader(tokens, reader):
569-
pass
566+
try:
567+
for processor in self.processors:
568+
tokens = processor(tokens, reader)
569+
for _ in reader(tokens, reader):
570+
pass
571+
except RecursionError as e:
572+
sys.stderr.write("[skip] fail to process '%s' with RecursionError - %s\n" % (filename, e))
570573
return context.fileinfo
571574

572575

lizard_languages/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from .clike import CLikeReader
44
from .java import JavaReader
55
from .javascript import JavaScriptReader
6+
from .kotlin import KotlinReader
67
from .python import PythonReader
78
from .objc import ObjCReader
89
from .ttcn import TTCNReader
@@ -37,7 +38,8 @@ def languages():
3738
LuaReader,
3839
RustReader,
3940
TypeScriptReader,
40-
FortranReader
41+
FortranReader,
42+
KotlinReader
4143
]
4244

4345

lizard_languages/kotlin.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
'''
2+
Language parser for Apple Swift
3+
'''
4+
5+
from .clike import CCppCommentsMixin
6+
from .code_reader import CodeReader, CodeStateMachine
7+
from .golike import GoLikeStates
8+
from .swift import SwiftReplaceLabel
9+
10+
11+
class KotlinReader(CodeReader, CCppCommentsMixin, SwiftReplaceLabel):
12+
# pylint: disable=R0903
13+
14+
ext = ['kt', 'kts']
15+
language_names = ['kotlin']
16+
_conditions = {
17+
'if', 'for', 'while', 'catch', '&&', '||', '?:'
18+
}
19+
20+
def __init__(self, context):
21+
super(KotlinReader, self).__init__(context)
22+
self.parallel_states = [KotlinStates(context)]
23+
24+
@staticmethod
25+
def generate_tokens(source_code, addition='', token_class=None):
26+
return CodeReader.generate_tokens(
27+
source_code,
28+
r"|`\w+`" +
29+
r"|\w+\?" +
30+
r"|\w+\!!" +
31+
r"|\?\?" +
32+
r"|\?:" +
33+
addition
34+
)
35+
36+
37+
class KotlinStates(GoLikeStates): # pylint: disable=R0903
38+
39+
FUNC_KEYWORD = 'fun'
40+
41+
def __init__(self, context, in_when_cases=False):
42+
super().__init__(context)
43+
self._in_when_cases = in_when_cases
44+
45+
def _state_global(self, token):
46+
if token in ('get', 'set'):
47+
self.context.push_new_function(token)
48+
self._state = self._expect_function_impl
49+
elif token == '->':
50+
if self._in_when_cases:
51+
self.context.add_condition()
52+
else:
53+
self.context.push_new_function("(anonymous)")
54+
self._state = super(KotlinStates, self)._expect_function_impl
55+
elif token in ('val', 'var', ','):
56+
self._state = self._expect_declaration_name
57+
elif token == 'interface':
58+
self._state = self._interface
59+
elif token == 'when':
60+
self._state = self._when_cases
61+
else:
62+
super(KotlinStates, self)._state_global(token)
63+
64+
def _expect_declaration_name(self, token):
65+
self._state = self._state_global
66+
67+
def _expect_function_impl(self, token):
68+
if token == '{' or token == '=':
69+
self.next(self._function_impl, token)
70+
71+
@CodeStateMachine.read_inside_brackets_then("{}")
72+
def _interface(self, end_token):
73+
if end_token == "}":
74+
self._state = self._state_global
75+
76+
def _function_name(self, token):
77+
if token == "<":
78+
self.next(self._template, token)
79+
else:
80+
return super(KotlinStates, self)._function_name(token)
81+
82+
@CodeStateMachine.read_inside_brackets_then("<>", "_function_name")
83+
def _template(self, tokens):
84+
pass
85+
86+
def _when_cases(self, token):
87+
def callback():
88+
self.context.add_condition(inc=-1)
89+
self.next(self._state_global)
90+
if token != '{':
91+
return
92+
self.sub_state(KotlinStates(self.context, in_when_cases=True), callback)

lizard_languages/swift.py

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,24 @@
77
from .golike import GoLikeStates
88

99

10-
class SwiftReader(CodeReader, CCppCommentsMixin):
10+
class SwiftReplaceLabel:
11+
def preprocess(self, tokens):
12+
tokens = list(t for t in tokens if not t.isspace() or t == '\n')
13+
14+
def replace_label(tokens, target, replace):
15+
for i in range(0, len(tokens) - len(target)):
16+
if tokens[i:i + len(target)] == target:
17+
for j, repl in enumerate(replace):
18+
tokens[i + j] = repl
19+
return tokens
20+
21+
for k in (k for k in self.conditions if k.isalpha()):
22+
tokens = replace_label(tokens, ["(", k, ":"], ["(", "_" + k, ":"])
23+
tokens = replace_label(tokens, [",", k, ":"], [",", "_" + k, ":"])
24+
return tokens
25+
26+
27+
class SwiftReader(CodeReader, CCppCommentsMixin, SwiftReplaceLabel):
1128
# pylint: disable=R0903
1229

1330
FUNC_KEYWORD = 'def'
@@ -30,20 +47,6 @@ def generate_tokens(source_code, addition='', token_class=None):
3047
r"|\?\?" +
3148
addition)
3249

33-
def preprocess(self, tokens):
34-
tokens = list(t for t in tokens if not t.isspace() or t == '\n')
35-
36-
def replace_label(tokens, target, replace):
37-
for i in range(0, len(tokens) - len(target)):
38-
if tokens[i:i + len(target)] == target:
39-
for j, repl in enumerate(replace):
40-
tokens[i + j] = repl
41-
return tokens
42-
for k in (k for k in self.conditions if k.isalpha()):
43-
tokens = replace_label(tokens, ["(", k, ":"], ["(", "_" + k, ":"])
44-
tokens = replace_label(tokens, [",", k, ":"], [",", "_" + k, ":"])
45-
return tokens
46-
4750

4851
class SwiftStates(GoLikeStates): # pylint: disable=R0903
4952
def _state_global(self, token):

0 commit comments

Comments
 (0)