cp-library-cpp

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub suisen-cp/cp-library-cpp

:warning: Parsing
(library/icpc/parsing.hpp)

Parsing

Code

#include <iostream>
#include <optional>
#include <string>

namespace suisen::parsing {
    using State = std::string::const_iterator;

    struct ParseError {
        ParseError(const std::string& message = "") {
            std::cerr << message << std::endl;
        }
    };

    namespace internal {
        void print_rest_of_string(State it) {
            std::cerr << "Rest string is '";
            while (*it)  std::cerr << *it++;
            std::cerr << "'" << std::endl;
        }
    }

    void consume(State& it, char expected) {
        if (*it == expected) {
            *it++;
        } else {
            std::cerr << "Expected '" << expected << "' but got '" << *it << "'" << std::endl;
            internal::print_rest_of_string(it);
            throw ParseError{};
        }
    }

    bool in(const State& it, char l, char r) {
        return l <= *it and *it <= r;
    }
    bool is(const State& it, char c) {
        return *it == c;
    }

    void assert_range(const State& it, char lo, char hi) {
        if (not in(it, lo, hi)) {
            std::cerr << "Expected [" << lo << "-" << hi << "] but got '" << *it << "'" << std::endl;
            internal::print_rest_of_string(it);
            throw ParseError{};
        }
    }
    void assert_exact(const State& it, char c) {
        if (not is(it, c)) {
            std::cerr << "Expected '" << c << "' but got '" << *it << "'" << std::endl;
            internal::print_rest_of_string(it);
            throw ParseError{};
        }
    }

    long long nonnegative_number(State& it) {
        long long res = 0;
        assert_range(it, '0', '9');
        while (in(it, '0', '9')) res = res * 10 + (*it++ - '0');
        return res;
    }
    long long number(State& it) {
        long long res = 0;
        bool neg = false;
        while (is(it, '-')) neg = not neg, consume(it, '-');
        while (in(it, '0', '9')) res = res * 10 + (*it++ - '0');
        if (neg) res = -res;
        return res;
    }

    namespace normal_expression {
        namespace internal {
            long long expr(State& it);
            long long term(State& it);
            long long factor(State& it);

            long long expr(State& it) {
                long long res = term(it);
                while (true) {
                    if (*it == '+') {
                        consume(it, '+');
                        res = res + term(it);
                    } else if (*it == '-') {
                        consume(it, '-');
                        res = res - term(it);
                    } else break;
                }
                return res;
            }
            long long term(State& it) {
                long long res = factor(it);
                while (true) {
                    if (*it == '*') {
                        consume(it, '*');
                        res = res * factor(it);
                    } else if (*it == '/') {
                        consume(it, '/');
                        res = res / factor(it);
                    } else break;
                }
                return res;
            }
            long long factor(State& it) {
                bool neg = false;
                while (is(it, '-')) neg = not neg, consume(it, '-');
                long long res;
                if (is(it, '(')) {
                    consume(it, '(');
                    res = expr(it);
                    consume(it, ')');
                } else {
                    res = nonnegative_number(it);
                }
                if (neg) res = -res;
                return res;
            }
        }

        long long parse(State& it) {
            return internal::expr(it);
        }
    }
}
#line 1 "library/icpc/parsing.hpp"
#include <iostream>
#include <optional>
#include <string>

namespace suisen::parsing {
    using State = std::string::const_iterator;

    struct ParseError {
        ParseError(const std::string& message = "") {
            std::cerr << message << std::endl;
        }
    };

    namespace internal {
        void print_rest_of_string(State it) {
            std::cerr << "Rest string is '";
            while (*it)  std::cerr << *it++;
            std::cerr << "'" << std::endl;
        }
    }

    void consume(State& it, char expected) {
        if (*it == expected) {
            *it++;
        } else {
            std::cerr << "Expected '" << expected << "' but got '" << *it << "'" << std::endl;
            internal::print_rest_of_string(it);
            throw ParseError{};
        }
    }

    bool in(const State& it, char l, char r) {
        return l <= *it and *it <= r;
    }
    bool is(const State& it, char c) {
        return *it == c;
    }

    void assert_range(const State& it, char lo, char hi) {
        if (not in(it, lo, hi)) {
            std::cerr << "Expected [" << lo << "-" << hi << "] but got '" << *it << "'" << std::endl;
            internal::print_rest_of_string(it);
            throw ParseError{};
        }
    }
    void assert_exact(const State& it, char c) {
        if (not is(it, c)) {
            std::cerr << "Expected '" << c << "' but got '" << *it << "'" << std::endl;
            internal::print_rest_of_string(it);
            throw ParseError{};
        }
    }

    long long nonnegative_number(State& it) {
        long long res = 0;
        assert_range(it, '0', '9');
        while (in(it, '0', '9')) res = res * 10 + (*it++ - '0');
        return res;
    }
    long long number(State& it) {
        long long res = 0;
        bool neg = false;
        while (is(it, '-')) neg = not neg, consume(it, '-');
        while (in(it, '0', '9')) res = res * 10 + (*it++ - '0');
        if (neg) res = -res;
        return res;
    }

    namespace normal_expression {
        namespace internal {
            long long expr(State& it);
            long long term(State& it);
            long long factor(State& it);

            long long expr(State& it) {
                long long res = term(it);
                while (true) {
                    if (*it == '+') {
                        consume(it, '+');
                        res = res + term(it);
                    } else if (*it == '-') {
                        consume(it, '-');
                        res = res - term(it);
                    } else break;
                }
                return res;
            }
            long long term(State& it) {
                long long res = factor(it);
                while (true) {
                    if (*it == '*') {
                        consume(it, '*');
                        res = res * factor(it);
                    } else if (*it == '/') {
                        consume(it, '/');
                        res = res / factor(it);
                    } else break;
                }
                return res;
            }
            long long factor(State& it) {
                bool neg = false;
                while (is(it, '-')) neg = not neg, consume(it, '-');
                long long res;
                if (is(it, '(')) {
                    consume(it, '(');
                    res = expr(it);
                    consume(it, ')');
                } else {
                    res = nonnegative_number(it);
                }
                if (neg) res = -res;
                return res;
            }
        }

        long long parse(State& it) {
            return internal::expr(it);
        }
    }
}
Back to top page