ArkScript
A small, fast, functional and scripting language for video games
Parser.hpp
Go to the documentation of this file.
1 /**
2  * @file Parser.hpp
3  * @author Alexandre Plateau (lexplt.dev@gmail.com)
4  * @brief Parses a token stream into an AST by using the Ark::Node
5  * @version 0.4
6  * @date 2020-10-27
7  *
8  * @copyright Copyright (c) 2020-2021
9  *
10  */
11 
12 #ifndef COMPILER_AST_PARSER_HPP
13 #define COMPILER_AST_PARSER_HPP
14 
15 #include <string>
16 #include <list>
17 #include <ostream>
18 #include <vector>
19 #include <cinttypes>
20 
21 #include <Ark/Constants.hpp>
24 
25 namespace Ark::internal
26 {
28  {
29  if (tt == TokenType::Capture)
30  return NodeType::Capture;
31  else if (tt == TokenType::GetField)
32  return NodeType::GetField;
33  else if (tt == TokenType::Spread)
34  return NodeType::Spread;
35 
36  return NodeType::Symbol;
37  }
38 
39  /**
40  * @brief The parser is responsible of constructing the Abstract Syntax Tree from a token list
41  *
42  */
43  class Parser
44  {
45  public:
46  /**
47  * @brief Construct a new Parser object
48  *
49  * @param debug the debug level
50  * @param options the parsing options
51  * @param lib_env fallback library search path
52  */
53  Parser(unsigned debug, uint16_t options, const std::vector<std::string>& lib_env) noexcept;
54 
55  /**
56  * @brief Give the code to parse
57  *
58  * @param code the ArkScript code
59  * @param filename the name of the file
60  */
61  void feed(const std::string& code, const std::string& filename = ARK_NO_NAME_FILE);
62 
63  /**
64  * @brief Return the generated AST
65  *
66  * @return const Node&
67  */
68  const Node& ast() const noexcept;
69 
70  /**
71  * @brief Return the list of files imported by the code given to the parser
72  *
73  * Each path of each imported file is relative to the filename given when feeding the parser.
74  *
75  * @return const std::vector<std::string>&
76  */
77  const std::vector<std::string>& getImports() const noexcept;
78 
79  friend std::ostream& operator<<(std::ostream& os, const Parser& P) noexcept;
80 
81  private:
82  unsigned m_debug;
83  std::vector<std::string> m_libenv;
84  uint16_t m_options;
88 
89  // path of the current file
90  std::string m_file;
91  // source code of the current file
92  std::string m_code;
93  // the files included by the "includer" to avoid multiple includes
94  std::vector<std::string> m_parent_include;
95 
96  /**
97  * @brief Applying syntactic sugar: {...} => (begin...), [...] => (list ...)
98  *
99  * @param tokens a list of tokens
100  */
101  void sugar(std::vector<Token>& tokens) noexcept;
102 
103  /**
104  * @brief Parse a list of tokens recursively
105  *
106  * @param tokens
107  * @param authorize_capture if we are authorized to consume TokenType::Capture tokens
108  * @param authorize_field_read if we are authorized to consume TokenType::GetField tokens
109  * @param in_macro if we are in a macro, there a bunch of things we can tolerate
110  * @return Node
111  */
112  Node parse(std::list<Token>& tokens, bool authorize_capture = false, bool authorize_field_read = false, bool in_macro = false);
113 
114  void parseIf(Node&, std::list<Token>&, bool);
115  void parseLetMut(Node&, Token&, std::list<Token>&, bool);
116  void parseSet(Node&, Token&, std::list<Token>&, bool);
117  void parseFun(Node&, Token&, std::list<Token>&, bool);
118  void parseWhile(Node&, Token&, std::list<Token>&, bool);
119  void parseBegin(Node&, std::list<Token>&, bool);
120  void parseImport(Node&, std::list<Token>&);
121  void parseQuote(Node&, std::list<Token>&, bool);
122  void parseDel(Node&, std::list<Token>&);
123  Node parseShorthand(Token&, std::list<Token>&, bool);
124  void checkForInvalidTokens(Node&, Token&, bool, bool, bool);
125 
126  /**
127  * @brief Get the next token if possible, from a list of tokens
128  *
129  * The list of tokens is modified.
130  *
131  * @param tokens list of tokens to get the next token from
132  * @return Token
133  */
134  Token nextToken(std::list<Token>& tokens);
135 
136  /**
137  * @brief Convert a token to a node
138  *
139  * @param token the token to converts
140  * @return Node
141  */
142  Node atom(const Token& token);
143 
144  /**
145  * @brief Search for all the includes in a given node, in its sub-nodes and replace them by the code of the included file
146  *
147  * @param n
148  * @param parent the parent node of the current one
149  * @param pos the position of the child node in the parent node list
150  * @return true if we found an import and replaced it by the corresponding code
151  */
152  bool checkForInclude(Node& n, Node& parent, std::size_t pos = 0);
153 
154  /**
155  * @brief Seek a file in the lib folder and everywhere
156  *
157  * @param file
158  * @return std::string
159  */
160  std::string seekFile(const std::string& file);
161 
162  /**
163  * @brief Throw a parse exception is the given predicated is false
164  *
165  * @param pred
166  * @param message error message to use
167  * @param token concerned token
168  */
169  void expect(bool pred, const std::string& message, Token token);
170 
171  /**
172  * @brief Throw a parse error related to a token (seek it in the related file and highlight the error)
173  *
174  * @param message
175  * @param token
176  */
177  [[noreturn]] void throwParseError(const std::string& message, Token token);
178  };
179 }
180 
181 #endif
Constants used by ArkScript.
#define ARK_NO_NAME_FILE
Definition: Constants.hpp:26
Tokenize ArkScript code.
AST node used by the parser, optimizer and compiler.
The lexer, in charge of creating a list of tokens.
Definition: Lexer.hpp:27
A node of an Abstract Syntax Tree for ArkScript.
Definition: Node.hpp:29
The parser is responsible of constructing the Abstract Syntax Tree from a token list.
Definition: Parser.hpp:44
void parseImport(Node &, std::list< Token > &)
Definition: Parser.cpp:321
void parseBegin(Node &, std::list< Token > &, bool)
Definition: Parser.cpp:308
friend std::ostream & operator<<(std::ostream &os, const Parser &P) noexcept
Definition: Parser.cpp:597
std::string m_code
Definition: Parser.hpp:92
void parseLetMut(Node &, Token &, std::list< Token > &, bool)
Definition: Parser.cpp:227
void parseDel(Node &, std::list< Token > &)
Definition: Parser.cpp:336
Node atom(const Token &token)
Convert a token to a node.
Definition: Parser.cpp:411
uint16_t m_options
Definition: Parser.hpp:84
void sugar(std::vector< Token > &tokens) noexcept
Applying syntactic sugar: {...} => (begin...), [...] => (list ...)
Definition: Parser.cpp:69
void expect(bool pred, const std::string &message, Token token)
Throw a parse exception is the given predicated is false.
Definition: Parser.cpp:579
const Node & ast() const noexcept
Return the generated AST.
Definition: Parser.cpp:59
void parseQuote(Node &, std::list< Token > &, bool)
Definition: Parser.cpp:330
void feed(const std::string &code, const std::string &filename=ARK_NO_NAME_FILE)
Give the code to parse.
Definition: Parser.cpp:21
void throwParseError(const std::string &message, Token token)
Throw a parse error related to a token (seek it in the related file and highlight the error)
Definition: Parser.cpp:585
std::string seekFile(const std::string &file)
Seek a file in the lib folder and everywhere.
Definition: Parser.cpp:547
std::vector< std::string > m_libenv
Definition: Parser.hpp:83
std::string m_file
Definition: Parser.hpp:90
void parseFun(Node &, Token &, std::list< Token > &, bool)
Definition: Parser.cpp:276
void parseSet(Node &, Token &, std::list< Token > &, bool)
Definition: Parser.cpp:250
void checkForInvalidTokens(Node &, Token &, bool, bool, bool)
Definition: Parser.cpp:377
void parseIf(Node &, std::list< Token > &, bool)
Definition: Parser.cpp:204
Node parse(std::list< Token > &tokens, bool authorize_capture=false, bool authorize_field_read=false, bool in_macro=false)
Parse a list of tokens recursively.
Definition: Parser.cpp:102
Parser(unsigned debug, uint16_t options, const std::vector< std::string > &lib_env) noexcept
Construct a new Parser object.
Definition: Parser.cpp:13
std::vector< std::string > m_parent_include
Definition: Parser.hpp:94
void parseWhile(Node &, Token &, std::list< Token > &, bool)
Definition: Parser.cpp:291
bool checkForInclude(Node &n, Node &parent, std::size_t pos=0)
Search for all the includes in a given node, in its sub-nodes and replace them by the code of the inc...
Definition: Parser.cpp:480
Node parseShorthand(Token &, std::list< Token > &, bool)
Definition: Parser.cpp:345
Token nextToken(std::list< Token > &tokens)
Get the next token if possible, from a list of tokens.
Definition: Parser.cpp:401
const std::vector< std::string > & getImports() const noexcept
Return the list of files imported by the code given to the parser.
Definition: Parser.cpp:64
NodeType
The different node types available.
Definition: Common.hpp:29
NodeType similarNodetypeFromTokentype(TokenType tt)
Definition: Parser.hpp:27