Skip to content

Commit

Permalink
Merge pull request #147 from abap34/feat/#143
Browse files Browse the repository at this point in the history
AST のノードの付け替えを実装
  • Loading branch information
abap34 authored Aug 6, 2024
2 parents 499f774 + 671f44e commit c7091f9
Show file tree
Hide file tree
Showing 29 changed files with 780 additions and 708 deletions.
86 changes: 54 additions & 32 deletions src/ast.hpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#pragma once

#include "utils.hpp"
#include "interfaces/ast.hpp"
#include "utils.hpp"

namespace almo {

struct uuid_gen_ {
int operator()(){
int operator()() {
static int uuid = 0;
return uuid++;
}
Expand All @@ -24,14 +24,15 @@ std::string ASTNode::to_json() const {
json += "\"uuid\":\"" + escape(get_uuid_str()) + "\",";

// add other properties
for (auto property : properties){
json += "\"" + property.first + "\":\"" + escape(property.second) + "\",";
for (auto property : properties) {
json +=
"\"" + property.first + "\":\"" + escape(property.second) + "\",";
}

// has childs
if (!childs.empty()){
if (!childs.empty()) {
json += "\"childs\":[";
for (auto child : childs){
for (auto child : childs) {
json += child->to_json();
json += ',';
}
Expand All @@ -48,73 +49,94 @@ std::string ASTNode::to_json() const {
return json;
}

std::string ASTNode::to_dot() const {
std::string ASTNode::concatenated_childs_dot() const {
std::map<std::string, std::string> properties = get_properties();

std::string node = get_uuid_str();
std::string label = "";

for (int i = 1; auto property : properties){
label += "<f" + std::to_string(i) + "> " + property.first + ": " + escape(property.second) + " | ";
for (int i = 1; auto property : properties) {
label += "<f" + std::to_string(i) + "> " + property.first + ": " +
escape(property.second) + " | ";
i++;
}

// is Leaf
if (childs.empty()){
return node + "[label=\"" + get_classname() + " | " + label + "\", shape=\"record\"]\n";
if (childs.empty()) {
return node + "[label=\"" + get_classname() + " | " + label +
"\", shape=\"record\"]\n";
}

// add child node
std::string childs_dot = "";
for (auto child : childs){
childs_dot += child->to_dot();
for (auto child : childs) {
childs_dot += child->concatenated_childs_dot();
}

// connect child node
std::string edges = "";
for (auto child : childs){
edges += node + ":f" + std::to_string(edges.length()) + " -> " + child->get_uuid_str() + "\n";
for (auto child : childs) {
edges += node + ":f" + std::to_string(edges.length()) + " -> " +
child->get_uuid_str() + "\n";
}

// if this node is root, you must format returned string r as follows :
// r = "digraph G {\n graph [labelloc=\"t\"; \n ]\n" + r + "}";
return node + "[label=\"<f0> " + get_classname() + " | " + label + "\", shape=\"record\"]\n" + childs_dot + edges;
return node + "[label=\"<f0> " + get_classname() + " | " + label +
"\", shape=\"record\"]\n" + childs_dot + edges;
}

std::string ASTNode::get_uuid_str() const {
return std::to_string(uuid);
}
std::string ASTNode::get_uuid_str() const { return std::to_string(uuid); }

void ASTNode::set_uuid(){
uuid = uuid_gen();
}
void ASTNode::set_uuid() { uuid = uuid_gen(); }

void ASTNode::add_child(std::shared_ptr<ASTNode> child){
void ASTNode::pushback_child(std::shared_ptr<ASTNode> child) {
childs.push_back(child);
}

void ASTNode::remove_child(std::shared_ptr<ASTNode> child) {
for (auto it = childs.begin(); it != childs.end(); it++) {
if (*it == child) {
childs.erase(it);
return;
}

(*it)->remove_child(child);
}
}

std::string ASTNode::concatenated_childs_html() const {
std::string ret = "";
for (auto child : childs){
for (auto child : childs) {
ret += child->to_html();
}
return ret;
}

std::vector<std::shared_ptr<ASTNode>> ASTNode::get_childs() const {
return childs;
}

std::vector<std::string> ASTNode::nodes_byclass(const std::string &classname) const {
std::vector<std::string> ret;
if (get_classname() == classname){
ret.push_back(get_uuid_str());
std::vector<std::shared_ptr<ASTNode>> ASTNode::nodes_byclass(
const std::string &classname) const {
std::vector<std::shared_ptr<ASTNode>> ret;
if (get_classname() == classname) {
ret.push_back(const_cast<ASTNode *>(this)->shared_from_this());
}
for (auto child : childs){
std::vector<std::string> childs_ret = child->nodes_byclass(classname);
for (auto child_ret : childs_ret){
for (auto child : childs) {
std::vector<std::shared_ptr<ASTNode>> childs_ret =
child->nodes_byclass(classname);
for (auto child_ret : childs_ret) {
ret.push_back(child_ret);
}
}
return ret;
}

void ASTNode::move_node(std::shared_ptr<ASTNode> node,
std::shared_ptr<ASTNode> new_parent) {
remove_child(node);
new_parent->pushback_child(node);
}

} // namespace almo
} // namespace almo
35 changes: 22 additions & 13 deletions src/interfaces/ast.hpp
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
#pragma once

#include <string>
#include <vector>
#include <map>
#include <memory>
#include <string>
#include <vector>

namespace almo {

struct ASTNode {

struct ASTNode : public std::enable_shared_from_this<ASTNode> {
// html
virtual std::string to_html() const = 0;

// json
std::string to_json() const ;
std::string to_json() const;

// dot
std::string to_dot() const ;
std::string concatenated_childs_dot() const;

// properties
virtual std::map<std::string, std::string> get_properties() const = 0;
Expand All @@ -25,24 +24,34 @@ struct ASTNode {
virtual std::string get_classname() const = 0;

// get uuid as string
std::string get_uuid_str() const ;
std::string get_uuid_str() const;

// set uuid
void set_uuid();

// add child
void add_child(std::shared_ptr<ASTNode> child);
void pushback_child(std::shared_ptr<ASTNode> child);

// remove child
void remove_child(std::shared_ptr<ASTNode> child);

std::vector<std::shared_ptr<ASTNode>> get_childs() const;

// child's html
std::string concatenated_childs_html() const ;
std::string concatenated_childs_html() const;

// get node's uuid from class name
std::vector<std::string> nodes_byclass(const std::string &classname) const ;
std::vector<std::shared_ptr<ASTNode>> nodes_byclass(
const std::string &classname) const;

protected:
void move_node(std::shared_ptr<ASTNode> node,
std::shared_ptr<ASTNode> new_parent);

public:
std::vector<std::shared_ptr<ASTNode>> childs;
private:

private:
int uuid;
};

} // namespace almo
} // namespace almo
80 changes: 71 additions & 9 deletions src/pyalmo.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/stl.h>

#include "almo.cpp"

// Macro to bind node
#define BIND_NODE(CLASS, BIND_CLASSNAME, CONSTRUCTOR_ARGS...) \
py::class_<CLASS, almo::ASTNode, std::shared_ptr<CLASS>>(m, \
BIND_CLASSNAME) \
.def(py::init<CONSTRUCTOR_ARGS>())

almo::Markdown parse_md(std::string md_content) {
almo::Markdown ast;
std::vector<std::string> content_splitted = split(md_content, "\n");
Expand All @@ -16,17 +22,73 @@ namespace py = pybind11;
PYBIND11_MODULE(almo, m) {
m.doc() = "almo interface for python.";

m.def("parse_md", &parse_md, "Parse markdown to AST.");
m.def("parse", &parse_md, "Parse markdown to AST.");

py::class_<almo::ASTNode, std::shared_ptr<almo::ASTNode>>(
m, "ASTNode", py::dynamic_attr())
.def("to_html", &almo::ASTNode::to_html)
.def("to_json", &almo::ASTNode::to_json)
.def("get_properties", &almo::ASTNode::get_properties)
.def("get_classname", &almo::ASTNode::get_classname)
.def("get_uuid_str", &almo::ASTNode::get_uuid_str)
.def("set_uuid", &almo::ASTNode::set_uuid)
.def("pushback_child", &almo::ASTNode::pushback_child)
.def("remove_child", &almo::ASTNode::remove_child)
.def("move_node", &almo::ASTNode::move_node)
.def("concatenated_childs_html",
&almo::ASTNode::concatenated_childs_html)
.def("nodes_byclass", &almo::ASTNode::nodes_byclass)
.def_readwrite("childs", &almo::ASTNode::childs)
.def("get_childs", &almo::ASTNode::get_childs)
.def("__repr__", [](const almo::ASTNode &ast_node) {
return "<almo." + ast_node.get_classname() +
" (uuid: " + ast_node.get_uuid_str() + ")>";
});

py::class_<almo::Markdown>(m, "Markdown")
py::class_<almo::Markdown, almo::ASTNode, std::shared_ptr<almo::Markdown>>(
m, "Markdown")
.def(py::init<>())
.def("to_html", &almo::Markdown::to_html)
.def("to_dot", &almo::Markdown::to_dot)
.def("to_json", &almo::Markdown::to_json)
.def("nodes_byclass", &almo::Markdown::nodes_byclass);
.def("__repr__", [](const almo::Markdown &md_ast) {
return "<almo.Markdown (uuid: " + md_ast.get_uuid_str() + ")>";
});

// CLASS, CONSTRUCTOR_ARGS
BIND_NODE(almo::CodeBlock, "CodeBlock", std::string, std::string);
BIND_NODE(almo::DivBlock, "DivBlock", std::string);
BIND_NODE(almo::EnumerateBlock, "EnumerateBlock");
BIND_NODE(almo::ExecutableCodeBlock, "ExecutableCodeBlock", std::string,
std::string);
BIND_NODE(almo::FootnoteDefinition, "FootnoteDefinition", std::string);
BIND_NODE(almo::Header, "Header", int);
BIND_NODE(almo::HorizontalLine, "HorizontalLine");
BIND_NODE(almo::InlineCodeBlock, "InlineCodeBlock", std::string);
BIND_NODE(almo::InlineFootnoteReference, "InlineFootnoteReference",
std::string);
BIND_NODE(almo::InlineImage, "InlineImage", std::string, std::string);
BIND_NODE(almo::InlineItalic, "InlineItalic");
BIND_NODE(almo::InlineMath, "InlineMath", std::string);
BIND_NODE(almo::InlineOverline, "InlineOverline");
BIND_NODE(almo::InlineStrong, "InlineStrong");
BIND_NODE(almo::InlineUrl, "InlineUrl", std::string, std::string);
BIND_NODE(almo::Item, "Item");
BIND_NODE(almo::Judge, "Judge", std::string, std::string, std::string,
std::string, std::string, std::string, std::string, std::string);
BIND_NODE(almo::ListBlock, "ListBlock");
BIND_NODE(almo::LoadLib, "LoadLib", std::vector<std::string>);
BIND_NODE(almo::MathBlock, "MathBlock", std::string);
BIND_NODE(almo::NewLine, "NewLine");
BIND_NODE(almo::Quote, "Quote");
BIND_NODE(almo::RawText, "RawText", std::string);
BIND_NODE(almo::Table, "Table",
std::vector<std::shared_ptr<almo::Markdown>>, int, int,
std::vector<std::string>, std::vector<int>);

#ifdef VERSION_INFO
m.attr("__version__") = VERSION_INFO;
#else
m.attr("__version__") = "dev";
#endif
#ifdef VERSION_INFO
m.attr("__version__") = VERSION_INFO;
#else
m.attr("__version__") = "dev";
#endif
}
Loading

0 comments on commit c7091f9

Please sign in to comment.