| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * License); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| #include "path_visitor.h" |
| |
| namespace storage { |
| antlrcpp::Any PathVisitor::visitPath(PathParser::PathContext* ctx) { |
| if (ctx->prefixPath() != nullptr) { |
| return visitPrefixPath(ctx->prefixPath()); |
| } else { |
| return visitSuffixPath(ctx->suffixPath()); |
| } |
| } |
| |
| antlrcpp::Any PathVisitor::visitPrefixPath(PathParser::PrefixPathContext* ctx) { |
| std::vector<PathParser::NodeNameContext*> node_names = ctx->nodeName(); |
| std::vector<std::string> path; |
| path.reserve(node_names.size() + 1); |
| path.push_back(ctx->ROOT()->getText()); |
| for (uint64_t i = 0; i < node_names.size(); i++) { |
| path.push_back(parse_node_name(node_names[i])); |
| } |
| return path; |
| } |
| |
| antlrcpp::Any PathVisitor::visitSuffixPath(PathParser::SuffixPathContext* ctx) { |
| std::vector<PathParser::NodeNameContext*> node_names = ctx->nodeName(); |
| std::vector<std::string> path; |
| path.reserve(node_names.size()); |
| for (uint64_t i = 0; i < node_names.size(); i++) { |
| path.emplace_back(parse_node_name(node_names[i])); |
| } |
| return path; |
| } |
| std::string PathVisitor::parse_node_name(PathParser::NodeNameContext* ctx) { |
| std::string node_name = ctx->getText(); |
| if (starts_with(node_name, BACK_QUOTE_STRING) && |
| ends_with(node_name, BACK_QUOTE_STRING)) { |
| std::string unWrapped = node_name.substr(1, node_name.length() - 2); |
| if (is_real_number(unWrapped) || |
| !std::regex_match(unWrapped, IDENTIFIER_PATTERN)) { |
| return node_name; |
| } |
| |
| return unWrapped; |
| } |
| |
| return node_name; |
| } |
| bool PathVisitor::is_real_number(const std::string& str) { |
| std::string s = str; |
| if (starts_with(s, "+") || starts_with(s, "-")) { |
| std::string removeSign = s.substr(1); |
| if (starts_with(removeSign, "+") || starts_with(removeSign, "-")) { |
| return false; |
| } else { |
| s = removeSign; |
| } |
| } |
| size_t index = 0; |
| auto it = std::find_if(s.begin(), s.end(), |
| [](const char& c) { return c != '0'; }); |
| if (it != s.end()) { |
| index = it - s.begin(); |
| } |
| |
| if (index > 0 && (s[index] == 'e' || s[index] == 'E')) { |
| return is_creatable(s.substr(index - 1)); |
| } else { |
| return is_creatable(s.substr(index)); |
| } |
| } |
| bool PathVisitor::starts_with(const std::string& str, |
| const std::string& prefix) { |
| if (prefix.size() > str.size()) { |
| return false; |
| } |
| return str.substr(0, prefix.size()) == prefix; |
| } |
| |
| bool PathVisitor::ends_with(const std::string& str, const std::string& suffix) { |
| if (suffix.size() > str.size()) { |
| return false; |
| } |
| return str.substr(str.size() - suffix.size()) == suffix; |
| } |
| |
| bool PathVisitor::is_creatable(const std::string& str) { |
| try { |
| std::stod(str); |
| return true; |
| } catch (const std::invalid_argument& e) { |
| return false; |
| } catch (const std::out_of_range& e) { |
| return false; |
| } |
| } |
| } // namespace storage |