@@ -11,38 +11,20 @@ class SceneNodesParser {
11
11
}
12
12
13
13
private class ScenesParser {
14
- fun parse (sceneFileContent : String ): Map <String , String > = sceneFileContent
15
- .let (::splitToSceneLines)
16
- .map(::parseSceneParams)
17
- .mapNotNull(::getSceneIdToPath)
18
- .let (::getScenePathsById)
19
-
20
- private fun splitToSceneLines (data : String ): List <String > {
21
- return data.split(" \n " ).filter { line ->
22
- line.startsWith(" [ext_resource type=\" PackedScene\" " ) && line.endsWith(" ]" )
23
- }.also (Log ::parsedSceneResources)
14
+ fun parse (sceneFileContent : String ): Map <String , String > {
15
+ Log .parsingScenePaths()
16
+ return splitToEntries(sceneFileContent, " ext_resource" )
17
+ .map(::parseEntryParams)
18
+ .mapNotNull(::extractSceneIdToPath)
19
+ .let (::getScenePathsById)
24
20
}
25
21
26
- private fun parseSceneParams (line : String ): Map <String , String > {
27
- Log .parsingSceneResource(line)
28
-
29
- val pattern = " ^\\ [ext_resource (.*)]$" .toRegex()
30
- val groups = pattern.find(line)?.groups?.filterNotNull() ? : emptyList()
31
- val paramsLine = groups.takeIf { it.size == 2 }?.last()?.value
32
- paramsLine ? : throw UnexpectedResourceFormat (line)
33
-
34
- val paramPattern = " \\ w+=\" .+?\" " .toRegex()
35
- val segments = paramPattern.findAll(paramsLine).map { it.value }.toList()
36
- return segments.associate(::parseParamSegment)
37
- }
38
-
39
-
40
- private fun getSceneIdToPath (params : Map <String , String >): Pair <String , String >? {
41
- val id = params.extract(" id" )
42
- val path = params.extract(" path" )
22
+ private fun extractSceneIdToPath (params : Map <String , String >): Pair <String , String >? {
23
+ val id = params[" id" ]
24
+ val path = params[" path" ]
43
25
44
26
if (id == null || path == null ) {
45
- Log .skippingSceneResource()
27
+ Log .skippingSceneResource(params )
46
28
return null
47
29
}
48
30
@@ -51,54 +33,35 @@ private class ScenesParser {
51
33
52
34
private fun getScenePathsById (sceneIdsToPaths : List <Pair <String , String >>): Map <String , String > {
53
35
val duplicates = sceneIdsToPaths
54
- .groupBy { it.first }
36
+ .groupBy( { it.first }, { it.second })
55
37
.filter { it.value.size > 1 }
56
- .mapValues { it.value.map { idToPath -> idToPath.second } }
57
38
58
39
if (duplicates.isNotEmpty()) {
59
- throw DuplicatedSceneResources (duplicates)
40
+ Log .duplicatedSceneResources (duplicates)
60
41
}
61
42
62
43
return sceneIdsToPaths.toMap()
63
44
}
64
45
}
65
46
66
47
private class NodesParser (val scenePathsById : Map <String , String >) {
67
- fun parse (sceneFileContent : String ): Node = sceneFileContent
68
- .let (::splitToNodeLines)
69
- .map(::parseNodeParams)
70
- .mapNotNull(::createNodeParams)
71
- .let (::createRootNode)
72
-
73
-
74
- private fun splitToNodeLines (data : String ): List <String > {
75
- return data.split(" \n " ).filter { line ->
76
- line.startsWith(" [node" ) && line.endsWith(" ]" )
77
- }.also (Log ::parsedSceneNodes)
78
- }
79
-
80
- private fun parseNodeParams (line : String ): Map <String , String > {
81
- Log .parsingNode(line)
82
-
83
- val pattern = " ^\\ [node (.*)]$" .toRegex()
84
- val groups = pattern.find(line)?.groups?.filterNotNull() ? : emptyList()
85
- val paramsLine = groups.takeIf { it.size == 2 }?.last()?.value
86
- paramsLine ? : throw UnexpectedNodeFormat (line)
87
-
88
- val paramPattern = " \\ w+=(\" .+?\" |\\ w+\\ (\" .+\"\\ ))" .toRegex()
89
- val segments = paramPattern.findAll(paramsLine).map { it.value }.toList()
90
- return segments.associate(::parseParamSegment)
48
+ fun parse (sceneFileContent : String ): Node {
49
+ Log .parsingSceneNodes()
50
+ return splitToEntries(sceneFileContent, " node" )
51
+ .map(::parseEntryParams)
52
+ .mapNotNull(::extractNodeParams)
53
+ .let (::createRootNode)
91
54
}
92
55
93
56
94
- private fun createNodeParams (params : Map <String , String >): NodeParams ? {
95
- val name = params.extract( " name" )
96
- val type = params.extract( " type" )
97
- val instance = params.extractResource( " instance" )
98
- val parent = params.extract( " parent" )
57
+ private fun extractNodeParams (params : Map <String , String >): NodeParams ? {
58
+ val name = params[ " name" ]
59
+ val type = params[ " type" ]
60
+ val instance = params[ " instance" ]
61
+ val parent = params[ " parent" ]
99
62
100
63
if (name == null || (type == null && instance == null ) || (type != null && instance != null )) {
101
- Log .skippingNode()
64
+ Log .skippingNode(params )
102
65
return null
103
66
}
104
67
@@ -140,10 +103,8 @@ data class NodeParams(
140
103
}
141
104
142
105
type == null && instance != null -> {
143
- val pattern = " ^res://(.*).tscn$" .toRegex()
144
- val scenePath = scenePathsById[instance] ? : throw UnexpectedSceneResource (instance)
145
- val scene = pattern.find(scenePath)?.groupValues?.getOrNull(1 )?.capitalize()
146
- scene ? : throw UnexpectedNodeFormat (scenePath)
106
+ val scene = scenePathsById[instance]?.let (::parseSceneName)?.capitalize()
107
+ scene ? : throw UnexpectedSceneResource (instance)
147
108
NestedScene (name = name, scene = scene)
148
109
}
149
110
@@ -152,16 +113,24 @@ data class NodeParams(
152
113
}
153
114
}
154
115
155
- private fun parseParamSegment ( segment : String ): Pair < String , String > {
156
- val paramPattern = " ^(.+)=(.+)$ " .toRegex( )
157
- val groups = paramPattern.find(segment)?.groups?.filterNotNull() ? : emptyList ()
158
- return groups.map { it.value }. let { it[ 1 ] to it[ 2 ] }
116
+ private fun splitToEntries ( data : String , entryType : String ): List < String > {
117
+ Log .splittingEntries(entryType )
118
+ val pattern = """ \[ ${entryType} .*] """ .toRegex ()
119
+ return pattern.findAll(data).mapNotNull { it.groupValues.firstOrNull() }.toList()
159
120
}
160
121
161
- private fun Map <String , String >.extract (key : String ): String? {
162
- return this [key]?.trim(' \" ' )
122
+ private fun parseEntryParams (entry : String ): Map <String , String > {
123
+ Log .parsingEntryParams(entry)
124
+ val pattern = """ (?:(\w+)=(?:\w+\("(.+)"\)|"(.+?)"))+""" .toRegex()
125
+ return pattern.findAll(entry).associate { match ->
126
+ val (key, argumentValue, plainValue) = match.destructured
127
+ val value = argumentValue.ifEmpty { plainValue }
128
+ key to value
129
+ }
163
130
}
164
131
165
- private fun Map <String , String >.extractResource (key : String ): String? {
166
- return this [key]?.removePrefix(" ExtResource(\" " )?.removeSuffix(" \" )" )
132
+ private fun parseSceneName (scenePath : String ): String? {
133
+ Log .parsingEntryParams(scenePath)
134
+ val pattern = """ ^res://(.*).tscn$""" .toRegex()
135
+ return pattern.find(scenePath)?.groupValues?.getOrNull(1 )
167
136
}
0 commit comments