Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,44 @@ public static void Main(string[] args)
var actualResult = transformer.Transform(helloWorldCode);
Assert.Equal(expectedResult, actualResult);
}

[Fact]
public void ExplicitConstructorTest()
{
const string csharpCode = @"class Range<T>
{
public Range(T value) => { _value = value; };
public static implicit operator Range<T>(T value) { return new Range<T>(value); }
}";
var transformer = new CSharpToCppTransformer();
var actualResult = transformer.Transform(csharpCode);

// For debugging - output the actual result
System.Console.WriteLine("=== ACTUAL RESULT ===");
System.Console.WriteLine(actualResult);
System.Console.WriteLine("=== END ACTUAL RESULT ===");

// Let's just check if explicit is present for now
Assert.Contains("explicit", actualResult);
}

[Fact]
public void ExplicitOperatorTest()
{
const string csharpCode = @"class Range<T>
{
public static implicit operator std::tuple<T, T>(Range<T> range) { return (range.Min, range.Max); }
}";
var transformer = new CSharpToCppTransformer();
var actualResult = transformer.Transform(csharpCode);

// For debugging - output the actual result
System.Console.WriteLine("=== ACTUAL OPERATOR RESULT ===");
System.Console.WriteLine(actualResult);
System.Console.WriteLine("=== END ACTUAL OPERATOR RESULT ===");

// Let's just check if explicit is present for now
Assert.Contains("explicit operator", actualResult);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ public class CSharpToCppTransformer : TextTransformer
// public abstract class
// class
(new Regex(@"((public|protected|private|internal|abstract|static) )*(?<category>interface|class|struct)"), "${category}", 0),
// public: static implicit operator TargetType(SourceType source) { ... }
// public: explicit operator TargetType() const { ... }
(new Regex(@"(?<access>(private|protected|public): )static implicit operator (?<targetType>[^\(\n]+)\((?<sourceType>[^\s\(\n]+) (?<variable>[a-zA-Z0-9]+)\)"), "${access}explicit operator ${targetType}() const", 0),
// class GenericCollectionMethodsBase<TElement> {
// template <typename TElement> class GenericCollectionMethodsBase {
(new Regex(@"(?<before>\r?\n)(?<indent>[ \t]*)(?<type>class|struct) (?<typeName>[a-zA-Z0-9]+)<(?<typeParameters>[a-zA-Z0-9 ,]+)>(?<typeDefinitionEnding>[^{]+){"), "${before}${indent}template <typename ...> ${type} ${typeName};" + Environment.NewLine + "${indent}template <typename ${typeParameters}> ${type} ${typeName}<${typeParameters}>${typeDefinitionEnding}{", 0),
Expand Down Expand Up @@ -150,8 +153,8 @@ public class CSharpToCppTransformer : TextTransformer
// static void NotImplementedException(ThrowExtensionRoot root) { return throw new NotImplementedException(); }
(new Regex(@"(^\s+)(private|protected|public)?(: )?(template \<[^>\r\n]+\> )?(static )?(override )?([a-zA-Z0-9]+ )([a-zA-Z0-9]+)\(([^\(\r\n]*)\)\s+=>\s+throw([^;\r\n]+);"), "$1$2$3$4$5$6$7$8($9) { throw$10; }", 0),
// SizeBalancedTree(int capacity) => a = b;
// SizeBalancedTree(int capacity) { a = b; }
(new Regex(@"(^\s+)(private|protected|public)?(: )?(template \<[^>\r\n]+\> )?(static )?(override )?(void )?([a-zA-Z0-9]+)\(([^\(\r\n]*)\)\s+=>\s+([^;\r\n]+);"), "$1$2$3$4$5$6$7$8($9) { $10; }", 0),
// explicit SizeBalancedTree(int capacity) noexcept { a = b; }
(new Regex(@"(^\s+)(private|protected|public)?(: )?(template \<[^>\r\n]+\> )?(static )?(override )?(void )?([a-zA-Z0-9]+)\(([^\(\r\n]*)\)\s+=>\s+([^;\r\n]+);"), "$1$2$3$4$5$6explicit $7$8($9) noexcept { $10; }", 0),
// int SizeBalancedTree(int capacity) => a;
// int SizeBalancedTree(int capacity) { return a; }
(new Regex(@"(^\s+)(private|protected|public)?(: )?(template \<[^>\r\n]+\> )?(static )?(override )?([a-zA-Z0-9]+ )([a-zA-Z0-9]+)\(([^\(\r\n]*)\)\s+=>\s+([^;\r\n]+);"), "$1$2$3$4$5$6$7$8($9) { return $10; }", 0),
Expand Down Expand Up @@ -554,12 +557,12 @@ public class CSharpToCppTransformer : TextTransformer
(new Regex(@"(?<classDeclarationBegin>\r?\n(?<indent>[\t ]*)(template\s*<[^<>\n]*> )?(struct|class) (?<fullType>(?<typeName>[a-zA-Z0-9]+)(<[^:\n]*>)?)(\s*:\s*[^{\n]+)?[\t ]*(\r?\n)?[\t ]*{)"), "${classDeclarationBegin}/*~type~${typeName}~${fullType}~*/", 0),
// Inside the scope of /*~type~Range<T>~*/ insert inner scope and replace:
// public: static implicit operator std::tuple<T, T>(Range<T> range)
// public: operator std::tuple<T, T>() const {/*~variable~Range<T>~*/
(new Regex(@"(?<scope>/\*~type~(?<typeName>[^~\n\*]+)~(?<fullType>[^~\n\*]+)~\*/)(?<separator>.|\n)(?<before>((?<!/\*~type~\k<typeName>~\k<fullType>~\*/)(.|\n))*?)(?<access>(private|protected|public): )static implicit operator (?<targetType>[^\(\n]+)\((?<argumentDeclaration>\k<fullType> (?<variable>[a-zA-Z0-9]+))\)(?<after>\s*\n?\s*{)"), "${scope}${separator}${before}${access}operator ${targetType}() const${after}/*~variable~${variable}~*/", 10),
// public: explicit operator std::tuple<T, T>() const {/*~variable~Range<T>~*/
(new Regex(@"(?<scope>/\*~type~(?<typeName>[^~\n\*]+)~(?<fullType>[^~\n\*]+)~\*/)(?<separator>.|\n)(?<before>((?<!/\*~type~\k<typeName>~\k<fullType>~\*/)(.|\n))*?)(?<access>(private|protected|public): )static implicit operator (?<targetType>[^\(\n]+)\((?<argumentDeclaration>\k<fullType> (?<variable>[a-zA-Z0-9]+))\)(?<after>\s*\n?\s*{)"), "${scope}${separator}${before}${access}explicit operator ${targetType}() const${after}/*~variable~${variable}~*/", 10),
// Inside the scope of /*~type~Range<T>~*/ replace:
// public: static implicit operator Range<T>(std::tuple<T, T> tuple) { return new Range<T>(std::get<1-1>(tuple), std::get<2-1>(tuple)); }
// public: Range(std::tuple<T, T> tuple) : Range(std::get<1-1>(tuple), std::get<2-1>(tuple)) { }
(new Regex(@"(?<scope>/\*~type~(?<typeName>[^~\n\*]+)~(?<fullType>[^~\n\*]+)~\*/)(?<separator>.|\n)(?<before>((?<!/\*~type~\k<typeName>~\k<fullType>~\*/)(.|\n))*?)(?<access>(private|protected|public): )static implicit operator (\k<fullType>|\k<typeName>)\((?<arguments>[^{}\n]+)\)(\s|\n)*{(\s|\n)*return (new )?(\k<fullType>|\k<typeName>)\((?<passedArguments>[^\n]+)\);(\s|\n)*}"), "${scope}${separator}${before}${access}${typeName}(${arguments}) : ${typeName}(${passedArguments}) { }", 10),
// public: explicit Range(std::tuple<T, T> tuple) : Range(std::get<1-1>(tuple), std::get<2-1>(tuple)) { }
(new Regex(@"(?<scope>/\*~type~(?<typeName>[^~\n\*]+)~(?<fullType>[^~\n\*]+)~\*/)(?<separator>.|\n)(?<before>((?<!/\*~type~\k<typeName>~\k<fullType>~\*/)(.|\n))*?)(?<access>(private|protected|public): )static implicit operator (\k<fullType>|\k<typeName>)\((?<arguments>[^{}\n]+)\)(\s|\n)*{(\s|\n)*return (new )?(\k<fullType>|\k<typeName>)\((?<passedArguments>[^\n]+)\);(\s|\n)*}"), "${scope}${separator}${before}${access}explicit ${typeName}(${arguments}) : ${typeName}(${passedArguments}) { }", 10),
// Inside the scope of /*~variable~range~*/ replace:
// range.Minimum
// this->Minimum
Expand Down
26 changes: 26 additions & 0 deletions debug_output.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using Platform.RegularExpressions.Transformer.CSharpToCpp;

class Program
{
static void Main()
{
var transformer = new CSharpToCppTransformer();

const string csharpCode1 = @"class Range<T>
{
public Range(T value) => { _value = value; };
public static implicit operator Range<T>(T value) { return new Range<T>(value); }
}";

const string csharpCode2 = @"class Range<T>
{
public static implicit operator std::tuple<T, T>(Range<T> range) { return (range.Min, range.Max); }
}";

Console.WriteLine("=== Test 1: Constructor ===");
Console.WriteLine(transformer.Transform(csharpCode1));
Console.WriteLine("\n=== Test 2: Operator ===");
Console.WriteLine(transformer.Transform(csharpCode2));
}
}
15 changes: 9 additions & 6 deletions python/cs2cpp/cs2cpp.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ def __init__(
# public abstract class
# class
SubRule(r"((public|protected|private|internal|abstract|static) )*(?P<category>interface|class|struct)", r"\g<category>", max_repeat=0),
# public: static implicit operator TargetType(SourceType source) { ... }
# public: explicit operator TargetType() const { ... }
SubRule(r"(?P<access>(private|protected|public): )static implicit operator (?P<targetType>[^\(\n]+)\((?P<sourceType>[^\s\(\n]+) (?P<variable>[a-zA-Z0-9]+)\)", r"\g<access>explicit operator \g<targetType>() const", max_repeat=0),
# class GenericCollectionMethodsBase<TElement> {
# template <typename TElement> class GenericCollectionMethodsBase {
SubRule(r"(?P<before>\r?\n)(?P<indent>[ \t]*)(?P<type>class|struct) (?P<typeName>[a-zA-Z0-9]+)<(?P<typeParameters>[a-zA-Z0-9 ,]+)>(?P<typeDefinitionEnding>[^{]+){", r"\g<before>\g<indent>template <typename ...> \g<type> \g<typeName>;\n" + "\g<indent>template <typename \g<typeParameters>> \g<type> \g<typeName><\g<typeParameters>>\g<typeDefinitionEnding>{", max_repeat=0),
Expand Down Expand Up @@ -149,8 +152,8 @@ def __init__(
# static void NotImplementedException(ThrowExtensionRoot root) { return throw new NotImplementedException(); }
SubRule(r"(^\s+)(private|protected|public)?(: )?(template \<[^>\r\n]+\> )?(static )?(override )?([a-zA-Z0-9]+ )([a-zA-Z0-9]+)\(([^\(\r\n]*)\)\s+=>\s+throw([^;\r\n]+);", r"\1\2\3\4\5\6\7\8(\9) { throw\10; }", max_repeat=0),
# SizeBalancedTree(int capacity) => a = b;
# SizeBalancedTree(int capacity) { a = b; }
SubRule(r"(^\s+)(private|protected|public)?(: )?(template \<[^>\r\n]+\> )?(static )?(override )?(void )?([a-zA-Z0-9]+)\(([^\(\r\n]*)\)\s+=>\s+([^;\r\n]+);", r"\1\2\3\4\5\6\7\8(\9) { \10; }", max_repeat=0),
# explicit SizeBalancedTree(int capacity) noexcept { a = b; }
SubRule(r"(^\s+)(private|protected|public)?(: )?(template \<[^>\r\n]+\> )?(static )?(override )?(void )?([a-zA-Z0-9]+)\(([^\(\r\n]*)\)\s+=>\s+([^;\r\n]+);", r"\1\2\3\4\5\6explicit \7\8(\9) noexcept { \10; }", max_repeat=0),
# int SizeBalancedTree(int capacity) => a;
# int SizeBalancedTree(int capacity) { return a; }
SubRule(r"(^\s+)(private|protected|public)?(: )?(template \<[^>\r\n]+\> )?(static )?(override )?([a-zA-Z0-9]+ )([a-zA-Z0-9]+)\(([^\(\r\n]*)\)\s+=>\s+([^;\r\n]+);", r"\1\2\3\4\5\6\7\8(\9) { return \10; }", max_repeat=0),
Expand Down Expand Up @@ -553,12 +556,12 @@ def __init__(
SubRule(r"(?P<classDeclarationBegin>\r?\n(?P<indent>[\t ]*)(template\s*<[^<>\n]*> )?(struct|class) (?P<fullType>(?P<typeName>[a-zA-Z0-9]+)(<[^:\n]*>)?)(\s*:\s*[^{\n]+)?[\t ]*(\r?\n)?[\t ]*{)", r"\g<classDeclarationBegin>/*~type~\g<typeName>~\g<fullType>~*/", max_repeat=0),
# Inside the scope of /*~type~Range<T>~*/ insert inner scope and replace:
# public: static implicit operator std::tuple<T, T>(Range<T> range)
# public: operator std::tuple<T, T>() const {/*~variable~Range<T>~*/
SubRule(r"(?P<scope>/\*~type~(?P<typeName>[^~\n\*]+)~(?P<fullType>[^~\n\*]+)~\*/)(?P<separator>.|\n)(?P<before>((?<!/\*~type~\k<typeName>~\k<fullType>~\*/)(.|\n))*?)(?P<access>(private|protected|public): )static implicit operator (?P<targetType>[^\(\n]+)\((?P<argumentDeclaration>\k<fullType> (?P<variable>[a-zA-Z0-9]+))\)(?P<after>\s*\n?\s*{)", r"\g<scope>\g<separator>\g<before>\g<access>operator \g<targetType>() const\g<after>/*~variable~\g<variable>~*/", max_repeat=10),
# public: explicit operator std::tuple<T, T>() const {/*~variable~Range<T>~*/
SubRule(r"(?P<scope>/\*~type~(?P<typeName>[^~\n\*]+)~(?P<fullType>[^~\n\*]+)~\*/)(?P<separator>.|\n)(?P<before>((?<!/\*~type~\k<typeName>~\k<fullType>~\*/)(.|\n))*?)(?P<access>(private|protected|public): )static implicit operator (?P<targetType>[^\(\n]+)\((?P<argumentDeclaration>\k<fullType> (?P<variable>[a-zA-Z0-9]+))\)(?P<after>\s*\n?\s*{)", r"\g<scope>\g<separator>\g<before>\g<access>explicit operator \g<targetType>() const\g<after>/*~variable~\g<variable>~*/", max_repeat=10),
# Inside the scope of /*~type~Range<T>~*/ replace:
# public: static implicit operator Range<T>(std::tuple<T, T> tuple) { return new Range<T>(std::get<1-1>(tuple), std::get<2-1>(tuple)); }
# public: Range(std::tuple<T, T> tuple) : Range(std::get<1-1>(tuple), std::get<2-1>(tuple)) { }
SubRule(r"(?P<scope>/\*~type~(?P<typeName>[^~\n\*]+)~(?P<fullType>[^~\n\*]+)~\*/)(?P<separator>.|\n)(?P<before>((?<!/\*~type~\k<typeName>~\k<fullType>~\*/)(.|\n))*?)(?P<access>(private|protected|public): )static implicit operator (\k<fullType>|\k<typeName>)\((?P<arguments>[^{}\n]+)\)(\s|\n)*{(\s|\n)*return (new )?(\k<fullType>|\k<typeName>)\((?P<passedArguments>[^\n]+)\);(\s|\n)*}", r"\g<scope>\g<separator>\g<before>\g<access>\g<typeName>(\g<arguments>) : \g<typeName>(\g<passedArguments>) { }", max_repeat=10),
# public: explicit Range(std::tuple<T, T> tuple) : Range(std::get<1-1>(tuple), std::get<2-1>(tuple)) { }
SubRule(r"(?P<scope>/\*~type~(?P<typeName>[^~\n\*]+)~(?P<fullType>[^~\n\*]+)~\*/)(?P<separator>.|\n)(?P<before>((?<!/\*~type~\k<typeName>~\k<fullType>~\*/)(.|\n))*?)(?P<access>(private|protected|public): )static implicit operator (\k<fullType>|\k<typeName>)\((?P<arguments>[^{}\n]+)\)(\s|\n)*{(\s|\n)*return (new )?(\k<fullType>|\k<typeName>)\((?P<passedArguments>[^\n]+)\);(\s|\n)*}", r"\g<scope>\g<separator>\g<before>\g<access>explicit \g<typeName>(\g<arguments>) : \g<typeName>(\g<passedArguments>) { }", max_repeat=10),
# Inside the scope of /*~variable~range~*/ replace:
# range.Minimum
# this->Minimum
Expand Down
22 changes: 22 additions & 0 deletions test_transform.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;

namespace TestApp
{
class Program
{
static void Main()
{
var transformer = new Platform.RegularExpressions.Transformer.CSharpToCpp.CSharpToCppTransformer();

const string csharpCode1 = @"class Range<T>
{
public Range(T value) => { _value = value; };
public static implicit operator Range<T>(T value) { return new Range<T>(value); }
}";

Console.WriteLine("=== Test 1: Constructor ===");
string result1 = transformer.Transform(csharpCode1);
Console.WriteLine(result1);
}
}
}
Loading