中缀 to 后缀 递归下降 Parser
写了一个 infix to postfix 的递归下降 parser,但感觉写得好长,也不知道怎么回事。
#include <algorithm>
#include <string_view>
#include <stdexcept>
class InfixToPostfixParser {
public:
auto infix_to_postfix(std::string_view infix) -> std::string {
m_lookahead = infix;
parse_expr();
return std::move(m_postfix);
}
private:
void parse_expr() {
if (no_more_tokens()) { return; }
parse_term();
parse_expr_rest();
}
void parse_expr_rest() {
char const token = current_token();
if (successfully_consume_one_of("+-")) {
parse_term();
m_postfix.push_back(token);
parse_expr_rest();
}
}
void parse_term() {
parse_factor();
parse_term_rest();
}
void parse_term_rest() {
char const token = current_token();
if (successfully_consume_one_of("*/")) {
parse_factor();
m_postfix.push_back(token);
parse_term_rest();
}
}
void parse_factor() {
parse_unit();
if (successfully_consume('^')) {
parse_factor();
m_postfix.push_back('^');
}
}
void parse_unit() {
if (successfully_consume('(')) {
parse_expr();
consume(')');
} else {
char const token = current_token();
consume_one_of("0123456789");
m_postfix.push_back(token);
}
}
bool successfully_consume(char const token) {
if (token != current_token()) { return false; }
to_next_token();
return true;
}
bool successfully_consume_one_of(std::string_view tokens) {
if (tokens.find(current_token()) == std::string_view::npos) { return false; }
to_next_token();
return true;
}
void consume(char const token) {
if (token != current_token()) {
throw std::invalid_argument("Syntax Error");
}
to_next_token();
}
void consume_one_of(std::string_view tokens) {
if (tokens.find(current_token()) == std::string_view::npos) {
throw std::invalid_argument("Syntax Error");
}
to_next_token();
}
void to_next_token() {
m_lookahead.remove_prefix(1);
}
[[nodiscard]] char current_token() const {
if (no_more_tokens()) { return '\0'; }
return m_lookahead.front();
}
[[nodiscard]] bool no_more_tokens() const {
return m_lookahead.empty();
}
std::string m_postfix;
std::string_view m_lookahead;
};

浙公网安备 33010602011771号