Line data Source code
1 : #include "../../../inc/visitors/validateTree/validateTree.h"
2 : #include "../../../inc/parsingAnalysis/ast/conditionals/ast_case.h"
3 : #include "../../../inc/parsingAnalysis/ast/conditionals/ast_default.h"
4 : #include "../../../inc/parsingAnalysis/ast/conditionals/ast_elseIf.h"
5 : #include "../../../inc/parsingAnalysis/ast/conditionals/ast_if.h"
6 : #include "../../../inc/parsingAnalysis/ast/conditionals/ast_switch.h"
7 : #include "../../../inc/parsingAnalysis/ast/conditionals/ast_ternary.h"
8 : #include "../../../inc/parsingAnalysis/checkPosition.h"
9 :
10 : namespace nicole {
11 :
12 : // statement / body / not null
13 : std::expected<bool, Error>
14 0 : ValidateTree::visit(const AST_IF *node) const noexcept {
15 0 : if (!node) {
16 0 : return createError(ERROR_TYPE::NULL_NODE, "invalid AST_IF");
17 0 : }
18 0 : if (!CheckPosition::itsBodyAncestorHasParent(node)) {
19 0 : return createError(ERROR_TYPE::VALIDATE_TREE,
20 0 : "a if statement must appear inside of a scope");
21 0 : }
22 0 : const auto condition{node->condition()->accept(*this)};
23 0 : if (!condition) {
24 0 : return createError(condition.error());
25 0 : }
26 0 : const auto body{node->body()->accept(*this)};
27 0 : if (!body) {
28 0 : return createError(body.error());
29 0 : }
30 0 : for (const auto &elseif_ : node->elseIf()) {
31 0 : const auto result{elseif_->accept(*this)};
32 0 : if (!result) {
33 0 : return createError(result.error());
34 0 : }
35 0 : }
36 0 : if (node->elseBody()) {
37 0 : const auto elseBody{node->elseBody()->accept(*this)};
38 0 : if (!elseBody) {
39 0 : return createError(elseBody.error());
40 0 : }
41 0 : }
42 0 : return true;
43 0 : }
44 :
45 : // if
46 : std::expected<bool, Error>
47 0 : ValidateTree::visit(const AST_ELSE_IF *node) const noexcept {
48 0 : if (!node) {
49 0 : return createError(ERROR_TYPE::NULL_NODE, "invalid AST_ELSE_IF");
50 0 : }
51 0 : if (!CheckPosition::hasEveryAncestorInOrder(node, {AST_TYPE::IF})) {
52 0 : return createError(ERROR_TYPE::VALIDATE_TREE,
53 0 : "a else if must follow a if statement");
54 0 : }
55 0 : const auto condition{node->condition()->accept(*this)};
56 0 : if (!condition) {
57 0 : return createError(condition.error());
58 0 : }
59 0 : const auto result{node->body()->accept(*this)};
60 0 : if (!result) {
61 0 : return createError(result.error());
62 0 : }
63 0 : return true;
64 0 : }
65 :
66 : // statement / body / not null
67 : std::expected<bool, Error>
68 0 : ValidateTree::visit(const AST_SWITCH *node) const noexcept {
69 0 : if (!node) {
70 0 : return createError(ERROR_TYPE::NULL_NODE, "invalid AST_SWITCH");
71 0 : }
72 0 : if (!CheckPosition::itsBodyAncestorHasParent(node)) {
73 0 : return createError(ERROR_TYPE::VALIDATE_TREE,
74 0 : "a switch statement must appear inside of a scope");
75 0 : }
76 0 : const auto condition{node->condition()->accept(*this)};
77 0 : if (!condition) {
78 0 : return createError(condition.error());
79 0 : }
80 0 : for (const auto &case_ : node->cases()) {
81 0 : const auto result{case_->accept(*this)};
82 0 : if (!result) {
83 0 : return createError(result.error());
84 0 : }
85 0 : }
86 0 : if (node->defaultCase()) {
87 0 : const auto defaultCase{node->defaultCase()->accept(*this)};
88 0 : if (!defaultCase) {
89 0 : return createError(defaultCase.error());
90 0 : }
91 0 : }
92 0 : return true;
93 0 : }
94 :
95 : // switch
96 : std::expected<bool, Error>
97 0 : ValidateTree::visit(const AST_CASE *node) const noexcept {
98 0 : if (!node) {
99 0 : return createError(ERROR_TYPE::NULL_NODE, "invalid AST_CASE");
100 0 : }
101 0 : if (!CheckPosition::hasEveryAncestorInOrder(node, {AST_TYPE::SWITCH})) {
102 0 : return createError(ERROR_TYPE::VALIDATE_TREE,
103 0 : "a case statement can only appear in a switch scope");
104 0 : }
105 0 : const auto match{node->match()->accept(*this)};
106 0 : if (!match) {
107 0 : return createError(match.error());
108 0 : }
109 0 : const auto result{node->body()->accept(*this)};
110 0 : if (!result) {
111 0 : return createError(result.error());
112 0 : }
113 0 : return true;
114 0 : }
115 :
116 : // switch
117 : std::expected<bool, Error>
118 0 : ValidateTree::visit(const AST_DEFAULT *node) const noexcept {
119 0 : if (!node) {
120 0 : return createError(ERROR_TYPE::NULL_NODE, "invalid AST_DEFAULT");
121 0 : }
122 0 : if (!CheckPosition::hasEveryAncestorInOrder(node, {AST_TYPE::SWITCH})) {
123 0 : return createError(ERROR_TYPE::VALIDATE_TREE,
124 0 : "a default statement can only appear in a switch scope");
125 0 : }
126 0 : const auto result{node->body()->accept(*this)};
127 0 : if (!result) {
128 0 : return createError(result.error());
129 0 : }
130 0 : return true;
131 0 : }
132 :
133 : std::expected<bool, Error>
134 0 : ValidateTree::visit(const AST_TERNARY *node) const noexcept {
135 0 : if (!node) {
136 0 : return createError(ERROR_TYPE::NULL_NODE, "invalid AST_TERNARY");
137 0 : }
138 0 : if (CheckPosition::isOutOfScope(node)) {
139 0 : return createError(ERROR_TYPE::VALIDATE_TREE,
140 0 : "a ternary operation cannot appear outside of a scope");
141 0 : }
142 0 : const auto condition{node->condition()->accept(*this)};
143 0 : if (!condition) {
144 0 : return createError(condition.error());
145 0 : }
146 0 : const auto first{node->first()->accept(*this)};
147 0 : if (!first) {
148 0 : return createError(first.error());
149 0 : }
150 0 : const auto second{node->second()->accept(*this)};
151 0 : if (!second) {
152 0 : return createError(second.error());
153 0 : }
154 0 : return true;
155 0 : }
156 :
157 : std::expected<bool, Error>
158 0 : ValidateTree::visit(const AST_CONDITION *node) const noexcept {
159 0 : if (!node) {
160 0 : return createError(ERROR_TYPE::NULL_NODE, "invalid AST_CONDITION");
161 0 : }
162 0 : if (CheckPosition::hasAnyAncestorOf(node, {AST_TYPE::IF, AST_TYPE::ELSE_IF,
163 0 : AST_TYPE::IF, AST_TYPE::SWITCH,
164 0 : AST_TYPE::DO_WHILE,
165 0 : AST_TYPE::WHILE, AST_TYPE::FOR})) {
166 0 : return createError(ERROR_TYPE::VALIDATE_TREE, "misplaced condition");
167 0 : }
168 0 : return node->condition()->accept(*this);
169 0 : }
170 :
171 : }
|