1 //===- Lexer.h - MLIR PDLL Frontend Lexer -----------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LIB_TOOLS_PDLL_PARSER_LEXER_H_ 10 #define LIB_TOOLS_PDLL_PARSER_LEXER_H_ 11 12 #include "mlir/Support/LLVM.h" 13 #include "llvm/ADT/StringRef.h" 14 #include "llvm/Support/SMLoc.h" 15 16 namespace llvm { 17 class SourceMgr; 18 } // namespace llvm 19 20 namespace mlir { 21 struct LogicalResult; 22 23 namespace pdll { 24 namespace ast { 25 class DiagnosticEngine; 26 } // namespace ast 27 28 //===----------------------------------------------------------------------===// 29 // Token 30 //===----------------------------------------------------------------------===// 31 32 class Token { 33 public: 34 enum Kind { 35 // Markers. 36 eof, 37 error, 38 39 // Keywords. 40 KW_BEGIN, 41 // Dependent keywords, i.e. those that are treated as keywords depending on 42 // the current parser context. 43 KW_DEPENDENT_BEGIN, 44 kw_attr, 45 kw_op, 46 kw_type, 47 KW_DEPENDENT_END, 48 49 // General keywords. 50 kw_Attr, 51 kw_erase, 52 kw_let, 53 kw_Constraint, 54 kw_Op, 55 kw_OpName, 56 kw_Pattern, 57 kw_replace, 58 kw_rewrite, 59 kw_Type, 60 kw_TypeRange, 61 kw_Value, 62 kw_ValueRange, 63 kw_with, 64 KW_END, 65 66 // Punctuation. 67 arrow, 68 colon, 69 comma, 70 dot, 71 equal, 72 equal_arrow, 73 semicolon, 74 // Paired punctuation. 75 less, 76 greater, 77 l_brace, 78 r_brace, 79 l_paren, 80 r_paren, 81 l_square, 82 r_square, 83 underscore, 84 85 // Tokens. 86 directive, 87 identifier, 88 integer, 89 string_block, 90 string 91 }; 92 Token(Kind kind, StringRef spelling) : kind(kind), spelling(spelling) {} 93 94 /// Given a token containing a string literal, return its value, including 95 /// removing the quote characters and unescaping the contents of the string. 96 std::string getStringValue() const; 97 98 /// Returns true if the current token is a string literal. 99 bool isString() const { return isAny(Token::string, Token::string_block); } 100 101 /// Returns true if the current token is a keyword. 102 bool isKeyword() const { 103 return kind > Token::KW_BEGIN && kind < Token::KW_END; 104 } 105 106 /// Returns true if the current token is a keyword in a dependent context, and 107 /// in any other situation (e.g. variable names) may be treated as an 108 /// identifier. 109 bool isDependentKeyword() const { 110 return kind > Token::KW_DEPENDENT_BEGIN && kind < Token::KW_DEPENDENT_END; 111 } 112 113 /// Return the bytes that make up this token. 114 StringRef getSpelling() const { return spelling; } 115 116 /// Return the kind of this token. 117 Kind getKind() const { return kind; } 118 119 /// Return true if this token is one of the specified kinds. 120 bool isAny(Kind k1, Kind k2) const { return is(k1) || is(k2); } 121 template <typename... T> 122 bool isAny(Kind k1, Kind k2, Kind k3, T... others) const { 123 return is(k1) || isAny(k2, k3, others...); 124 } 125 126 /// Return if the token does not have the given kind. 127 bool isNot(Kind k) const { return k != kind; } 128 template <typename... T> bool isNot(Kind k1, Kind k2, T... others) const { 129 return !isAny(k1, k2, others...); 130 } 131 132 /// Return if the token has the given kind. 133 bool is(Kind k) const { return kind == k; } 134 135 /// Return a location for the start of this token. 136 llvm::SMLoc getStartLoc() const { 137 return llvm::SMLoc::getFromPointer(spelling.data()); 138 } 139 /// Return a location at the end of this token. 140 llvm::SMLoc getEndLoc() const { 141 return llvm::SMLoc::getFromPointer(spelling.data() + spelling.size()); 142 } 143 /// Return a location for the range of this token. 144 llvm::SMRange getLoc() const { 145 return llvm::SMRange(getStartLoc(), getEndLoc()); 146 } 147 148 private: 149 /// Discriminator that indicates the kind of token this is. 150 Kind kind; 151 152 /// A reference to the entire token contents; this is always a pointer into 153 /// a memory buffer owned by the source manager. 154 StringRef spelling; 155 }; 156 157 //===----------------------------------------------------------------------===// 158 // Lexer 159 //===----------------------------------------------------------------------===// 160 161 class Lexer { 162 public: 163 Lexer(llvm::SourceMgr &mgr, ast::DiagnosticEngine &diagEngine); 164 ~Lexer(); 165 166 /// Return a reference to the source manager used by the lexer. 167 llvm::SourceMgr &getSourceMgr() { return srcMgr; } 168 169 /// Return a reference to the diagnostic engine used by the lexer. 170 ast::DiagnosticEngine &getDiagEngine() { return diagEngine; } 171 172 /// Push an include of the given file. This will cause the lexer to start 173 /// processing the provided file. Returns failure if the file could not be 174 /// opened, success otherwise. 175 LogicalResult pushInclude(StringRef filename); 176 177 /// Lex the next token and return it. 178 Token lexToken(); 179 180 /// Change the position of the lexer cursor. The next token we lex will start 181 /// at the designated point in the input. 182 void resetPointer(const char *newPointer) { curPtr = newPointer; } 183 184 /// Emit an error to the lexer with the given location and message. 185 Token emitError(llvm::SMRange loc, const Twine &msg); 186 Token emitError(const char *loc, const Twine &msg); 187 Token emitErrorAndNote(llvm::SMRange loc, const Twine &msg, 188 llvm::SMRange noteLoc, const Twine ¬e); 189 190 private: 191 Token formToken(Token::Kind kind, const char *tokStart) { 192 return Token(kind, StringRef(tokStart, curPtr - tokStart)); 193 } 194 195 /// Return the next character in the stream. 196 int getNextChar(); 197 198 /// Lex methods. 199 void lexComment(); 200 Token lexDirective(const char *tokStart); 201 Token lexIdentifier(const char *tokStart); 202 Token lexNumber(const char *tokStart); 203 Token lexString(const char *tokStart, bool isStringBlock); 204 205 llvm::SourceMgr &srcMgr; 206 int curBufferID; 207 StringRef curBuffer; 208 const char *curPtr; 209 210 /// The engine used to emit diagnostics during lexing/parsing. 211 ast::DiagnosticEngine &diagEngine; 212 213 /// A flag indicating if we added a default diagnostic handler to the provided 214 /// diagEngine. 215 bool addedHandlerToDiagEngine; 216 }; 217 } // namespace pdll 218 } // namespace mlir 219 220 #endif // LIB_TOOLS_PDLL_PARSER_LEXER_H_ 221