1
+ using System ;
2
+ using System . Text ;
3
+ using System . Text . RegularExpressions ;
4
+
5
+ class Program
6
+ {
7
+ private static Regex reCls = new ( @"^ *(class|struct) ([A-z_0-9 ]+)\W*(\{(?:[^{}]|(?<open>\{)|(?<-open>\}))+(?(open)(?!))\})" , RegexOptions . Multiline ) ;
8
+ private static Regex reCom = new ( @"/\*\w+\*/" ) ;
9
+ private static Regex reDeclDef = new ( @"^([A-z_0-9 :<,>]+)\(([A-z_0-9\- ,=:<>&*/.\r\n]*)\)\s*((\{(?:[^{}]|(?<open>\{)|(?<-open>\}))+(?(open)(?!))\})|;)" , RegexOptions . Multiline ) ;
10
+ private static Regex reImpl = new ( @"^([A-z_0-9 :<,>]+)\(([A-z_0-9 ,=:<>&*/.\r\n]*)\)[\sa-z]*((:([\s ]*[A-z_0-9]+\{[A-z0-9.]+\},)+[\s ]*[A-z_0-9]+\{[A-z0-9.]+\})?\s*(\{(?:[^{}]|(?<open>\{)|(?<-open>\}))+(?(open)(?!))\}))" , RegexOptions . Multiline ) ;
11
+ private static Regex reMemb = new ( @"^([A-z_0-9 :<,>]+)(\{[A-z0-9.:]+\})?;" , RegexOptions . Multiline ) ;
12
+ private static Regex reVector = new ( @"std::vector<([^,<>]*)>" ) ;
13
+ private static Regex reListInit = new ( @"(System::Collections::Generic::List<[A-z0-9_]+>)\^\s*(\w+);" ) ;
14
+ private static Regex reLambda = new ( @"\[\]\((.*)\)\s*->\s*([A-z]+)\s*(\{(?:[^{}]|(?<open>\{)|(?<-open>\}))+(?(open)(?!))\})" ) ;
15
+ private static Regex reInclude = new ( @"^#include .*$" , RegexOptions . Multiline ) ;
16
+ private static Regex reEndif = new ( @"^#endif .*$" , RegexOptions . Multiline ) ;
17
+
18
+ private static string Namespace = "AAPlusSharp" ;
19
+
20
+ public static int Main ( string [ ] args )
21
+ {
22
+ if ( args . Length != 2 )
23
+ return 1 ;
24
+
25
+ Console . WriteLine ( "currently no AAVSOP2013" ) ;
26
+
27
+ var input = args [ 0 ] ;
28
+ var output = args [ 1 ] ;
29
+
30
+ Directory . CreateDirectory ( output ) ;
31
+ var exclusion = new string [ ] { "AA+.h" , "stdafx.h" , "stdafx.cpp" } ;
32
+
33
+ foreach ( var p in Directory . EnumerateFiles ( input , "*.h" ) )
34
+ {
35
+ using var sr = new StreamReader ( p ) ;
36
+ using var sw = new StreamWriter ( Path . Combine ( output , Path . GetFileName ( p ) ) ) ;
37
+ if ( exclusion . Any ( e => p . EndsWith ( e ) ) )
38
+ sw . Write ( sr . ReadToEnd ( ) ) ;
39
+ else
40
+ sw . Write ( ProcessHeader ( sr . ReadToEnd ( ) ) ) ;
41
+ }
42
+
43
+ foreach ( var p in Directory . EnumerateFiles ( input , "*.cpp" ) )
44
+ {
45
+ using var sr = new StreamReader ( p ) ;
46
+ using var sw = new StreamWriter ( Path . Combine ( output , Path . GetFileName ( p ) ) ) ;
47
+ if ( exclusion . Any ( e => p . EndsWith ( e ) ) )
48
+ sw . Write ( sr . ReadToEnd ( ) ) ;
49
+ else
50
+ sw . Write ( ProcessImpl ( sr . ReadToEnd ( ) ) ) ;
51
+ }
52
+
53
+ return 0 ;
54
+ }
55
+
56
+ private static string RemoveQualifiers ( string cpp )
57
+ {
58
+ var cli = new StringBuilder ( cpp ) ;
59
+ cli . Replace ( ") noexcept" , ")" ) ;
60
+ cli . Replace ( ") const noexcept" , ")" ) ;
61
+ cli . Replace ( "constexpr " , "" ) ;
62
+ cli . Replace ( "const " , "" ) ; // !!!
63
+ cli . Replace ( " const" , "" ) ; // !!!
64
+ return cli . ToString ( ) ;
65
+ }
66
+
67
+ private static string ReplaceStd ( string cpp )
68
+ {
69
+ //var cli = new StringBuilder(cpp);
70
+ //cli.Replace("#include <vector>", "#include \"AAPArray.h\"");
71
+ //cli.Replace("std::vector", "AAPArray");
72
+ //return cli.ToString();
73
+
74
+ //cpp = cpp.Replace("#include <vector>", "#include \"AAPArray.h\"");
75
+ cpp = cpp . Replace ( "#include <vector>" , "" ) ;
76
+ //cpp = reVector.Replace(cpp, "AAPArray<$1>");
77
+ cpp = reVector . Replace ( cpp , "System::Collections::Generic::List<$1>^" ) ;
78
+ cpp = cpp . Replace ( ".push_back" , "->Add" ) ;
79
+ cpp = reListInit . Replace ( cpp , "$1^ $2 = gcnew $1(0);" ) ;
80
+ return cpp ;
81
+ }
82
+
83
+ public static string ProcessHeader ( string cpp )
84
+ {
85
+ cpp = RemoveQualifiers ( cpp ) ;
86
+ cpp = ReplaceStd ( cpp ) ;
87
+
88
+ var cli = new StringBuilder ( cpp ) ;
89
+ var matches = reCls . Matches ( cpp ) ;
90
+ foreach ( Match m in matches . Reverse < Match > ( ) )
91
+ {
92
+ var name = m . Groups [ 2 ] . Value ;
93
+ if ( name . Contains ( "Coefficient" ) )
94
+ {
95
+ // native type, do nothing
96
+ }
97
+ else
98
+ {
99
+ var type = m . Groups [ 1 ] . Value ;
100
+ //var isRef = type == "class";
101
+ //var isRef = !name.Contains("Details2");
102
+ var body = ProcessHeaderClassBody ( out var isRef , name , m . Groups [ 3 ] . Value ) ;
103
+ var rv = isRef ? "ref" : "value" ;
104
+ var cls = $ "public { rv } { type } { name } \r \n { body } ";
105
+ cli . Remove ( m . Index , m . Length ) ;
106
+ cli . Insert ( m . Index , cls ) ;
107
+ }
108
+ }
109
+ cpp = cli . ToString ( ) ;
110
+
111
+ cpp = EdgeCases ( cpp ) ;
112
+ if ( matches . Count > 0 )
113
+ cpp = AddNamespace ( cpp , matches [ 0 ] . Index , reEndif . Matches ( cpp ) . Last ( ) . Index ) ;
114
+
115
+ return cpp ;
116
+ }
117
+
118
+ public static string ProcessHeaderClassBody ( out bool isRef , string name , string body )
119
+ {
120
+ int numMethods = reDeclDef . Matches ( body ) . Count ;
121
+ body = FixHeaderOverload ( body , reDeclDef . Matches ( body ) ) ;
122
+ body = FixHeaderRefPointer ( body , reDeclDef . Matches ( body ) ) ;
123
+
124
+ // pure data struct, require copy constructor and operator=
125
+ //if (isRef && numMethods == 0)
126
+ //{
127
+ // var co = GenConstructorAndOperator(name, body);
128
+ // var bd = new StringBuilder(body);
129
+ // bd.Insert(body.Length - 1, co);
130
+ // body = bd.ToString();
131
+ //}
132
+ isRef = numMethods > 0 ;
133
+ if ( ! isRef )
134
+ {
135
+ body = reMemb . Replace ( body , "$1;" ) ;
136
+ }
137
+
138
+ return body ;
139
+ }
140
+
141
+ private static string FixHeaderRefPointer ( string body , MatchCollection matches )
142
+ {
143
+ var bd = new StringBuilder ( body ) ;
144
+ foreach ( var m in matches . Reverse ( ) )
145
+ {
146
+ var param = m . Groups [ 2 ] . Value ;
147
+ param = reCom . Replace ( param , string . Empty ) ;
148
+ param = param . Replace ( '&' , '%' ) ;
149
+ //param = param.Replace('*', '^');
150
+ bd . Remove ( m . Groups [ 2 ] . Index , m . Groups [ 2 ] . Length ) ;
151
+ bd . Insert ( m . Groups [ 2 ] . Index , param ) ;
152
+ }
153
+ body = bd . ToString ( ) ;
154
+ return body ;
155
+ }
156
+
157
+ private static string FixHeaderOverload ( string body , MatchCollection matches )
158
+ {
159
+ var bd = new StringBuilder ( body ) ;
160
+ foreach ( var m in matches . Reverse ( ) )
161
+ {
162
+ var param = m . Groups [ 2 ] . Value ;
163
+ if ( param . Contains ( '=' ) )
164
+ {
165
+ var ol = GenOverloads ( m ) ;
166
+ bd . Remove ( m . Index , m . Length ) ;
167
+ bd . Insert ( m . Index , ol ) ;
168
+ }
169
+ }
170
+ body = bd . ToString ( ) ;
171
+ return body ;
172
+ }
173
+
174
+ public static string GenOverloads ( Match m )
175
+ {
176
+ var ol = new StringBuilder ( ) ;
177
+ var qualName = m . Groups [ 1 ] . Value ;
178
+ var sptOpt = StringSplitOptions . RemoveEmptyEntries | StringSplitOptions . TrimEntries ;
179
+ var name = qualName . Split ( ' ' , sptOpt ) . Last ( ) ;
180
+ var paramList = m . Groups [ 2 ] . Value . Split ( ',' , sptOpt ) ;
181
+ var normParams = paramList . TakeWhile ( p => ! p . Contains ( '=' ) ) . ToArray ( ) ;
182
+ var normParamNames = normParams . Select ( p => p . Split ( ' ' , sptOpt ) . Last ( ) ) ;
183
+ var defParams = paramList . SkipWhile ( p => ! p . Contains ( '=' ) ) . ToArray ( ) ;
184
+ var defParamTypeNameValues = defParams . Select ( p => p . Split ( '=' , sptOpt ) ) . ToArray ( ) ;
185
+ var defParamTpyeNames = defParamTypeNameValues . Select ( tnv => tnv [ 0 ] ) ;
186
+ var defParamNames = defParamTpyeNames . Select ( tn => tn . Split ( ' ' , sptOpt ) . Last ( ) ) ;
187
+ var defParamValues = defParamTypeNameValues . Select ( tnv => tnv [ 1 ] ) ;
188
+ var body = m . Groups [ 3 ] . Value ;
189
+ ol . Append ( qualName ) ;
190
+ ol . Append ( '(' ) ;
191
+ ol . Append ( string . Join ( ", " , normParams . Concat ( defParamTpyeNames ) ) ) ;
192
+ ol . Append ( ')' ) ;
193
+ ol . AppendLine ( body ) ;
194
+ for ( var i = 0 ; i < defParams . Length ; i ++ )
195
+ {
196
+ ol . Append ( qualName ) ;
197
+ ol . Append ( '(' ) ;
198
+ ol . Append ( string . Join ( ", " , normParams . Concat ( defParamTpyeNames . Take ( i ) ) ) ) ;
199
+ ol . Append ( ") { return " ) ;
200
+ ol . Append ( name ) ;
201
+ ol . Append ( '(' ) ;
202
+ var actualParam = normParamNames . Concat ( defParamNames . Take ( i ) )
203
+ . Concat ( defParamValues . TakeLast ( defParams . Length - i ) ) ;
204
+ ol . Append ( string . Join ( ", " , actualParam ) ) ;
205
+ ol . AppendLine ( "); }" ) ;
206
+ }
207
+ return ol . ToString ( ) ;
208
+ }
209
+
210
+ public static string GenConstructorAndOperator ( string name , string body )
211
+ {
212
+ var sptOpt = StringSplitOptions . RemoveEmptyEntries | StringSplitOptions . TrimEntries ;
213
+
214
+ var membs = reMemb . Matches ( body ) ;
215
+ var membNames = membs . Select ( m => m . Groups [ 1 ] . Value . Split ( ' ' , sptOpt ) . Last ( ) ) . ToArray ( ) ;
216
+ var assign = string . Join ( "\r \n " , membNames . Select ( n => $ " { n } = other.{ n } ;") ) ;
217
+
218
+ name = name . Split ( ' ' , sptOpt ) . Last ( ) ;
219
+ var co = new StringBuilder ( ) ;
220
+ co . AppendLine ( "public:" ) ;
221
+ co . AppendLine ( $ " { name } () {{}}") ;
222
+ co . AppendLine ( $ " { name } ({ name } % other)\r \n {{") ;
223
+ co . AppendLine ( assign ) ;
224
+ co . AppendLine ( " }" ) ;
225
+ //co.AppendLine($" {name}% operator=({name} other)\r\n {{");
226
+ //co.AppendLine(assign);
227
+ //co.AppendLine(" return *this;");
228
+ //co.AppendLine(" }");
229
+ //co.AppendLine($" {name}% operator=({name}% other)\r\n {{");
230
+ //co.AppendLine(assign);
231
+ //co.AppendLine(" return *this;");
232
+ //co.AppendLine(" }");
233
+ co . AppendLine ( $ " void operator=({ name } % other)\r \n {{") ;
234
+ co . AppendLine ( assign ) ;
235
+ co . AppendLine ( " }" ) ;
236
+ return co . ToString ( ) ;
237
+ }
238
+
239
+ public static string ProcessImpl ( string cpp )
240
+ {
241
+ cpp = RemoveQualifiers ( cpp ) ;
242
+ cpp = ReplaceStd ( cpp ) ;
243
+
244
+ var cli = new StringBuilder ( cpp ) ;
245
+ var lambdas = new Dictionary < string , string > ( ) ;
246
+ var matches = reImpl . Matches ( cpp ) ;
247
+ foreach ( var m in matches . Reverse ( ) )
248
+ {
249
+ var impl = ProcessImplBody ( m . Groups [ 1 ] . Value , m . Groups [ 2 ] . Value , m . Groups [ 3 ] . Value , ref lambdas ) ;
250
+ cli . Remove ( m . Index , m . Length ) ;
251
+ cli . Insert ( m . Index , impl ) ;
252
+ }
253
+ if ( lambdas . Count > 0 )
254
+ {
255
+ var lds = String . Join ( "\r \n " , lambdas . Values ) ;
256
+ cli . Insert ( matches [ 0 ] . Index , lds ) ;
257
+ }
258
+ cpp = cli . ToString ( ) ;
259
+
260
+ cpp = EdgeCases ( cpp ) ;
261
+
262
+ cli = new StringBuilder ( cpp ) ;
263
+ var lastInclude = reInclude . Matches ( cpp ) . Last ( ) ;
264
+ cli . Insert ( lastInclude . Index + lastInclude . Length + 1 , $ "using namespace { Namespace } ;") ;
265
+ cpp = cli . ToString ( ) ;
266
+ return cpp ;
267
+ }
268
+
269
+ public static string ProcessImplBody ( string qualName , string paramList , string initBody , ref Dictionary < string , string > lambdas )
270
+ {
271
+ paramList = reCom . Replace ( paramList , string . Empty ) ;
272
+ paramList = paramList . Replace ( '&' , '%' ) ;
273
+ //paramList = paramList.Replace('*', '^');
274
+
275
+ foreach ( var m in reLambda . Matches ( initBody ) . Reverse ( ) )
276
+ {
277
+ var li = lambdas . Count ;
278
+ var name = $ "_CliGenLambda{ li } ";
279
+ var pl = m . Groups [ 1 ] . Value ;
280
+ pl = $ "const { pl . Replace ( "," , ", const " ) } "; // A temp fix
281
+ lambdas [ name ] = $ "{ m . Groups [ 2 ] . Value } { name } ({ pl } ){ m . Groups [ 3 ] . Value } \r \n ";
282
+ var ib = new StringBuilder ( initBody ) ;
283
+ ib . Remove ( m . Index , m . Length ) ;
284
+ ib . Insert ( m . Index , name ) ;
285
+ initBody = ib . ToString ( ) ;
286
+ }
287
+
288
+ var impl = new StringBuilder ( ) ;
289
+ impl . Append ( qualName ) ;
290
+ impl . Append ( '(' ) ;
291
+ impl . Append ( paramList ) ;
292
+ impl . Append ( ")" ) ;
293
+ if ( initBody [ 0 ] == ':' )
294
+ impl . Append ( ' ' ) ;
295
+ else
296
+ impl . AppendLine ( ) ;
297
+ impl . Append ( initBody ) ;
298
+ return impl . ToString ( ) ;
299
+ }
300
+
301
+ private static string AddNamespace ( string cpp , int beg , int end )
302
+ {
303
+ var cli = new StringBuilder ( cpp ) ;
304
+ cli . Insert ( end , "}\r \n " ) ;
305
+ cli . Insert ( beg , $ "namespace { Namespace } \r \n {{\r \n ") ;
306
+ return cli . ToString ( ) ;
307
+ }
308
+
309
+ private static string EdgeCases ( string cpp )
310
+ {
311
+ // AAJewishCalendar.cpp L80,83
312
+ //cpp = cpp.Replace("const CAADate CurrentYear{CivilYear, CurrentPesach.Month, static_cast<double>(CurrentPesach.Day), bGregorian};",
313
+ // "CAADate CurrentYear{CivilYear, CurrentPesach.Month, static_cast<double>(CurrentPesach.Day), bGregorian};");
314
+ //cpp = cpp.Replace("const CAADate NextYear{CivilYear+1, NextPesach.Month, static_cast<double>(NextPesach.Day), bGregorian};",
315
+ // "CAADate NextYear{CivilYear+1, NextPesach.Month, static_cast<double>(NextPesach.Day), bGregorian};");
316
+
317
+ // AADynamicalTime.h, L67
318
+ cpp = cpp . Replace ( "static DELTAT_PROC sm_pDeltaTProc;" ,
319
+ "static DELTAT_PROC sm_pDeltaTProc{ nullptr };" ) ;
320
+ // AADynamicalTime.cpp, L19771
321
+ cpp = cpp . Replace ( "CAADynamicalTime::DELTAT_PROC CAADynamicalTime::sm_pDeltaTProc{nullptr};" ,
322
+ "//CAADynamicalTime::DELTAT_PROC CAADynamicalTime::sm_pDeltaTProc{nullptr};" ) ;
323
+
324
+ // AADynamicalTime.cpp, L19813
325
+ //cpp = cpp.Replace("const CAADate date{JD, CAADate::AfterPapalReform(JD)};",
326
+ // "CAADate date{JD, CAADate::AfterPapalReform(JD)};");
327
+
328
+ // ...
329
+ cpp = cpp . Replace ( "CAA3DCoordinate*" , "CAA3DCoordinate^" ) ;
330
+ cpp = cpp . Replace ( "CAA3DCoordinate Ecliptic{EclipticRectangularCoordinates(pT, nTSize, correction, &EclipticDerivative)};" ,
331
+ "CAA3DCoordinate Ecliptic{EclipticRectangularCoordinates(pT, nTSize, correction, %EclipticDerivative)};" ) ;
332
+
333
+ // AAELP2000.cpp, L107 && AAELPMPP02.cpp, L252
334
+ cpp = cpp . Replace ( "std::array<std::array<double, 2>, 8> g_P" ,
335
+ "static std::array<std::array<double, 2>, 8> g_P" ) ;
336
+
337
+ return cpp ;
338
+ }
339
+ }
0 commit comments