ArkScript
A small, lisp-inspired, functional scripting language
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 = 120; ///< 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
46
47 void processAst(const Ark::internal::Node& ast);
48
49 /**
50 * @brief Given the original code, produce a warning if comments from it were removed during formatting
51 * @param original_code
52 * @param filename
53 */
54 void warnIfCommentsWereRemoved(const std::string& original_code, const std::string& filename);
55
56 /**
57 * @brief Check if a given node starts with a given keyword
58 * @param node
59 * @param keyword
60 * @return bool
61 */
62 [[nodiscard]] static bool isListStartingWithKeyword(const Ark::internal::Node& node, Ark::internal::Keyword keyword);
63
64 /**
65 * @brief Check if a node is a begin block
66 * @param node
67 * @return bool
68 */
69 [[nodiscard]] static bool isBeginBlock(const Ark::internal::Node& node);
70
71 /**
72 * @brief Check if a node is a function definition (fun (args) body)
73 * @param node
74 * @return bool
75 */
76 [[nodiscard]] static bool isFuncDef(const Ark::internal::Node& node);
77
78 /**
79 * @brief Check if a node is a function call (foo bar egg)
80 * @param node
81 * @return bool
82 */
83 [[nodiscard]] static bool isFuncCall(const Ark::internal::Node& node);
84
85 /**
86 * @brief Compute the line on which the deepest right most node of node is at
87 * @param node
88 * @return
89 */
90 static std::size_t lineOfLastNodeIn(const Ark::internal::Node& node);
91
92 [[nodiscard]] bool isLongLine(const Ark::internal::Node& node);
93
94 /**
95 * @brief Decide if a node should be split on a newline or not
96 * @param node
97 * @return bool
98 */
99 [[nodiscard]] bool shouldSplitOnNewline(const Ark::internal::Node& node);
100
101 /**
102 * @brief Decide if we should add a newline after a node in a block
103 * @param node a List node
104 * @param at the node we are currently formatting
105 * @return
106 */
107 [[nodiscard]] bool shouldAddNewLineBetweenNodes(const Ark::internal::Node& node, std::size_t at);
108
109 /**
110 * @brief Compute indentation level
111 * @param indent indentation level
112 * @return std::string
113 */
114 [[nodiscard]] static std::string prefix(const std::size_t indent)
115 {
116 return std::string(indent * FormatterConfig::SpacePerIndent, ' ');
117 }
118
119 /**
120 * @brief Handles all node formatting
121 * @param node
122 * @param indent indentation level, starting at 0, increment by 1
123 * @param after_newline when false, do not add prefix
124 * @return
125 */
126 [[nodiscard]] std::string format(const Ark::internal::Node& node, std::size_t indent, bool after_newline);
127
128 [[nodiscard]] std::string formatComment(const std::string& comment, std::size_t indent) const;
129
130 [[nodiscard]] std::string formatBlock(const Ark::internal::Node& node, std::size_t indent, bool after_newline);
131
132 [[nodiscard]] std::string formatFunction(const Ark::internal::Node& node, std::size_t indent);
133 [[nodiscard]] std::string formatVariable(const Ark::internal::Node& node, std::size_t indent);
134 [[nodiscard]] std::string formatCondition(const Ark::internal::Node& node, std::size_t indent, bool is_macro = false);
135 [[nodiscard]] std::string formatLoop(const Ark::internal::Node& node, std::size_t indent);
136 [[nodiscard]] std::string formatBegin(const Ark::internal::Node& node, std::size_t indent, bool after_newline);
137 [[nodiscard]] std::string formatImport(const Ark::internal::Node& node, std::size_t indent);
138 [[nodiscard]] std::string formatDel(const Ark::internal::Node& node, std::size_t indent);
139 [[nodiscard]] std::string formatCall(const Ark::internal::Node& node, std::size_t indent);
140 [[nodiscard]] std::string formatMacro(const Ark::internal::Node& node, std::size_t indent);
141};
142
143#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:32
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.
Ark::internal::Logger m_logger
Definition Formatter.hpp:45
void run()
Read the file and process it. The file isn't modified.
Definition Formatter.cpp:24
std::string formatVariable(const Ark::internal::Node &node, std::size_t indent)
bool codeModified() const
Definition Formatter.cpp:62
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:67
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:16
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:57
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:41
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:90
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.
bool isLongLine(const Ark::internal::Node &node)
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:79
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