mirror of
https://github.com/arabine/open-story-teller.git
synced 2025-12-06 17:09:06 +01:00
(wip) compiler with ast
This commit is contained in:
parent
bbf149dedd
commit
d3a8b10120
10 changed files with 18631 additions and 26 deletions
27
.gitignore
vendored
27
.gitignore
vendored
|
|
@ -5,8 +5,6 @@ www-docs/node_modules/
|
||||||
|
|
||||||
*.lock
|
*.lock
|
||||||
|
|
||||||
build-story-editor-Desktop_Qt_6_4_1_GCC_64bit-Debug/
|
|
||||||
|
|
||||||
docs/resources/
|
docs/resources/
|
||||||
|
|
||||||
docs/node_modules/
|
docs/node_modules/
|
||||||
|
|
@ -21,23 +19,11 @@ hardware/kicad/ost-pico-addon/fp-info-cache
|
||||||
|
|
||||||
*.png~
|
*.png~
|
||||||
|
|
||||||
build-story-editor-Desktop_Qt_6_5_1_GCC_64bit-Debug/
|
|
||||||
|
|
||||||
build-story-editor-Desktop_Qt_6_5_1_MinGW_64_bit-Debug/
|
|
||||||
|
|
||||||
build-story-editor-Desktop_Qt_6_5_1_MinGW_64_bit-Release/
|
|
||||||
|
|
||||||
build-story-editor-Desktop_Qt_6_5_1_MSVC2019_64bit-Debug/
|
|
||||||
|
|
||||||
release/
|
release/
|
||||||
|
|
||||||
story-editor/windows-setup/Output/
|
story-editor/windows-setup/Output/
|
||||||
|
|
||||||
build-story-editor-Desktop_Qt_6_5_1_GCC_64bit-Release/
|
|
||||||
|
|
||||||
build-story-player-Desktop_Qt_6_5_1_GCC_64bit-Debug/
|
|
||||||
|
|
||||||
build-story-player-Desktop_Qt_GCC_64bit-Debug/
|
|
||||||
|
|
||||||
*.user
|
*.user
|
||||||
|
|
||||||
|
|
@ -47,20 +33,12 @@ software/.vscode/.cortex-debug.registers.state.json
|
||||||
|
|
||||||
story-player/build/
|
story-player/build/
|
||||||
|
|
||||||
story-editor/tools/build-audio-System_Qt5_15_8-Debug/
|
|
||||||
|
|
||||||
software/.vscode/.cortex-debug.peripherals.state.json
|
software/.vscode/.cortex-debug.peripherals.state.json
|
||||||
story-editor/build
|
story-editor/build
|
||||||
|
|
||||||
build-story-editor-v2-System_Qt5_15_8-Debug/
|
|
||||||
|
|
||||||
story-editor-v2/src/CMakeSettings.json
|
|
||||||
|
|
||||||
story-editor-v2/imgui.ini
|
|
||||||
|
|
||||||
story-editor-v2/src/.vscode/
|
|
||||||
|
|
||||||
build-story-editor-v2-Desktop-Debug/
|
|
||||||
|
|
||||||
build-story-editor-Desktop-Debug/
|
build-story-editor-Desktop-Debug/
|
||||||
|
|
||||||
|
|
@ -75,7 +53,6 @@ software/.cache/
|
||||||
story-editor/.idea/
|
story-editor/.idea/
|
||||||
|
|
||||||
|
|
||||||
build-story-editor-Desktop_Qt_GCC_64bit-Debug/
|
|
||||||
|
|
||||||
firmware/build/
|
firmware/build/
|
||||||
|
|
||||||
|
|
@ -107,3 +84,5 @@ story-editor/cmake-build-debug/
|
||||||
story-editor/.flatpak-builder
|
story-editor/.flatpak-builder
|
||||||
story-editor/flatpak_build/
|
story-editor/flatpak_build/
|
||||||
story-editor/AppDir/
|
story-editor/AppDir/
|
||||||
|
|
||||||
|
core/story-manager/tests/build
|
||||||
|
|
|
||||||
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
|
|
@ -1,10 +1,11 @@
|
||||||
{
|
{
|
||||||
|
|
||||||
"cmake.sourceDirectory": [
|
"cmake.sourceDirectory": [
|
||||||
|
"${workspaceFolder}/core/chip32/tests",
|
||||||
|
"${workspaceFolder}/core/story-manager/tests",
|
||||||
"${workspaceFolder}/story-editor",
|
"${workspaceFolder}/story-editor",
|
||||||
"${workspaceFolder}/story-player-raylib",
|
"${workspaceFolder}/story-player-raylib",
|
||||||
"${workspaceFolder}/software",
|
"${workspaceFolder}/software"
|
||||||
"${workspaceFolder}/core/chip32/tests"
|
|
||||||
],
|
],
|
||||||
"files.associations": {
|
"files.associations": {
|
||||||
"*.css": "tailwindcss",
|
"*.css": "tailwindcss",
|
||||||
|
|
|
||||||
306
core/chip32/chip32_compiler.cpp
Normal file
306
core/chip32/chip32_compiler.cpp
Normal file
|
|
@ -0,0 +1,306 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <cctype>
|
||||||
|
#include <memory>
|
||||||
|
#include <fstream>
|
||||||
|
enum class TokenType {
|
||||||
|
FUNC, IDENTIFIER, INT, CONST, VAR, IF, ELSE, WHILE, NUMBER, ASSIGN, PLUS, MINUS, MULT, DIV, SEMICOLON,
|
||||||
|
LPAREN, RPAREN, LBRACE, RBRACE, END, GREATER, LESS, EQUAL, NOTEQUAL
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Token {
|
||||||
|
TokenType type;
|
||||||
|
std::string value;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Lexer {
|
||||||
|
public:
|
||||||
|
Lexer(const std::string& input) : input(input), pos(0) {}
|
||||||
|
|
||||||
|
std::vector<Token> tokenize() {
|
||||||
|
std::vector<Token> tokens;
|
||||||
|
|
||||||
|
while (pos < input.size()) {
|
||||||
|
if (std::isspace(input[pos])) {
|
||||||
|
++pos;
|
||||||
|
} else if (std::isalpha(input[pos])) {
|
||||||
|
std::string ident = readIdentifier();
|
||||||
|
if (ident == "func") {
|
||||||
|
tokens.push_back({TokenType::FUNC, ident});
|
||||||
|
} else if (ident == "int") {
|
||||||
|
tokens.push_back({TokenType::INT, ident});
|
||||||
|
} else if (ident == "const") {
|
||||||
|
tokens.push_back({TokenType::CONST, ident});
|
||||||
|
} else if (ident == "var") {
|
||||||
|
tokens.push_back({TokenType::VAR, ident});
|
||||||
|
} else if (ident == "if") {
|
||||||
|
tokens.push_back({TokenType::IF, ident});
|
||||||
|
} else if (ident == "else") {
|
||||||
|
tokens.push_back({TokenType::ELSE, ident});
|
||||||
|
} else if (ident == "while") {
|
||||||
|
tokens.push_back({TokenType::WHILE, ident});
|
||||||
|
} else {
|
||||||
|
tokens.push_back({TokenType::IDENTIFIER, ident});
|
||||||
|
}
|
||||||
|
} else if (std::isdigit(input[pos])) {
|
||||||
|
tokens.push_back({TokenType::NUMBER, readNumber()});
|
||||||
|
} else {
|
||||||
|
switch (input[pos]) {
|
||||||
|
case '(': tokens.push_back({TokenType::LPAREN, "("}); break;
|
||||||
|
case ')': tokens.push_back({TokenType::RPAREN, ")"}); break;
|
||||||
|
case '{': tokens.push_back({TokenType::LBRACE, "{"}); break;
|
||||||
|
case '}': tokens.push_back({TokenType::RBRACE, "}"}); break;
|
||||||
|
case '=': tokens.push_back({TokenType::ASSIGN, "="}); break;
|
||||||
|
case '+': tokens.push_back({TokenType::PLUS, "+"}); break;
|
||||||
|
case '-': tokens.push_back({TokenType::MINUS, "-"}); break;
|
||||||
|
case '*': tokens.push_back({TokenType::MULT, "*"}); break;
|
||||||
|
case '/': tokens.push_back({TokenType::DIV, "/"}); break;
|
||||||
|
case ';': tokens.push_back({TokenType::SEMICOLON, ";"}); break;
|
||||||
|
case '>': tokens.push_back({TokenType::GREATER, ">"}); break;
|
||||||
|
case '<': tokens.push_back({TokenType::LESS, "<"}); break;
|
||||||
|
default: std::cerr << "Caractère inattendu : " << input[pos] << std::endl;
|
||||||
|
}
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tokens.push_back({TokenType::END, ""});
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string input;
|
||||||
|
size_t pos;
|
||||||
|
|
||||||
|
std::string readIdentifier() {
|
||||||
|
size_t start = pos;
|
||||||
|
while (pos < input.size() && std::isalnum(input[pos])) ++pos;
|
||||||
|
return input.substr(start, pos - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string readNumber() {
|
||||||
|
size_t start = pos;
|
||||||
|
while (pos < input.size() && std::isdigit(input[pos])) ++pos;
|
||||||
|
return input.substr(start, pos - start);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// AST Nodes
|
||||||
|
struct ASTNode {
|
||||||
|
virtual ~ASTNode() = default;
|
||||||
|
virtual void print(int indent = 0) const = 0;
|
||||||
|
virtual void generateAssembly(std::ofstream& out) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpressionNode : public ASTNode {
|
||||||
|
std::string value;
|
||||||
|
ExpressionNode(std::string value) : value(std::move(value)) {}
|
||||||
|
|
||||||
|
void print(int indent = 0) const override {
|
||||||
|
std::cout << std::string(indent, ' ') << "Number: " << value << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateAssembly(std::ofstream& out) const override {
|
||||||
|
out << "\tmov eax, " << value << "\n";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BinaryOpNode : public ASTNode {
|
||||||
|
std::unique_ptr<ASTNode> left;
|
||||||
|
std::unique_ptr<ASTNode> right;
|
||||||
|
TokenType op;
|
||||||
|
|
||||||
|
BinaryOpNode(std::unique_ptr<ASTNode> left, TokenType op, std::unique_ptr<ASTNode> right)
|
||||||
|
: left(std::move(left)), op(op), right(std::move(right)) {}
|
||||||
|
|
||||||
|
void print(int indent = 0) const override {
|
||||||
|
std::cout << std::string(indent, ' ') << "BinaryOp: ";
|
||||||
|
left->print(indent + 2);
|
||||||
|
std::cout << std::string(indent + 2, ' ') << (op == TokenType::PLUS ? "+" :
|
||||||
|
op == TokenType::MINUS ? "-" :
|
||||||
|
op == TokenType::MULT ? "*" : "/") << std::endl;
|
||||||
|
right->print(indent + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateAssembly(std::ofstream& out) const override {
|
||||||
|
left->generateAssembly(out);
|
||||||
|
out << "\tpush eax\n";
|
||||||
|
right->generateAssembly(out);
|
||||||
|
out << "\tpop ebx\n";
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
case TokenType::PLUS: out << "\tadd eax, ebx\n"; break;
|
||||||
|
case TokenType::MINUS: out << "\tsub eax, ebx\n"; break;
|
||||||
|
case TokenType::MULT: out << "\timul eax, ebx\n"; break;
|
||||||
|
case TokenType::DIV: out << "\tcdq\n\tidiv ebx\n"; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AssignmentNode : public ASTNode {
|
||||||
|
std::string varName;
|
||||||
|
std::unique_ptr<ASTNode> expression;
|
||||||
|
|
||||||
|
AssignmentNode(std::string varName, std::unique_ptr<ASTNode> expression)
|
||||||
|
: varName(std::move(varName)), expression(std::move(expression)) {}
|
||||||
|
|
||||||
|
void print(int indent = 0) const override {
|
||||||
|
std::cout << std::string(indent, ' ') << "Assignment: " << varName << " = " << std::endl;
|
||||||
|
expression->print(indent + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateAssembly(std::ofstream& out) const override {
|
||||||
|
expression->generateAssembly(out);
|
||||||
|
out << "\tmov [" << varName << "], eax\n";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FunctionNode : public ASTNode {
|
||||||
|
std::string name;
|
||||||
|
std::vector<std::unique_ptr<ASTNode>> body;
|
||||||
|
|
||||||
|
FunctionNode(std::string name) : name(std::move(name)) {}
|
||||||
|
|
||||||
|
void print(int indent = 0) const override {
|
||||||
|
std::cout << "Function: " << name << std::endl;
|
||||||
|
for (const auto& stmt : body) {
|
||||||
|
stmt->print(indent + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateAssembly(std::ofstream& out) const override {
|
||||||
|
out << "." << name << ":\n";
|
||||||
|
for (const auto& stmt : body) {
|
||||||
|
stmt->generateAssembly(out);
|
||||||
|
}
|
||||||
|
out << "\tret\n";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct StatementNode : public ASTNode {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct VariableDeclarationNode : public StatementNode {
|
||||||
|
std::string name;
|
||||||
|
std::unique_ptr<ExpressionNode> value;
|
||||||
|
|
||||||
|
void print(int indent = 0) const override {
|
||||||
|
std::cout << std::string(indent, ' ') << "VarDecl: " << name << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateAssembly(std::ofstream& out) const override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IfNode : public StatementNode {
|
||||||
|
std::unique_ptr<ExpressionNode> condition;
|
||||||
|
std::vector<std::unique_ptr<ASTNode>> thenBranch;
|
||||||
|
std::vector<std::unique_ptr<ASTNode>> elseBranch;
|
||||||
|
|
||||||
|
void print(int indent = 0) const override {
|
||||||
|
std::cout << std::string(indent, ' ') << "If Statement" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateAssembly(std::ofstream& out) const override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WhileNode : public StatementNode {
|
||||||
|
std::unique_ptr<ExpressionNode> condition;
|
||||||
|
std::vector<std::unique_ptr<ASTNode>> body;
|
||||||
|
|
||||||
|
void print(int indent = 0) const override {
|
||||||
|
std::cout << std::string(indent, ' ') << "While Statement" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateAssembly(std::ofstream& out) const override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Parser {
|
||||||
|
public:
|
||||||
|
Parser(const std::vector<Token>& tokens) : tokens(tokens), pos(0) {}
|
||||||
|
|
||||||
|
std::unique_ptr<ASTNode> parse() {
|
||||||
|
if (match(TokenType::FUNC)) {
|
||||||
|
consume(TokenType::FUNC);
|
||||||
|
std::string funcName = consume(TokenType::IDENTIFIER).value;
|
||||||
|
consume(TokenType::LPAREN);
|
||||||
|
consume(TokenType::RPAREN);
|
||||||
|
consume(TokenType::LBRACE);
|
||||||
|
std::vector<std::unique_ptr<StatementNode>> body;
|
||||||
|
while (!match(TokenType::RBRACE)) {
|
||||||
|
body.push_back(parseStatement());
|
||||||
|
}
|
||||||
|
consume(TokenType::RBRACE);
|
||||||
|
return std::make_unique<FunctionNode>(funcName);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::vector<Token>& tokens;
|
||||||
|
size_t pos;
|
||||||
|
|
||||||
|
bool match(TokenType type) {
|
||||||
|
return pos < tokens.size() && tokens[pos].type == type;
|
||||||
|
}
|
||||||
|
|
||||||
|
Token consume(TokenType type) {
|
||||||
|
if (match(type)) {
|
||||||
|
return tokens[pos++];
|
||||||
|
}
|
||||||
|
std::cout << "type: " << (int)type << std::endl;
|
||||||
|
throw std::runtime_error("Unexpected token: expected " + std::to_string(static_cast<int>(type)) +
|
||||||
|
", got " + std::to_string(static_cast<int>(tokens[pos].type)) +
|
||||||
|
" (" + tokens[pos].value + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<StatementNode> parseStatement() { return nullptr; }
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::string code = R"(
|
||||||
|
|
||||||
|
def MaFonction()
|
||||||
|
var x
|
||||||
|
x = 5 + 3
|
||||||
|
|
||||||
|
|
||||||
|
)";
|
||||||
|
Lexer lexer(code);
|
||||||
|
std::vector<Token> tokens = lexer.tokenize();
|
||||||
|
|
||||||
|
for (const auto& token : tokens) {
|
||||||
|
std::cout << "Token: " << static_cast<int>(token.type) << " (" << token.value << ")\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
Parser parser(tokens);
|
||||||
|
std::unique_ptr<ASTNode> ast = parser.parse();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (ast) {
|
||||||
|
ast->print();
|
||||||
|
|
||||||
|
std::ofstream outFile("output.asm");
|
||||||
|
if (outFile.is_open()) {
|
||||||
|
ast->generateAssembly(outFile);
|
||||||
|
outFile.close();
|
||||||
|
std::cout << "Code assembleur généré dans output.asm" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cerr << "Erreur lors de l'ouverture du fichier" << std::endl;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::cerr << "Erreur de parsing" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch(const std::exception &e) {
|
||||||
|
std::cerr << "Erreur de parsing: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,38 @@
|
||||||
|
|
||||||
#include "sys_lib.h"
|
#include "sys_lib.h"
|
||||||
#include "i_story_project.h"
|
#include "i_story_project.h"
|
||||||
|
#include "base_node.h"
|
||||||
|
#include "connection.h"
|
||||||
|
|
||||||
|
struct AstNode
|
||||||
|
{
|
||||||
|
std::shared_ptr<BaseNode> node; // pointeur vers le noeud en cours
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<AstNode>> inputs;
|
||||||
|
std::shared_ptr<AstNode> condition; // Pour les boucles et les branchements
|
||||||
|
std::vector<std::shared_ptr<AstNode>> body; // Pour les boucles et les branchements
|
||||||
|
std::shared_ptr<AstNode> elseBody; // Pour les branchements
|
||||||
|
|
||||||
|
std::pair<int, int> position;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// AST (Arbre de syntaxe abstraite)
|
||||||
|
struct AST {
|
||||||
|
|
||||||
|
std::map<std::string, int> variables; // Stockage des variables (adresses mémoire)
|
||||||
|
std::string assemblyCode;
|
||||||
|
int labelCounter = 0;
|
||||||
|
std::map<std::string, std::shared_ptr<AstNode>> nodeMap;
|
||||||
|
|
||||||
|
// Fonction pour générer un label unique
|
||||||
|
std::string generateLabel(AST& ast) {
|
||||||
|
return "label" + std::to_string(ast.labelCounter++);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Compiler
|
class Compiler
|
||||||
{
|
{
|
||||||
|
|
@ -10,7 +42,110 @@ public:
|
||||||
Compiler() = default;
|
Compiler() = default;
|
||||||
~Compiler() = default;
|
~Compiler() = default;
|
||||||
|
|
||||||
|
|
||||||
static std::string FileToConstant(const std::string &FileName, const std::string &extension, IStoryProject &project);
|
static std::string FileToConstant(const std::string &FileName, const std::string &extension, IStoryProject &project);
|
||||||
|
|
||||||
|
|
||||||
|
// Fonction pour construire l'AST à partir des nœuds et des connexions
|
||||||
|
void buildAST(std::vector<std::shared_ptr<BaseNode>>& nodes, std::vector<std::shared_ptr<Connection>>& connections) {
|
||||||
|
|
||||||
|
m_ast.nodeMap.clear();
|
||||||
|
|
||||||
|
// Créer une map pour accéder aux nœuds par ID
|
||||||
|
int x = 0, y = 0;
|
||||||
|
for (auto& node : nodes) {
|
||||||
|
auto astNode = std::make_shared<AstNode>();
|
||||||
|
|
||||||
|
astNode->position = {0, 0};
|
||||||
|
x += 10; // Espacement horizontal
|
||||||
|
if (x > 50) { // Nouvelle ligne
|
||||||
|
x = 0;
|
||||||
|
y += 5; // Espacement vertical
|
||||||
|
}
|
||||||
|
|
||||||
|
astNode->node = node;
|
||||||
|
m_ast.nodeMap[node->GetId()] = astNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construire les connexions entre les nœuds
|
||||||
|
for (auto& connection : connections) {
|
||||||
|
std::shared_ptr<AstNode> outNode = m_ast.nodeMap[connection->outNodeId];
|
||||||
|
std::shared_ptr<AstNode> inNode = m_ast.nodeMap[connection->inNodeId];
|
||||||
|
inNode->inputs.push_back(outNode); // Ajoute le noeud de sortie en entrée du noeud d'entrée
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gestion des conditions et des corps de boucles/branches
|
||||||
|
/*
|
||||||
|
for(auto& node : nodes) {
|
||||||
|
if (node.type == Node::Type::LOOP || node.type == Node::Type::BRANCH){
|
||||||
|
for (auto& connection : connections) {
|
||||||
|
if (connection.inNodeId == node.id && connection.inPortIndex == 0) { // Condition
|
||||||
|
node.condition = nodeMap[connection.outNodeId];
|
||||||
|
}
|
||||||
|
if (connection.inNodeId == node.id && connection.inPortIndex == 1) { // Body
|
||||||
|
node.body.push_back(nodeMap[connection.outNodeId]);
|
||||||
|
}
|
||||||
|
if (node.type == Node::Type::BRANCH && connection.inNodeId == node.id && connection.inPortIndex == 2) { // ElseBody
|
||||||
|
if(node.elseBody == nullptr) {
|
||||||
|
node.elseBody = new Node(Node::Type::VARIABLE, "dummy"); // Créer un noeud dummy juste pour l'elsebody.
|
||||||
|
node.elseBody->body.push_back(nodeMap[connection.outNodeId]);
|
||||||
|
} else {
|
||||||
|
node.elseBody->body.push_back(nodeMap[connection.outNodeId]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Fonction pour afficher le schéma des nœuds
|
||||||
|
void displayNodeSchema() {
|
||||||
|
|
||||||
|
// Afficher les nœuds
|
||||||
|
for (auto& astNode : m_ast.nodeMap) {
|
||||||
|
auto pos = astNode.second->position;
|
||||||
|
std::cout << "\033[" << pos.second + 1 << ";" << pos.first + 1 << "H"; // Déplacer le curseur
|
||||||
|
std::cout << "[" << astNode.second->node->GetTypeName() << "]";
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
// Afficher les connexions
|
||||||
|
for (auto& connection : connections) {
|
||||||
|
auto outPos = nodePositions[connection.outNodeId];
|
||||||
|
auto inPos = nodePositions[connection.inNodeId];
|
||||||
|
|
||||||
|
// Dessiner une ligne entre les nœuds (simplifié)
|
||||||
|
int startX = outPos.first + 10;
|
||||||
|
int startY = outPos.second + 1;
|
||||||
|
int endX = inPos.first;
|
||||||
|
int endY = inPos.second + 1;
|
||||||
|
|
||||||
|
if (startY == endY) { // Ligne horizontale
|
||||||
|
for (int i = startX; i < endX; ++i) {
|
||||||
|
std::cout << "\033[" << startY << ";" << i + 1 << "H-";
|
||||||
|
}
|
||||||
|
} else { // Ligne verticale + horizontale
|
||||||
|
for (int i = startX; i < startX + (endX - startX) / 2; ++i) {
|
||||||
|
std::cout << "\033[" << startY << ";" << i + 1 << "H-";
|
||||||
|
}
|
||||||
|
for (int i = std::min(startY, endY); i < std::max(startY, endY); ++i) {
|
||||||
|
std::cout << "\033[" << i + 1 << ";" << startX + (endX - startX) / 2 + 1 << "H|";
|
||||||
|
}
|
||||||
|
for (int i = startX + (endX - startX) / 2 + 1; i < endX; ++i) {
|
||||||
|
std::cout << "\033[" << endY << ";" << i + 1 << "H-";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << "\033[" << endY << ";" << endX << "H>";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "\033[" << 100 << ";" << 1 << "H"; // Déplacer le curseur en bas
|
||||||
|
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
AST m_ast;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
53
core/story-manager/src/print_node.cpp
Normal file
53
core/story-manager/src/print_node.cpp
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
#include "print_node.h"
|
||||||
|
#include "story_project.h"
|
||||||
|
#include "connection.h"
|
||||||
|
#include "sys_lib.h"
|
||||||
|
#include "compiler.h"
|
||||||
|
|
||||||
|
|
||||||
|
PrintNode::PrintNode(const std::string &type)
|
||||||
|
: BaseNode(type, "Print Node")
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PrintNode::Initialize()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PrintNode::GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns)
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PrintNode::Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
|
||||||
|
std::list<std::shared_ptr<Connection>> conns;
|
||||||
|
page.GetNodeConnections(conns, GetId());
|
||||||
|
int i = 0;
|
||||||
|
std::list<std::shared_ptr<Connection>>::iterator c = conns.begin();
|
||||||
|
|
||||||
|
if (conns.size() == 2)
|
||||||
|
{
|
||||||
|
ss << R"(; ---------------------------- )"
|
||||||
|
<< GetTitle()
|
||||||
|
<< " Type: Branch"
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
ss << "eq r0, r0, r1\n"
|
||||||
|
<< "skipz r0\n"
|
||||||
|
<< "jump " << BaseNode::GetEntryLabel((*c)->inNodeId);
|
||||||
|
++c;
|
||||||
|
ss << "jump " << BaseNode::GetEntryLabel((*c)->inNodeId);
|
||||||
|
}
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
21
core/story-manager/src/print_node.h
Normal file
21
core/story-manager/src/print_node.h
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "i_story_manager.h"
|
||||||
|
#include "base_node.h"
|
||||||
|
#include "i_script_node.h"
|
||||||
|
#include "i_story_project.h"
|
||||||
|
|
||||||
|
class PrintNode : public BaseNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PrintNode(const std::string &type);
|
||||||
|
|
||||||
|
virtual void Initialize() override;
|
||||||
|
virtual std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override;
|
||||||
|
virtual std::string GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns) override;
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
16
core/story-manager/tests/CMakeLists.txt
Normal file
16
core/story-manager/tests/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
|
project(compiler_test LANGUAGES CXX C)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
add_executable(${PROJECT_NAME}
|
||||||
|
main.cpp
|
||||||
|
test_ast.cpp
|
||||||
|
|
||||||
|
../../chip32/chip32_assembler.cpp
|
||||||
|
../../chip32/chip32_vm.c
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(${PROJECT_NAME} PRIVATE ../../chip32)
|
||||||
17966
core/story-manager/tests/catch.hpp
Normal file
17966
core/story-manager/tests/catch.hpp
Normal file
File diff suppressed because it is too large
Load diff
46
core/story-manager/tests/main.cpp
Normal file
46
core/story-manager/tests/main.cpp
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
The MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 Anthony Rabine
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#define CATCH_CONFIG_MAIN
|
||||||
|
#include "catch.hpp"
|
||||||
|
|
||||||
|
void hexdump(void *ptr, int buflen) {
|
||||||
|
unsigned char *buf = (unsigned char*)ptr;
|
||||||
|
int i, j;
|
||||||
|
for (i=0; i<buflen; i+=16) {
|
||||||
|
printf("%06x: ", i);
|
||||||
|
for (j=0; j<16; j++)
|
||||||
|
if (i+j < buflen)
|
||||||
|
printf("%02x ", buf[i+j]);
|
||||||
|
else
|
||||||
|
printf(" ");
|
||||||
|
printf(" ");
|
||||||
|
for (j=0; j<16; j++)
|
||||||
|
if (i+j < buflen)
|
||||||
|
printf("%c", isprint(buf[i+j]) ? buf[i+j] : '.');
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
82
core/story-manager/tests/test_ast.cpp
Normal file
82
core/story-manager/tests/test_ast.cpp
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
The MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 Anthony Rabine
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#include "catch.hpp"
|
||||||
|
#include "chip32_assembler.h"
|
||||||
|
#include "chip32_macros.h"
|
||||||
|
#include "compiler.h"
|
||||||
|
#include "branch_node.h"
|
||||||
|
#include "print_node.h"
|
||||||
|
#include "variable_node.h"
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE( "Check various indentations and typos" ) {
|
||||||
|
|
||||||
|
Compiler compiler;
|
||||||
|
|
||||||
|
auto printNode = std::make_shared<PrintNode>();
|
||||||
|
auto branchNode = std::make_shared<BranchNode>();
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<BaseNode>> nodes;
|
||||||
|
|
||||||
|
nodes.push_back(printNode);
|
||||||
|
nodes.push_back(branchNode);
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<Connection>> connections;
|
||||||
|
|
||||||
|
auto cn1 = std::make_shared<Connection>();
|
||||||
|
|
||||||
|
// // Création des nœuds
|
||||||
|
// std::vector<Node> nodes = {
|
||||||
|
// Node(Node::Type::VARIABLE, "i", "node_i"),
|
||||||
|
// Node(Node::Type::CONSTANT, 10, "node_10"),
|
||||||
|
// Node(Node::Type::SUBTRACT, "node_subtract"),
|
||||||
|
// Node(Node::Type::CONSTANT, 1, "node_1"),
|
||||||
|
// Node(Node::Type::ADD, "node_add"),
|
||||||
|
// Node(Node::Type::ASSIGN, "i", "node_assign"),
|
||||||
|
// Node(Node::Type::VARIABLE, "conditionVar", "node_condVar"),
|
||||||
|
// Node(Node::Type::CONSTANT, 2, "node_2"),
|
||||||
|
// Node(Node::Type::MULTIPLY, "node_multiply"),
|
||||||
|
// Node(Node::Type::ASSIGN, "i", "node_assign_multiply"),
|
||||||
|
// Node(Node::Type::BRANCH, "node_branch"),
|
||||||
|
// Node(Node::Type::LOOP, "node_loop")
|
||||||
|
// };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Construction de l'AST
|
||||||
|
AST ast = buildAST(nodes, connections);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
REQUIRE( parseResult == true );
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue