blob: c5148c43a46e20667b891283a4c5f13cd33f4780 [file] [log] [blame]
#ifndef EXPERIMENTAL_LAVM_LEXER_H_
#define EXPERIMENTAL_LAVM_LEXER_H_
#include <iostream>
#include "llvm/ADT/StringRef.h"
namespace mlir {
namespace lavm {
using Token = llvm::StringRef;
class Lexer {
public:
static bool is_newline(char c) { return c == '\n'; }
static bool is_whitespace(char c) {
return is_newline(c) || c == ' ' || c == '\t';
}
static bool is_list_separator(char c) { return c == ','; }
static bool is_open_paren(char c) { return c == '('; }
static bool is_close_paren(char c) { return c == ')'; }
static bool is_open_angle(char c) {
return false; // c == '<';
}
static bool is_close_angle(char c) {
return false; // c == '>'; conflicts with "->"
}
static bool is_separator(char c) {
return is_list_separator(c) || is_open_paren(c) || is_close_paren(c) ||
is_open_angle(c) || is_close_angle(c) || c == ':';
}
static bool is_terminator(char c) { return c == ';'; }
static bool is_name_marker(char c) { return c == '%'; }
static bool is_cache_marker(char c) { return c == '$'; }
static bool is_comment(char c) { return c == '#'; }
static bool is_end(char c) { return c == '\0'; }
static bool is_end(Token token) { return token.empty(); }
static bool is_separator(Token token) {
return token.size() == 1 && is_separator(token.front());
}
static bool is_terminator(Token token) {
return token.size() == 1 && is_terminator(token.front());
}
static bool is_arrow(Token token) {
return token.size() == 2 && token.front() == '-' && token.back() == '>';
}
static std::string TokenToString(Token token) {
return is_end(token) ? "END-OF-FILE" : token.str();
}
static Token FindToken(const char* start_at,
bool skip_terminators_and_separators = true) {
const char* first = start_at;
if (is_end(*first)) {
return "";
}
while (is_whitespace(*first) ||
(skip_terminators_and_separators &&
(is_terminator(*first) || is_separator(*first)))) {
first++;
}
if (is_separator(*first) || is_terminator(*first)) {
assert(!skip_terminators_and_separators);
return Token(first, 1);
}
if (is_comment(*first)) {
// Skip the rest of the line
while (!is_end(*first) && !is_newline(*first)) {
first++;
}
// Pass either 'end' or 'newline' in.
return FindToken(first, skip_terminators_and_separators);
}
const char* last = first;
while (!is_end(*last) && !is_whitespace(*last) && !is_separator(*last) &&
!is_terminator(*last))
last++;
return Token(first, last - first);
}
static Token NextToken(Token token,
bool skip_terminators_and_separators = true) {
const char* start_at = token.data() + token.size();
Token next = FindToken(start_at, skip_terminators_and_separators);
return next;
}
static bool Eat(const std::string& food, Token* token,
bool skip_terminators_and_separators = true) {
if (food == token->str()) {
*token = NextToken(*token, skip_terminators_and_separators);
return true;
}
return false;
}
static bool EatOrError(const std::string& food, Token* token,
bool skip_terminators_and_separators = true) {
return Eat(food, token, skip_terminators_and_separators) ||
ParseErrorExpected(food, *token);
}
static bool ParseError(const std::string& message) {
std::cerr << "ERROR: " << message << std::endl;
return false;
}
static bool ParseErrorExpected(const std::string& expected, Token token) {
ParseError("Expect to see '" + expected + "', instead '" +
TokenToString(token) + "' found");
return false;
}
static bool ParseWarning(const std::string& message) {
// FIXME? suppress warnings if any error messages had been emitted.
std::cerr << "WARNING: " << message << std::endl;
return false;
}
// static Type ParseType(Token token, MLIRContext* context) {
// // suppress "unexpected character" error message after the type token
// std::string t(token.begin(), token.end());
// return mlir::parseType(t, context);
// }
};
} // namespace lavm
} // namespace mlir
#endif // EXPERIMENTAL_LAVM_LEXER_H_