@@ -13,9 +13,11 @@ import SwiftSemantics
1313class Generator {
1414
1515 let source : String
16+ let mapUnderscoreToCamelCase : Bool
1617
17- init ( source: String ) {
18+ init ( source: String , mapUnderscoreToCamelCase : Bool = false ) {
1819 self . source = source
20+ self . mapUnderscoreToCamelCase = mapUnderscoreToCamelCase
1921 }
2022
2123 var encode : [ String ] = [ """
@@ -35,17 +37,43 @@ class Generator {
3537 """
3638 ]
3739
38- func addNode( name: String , type: String , isOptional: Bool = false ) {
40+ func addNode( name: String , type: String , isOptional: Bool = false ) {
3941 encode. append ( " try container.encode( \( name) , forKey: . \( name) ) " )
4042 if isOptional {
4143 initStrings. append ( " \( name) = try container.decodeIfPresent( \( type. trimmingCharacters ( in: . init( charactersIn: " ? " ) ) ) .self, forKey: . \( name) ) " )
4244 } else {
4345 initStrings. append ( " \( name) = try container.decode( \( type) .self, forKey: . \( name) ) " )
4446 }
45- codingKeys. append ( " case \( name) = \" \( name) \" " )
47+
48+ if mapUnderscoreToCamelCase {
49+ codingKeys. append ( " case \( name) = \" \( mapCamelToUnderscore ( name) ) \" " )
50+ } else {
51+ codingKeys. append ( " case \( name) = \" \( name) \" " )
52+ }
53+ }
54+
55+ func mapCamelToUnderscore( _ string: String ) -> String {
56+ var res = " "
57+
58+ var strCopy = string [ ... ]
59+ while let match = parseWord ( str: & strCopy) {
60+ res += " _ " + match. lowercased ( )
61+ }
62+ return res. trimmingCharacters ( in: CharacterSet . init ( charactersIn: " _ " ) )
4663 }
4764
48- /// Generation is based on dumb pattern matchint
65+ func parseWord( str: inout Substring ) -> String ? {
66+
67+ if let lowerMatch = Parser . lower. run ( & str) {
68+ return lowerMatch
69+ }
70+ if let upperThenLower = zip ( Parser . upper, Parser . lower) . run ( & str) {
71+ return upperThenLower. 0 + upperThenLower. 1
72+ }
73+ return Parser . upper. run ( & str)
74+ }
75+
76+ /// Generation is based on dumb pattern matchint
4977 func generate( ) throws -> String {
5078 var collector = DeclarationCollector ( )
5179 let tree = try SyntaxParser . parse ( source: source)
@@ -82,3 +110,37 @@ class Generator {
82110 }
83111}
84112
113+ struct Parser < A> {
114+ let run : ( inout Substring ) -> A ?
115+ }
116+
117+ extension Parser where A == String {
118+
119+ static func predicate( _ predicate: @escaping ( Character ) -> Bool ) -> Parser {
120+ Parser { str in
121+ let match = str. prefix ( while: predicate)
122+ guard !match. isEmpty else { return nil }
123+ str. removeFirst ( match. count)
124+ return String ( match)
125+ }
126+ }
127+
128+ static let upper : Parser = . predicate { $0. isUppercase }
129+
130+ static let lower : Parser = . predicate { $0. isLowercase }
131+ }
132+
133+ func zip< A, B> ( _ pa: Parser < A > , _ pb: Parser < B > ) -> Parser < ( A , B ) > {
134+ Parser { str in
135+ let originalString = str
136+ guard let a = pa. run ( & str) else {
137+ return nil
138+ }
139+ guard let b = pb. run ( & str) else {
140+ str = originalString
141+ return nil
142+ }
143+ return ( a, b)
144+ }
145+ }
146+
0 commit comments