Skip to content

Commit 651a633

Browse files
authored
Support basic numeric expressions [chibcc](rui314/chibicc@725badf) (#1)
1 parent 0982815 commit 651a633

22 files changed

Lines changed: 1820 additions & 4 deletions

.github/workflows/test.yml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
build-and-test:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout code
15+
uses: actions/checkout@v4
16+
17+
- name: Install dependencies
18+
run: |
19+
sudo apt-get update
20+
sudo apt-get install -y build-essential cmake gcc g++
21+
22+
- name: Setup build directory
23+
run: mkdir -p build
24+
25+
- name: Configure CMake
26+
run: |
27+
cd build
28+
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++
29+
30+
- name: Build
31+
run: |
32+
cmake --build build -j32
33+
34+
- name: Run comprehensive tests
35+
run: |
36+
chmod +x test_compiler.sh
37+
./test_compiler.sh
38+
39+
- name: Upload test results
40+
if: always()
41+
uses: actions/upload-artifact@v4
42+
with:
43+
name: test-results-gcc
44+
path: |
45+
test_results/
46+
retention-days: 14

.gitignore

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1-
build
2-
.cache
3-
install
1+
build
2+
.cache
3+
install
4+
test_cases
5+
test_results
6+
a.out

CMakeLists.txt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
cmake_minimum_required(VERSION 3.16)
2+
project(ChibCC VERSION 1.0.0 LANGUAGES CXX)
3+
4+
# Set C++ standard
5+
set(CMAKE_CXX_STANDARD 17)
6+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
7+
8+
include_directories(include)
9+
10+
# Source files
11+
set(SOURCES
12+
src/Diagnostic.cpp
13+
src/TokenKinds.cpp
14+
src/Tokenizer.cpp
15+
src/Parser.cpp
16+
src/CodeGenerator.cpp
17+
main.cpp
18+
)
19+
20+
# Create executable
21+
add_executable(chibcc ${SOURCES})
22+
23+
# Set output directory
24+
set_target_properties(chibcc PROPERTIES
25+
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
26+
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
27+
)

README

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
## A CPP implementation for [chibcc](https://github.com/rui314/chibicc.git)
1+
## A CPP implementation for (chibcc)[https://github.com/rui314/chibicc.git]

a.out

15.4 KB
Binary file not shown.

include/AST.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#ifndef CHIBCC_AST_H
2+
#define CHIBCC_AST_H
3+
4+
#include "Common.h"
5+
6+
namespace chibcc {
7+
8+
//===----------------------------------------------------------------------===//
9+
// AST Node Types
10+
//===----------------------------------------------------------------------===//
11+
12+
enum class NodeKind {
13+
Add, // +
14+
Sub, // -
15+
Mul, // *
16+
Div, // /
17+
Neg, // unary -
18+
Eq, // ==
19+
Ne, // !=
20+
Lt, // <
21+
Le, // <=
22+
Num, // Integer
23+
};
24+
25+
class Node {
26+
public:
27+
NodeKind Kind;
28+
std::unique_ptr<Node> Lhs;
29+
std::unique_ptr<Node> Rhs;
30+
int Val;
31+
32+
explicit Node(NodeKind K) : Kind(K), Lhs(nullptr), Rhs(nullptr), Val(0) {}
33+
};
34+
35+
} // namespace chibcc
36+
37+
#endif // CHIBCC_AST_H

include/CodeGenerator.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#ifndef CHIBCC_CODEGENERATOR_H
2+
#define CHIBCC_CODEGENERATOR_H
3+
4+
#include "AST.h"
5+
6+
namespace chibcc {
7+
8+
//===----------------------------------------------------------------------===//
9+
// Code Generator
10+
//===----------------------------------------------------------------------===//
11+
12+
class CodeGenerator {
13+
private:
14+
int Depth;
15+
16+
void push();
17+
void pop(const char *Arg);
18+
void genExpr(Node *N);
19+
20+
public:
21+
CodeGenerator() : Depth(0) {}
22+
23+
void codegen(Node *N);
24+
};
25+
26+
} // namespace chibcc
27+
28+
#endif // CHIBCC_CODEGENERATOR_H

include/Common.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#ifndef CHIBCC_COMMON_H
2+
#define CHIBCC_COMMON_H
3+
4+
#include <cassert>
5+
#include <cctype>
6+
#include <cstdarg>
7+
#include <cstdio>
8+
#include <cstdlib>
9+
#include <cstring>
10+
#include <memory>
11+
#include <string>
12+
#include <vector>
13+
14+
namespace chibcc {
15+
16+
//===----------------------------------------------------------------------===//
17+
// Forward Declarations
18+
//===----------------------------------------------------------------------===//
19+
20+
class DiagnosticEngine;
21+
class SourceLocation;
22+
23+
//===----------------------------------------------------------------------===//
24+
// Legacy Error Handling (for compatibility)
25+
//===----------------------------------------------------------------------===//
26+
27+
void error(const char *Fmt, ...);
28+
void errorAt(const char *Loc, const char *Fmt, ...);
29+
30+
} // namespace chibcc
31+
32+
#endif // CHIBCC_COMMON_H

include/Diagnostic.h

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
#ifndef CHIBCC_DIAGNOSTIC_H
2+
#define CHIBCC_DIAGNOSTIC_H
3+
4+
#include "Common.h"
5+
6+
namespace chibcc {
7+
8+
//===----------------------------------------------------------------------===//
9+
// Diagnostic Levels
10+
//===----------------------------------------------------------------------===//
11+
12+
enum class DiagnosticLevel {
13+
Ignored = 0,
14+
Note,
15+
Remark,
16+
Warning,
17+
Error,
18+
Fatal
19+
};
20+
21+
//===----------------------------------------------------------------------===//
22+
// Diagnostic IDs
23+
//===----------------------------------------------------------------------===//
24+
25+
namespace diag {
26+
enum {
27+
#define DIAG(ENUM, LEVEL, DESC) ENUM,
28+
#include "DiagnosticKinds.def"
29+
NUM_BUILTIN_DIAGNOSTICS
30+
};
31+
} // namespace diag
32+
33+
//===----------------------------------------------------------------------===//
34+
// Source Location
35+
//===----------------------------------------------------------------------===//
36+
37+
class SourceLocation {
38+
private:
39+
const char *Ptr;
40+
41+
public:
42+
SourceLocation() : Ptr(nullptr) {}
43+
explicit SourceLocation(const char *Loc) : Ptr(Loc) {}
44+
45+
bool isValid() const { return Ptr != nullptr; }
46+
bool isInvalid() const { return Ptr == nullptr; }
47+
48+
const char *getPointer() const { return Ptr; }
49+
50+
bool operator==(const SourceLocation &RHS) const { return Ptr == RHS.Ptr; }
51+
bool operator!=(const SourceLocation &RHS) const { return Ptr != RHS.Ptr; }
52+
};
53+
54+
//===----------------------------------------------------------------------===//
55+
// Source Range
56+
//===----------------------------------------------------------------------===//
57+
58+
class SourceRange {
59+
private:
60+
SourceLocation Begin, End;
61+
62+
public:
63+
SourceRange() = default;
64+
SourceRange(SourceLocation Loc) : Begin(Loc), End(Loc) {}
65+
SourceRange(SourceLocation Begin, SourceLocation End)
66+
: Begin(Begin), End(End) {}
67+
68+
SourceLocation getBegin() const { return Begin; }
69+
SourceLocation getEnd() const { return End; }
70+
71+
void setBegin(SourceLocation Loc) { Begin = Loc; }
72+
void setEnd(SourceLocation Loc) { End = Loc; }
73+
74+
bool isValid() const { return Begin.isValid() && End.isValid(); }
75+
bool isInvalid() const { return !isValid(); }
76+
};
77+
78+
//===----------------------------------------------------------------------===//
79+
// Diagnostic Engine
80+
//===----------------------------------------------------------------------===//
81+
82+
class DiagnosticEngine {
83+
private:
84+
const char *SourceBuffer;
85+
std::string FileName;
86+
unsigned NumWarnings;
87+
unsigned NumErrors;
88+
bool SuppressAllDiagnostics;
89+
bool WarningsAsErrors;
90+
91+
void emitDiagnostic(SourceLocation Loc, DiagnosticLevel Level,
92+
const std::string &Message);
93+
void printSourceLine(SourceLocation Loc);
94+
void printCaretDiagnostic(SourceLocation Loc, SourceRange Range);
95+
96+
public:
97+
DiagnosticEngine(const char *Buffer, const std::string &File = "<input>")
98+
: SourceBuffer(Buffer), FileName(File), NumWarnings(0), NumErrors(0),
99+
SuppressAllDiagnostics(false), WarningsAsErrors(false) {}
100+
101+
/// \brief Report a diagnostic at the given location.
102+
void report(SourceLocation Loc, unsigned DiagID, const std::string &Message);
103+
104+
/// \brief Report a diagnostic with a source range.
105+
void report(SourceRange Range, unsigned DiagID, const std::string &Message);
106+
107+
/// \brief Convenience methods for common diagnostic levels
108+
void reportError(SourceLocation Loc, const std::string &Message);
109+
void reportWarning(SourceLocation Loc, const std::string &Message);
110+
void reportNote(SourceLocation Loc, const std::string &Message);
111+
void reportFatal(SourceLocation Loc, const std::string &Message);
112+
113+
/// \brief Get diagnostic counts
114+
unsigned getNumWarnings() const { return NumWarnings; }
115+
unsigned getNumErrors() const { return NumErrors; }
116+
bool hasErrorOccurred() const { return NumErrors > 0; }
117+
118+
/// \brief Control diagnostic behavior
119+
void setSuppressAllDiagnostics(bool Val = true) {
120+
SuppressAllDiagnostics = Val;
121+
}
122+
void setWarningsAsErrors(bool Val = true) { WarningsAsErrors = Val; }
123+
124+
/// \brief Get the diagnostic level for a given diagnostic ID
125+
static DiagnosticLevel getDiagnosticLevel(unsigned DiagID);
126+
127+
/// \brief Get the diagnostic description for a given diagnostic ID
128+
static const char *getDiagnosticText(unsigned DiagID);
129+
};
130+
131+
//===----------------------------------------------------------------------===//
132+
// Diagnostic Builder
133+
//===----------------------------------------------------------------------===//
134+
135+
class DiagnosticBuilder {
136+
private:
137+
DiagnosticEngine *Engine;
138+
SourceLocation Loc;
139+
SourceRange Range;
140+
unsigned DiagID;
141+
std::string Message;
142+
bool IsActive;
143+
144+
public:
145+
DiagnosticBuilder(DiagnosticEngine *Engine, SourceLocation Loc,
146+
unsigned DiagID)
147+
: Engine(Engine), Loc(Loc), Range(Loc), DiagID(DiagID), IsActive(true) {}
148+
149+
DiagnosticBuilder(DiagnosticBuilder &&Other)
150+
: Engine(Other.Engine), Loc(Other.Loc), Range(Other.Range),
151+
DiagID(Other.DiagID), Message(std::move(Other.Message)),
152+
IsActive(Other.IsActive) {
153+
Other.IsActive = false;
154+
}
155+
156+
~DiagnosticBuilder() {
157+
if (IsActive && Engine) {
158+
Engine->report(Range, DiagID, Message);
159+
}
160+
}
161+
162+
/// \brief Add a string to the diagnostic message
163+
DiagnosticBuilder &operator<<(const std::string &Str) {
164+
Message += Str;
165+
return *this;
166+
}
167+
168+
DiagnosticBuilder &operator<<(const char *Str) {
169+
Message += Str;
170+
return *this;
171+
}
172+
173+
DiagnosticBuilder &operator<<(int Val) {
174+
Message += std::to_string(Val);
175+
return *this;
176+
}
177+
178+
/// \brief Add a source range to highlight
179+
DiagnosticBuilder &addRange(SourceRange R) {
180+
Range = R;
181+
return *this;
182+
}
183+
184+
/// \brief Add a fix-it hint
185+
DiagnosticBuilder &addFixItHint(SourceRange, const std::string &Text) {
186+
// For now, just add to message - could be enhanced later
187+
Message += " (fix: replace with '" + Text + "')";
188+
return *this;
189+
}
190+
};
191+
192+
} // namespace chibcc
193+
194+
#endif // CHIBCC_DIAGNOSTIC_H

0 commit comments

Comments
 (0)