blob: 0135f295f7565440d9c7110975314a72f1b1ddc7 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include <string>
#include <string_view>
#include <vector>
#include "garnet/bin/zxdb/common/err.h"
#include "garnet/bin/zxdb/expr/expr_token.h"
namespace zxdb {
class ExprTokenizer {
public:
explicit ExprTokenizer(const std::string& input);
// Returns true on successful tokenizing. In this case, the tokens can be
// read from tokens(). On failure, err() will contain the error message, and
// error_location() will contain the error location.
bool Tokenize();
const std::string& input() const { return input_; }
// The result of parsing. This will be multiline and will indicate the
// location of the problem.
const Err& err() const { return err_; }
// When err is set, this will be the index into the input() string where the
// error occurred.
size_t error_location() const { return error_location_; }
// When parsing is successful, this contains the extracted tokens.
const std::vector<ExprToken>& tokens() const { return tokens_; }
std::vector<ExprToken> TakeTokens() { return std::move(tokens_); }
// Returns two context lines for an error message. It will quote a relevant
// portion of the input showing the byte offset, and add a "^" on the next
// line to indicate where the error is.
static std::string GetErrorContext(const std::string& input,
size_t byte_offset);
private:
void AdvanceChars(int n);
void AdvanceOneChar();
void AdvanceToNextToken();
void AdvanceToEndOfToken(ExprToken::Type type);
bool IsCurrentWhitespace() const;
// Returns true if the next characters in the buffer are the given ones. This
// doesn't check anything afterward so the end need not represent a name
// boundary.
bool IsCurrentString(std::string_view s) const;
// Returns true if the next characters in the buffer are the given ones, and
// the one after that is a name boundary (puntuation, end of buffer, etc.).
bool IsCurrentName(std::string_view s) const;
ExprToken::Type ClassifyCurrent();
bool done() const { return at_end() || has_error(); }
bool has_error() const { return err_.has_error(); }
bool at_end() const { return cur_ == input_.size(); }
char cur_char() const { return input_[cur_]; }
bool can_advance() const { return cur_ < input_.size() - 1; }
bool can_advance(int n) const { return cur_ + n < input_.size(); }
std::string input_;
size_t cur_ = 0; // Character offset into input_.
Err err_;
size_t error_location_ = 0;
std::vector<ExprToken> tokens_;
};
} // namespace zxdb