ArkScript
A small, lisp-inspired, functional scripting language
Parser.hpp
Go to the documentation of this file.
1/**
2 * @file Parser.hpp
3 * @author Lex Plateau (lexplt.dev@gmail.com)
4 * @brief Parse ArkScript code, but do not handle any import declarations
5 * @date 2024-05-12
6 *
7 * @copyright Copyright (c) 2024-2025
8 *
9 */
10
11#ifndef ARK_COMPILER_AST_PARSER_HPP
12#define ARK_COMPILER_AST_PARSER_HPP
13
17#include <Ark/Utils/Logger.hpp>
18#include <Ark/Utils/Utils.hpp>
20
21#include <string>
22#include <vector>
23#include <optional>
24#include <functional>
25
26#include <utf8.hpp>
27
28namespace Ark::internal
29{
30 enum class ParserMode
31 {
32 Interpret, ///< Escape sequences and `()` will be replaced by their UTF8 representation and `nil`, respectively
33 Raw ///< Keep all text as is without modifying it (useful for the code formatter)
34 };
35
36 class ARK_API Parser final : public BaseParser
37 {
38 public:
39 /**
40 * @brief Constructs a new Parser object
41 * @param debug debug level
42 * @param mode how the parser should behave regarding certain nodes and errors
43 */
44 explicit Parser(unsigned debug, ParserMode mode = ParserMode::Interpret);
45
46 /**
47 * @brief Parse the given code
48 * @param filename can be left empty, used for error generation
49 * @param code content of the file
50 */
51 void process(const std::string& filename, const std::string& code);
52
53 /**
54 *
55 * @return const Node& resulting AST after processing the given code
56 */
57 [[nodiscard]] const Node& ast() const noexcept;
58
59 /**
60 *
61 * @return const std::vector<Import>& list of imports detected by the parser
62 */
63 [[nodiscard]] const std::vector<Import>& imports() const;
64
65 private:
69 std::vector<Import> m_imports;
70 unsigned m_allow_macro_behavior; ///< Toggled on when inside a macro definition, off afterward
71 std::size_t m_nested_nodes; ///< Nested node counter
72 std::vector<std::function<std::optional<Node>(FilePosition)>> m_parsers;
73
74 [[nodiscard]] Node positioned(Node node, FilePosition cursor) const;
75 [[nodiscard]] std::optional<Node>& positioned(std::optional<Node>& node, FilePosition cursor) const;
76
77 std::optional<Node> node();
78 std::optional<Node> letMutSet(FilePosition filepos);
79 std::optional<Node> del(FilePosition filepos);
80 std::optional<Node> condition(FilePosition filepos);
81 std::optional<Node> loop(FilePosition filepos);
82 std::optional<Node> import_(FilePosition filepos);
83 std::optional<Node> block(FilePosition filepos);
84 std::optional<Node> functionArgs(FilePosition filepos);
85 std::optional<Node> function(FilePosition filepos);
86 std::optional<Node> macroCondition(FilePosition filepos);
87 std::optional<Node> macroArgs(FilePosition filepos);
88 std::optional<Node> macro(FilePosition filepos);
89 std::optional<Node> functionCall(FilePosition filepos);
90 std::optional<Node> list(FilePosition filepos);
91
92 std::optional<Node> number(FilePosition filepos);
93 std::optional<Node> string(FilePosition filepos);
94 std::optional<Node> field(FilePosition filepos);
95 std::optional<Node> symbol(FilePosition filepos);
96 std::optional<Node> spread(FilePosition filepos);
97 std::optional<Node> nil(FilePosition filepos);
98
99 /**
100 * @brief Try to parse an atom (number, string, spread, field, symbol, nil)
101 * @return std::optional<Node> std::nullopt if no atom could be parsed
102 */
103 std::optional<Node> atom();
104
105 /**
106 * @brief Try to parse an atom, if any, match its type against the given list
107 * @param types authorized types
108 * @return std::optional<Node> std::nullopt if the parsed atom didn't match the given types
109 */
110 std::optional<Node> anyAtomOf(std::initializer_list<NodeType> types);
111
112 /**
113 * @brief Try to parse an atom first, if it fails try to parse a node
114 * @return std::optional<Node> std::nullopt if no atom or node could be parsed
115 */
116 std::optional<Node> nodeOrValue();
117
118 /**
119 * @brief Try to parse using a given parser, prefixing and suffixing it with (...), handling comments around the parsed node
120 * @param parser parser method returning a std::optional<Node>
121 * @param name construction name, eg "let", "condition"
122 * @return std::optional<Node> std::nullopt if the parser didn't match
123 */
124 std::optional<Node> wrapped(std::optional<Node> (Parser::*parser)(FilePosition), const std::string& name);
125 };
126}
127
128#endif // ARK_COMPILER_AST_PARSER_HPP
Lots of utilities about string, filesystem and more.
Internal logger.
#define ARK_API
Definition Module.hpp:22
AST node used by the parser, optimizer and compiler.
ArkScript configuration macros.
A node of an Abstract Syntax Tree for ArkScript.
Definition Node.hpp:32
std::vector< std::function< std::optional< Node >(FilePosition)> > m_parsers
Definition Parser.hpp:72
ParserMode m_mode
Definition Parser.hpp:66
unsigned m_allow_macro_behavior
Toggled on when inside a macro definition, off afterward.
Definition Parser.hpp:70
std::vector< Import > m_imports
Definition Parser.hpp:69
std::size_t m_nested_nodes
Nested node counter.
Definition Parser.hpp:71
@ Raw
Keep all text as is without modifying it (useful for the code formatter)
@ Interpret
Escape sequences and () will be replaced by their UTF8 representation and nil, respectively.
Describe a position in a given file ; handled by the BaseParser.