Skip to content
Merged
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
46 changes: 46 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: CI

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
build-and-test:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake gcc g++

- name: Setup build directory
run: mkdir -p build

- name: Configure CMake
run: |
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++

- name: Build
run: |
cmake --build build -j32

- name: Run comprehensive tests
run: |
chmod +x test_compiler.sh
./test_compiler.sh

- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-gcc
path: |
test_results/
retention-days: 14
9 changes: 6 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
build
.cache
install
build
.cache
install
test_cases
test_results
a.out
27 changes: 27 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
cmake_minimum_required(VERSION 3.16)
project(ChibCC VERSION 1.0.0 LANGUAGES CXX)

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

include_directories(include)

# Source files
set(SOURCES
src/Diagnostic.cpp
src/TokenKinds.cpp
src/Tokenizer.cpp
src/Parser.cpp
src/CodeGenerator.cpp
main.cpp
)

# Create executable
add_executable(chibcc ${SOURCES})

# Set output directory
set_target_properties(chibcc PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
)
2 changes: 1 addition & 1 deletion README
Original file line number Diff line number Diff line change
@@ -1 +1 @@
## A CPP implementation for [chibcc](https://github.com/rui314/chibicc.git)
## A CPP implementation for (chibcc)[https://github.com/rui314/chibicc.git]
Binary file added a.out
Binary file not shown.
37 changes: 37 additions & 0 deletions include/AST.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#ifndef CHIBCC_AST_H
#define CHIBCC_AST_H

#include "Common.h"

namespace chibcc {

//===----------------------------------------------------------------------===//
// AST Node Types
//===----------------------------------------------------------------------===//

enum class NodeKind {
Add, // +
Sub, // -
Mul, // *
Div, // /
Neg, // unary -
Eq, // ==
Ne, // !=
Lt, // <
Le, // <=
Num, // Integer
};

class Node {
public:
NodeKind Kind;
std::unique_ptr<Node> Lhs;
std::unique_ptr<Node> Rhs;
int Val;

explicit Node(NodeKind K) : Kind(K), Lhs(nullptr), Rhs(nullptr), Val(0) {}
};

} // namespace chibcc

#endif // CHIBCC_AST_H
28 changes: 28 additions & 0 deletions include/CodeGenerator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef CHIBCC_CODEGENERATOR_H
#define CHIBCC_CODEGENERATOR_H

#include "AST.h"

namespace chibcc {

//===----------------------------------------------------------------------===//
// Code Generator
//===----------------------------------------------------------------------===//

class CodeGenerator {
private:
int Depth;

void push();
void pop(const char *Arg);
void genExpr(Node *N);

public:
CodeGenerator() : Depth(0) {}

void codegen(Node *N);
};

} // namespace chibcc

#endif // CHIBCC_CODEGENERATOR_H
32 changes: 32 additions & 0 deletions include/Common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#ifndef CHIBCC_COMMON_H
#define CHIBCC_COMMON_H

#include <cassert>
#include <cctype>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <memory>
#include <string>
#include <vector>

namespace chibcc {

//===----------------------------------------------------------------------===//
// Forward Declarations
//===----------------------------------------------------------------------===//

class DiagnosticEngine;
class SourceLocation;

//===----------------------------------------------------------------------===//
// Legacy Error Handling (for compatibility)
//===----------------------------------------------------------------------===//

void error(const char *Fmt, ...);
void errorAt(const char *Loc, const char *Fmt, ...);

} // namespace chibcc

#endif // CHIBCC_COMMON_H
194 changes: 194 additions & 0 deletions include/Diagnostic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
#ifndef CHIBCC_DIAGNOSTIC_H
#define CHIBCC_DIAGNOSTIC_H

#include "Common.h"

namespace chibcc {

//===----------------------------------------------------------------------===//
// Diagnostic Levels
//===----------------------------------------------------------------------===//

enum class DiagnosticLevel {
Ignored = 0,
Note,
Remark,
Warning,
Error,
Fatal
};

//===----------------------------------------------------------------------===//
// Diagnostic IDs
//===----------------------------------------------------------------------===//

namespace diag {
enum {
#define DIAG(ENUM, LEVEL, DESC) ENUM,
#include "DiagnosticKinds.def"
NUM_BUILTIN_DIAGNOSTICS
};
} // namespace diag

//===----------------------------------------------------------------------===//
// Source Location
//===----------------------------------------------------------------------===//

class SourceLocation {
private:
const char *Ptr;

public:
SourceLocation() : Ptr(nullptr) {}
explicit SourceLocation(const char *Loc) : Ptr(Loc) {}

bool isValid() const { return Ptr != nullptr; }
bool isInvalid() const { return Ptr == nullptr; }

const char *getPointer() const { return Ptr; }

bool operator==(const SourceLocation &RHS) const { return Ptr == RHS.Ptr; }
bool operator!=(const SourceLocation &RHS) const { return Ptr != RHS.Ptr; }
};

//===----------------------------------------------------------------------===//
// Source Range
//===----------------------------------------------------------------------===//

class SourceRange {
private:
SourceLocation Begin, End;

public:
SourceRange() = default;
SourceRange(SourceLocation Loc) : Begin(Loc), End(Loc) {}
SourceRange(SourceLocation Begin, SourceLocation End)
: Begin(Begin), End(End) {}

SourceLocation getBegin() const { return Begin; }
SourceLocation getEnd() const { return End; }

void setBegin(SourceLocation Loc) { Begin = Loc; }
void setEnd(SourceLocation Loc) { End = Loc; }

bool isValid() const { return Begin.isValid() && End.isValid(); }
bool isInvalid() const { return !isValid(); }
};

//===----------------------------------------------------------------------===//
// Diagnostic Engine
//===----------------------------------------------------------------------===//

class DiagnosticEngine {
private:
const char *SourceBuffer;
std::string FileName;
unsigned NumWarnings;
unsigned NumErrors;
bool SuppressAllDiagnostics;
bool WarningsAsErrors;

void emitDiagnostic(SourceLocation Loc, DiagnosticLevel Level,
const std::string &Message);
void printSourceLine(SourceLocation Loc);
void printCaretDiagnostic(SourceLocation Loc, SourceRange Range);

public:
DiagnosticEngine(const char *Buffer, const std::string &File = "<input>")
: SourceBuffer(Buffer), FileName(File), NumWarnings(0), NumErrors(0),
SuppressAllDiagnostics(false), WarningsAsErrors(false) {}

/// \brief Report a diagnostic at the given location.
void report(SourceLocation Loc, unsigned DiagID, const std::string &Message);

/// \brief Report a diagnostic with a source range.
void report(SourceRange Range, unsigned DiagID, const std::string &Message);

/// \brief Convenience methods for common diagnostic levels
void reportError(SourceLocation Loc, const std::string &Message);
void reportWarning(SourceLocation Loc, const std::string &Message);
void reportNote(SourceLocation Loc, const std::string &Message);
void reportFatal(SourceLocation Loc, const std::string &Message);

/// \brief Get diagnostic counts
unsigned getNumWarnings() const { return NumWarnings; }
unsigned getNumErrors() const { return NumErrors; }
bool hasErrorOccurred() const { return NumErrors > 0; }

/// \brief Control diagnostic behavior
void setSuppressAllDiagnostics(bool Val = true) {
SuppressAllDiagnostics = Val;
}
void setWarningsAsErrors(bool Val = true) { WarningsAsErrors = Val; }

/// \brief Get the diagnostic level for a given diagnostic ID
static DiagnosticLevel getDiagnosticLevel(unsigned DiagID);

/// \brief Get the diagnostic description for a given diagnostic ID
static const char *getDiagnosticText(unsigned DiagID);
};

//===----------------------------------------------------------------------===//
// Diagnostic Builder
//===----------------------------------------------------------------------===//

class DiagnosticBuilder {
private:
DiagnosticEngine *Engine;
SourceLocation Loc;
SourceRange Range;
unsigned DiagID;
std::string Message;
bool IsActive;

public:
DiagnosticBuilder(DiagnosticEngine *Engine, SourceLocation Loc,
unsigned DiagID)
: Engine(Engine), Loc(Loc), Range(Loc), DiagID(DiagID), IsActive(true) {}

DiagnosticBuilder(DiagnosticBuilder &&Other)
: Engine(Other.Engine), Loc(Other.Loc), Range(Other.Range),
DiagID(Other.DiagID), Message(std::move(Other.Message)),
IsActive(Other.IsActive) {
Other.IsActive = false;
}

~DiagnosticBuilder() {
if (IsActive && Engine) {
Engine->report(Range, DiagID, Message);
}
}

/// \brief Add a string to the diagnostic message
DiagnosticBuilder &operator<<(const std::string &Str) {
Message += Str;
return *this;
}

DiagnosticBuilder &operator<<(const char *Str) {
Message += Str;
return *this;
}

DiagnosticBuilder &operator<<(int Val) {
Message += std::to_string(Val);
return *this;
}

/// \brief Add a source range to highlight
DiagnosticBuilder &addRange(SourceRange R) {
Range = R;
return *this;
}

/// \brief Add a fix-it hint
DiagnosticBuilder &addFixItHint(SourceRange, const std::string &Text) {
// For now, just add to message - could be enhanced later
Message += " (fix: replace with '" + Text + "')";
return *this;
}
};

} // namespace chibcc

#endif // CHIBCC_DIAGNOSTIC_H
Loading