| #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_ |