// Copyright 2023 PingCAP, Inc. // // Licensed 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. #pragma once #include #include #include #include #include #include namespace DB { /** Collects variants, how parser could proceed further at rightmost position. */ struct Expected { const char * max_parsed_pos = nullptr; std::set variants; /// 'description' should be statically allocated string. void add(const char * current_pos, const char * description) { if (!max_parsed_pos || current_pos > max_parsed_pos) { variants.clear(); max_parsed_pos = current_pos; } if (!max_parsed_pos || current_pos >= max_parsed_pos) variants.insert(description); } void add(TokenIterator it, const char * description) { add(it->begin, description); } }; /** Interface for parser classes */ class IParser { public: using Pos = TokenIterator; /** Get the text of this parser parses. */ virtual const char * getName() const = 0; /** Parse piece of text from position `pos`, but not beyond end of line (`end` - position after end of line), * move pointer `pos` to the maximum position to which it was possible to parse, * in case of success return `true` and the result in `node` if it is needed, otherwise false, * in `expected` write what was expected in the maximum position, * to which it was possible to parse if parsing was unsuccessful, * or what this parser parse if parsing was successful. * The string to which the [begin, end) range is included may be not 0-terminated. */ virtual bool parse(Pos & pos, ASTPtr & node, Expected & expected) = 0; bool ignore(Pos & pos, Expected & expected) { ASTPtr ignore_node; return parse(pos, ignore_node, expected); } bool ignore(Pos & pos) { Expected expected; return ignore(pos, expected); } /** The same, but do not move the position and do not write the result to node. */ bool check(Pos & pos, Expected & expected) { Pos begin = pos; ASTPtr node; if (!parse(pos, node, expected)) { pos = begin; return false; } else return true; } virtual ~IParser() {} }; using ParserPtr = std::unique_ptr; } // namespace DB