Line data Source code
1 : #include "../../../inc/parsingAnalysis/algorithm/topDown.h"
2 : #include <memory>
3 :
4 : namespace nicole {
5 :
6 : const std::expected<std::shared_ptr<Tree>, Error>
7 0 : TopDown::parse(const std::filesystem::path &entryFile) const noexcept {
8 0 : parsedFiles_.insert(entryFile);
9 :
10 0 : const auto tkStream{lexer_.analyze(entryFile)};
11 :
12 0 : if (!tkStream) {
13 0 : return createError(tkStream.error());
14 0 : }
15 :
16 0 : tkStream_ = *tkStream;
17 :
18 0 : const std::expected<std::shared_ptr<AST_BODY>, Error> root{parseStart()};
19 :
20 0 : if (!root || !*root) {
21 0 : return createError(root ? Error{ERROR_TYPE::NULL_NODE, "Tree is null"}
22 0 : : root.error());
23 0 : }
24 :
25 0 : const auto tree{Builder::createTree(*root)};
26 :
27 0 : if (!tree) {
28 0 : return createError(tree.error());
29 0 : }
30 :
31 0 : return *tree;
32 0 : }
33 :
34 : const std::expected<std::shared_ptr<AST_BODY>, Error>
35 0 : TopDown::parseStart() const noexcept {
36 0 : std::vector<std::shared_ptr<AST_STATEMENT>> statements{};
37 :
38 0 : const auto firsToken{tkStream_.current()};
39 :
40 0 : while (tkStream_.currentPos() < tkStream_.size()) {
41 0 : const std::expected<std::shared_ptr<AST_STATEMENT>, Error> statement{
42 0 : parseStatement()};
43 0 : if (!statement || !*statement) {
44 0 : return createError(statement
45 0 : ? Error{ERROR_TYPE::NULL_NODE, "Statement is null"}
46 0 : : statement.error());
47 0 : }
48 0 : statements.push_back(*statement);
49 0 : if (tkStream_.current()->type() == TokenType::SEMICOLON &&
50 0 : !tkStream_.eat()) {
51 0 : return createError(ERROR_TYPE::SINTAX, "Failed to consume semicolon");
52 0 : }
53 0 : }
54 :
55 0 : const std::expected<std::shared_ptr<AST_BODY>, Error> body{
56 0 : Builder::createBody(SourceLocation{*firsToken, *tkStream_.lastRead()},
57 0 : statements)};
58 0 : if (!body) {
59 0 : return createError(body.error());
60 0 : }
61 :
62 0 : return body;
63 0 : }
64 :
65 : const std::expected<std::shared_ptr<AST_BODY>, Error>
66 0 : TopDown::parseBody() const noexcept {
67 :
68 0 : const auto firsToken{tkStream_.current()};
69 :
70 0 : if (tkStream_.current()->type() != TokenType::LB) {
71 0 : return createError(ERROR_TYPE::SINTAX,
72 0 : "missing { at " + tkStream_.current()->locInfo());
73 0 : }
74 0 : if (auto res = tryEat(); !res) {
75 0 : return createError(res.error());
76 0 : }
77 :
78 0 : std::vector<std::shared_ptr<AST_STATEMENT>> statements{};
79 :
80 0 : while (tkStream_.currentPos() < tkStream_.size() and
81 0 : tkStream_.current()->type() != TokenType::RB) {
82 0 : const std::expected<std::shared_ptr<AST_STATEMENT>, Error> statement{
83 0 : parseStatement()};
84 0 : if (!statement || !*statement) {
85 0 : return createError(statement
86 0 : ? Error{ERROR_TYPE::NULL_NODE, "Statement is null"}
87 0 : : statement.error());
88 0 : }
89 0 : statements.push_back(*statement);
90 0 : if (tkStream_.current()->type() == TokenType::SEMICOLON &&
91 0 : !tkStream_.eat()) {
92 0 : return createError(ERROR_TYPE::SINTAX, "Failed to consume semicolon");
93 0 : }
94 0 : }
95 0 : if (tkStream_.current()->type() != TokenType::RB) {
96 0 : return createError(ERROR_TYPE::SINTAX,
97 0 : "missing } at " + tkStream_.current()->locInfo());
98 0 : }
99 0 : if (auto res = tryEat(); !res) {
100 0 : return createError(res.error());
101 0 : }
102 :
103 0 : const std::expected<std::shared_ptr<AST_BODY>, Error> body{
104 0 : Builder::createBody(SourceLocation{*firsToken, *tkStream_.lastRead()},
105 0 : statements)};
106 0 : if (!body) {
107 0 : return createError(body.error());
108 0 : }
109 :
110 0 : return body;
111 0 : }
112 :
113 : const std::expected<std::shared_ptr<AST_STATEMENT>, Error>
114 0 : TopDown::parseStatement() const noexcept {
115 0 : const auto firsToken{tkStream_.current()};
116 : // Función auxiliar para elegir la sentencia a parsear.
117 0 : auto parseStmt = [&]() -> std::expected<std::shared_ptr<AST>, Error> {
118 : // in case that it is an assignment
119 0 : if (tkStream_.isTokenAheadBeforeSemicolon(TokenType::DOTDOT_ASSIGNMENT) ||
120 0 : tkStream_.isTokenAheadBeforeSemicolon(TokenType::SELF_ADD) ||
121 0 : tkStream_.isTokenAheadBeforeSemicolon(TokenType::SELF_SUB) ||
122 0 : tkStream_.isTokenAheadBeforeSemicolon(TokenType::SELF_MULT) ||
123 0 : tkStream_.isTokenAheadBeforeSemicolon(TokenType::SELF_DIV))
124 0 : return parseAssignment(false);
125 :
126 : // Se obtiene el tipo del token actual para decidir la rama de parseo.
127 0 : switch (tkStream_.current()->type()) {
128 0 : case TokenType::IF:
129 0 : return parseIf();
130 0 : case TokenType::SWITCH:
131 0 : return parseSwitch();
132 0 : case TokenType::WHILE:
133 0 : return parseWhile();
134 0 : case TokenType::DO:
135 0 : return parseDoWhile();
136 0 : case TokenType::FOR:
137 0 : return parseFor();
138 0 : case TokenType::PASS:
139 0 : return parsePass();
140 0 : case TokenType::STOP:
141 0 : return parseStop();
142 0 : case TokenType::FUNCTION:
143 0 : return parseFuncDecl();
144 0 : case TokenType::RETURN:
145 0 : return parseReturn();
146 0 : case TokenType::ENUM:
147 0 : return parseEnum();
148 0 : case TokenType::STRUCT:
149 0 : return parseStructDecl();
150 0 : case TokenType::DELETE:
151 0 : return parseDelete();
152 0 : case TokenType::IMPORT:
153 0 : return parseImport();
154 0 : case TokenType::PRINT:
155 0 : return parsePrint();
156 0 : default:
157 0 : return parseVarDecl(false);
158 0 : }
159 0 : };
160 :
161 0 : auto statement = parseStmt();
162 :
163 0 : if (!statement || !*statement)
164 0 : return createError(statement ? Error{ERROR_TYPE::NULL_NODE, "node is null"}
165 0 : : statement.error());
166 :
167 0 : return Builder::createStatement(
168 0 : SourceLocation{*firsToken, *tkStream_.lastRead()}, *statement);
169 0 : }
170 :
171 : // topDown.cpp
172 0 : std::expected<std::monostate, Error> TopDown::tryEat() const noexcept {
173 0 : if (!tkStream_.eat())
174 0 : return createError(ERROR_TYPE::SINTAX,
175 0 : "failed to eat " + tkStream_.current()->raw() + " at " +
176 0 : tkStream_.current()->locInfo());
177 0 : return {};
178 0 : }
179 :
180 : } // namespace nicole
|