/** * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * 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. */ #ifndef PANDA_VERIF_PARSER_H_ #define PANDA_VERIF_PARSER_H_ #include "charset.h" #include "util/callable.h" namespace panda::parser { template struct type_sum; template struct type_prod; struct op_next; struct op_end; struct op_optional; struct op_action; struct op_sequence; struct op_or; struct op_and; struct op_lookup; struct op_not; struct op_times; struct op_times_ref; template struct if_type { }; template struct if_type { using type = C; }; template T &ref_to(); template T val_of(); enum class action { START, PARSED, CANCEL }; template struct base_parser : public verifier::callable { template constexpr base_parser(const F &f) : verifier::callable {f} { } using Ctx = Context; using T = Type; base_parser() = default; template using next = base_parser, Char, Iter>; using p = base_parser, Char, Iter>; static next> of_charset(const charset &c) { static const auto l = [c](Context &, Iter &start, Iter end) { Iter s = start; while (s != end && c(*s)) { s++; } bool result = (s != start); if (result) { start = s; } return result; }; return l; } static next of_string(Char *str) { static const auto l = [=](Context &, Iter &start, Iter end) { Iter s = start; Iter c = str; while (s != end && *c != 0 && *c == *s) { ++c; ++s; } bool result = (*c == 0); if (result) { start = s; } return result; }; return l; } static next end() { static const auto l = [](Context &, Iter &start, Iter end) { return start == end; }; return l; } next operator~() && { static const auto l = [p = *this](Context &c, Iter &start, Iter end) { p(c, start, end); return true; }; return l; } next operator~() const & { static const auto l = [this](Context &c, Iter &start, Iter end) { (*this)(c, start, end); return true; }; return l; } template auto operator|=(F f) const -> typename if_type(), ref_to(), val_of(), val_of())), bool, next>>::type { static const auto l = [p = *this, f](Context &c, Iter &start, Iter end) { auto saved = start; if (!f(action::START, c, start, start, end)) { start = saved; return false; } bool result = p(c, start, end); auto new_saved = saved; if (!result) { f(action::CANCEL, c, new_saved, start, end); start = saved; return false; } if (!f(action::PARSED, c, new_saved, start, end)) { start = saved; return false; } return true; }; return l; } template auto operator|=(F f) const -> typename if_type(), ref_to(), val_of())), bool, next>>::type { static const auto l = [p = *this, f](Context &c, Iter &start, Iter end) { auto saved = start; if (!f(action::START, c, start, start)) { start = saved; return false; } bool result = p(c, start, end); auto new_saved = saved; if (!result) { f(action::CANCEL, c, new_saved, start); start = saved; return false; } if (!f(action::PARSED, c, new_saved, start)) { start = saved; return false; } return true; }; return l; } template auto operator|=(F f) const -> typename if_type(), ref_to())), bool, next>>::type { static const auto l = [p = *this, f](Context &c, Iter &start, Iter end) { auto saved = start; if (!f(action::START, c, start)) { start = saved; return false; } bool result = p(c, start, end); auto new_saved = saved; if (!result) { f(action::CANCEL, c, new_saved); start = saved; return false; } if (!f(action::PARSED, c, new_saved)) { start = saved; return false; } return true; }; return l; } template auto operator|=(F f) const -> typename if_type())), bool, next>>::type { static const auto l = [p = *this, f](Context &c, Iter &start, Iter end) { auto saved = start; if (!f(action::START, c)) { start = saved; return false; } bool result = p(c, start, end); if (!result) { f(action::CANCEL, c); start = saved; return false; } if (!f(action::PARSED, c)) { start = saved; return false; } return true; }; return l; } template next> operator>>(P pa) const { static const auto l = [left = *this, right = pa](Context &c, Iter &start, Iter end) { auto saved = start; if (left(c, start, end) && right(c, start, end)) { return true; } start = saved; return false; }; return l; } template next> operator|(P pa) const { static const auto l = [left = *this, right = pa](Context &c, Iter &start, Iter end) { auto saved = start; if (left(c, start, end)) { return true; } start = saved; if (right(c, start, end)) { return true; } start = saved; return false; }; return l; } template next> operator&(P pa) const { static const auto l = [left = *this, right = pa](Context &c, Iter &start, Iter end) { auto saved = start; if (left(c, start, end)) { start = saved; return right(c, start, end); } start = saved; return false; }; return l; } template next> operator<<(P pa) const { static const auto l = [left = *this, right = pa](Context &c, Iter &start, Iter end) { auto saved1 = start; if (left(c, start, end)) { auto saved2 = start; if (right(c, start, end)) { start = saved2; return true; } } start = saved1; return false; }; return l; } next operator!() && { static const auto l = [p = *this](Context &c, Iter &start, Iter end) { auto saved = start; if (p(c, start, end)) { start = saved; return false; } start = saved; return true; }; return l; } next operator!() const & { static const auto l = [this](Context &c, Iter &start, Iter end) { auto saved = start; if ((*this)(c, start, end)) { start = saved; return false; } start = saved; return true; }; return l; } next operator*() && { static const auto l = [p = *this](Context &c, Iter &start, Iter end) { while (true) { auto saved = start; if (!p(c, start, end)) { start = saved; break; } } return true; }; return l; } next operator*() const & { static const auto l = [this](Context &c, Iter &start, Iter end) { while (true) { auto saved = start; if (!(*this)(c, start, end)) { start = saved; break; } } return true; }; return l; } }; struct initial; template using parser = base_parser; } // namespace panda::parser #endif //! PANDA_VERIF_PARSER_H_