Line data Source code
1 : #include "../../../../inc/parsingAnalysis/algorithm/topDown.h"
2 : #include <expected>
3 : #include <memory>
4 : #include <vector>
5 :
6 : namespace nicole {
7 :
8 : const std::expected<std::shared_ptr<AST_CHAINED>, Error>
9 0 : TopDown::parseChainedExpression() const noexcept {
10 0 : const auto firsToken{tkStream_.current()};
11 0 : if (tkStream_.current()->type() != TokenType::ID) {
12 0 : return createError(ERROR_TYPE::SINTAX, "Expected identifier at " +
13 0 : tkStream_.current()->locInfo());
14 0 : }
15 :
16 0 : const Token baseToken{*tkStream_.current()};
17 0 : if (auto res = tryEat(); !res) {
18 0 : return createError(res.error());
19 0 : }
20 :
21 0 : std::expected<std::vector<std::shared_ptr<Type>>, Error>
22 0 : replacementOfGenerics{parseReplacementOfGenerics()};
23 0 : bool cannotBeVarCall{false};
24 0 : if (!replacementOfGenerics) {
25 0 : return createError(replacementOfGenerics.error());
26 0 : }
27 :
28 0 : if ((tkStream_.current()->type() != TokenType::LP or
29 0 : tkStream_.current()->type() != TokenType::LB) and replacementOfGenerics->size()) {
30 0 : cannotBeVarCall = true;
31 0 : }
32 :
33 : // 2. Determinar si es un simple varCall o una funcCall
34 0 : std::shared_ptr<AST> basePtr = nullptr;
35 0 : if (tkStream_.current()->type() == TokenType::LP) {
36 0 : const std::expected<std::vector<std::shared_ptr<AST>>, Error> arguemnts{
37 0 : parseArguments({TokenType::LP, TokenType::RP}, true)};
38 0 : if (!arguemnts) {
39 0 : return createError(arguemnts.error());
40 0 : }
41 :
42 : // Crear nodo de función
43 0 : auto funcCall = Builder::createFunCall(SourceLocation{*firsToken, *tkStream_.lastRead()},baseToken.raw(),
44 0 : *replacementOfGenerics, *arguemnts);
45 0 : if (!funcCall || !*funcCall) {
46 0 : return createError(
47 0 : funcCall ? Error{ERROR_TYPE::NULL_NODE, "Failed to create func call"}
48 0 : : funcCall.error());
49 0 : }
50 0 : basePtr = *funcCall;
51 0 : } else if (tkStream_.current()->type() == TokenType::LB) {
52 :
53 0 : const std::expected<std::vector<std::shared_ptr<AST>>, Error> arguemnts{
54 0 : parseArguments({TokenType::LB, TokenType::RB}, true)};
55 0 : if (!arguemnts) {
56 0 : return createError(arguemnts.error());
57 0 : }
58 :
59 0 : auto constructorCall = Builder::createConstructorCall(SourceLocation{*firsToken, *tkStream_.lastRead()},
60 0 : baseToken.raw(), *replacementOfGenerics, *arguemnts);
61 0 : if (!constructorCall || !*constructorCall) {
62 0 : return createError(constructorCall
63 0 : ? Error{ERROR_TYPE::NULL_NODE,
64 0 : "Failed to create constructor call"}
65 0 : : constructorCall.error());
66 0 : }
67 0 : basePtr = *constructorCall;
68 0 : } else {
69 0 : if (cannotBeVarCall) {
70 0 : return createError(
71 0 : ERROR_TYPE::SINTAX,
72 0 : "a variable call cannot have replacements of generics, at" +
73 0 : tkStream_.lastRead()->locInfo());
74 0 : }
75 : // Variable normal
76 0 : auto varCall = Builder::createVarCall(SourceLocation{*firsToken, *tkStream_.lastRead()},baseToken.raw());
77 0 : if (!varCall || !*varCall) {
78 0 : return createError(
79 0 : varCall ? Error{ERROR_TYPE::NULL_NODE, "Failed to create var call"}
80 0 : : varCall.error());
81 0 : }
82 0 : basePtr = *varCall;
83 0 : }
84 :
85 : // 3. Operaciones encadenadas: [index], .atributo, .metodo(...)
86 0 : std::vector<std::shared_ptr<AST>> operations;
87 0 : while (tkStream_.currentPos() < tkStream_.size() and
88 0 : (tkStream_.current()->type() == TokenType::LC or
89 0 : tkStream_.current()->type() == TokenType::DOT)) {
90 0 : TokenType ttype = tkStream_.current()->type();
91 0 : switch (ttype) {
92 : // Acceso a índice -> base[index]
93 0 : case TokenType::LC: {
94 : // Consumir '['
95 0 : if (auto res = tryEat(); !res) {
96 0 : return createError(res.error());
97 0 : }
98 : // parseOr() para la expresión de índice
99 0 : auto indexExpr = parseOr();
100 0 : if (!indexExpr || !*indexExpr) {
101 0 : return createError(indexExpr
102 0 : ? Error{ERROR_TYPE::NULL_NODE, "index is null"}
103 0 : : indexExpr.error());
104 0 : }
105 : // Consumir ']'
106 0 : if (tkStream_.current()->type() != TokenType::RC || !tkStream_.eat()) {
107 0 : return createError(ERROR_TYPE::SINTAX,
108 0 : "Missing ']' at " + tkStream_.current()->locInfo());
109 0 : }
110 : // Crear nodo de índice
111 0 : auto indexNode = Builder::createIndex(SourceLocation{*firsToken, *tkStream_.lastRead()},*indexExpr);
112 0 : if (!indexNode || !*indexNode) {
113 0 : return createError(indexNode ? Error{ERROR_TYPE::NULL_NODE,
114 0 : "Failed to create index node"}
115 0 : : indexNode.error());
116 0 : }
117 0 : operations.push_back(*indexNode);
118 0 : break;
119 0 : }
120 :
121 : // Punto -> base.atributo o base.metodo(...)
122 0 : case TokenType::DOT: {
123 : // Consumir '.'
124 0 : if (auto res = tryEat(); !res) {
125 0 : return createError(res.error());
126 0 : }
127 0 : if (tkStream_.current()->type() != TokenType::ID) {
128 0 : return createError(ERROR_TYPE::SINTAX,
129 0 : "Expected identifier after '.' at " +
130 0 : tkStream_.current()->locInfo());
131 0 : }
132 :
133 : // Leer el nombre del atributo/método
134 0 : Token attrToken{*tkStream_.current()};
135 0 : if (auto res = tryEat(); !res) {
136 0 : return createError(res.error());
137 0 : }
138 :
139 0 : std::expected<std::vector<std::shared_ptr<Type>>, Error>
140 0 : replacementOfGenerics2{parseReplacementOfGenerics()};
141 0 : bool cannotBeAttrAccess{false};
142 0 : if (!replacementOfGenerics2) {
143 0 : return createError(replacementOfGenerics2.error());
144 0 : }
145 :
146 0 : if (tkStream_.current()->type() != TokenType::LP and replacementOfGenerics->size()) {
147 0 : cannotBeAttrAccess = true;
148 0 : }
149 :
150 : // Comprobar si es método -> un '(' a continuación
151 0 : if (tkStream_.current()->type() == TokenType::LP) {
152 :
153 0 : const std::expected<std::vector<std::shared_ptr<AST>>, Error> arguemnts{
154 0 : parseArguments({TokenType::LP, TokenType::RP}, true)};
155 0 : if (!arguemnts) {
156 0 : return createError(arguemnts.error());
157 0 : }
158 :
159 0 : auto methodNode = Builder::createMethodCall(SourceLocation{*firsToken, *tkStream_.lastRead()},
160 0 : attrToken.raw(), *replacementOfGenerics2, *arguemnts);
161 0 : if (!methodNode || !*methodNode) {
162 0 : return createError(methodNode ? Error{ERROR_TYPE::NULL_NODE,
163 0 : "Failed to create method call"}
164 0 : : methodNode.error());
165 0 : }
166 0 : operations.push_back(*methodNode);
167 0 : } else {
168 0 : if (cannotBeAttrAccess) {
169 0 : return createError(
170 0 : ERROR_TYPE::SINTAX,
171 0 : "a attr access cannot have replacements of generics, at" +
172 0 : tkStream_.lastRead()->locInfo());
173 0 : }
174 : // Es un atributo
175 0 : auto attrNode = Builder::createAttrAccess(SourceLocation{*firsToken, *tkStream_.lastRead()},attrToken.raw());
176 0 : if (!attrNode || !*attrNode) {
177 0 : return createError(attrNode
178 0 : ? Error{ERROR_TYPE::NULL_NODE,
179 0 : "Failed to create attribute access"}
180 0 : : attrNode.error());
181 0 : }
182 0 : operations.push_back(*attrNode);
183 0 : }
184 0 : break;
185 0 : }
186 :
187 0 : default:
188 : // Si ya no es ni '[', ni '.', ni '(', terminamos
189 0 : return Builder::createChained(SourceLocation{*firsToken, *tkStream_.lastRead()},basePtr, operations);
190 0 : }
191 0 : }
192 :
193 : // Si se acaban los tokens, retornamos la cadena
194 0 : return Builder::createChained(SourceLocation{*firsToken, *tkStream_.lastRead()},basePtr, operations);
195 0 : }
196 :
197 : } // namespace nicole
|