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
36 changes: 36 additions & 0 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
cmake_minimum_required(VERSION 3.10)
project(CSharpToCppTransformer VERSION 1.0.0)

# Set C++17 standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Add compiler flags
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
add_compile_options(-Wall -Wextra -O2)
endif()

# Add the library
add_library(CSharpToCppTransformer
CSharpToCppTransformer.cpp
)

target_include_directories(CSharpToCppTransformer PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)

# Add the test executable
add_executable(cs2cpp_test
main.cpp
)

target_link_libraries(cs2cpp_test
CSharpToCppTransformer
)

# Add custom target for running tests
add_custom_target(run_test
COMMAND cs2cpp_test
DEPENDS cs2cpp_test
COMMENT "Running C# to C++ transformer tests"
)
141 changes: 141 additions & 0 deletions cpp/CSharpToCppTransformer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#include "CSharpToCppTransformer.h"
#include <algorithm>

namespace Platform::RegularExpressions::Transformer::CSharpToCpp
{
// SubstitutionRule implementation
SubstitutionRule::SubstitutionRule(const std::string& pattern, const std::string& replacement, int maxRepeat)
: _pattern(pattern), _replacement(replacement), _maxRepeat(maxRepeat)
{
}

std::string SubstitutionRule::Apply(const std::string& text) const
{
std::string result = text;
int repeatCount = 0;

if (_maxRepeat == 0)
{
// Apply once
result = std::regex_replace(result, _pattern, _replacement);
}
else
{
// Apply up to maxRepeat times
while (repeatCount < _maxRepeat && std::regex_search(result, _pattern))
{
result = std::regex_replace(result, _pattern, _replacement);
repeatCount++;
}
}

return result;
}

// TextTransformer implementation
TextTransformer::TextTransformer(const std::vector<SubstitutionRule>& rules)
: _rules(rules)
{
}

std::string TextTransformer::Transform(const std::string& text)
{
std::string result = text;

for (const auto& rule : _rules)
{
result = rule.Apply(result);
}

return result;
}

// CSharpToCppTransformer implementation
std::vector<SubstitutionRule> CSharpToCppTransformer::CreateFirstStageRules()
{
return {
// Remove single-line comments
SubstitutionRule(R"(//.*)", "", 0),

// Remove pragma directives
SubstitutionRule(R"(#pragma.*)", "", 0),

// Using statement removal
SubstitutionRule(R"(using [^;]+;)", "", 0),

// String type conversion
SubstitutionRule(R"(\bstring\b)", "std::string", 0),

// String array conversion
SubstitutionRule(R"(std::string\[\] ([a-zA-Z0-9]+))", "std::string $1[]", 0),

// Console.WriteLine conversion
SubstitutionRule(R"(Console\.WriteLine\(\"([^"]*)\"\);)", "printf(\"$1\\n\");", 0),

// Access modifier conversion - simplified
SubstitutionRule(R"((public|private|protected) ([a-zA-Z]))", "$1: $2", 0),

// Class/interface/struct declaration cleanup
SubstitutionRule(R"((public|protected|private|internal|abstract|static) +(interface|class|struct))", "$2", 0),

// Namespace separator conversion
SubstitutionRule(R"(namespace ([a-zA-Z0-9]+)\.([a-zA-Z0-9\.]+))", "namespace $1::$2", 0),

// nameof conversion - simplified
SubstitutionRule(R"(nameof\(([a-zA-Z0-9_]+)\))", "\"$1\"", 0)
};
}

std::vector<SubstitutionRule> CSharpToCppTransformer::CreateLastStageRules()
{
return {
// null conversion
SubstitutionRule(R"(\bnull\b)", "nullptr", 0),

// default conversion
SubstitutionRule(R"(\bdefault\b)", "0", 0),

// object type conversion
SubstitutionRule(R"(\bobject\b)", "void*", 0),
SubstitutionRule(R"(System\.Object)", "void*", 0),

// new keyword removal
SubstitutionRule(R"(\bnew\s+)", "", 0),

// ToString conversion
SubstitutionRule(R"(([a-zA-Z0-9_]+)\.ToString\(\))", "Platform::Converters::To<std::string>($1).data()", 0),

// Exception type conversions
SubstitutionRule(R"(ArgumentNullException)", "std::invalid_argument", 0),
SubstitutionRule(R"(System\.ArgumentNullException)", "std::invalid_argument", 0),
SubstitutionRule(R"(InvalidOperationException)", "std::runtime_error", 0),
SubstitutionRule(R"(ArgumentException)", "std::invalid_argument", 0),
SubstitutionRule(R"(ArgumentOutOfRangeException)", "std::invalid_argument", 0),
SubstitutionRule(R"(\bException\b)", "std::runtime_error", 0)
};
}

const std::vector<SubstitutionRule> CSharpToCppTransformer::FirstStage = CreateFirstStageRules();
const std::vector<SubstitutionRule> CSharpToCppTransformer::LastStage = CreateLastStageRules();

CSharpToCppTransformer::CSharpToCppTransformer()
: TextTransformer([&]() {
std::vector<SubstitutionRule> allRules;
allRules.insert(allRules.end(), FirstStage.begin(), FirstStage.end());
allRules.insert(allRules.end(), LastStage.begin(), LastStage.end());
return allRules;
}())
{
}

CSharpToCppTransformer::CSharpToCppTransformer(const std::vector<SubstitutionRule>& extraRules)
: TextTransformer([&]() {
std::vector<SubstitutionRule> allRules;
allRules.insert(allRules.end(), FirstStage.begin(), FirstStage.end());
allRules.insert(allRules.end(), extraRules.begin(), extraRules.end());
allRules.insert(allRules.end(), LastStage.begin(), LastStage.end());
return allRules;
}())
{
}
}
97 changes: 97 additions & 0 deletions cpp/CSharpToCppTransformer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#pragma once

#include <string>
#include <vector>
#include <regex>
#include <memory>
#include <iostream>

namespace Platform::RegularExpressions::Transformer::CSharpToCpp
{
/// <summary>
/// Represents a substitution rule that can be applied to transform text.
/// </summary>
class SubstitutionRule
{
private:
std::regex _pattern;
std::string _replacement;
int _maxRepeat;

public:
/// <summary>
/// Initializes a new SubstitutionRule instance.
/// </summary>
/// <param name="pattern">The regular expression pattern to match.</param>
/// <param name="replacement">The replacement string.</param>
/// <param name="maxRepeat">Maximum number of times to apply this rule.</param>
SubstitutionRule(const std::string& pattern, const std::string& replacement, int maxRepeat = 0);

/// <summary>
/// Applies the substitution rule to the input text.
/// </summary>
/// <param name="text">The text to transform.</param>
/// <returns>The transformed text.</returns>
std::string Apply(const std::string& text) const;

/// <summary>
/// Gets the maximum repeat count for this rule.
/// </summary>
int GetMaxRepeat() const { return _maxRepeat; }
};

/// <summary>
/// Base class for text transformers.
/// </summary>
class TextTransformer
{
protected:
std::vector<SubstitutionRule> _rules;

public:
/// <summary>
/// Initializes a new TextTransformer instance.
/// </summary>
/// <param name="rules">The substitution rules to apply.</param>
TextTransformer(const std::vector<SubstitutionRule>& rules);

/// <summary>
/// Transforms the input text using all substitution rules.
/// </summary>
/// <param name="text">The text to transform.</param>
/// <returns>The transformed text.</returns>
virtual std::string Transform(const std::string& text);
};

/// <summary>
/// Represents the C# to C++ transformer.
/// </summary>
class CSharpToCppTransformer : public TextTransformer
{
private:
static std::vector<SubstitutionRule> CreateFirstStageRules();
static std::vector<SubstitutionRule> CreateLastStageRules();

public:
/// <summary>
/// The first stage transformation rules.
/// </summary>
static const std::vector<SubstitutionRule> FirstStage;

/// <summary>
/// The last stage transformation rules.
/// </summary>
static const std::vector<SubstitutionRule> LastStage;

/// <summary>
/// Initializes a new CSharpToCppTransformer instance.
/// </summary>
CSharpToCppTransformer();

/// <summary>
/// Initializes a new CSharpToCppTransformer instance with extra rules.
/// </summary>
/// <param name="extraRules">Additional transformation rules to include.</param>
CSharpToCppTransformer(const std::vector<SubstitutionRule>& extraRules);
};
}
25 changes: 25 additions & 0 deletions cpp/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
CXX = g++
CXXFLAGS = -std=c++17 -Wall -Wextra -O2
TARGET = cs2cpp_test
SOURCES = CSharpToCppTransformer.cpp main.cpp
OBJECTS = $(SOURCES:.cpp=.o)

.PHONY: all clean test

all: $(TARGET)

$(TARGET): $(OBJECTS)
$(CXX) $(CXXFLAGS) -o $@ $^

%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@

test: $(TARGET)
./$(TARGET)

clean:
rm -f $(OBJECTS) $(TARGET)

# Dependencies
CSharpToCppTransformer.o: CSharpToCppTransformer.cpp CSharpToCppTransformer.h
main.o: main.cpp CSharpToCppTransformer.h
Loading
Loading