ArkScript
A small, fast, functional and scripting language for video games
Formatter.hpp
Go to the documentation of this file.
1#ifndef ARK_FORMATTER_HPP
2#define ARK_FORMATTER_HPP
3
4#include <string>
5
7
8constexpr struct FormatterConfig
9{
10 static constexpr std::size_t SpacePerIndent = 2; ///< Indentation level of each node
11 static constexpr std::size_t LongLineLength = 32; ///< Max number of characters per line segment to consider splitting
13
14class Formatter final
15{
16public:
17 explicit Formatter(bool dry_run);
18 Formatter(std::string filename, bool dry_run);
19
20 /**
21 * @brief Read the file and process it. The file isn't modified
22 */
23 void run();
24
25 /**
26 *
27 * @param code code to process (bypass reading the file if initialized with a filename)
28 */
29 void runWithString(const std::string& code);
30
31 [[nodiscard]] const std::string& output() const;
32
33 /**
34 *
35 * @return true if code has been modified by the formatter
36 */
37 [[nodiscard]] bool codeModified() const;
38
39private:
40 const std::string m_filename;
41 bool m_dry_run; ///< If true, only prints the formatted file instead of saving it to disk
43 std::string m_output;
44 bool m_updated; ///< True if the original code now difer from the formatted one
45
46 void processAst(const Ark::internal::Node& ast);
47
48 /**
49 * @brief Given the original code, produce a warning if comments from it were removed during formatting
50 * @param original_code
51 * @param filename
52 */
53 void warnIfCommentsWereRemoved(const std::string& original_code, const std::string& filename);
54
55 /**
56 * @brief Check if a given node starts with a given keyword
57 * @param node
58 * @param keyword
59 * @return bool
60 */
61 [[nodiscard]] static bool isListStartingWithKeyword(const Ark::internal::Node& node, Ark::internal::Keyword keyword);
62
63 /**
64 * @brief Check if a node is a begin block
65 * @param node
66 * @return bool
67 */
68 [[nodiscard]] static bool isBeginBlock(const Ark::internal::Node& node);
69
70 /**
71 * @brief Check if a node is a function definition (fun (args) body)
72 * @param node
73 * @return bool
74 */
75 [[nodiscard]] static bool isFuncDef(const Ark::internal::Node& node);
76
77 /**
78 * @brief Check if a node is a function call (foo bar egg)
79 * @param node
80 * @return bool
81 */
82 [[nodiscard]] static bool isFuncCall(const Ark::internal::Node& node);
83
84 /**
85 * @brief Compute the line on which the deepest right most node of node is at
86 * @param node
87 * @return
88 */
89 static std::size_t lineOfLastNodeIn(const Ark::internal::Node& node);
90
91 /**
92 * @brief Decide if a node should be split on a newline or not
93 * @param node
94 * @return bool
95 */
96 [[nodiscard]] bool shouldSplitOnNewline(const Ark::internal::Node& node);
97
98 /**
99 * @brief Decide if we should add a newline after a node in a block
100 * @param node a List node
101 * @param at the node we are currently formatting
102 * @return
103 */
104 [[nodiscard]] bool shouldAddNewLineBetweenNodes(const Ark::internal::Node& node, std::size_t at);
105
106 /**
107 * @brief Compute indentation level
108 * @param indent indentation level
109 * @return std::string
110 */
111 static std::string prefix(const std::size_t indent)
112 {
113 return std::string(indent * FormatterConfig::SpacePerIndent, ' ');
114 }
115
116 /**
117 * @brief Handles all node formatting
118 * @param node
119 * @param indent indentation level, starting at 0, increment by 1
120 * @param after_newline when false, do not add prefix
121 * @return
122 */
123 std::string format(const Ark::internal::Node& node, std::size_t indent, bool after_newline);
124
125 std::string formatComment(const std::string& comment, std::size_t indent) const;
126
127 std::string formatBlock(const Ark::internal::Node& node, std::size_t indent, bool after_newline);
128
129 std::string formatFunction(const Ark::internal::Node& node, std::size_t indent);
130 std::string formatVariable(const Ark::internal::Node& node, std::size_t indent);
131 std::string formatCondition(const Ark::internal::Node& node, std::size_t indent, bool is_macro = false);
132 std::string formatLoop(const Ark::internal::Node& node, std::size_t indent);
133 std::string formatBegin(const Ark::internal::Node& node, std::size_t indent, bool after_newline);
134 std::string formatImport(const Ark::internal::Node& node, std::size_t indent);
135 std::string formatDel(const Ark::internal::Node& node, std::size_t indent);
136 std::string formatCall(const Ark::internal::Node& node, std::size_t indent);
137 std::string formatMacro(const Ark::internal::Node& node, std::size_t indent);
138};
139
140#endif // ARK_FORMATTER_HPP
constexpr struct FormatterConfig FormatterConfig
Parse ArkScript code, but do not handle any import declarations.
A node of an Abstract Syntax Tree for ArkScript.
Definition Node.hpp:31
std::string formatMacro(const Ark::internal::Node &node, std::size_t indent)
bool shouldSplitOnNewline(const Ark::internal::Node &node)
Decide if a node should be split on a newline or not.
void run()
Read the file and process it. The file isn't modified.
Definition Formatter.cpp:22
std::string formatVariable(const Ark::internal::Node &node, std::size_t indent)
bool codeModified() const
Definition Formatter.cpp:60
std::string formatBlock(const Ark::internal::Node &node, std::size_t indent, bool after_newline)
std::string formatDel(const Ark::internal::Node &node, std::size_t indent)
void processAst(const Ark::internal::Node &ast)
Definition Formatter.cpp:65
static std::string prefix(const std::size_t indent)
Compute indentation level.
std::string formatCall(const Ark::internal::Node &node, std::size_t indent)
static bool isBeginBlock(const Ark::internal::Node &node)
Check if a node is a begin block.
bool m_dry_run
If true, only prints the formatted file instead of saving it to disk.
Definition Formatter.hpp:41
static bool isFuncCall(const Ark::internal::Node &node)
Check if a node is a function call (foo bar egg)
static bool isFuncDef(const Ark::internal::Node &node)
Check if a node is a function definition (fun (args) body)
Ark::internal::Parser m_parser
Definition Formatter.hpp:42
bool shouldAddNewLineBetweenNodes(const Ark::internal::Node &node, std::size_t at)
Decide if we should add a newline after a node in a block.
std::string formatBegin(const Ark::internal::Node &node, std::size_t indent, bool after_newline)
bool m_updated
True if the original code now difer from the formatted one.
Definition Formatter.hpp:44
Formatter(bool dry_run)
Definition Formatter.cpp:14
std::string formatFunction(const Ark::internal::Node &node, std::size_t indent)
std::string formatLoop(const Ark::internal::Node &node, std::size_t indent)
std::string m_output
Definition Formatter.hpp:43
const std::string & output() const
Definition Formatter.cpp:55
std::string formatImport(const Ark::internal::Node &node, std::size_t indent)
std::string formatComment(const std::string &comment, std::size_t indent) const
const std::string m_filename
Definition Formatter.hpp:40
void runWithString(const std::string &code)
Definition Formatter.cpp:39
void warnIfCommentsWereRemoved(const std::string &original_code, const std::string &filename)
Given the original code, produce a warning if comments from it were removed during formatting.
Definition Formatter.cpp:88
static std::size_t lineOfLastNodeIn(const Ark::internal::Node &node)
Compute the line on which the deepest right most node of node is at.
std::string format(const Ark::internal::Node &node, std::size_t indent, bool after_newline)
Handles all node formatting.
static bool isListStartingWithKeyword(const Ark::internal::Node &node, Ark::internal::Keyword keyword)
Check if a given node starts with a given keyword.
std::string formatCondition(const Ark::internal::Node &node, std::size_t indent, bool is_macro=false)
Keyword
The different keywords available.
Definition Common.hpp:60
static constexpr std::size_t SpacePerIndent
Indentation level of each node.
Definition Formatter.hpp:10
static constexpr std::size_t LongLineLength
Max number of characters per line segment to consider splitting.
Definition Formatter.hpp:11