Skip to content

Commit ff68984

Browse files
authored
Treant.js formatted JSON from parse tree representation (#36)
* Treant Formatted JSON * debug removed * new edge case test added * updates * codecov * Stuructural change * codecov will be handled in seperate PR
1 parent 59389c9 commit ff68984

File tree

3 files changed

+90
-4
lines changed

3 files changed

+90
-4
lines changed

src/include/parser/parser.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,20 @@ class Parser {
7272
*/
7373
static std::string GenerateErrorMessage(const std::string &current_token);
7474

75+
/**
76+
* Supportive function for Parser::FormattedJSON
77+
* @param value
78+
* @return { text: { name: "value" } }
79+
*/
80+
static json GetTextNode(const std::string & /* value */);
81+
82+
/**
83+
* Utility recursive function for Parser::FormattedJSON
84+
* @param body, a json
85+
* @returns Treant.js formatted JSON
86+
*/
87+
static json RecRunner(const json & /*main*/, std::string /* key */);
88+
7589
public:
7690
/**
7791
* Constructor for initializing stack and other members.
@@ -106,9 +120,18 @@ class Parser {
106120

107121
/**
108122
* Dumps the parse tree in given path in json format
123+
* @param filepath
124+
* @param formatted (Default is in Treant.js format else raw if value is set "false")
109125
* @returns true on success
110126
*/
111-
bool WriteParseTree(const std::string &filepath);
127+
bool WriteParseTree(const std::string &filepath, bool formatted);
128+
129+
/**
130+
* Takes a json with no array, ideally received from parser::GetParseTree()
131+
* Format is given here https://fperucic.github.io/treant-js/
132+
* @returns a formatted JSON which acts as a input for Treant.js
133+
*/
134+
[[maybe_unused]] [[nodiscard]] static json FormattedJSON(const json & /* body */);
112135

113136
/* getters and setters*/
114137
void SetInputString(std::vector<std::string> inps);

src/parser/parser.cpp

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,14 +160,41 @@ void Parser::BuildParseTree() {
160160
}
161161
}
162162

163-
bool Parser::WriteParseTree(const std::string &filepath) {
163+
bool Parser::WriteParseTree(const std::string &filepath, bool formatted = true) {
164164
std::ofstream ofs(filepath);
165165
if (ofs.is_open()) {
166-
ofs << parse_tree_.dump(INDENTATION) << '\n';
166+
ofs << (formatted ? FormattedJSON(parse_tree_) : parse_tree_).dump(INDENTATION) << '\n';
167167
return true;
168168
}
169-
170169
return false;
171170
}
172171

172+
json Parser::GetTextNode(const std::string &value) {
173+
json j;
174+
j["text"]["name"] = value;
175+
return j;
176+
}
177+
178+
json Parser::RecRunner(const json &main, std::string key = "") {
179+
if (main.empty()) {
180+
return GetTextNode(key);
181+
}
182+
auto body = main;
183+
if (key.empty()) {
184+
for (auto it = main.begin(); it != main.end();) {
185+
key = it.key();
186+
body = it.value();
187+
break;
188+
}
189+
}
190+
191+
json j = GetTextNode(key);
192+
for (auto it = body.begin(); it != body.end(); it++) {
193+
j["children"].push_back(RecRunner(it.value(), it.key()));
194+
}
195+
return j;
196+
}
197+
198+
json Parser::FormattedJSON(const json &body) { return Parser::RecRunner(body); }
199+
173200
} // namespace jucc::parser

test/parser/parser_test.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,4 +363,40 @@ TEST(parser, Parser4) {
363363
pars.BuildParseTree();
364364
auto tree = pars.GetParseTree();
365365
ASSERT_EQ(tree.dump(), "{\"S\":{\"A\":{\"a\":null},\"B\":{\"b\":null},\"A_1\":{\"a\":null}}}");
366+
367+
/**
368+
* Output
369+
* {
370+
* "text": { "name": "S" },
371+
* "children": [ {
372+
* "text": { "name": "A" },
373+
* "children": [
374+
* { "text": { "name": "a" } }
375+
* ] },
376+
* {
377+
* "text": {"name": "B"},
378+
* "children": [
379+
* { "text": {"name": "b"} }
380+
* ] },
381+
* {
382+
* "text": { "name": "A_1" },
383+
* "children": [
384+
* { "text": { "name": "a" }
385+
* } ]
386+
* }
387+
* ]
388+
* }
389+
*/
390+
json formatted = Parser::FormattedJSON(tree);
391+
ASSERT_EQ(formatted.dump(),
392+
"{\"text\":{\"name\":\"S\"},\"children\":[{\"text\":{\"name\":\"A\"},\"children\":[{\"text\":{\"name\":"
393+
"\"a\"}}]},{\"text\":{\"name\":\"B\"},\"children\":[{\"text\":{\"name\":\"b\"}}]},{\"text\":{\"name\":\"A_"
394+
"1\"},\"children\":[{\"text\":{\"name\":\"a\"}}]}]}");
395+
}
396+
397+
TEST(parser, parser5) {
398+
json j;
399+
j["S"] = nullptr;
400+
// No children case
401+
ASSERT_EQ(Parser::FormattedJSON(j).dump(), "{\"text\":{\"name\":\"S\"}}");
366402
}

0 commit comments

Comments
 (0)