14 #include "mlir/IR/Diagnostics.h"
15 #include "llvm/ADT/StringExtras.h"
16 #include "llvm/ADT/StringSwitch.h"
17 #include "llvm/Support/SourceMgr.h"
18 #include "llvm/Support/raw_ostream.h"
20 using namespace circt;
21 using namespace firrtl;
24 using llvm::SourceMgr;
26 #define isdigit(x) DO_NOT_USE_SLOW_CTYPE_FUNCTIONS
27 #define isalpha(x) DO_NOT_USE_SLOW_CTYPE_FUNCTIONS
34 return SMLoc::getFromPointer(
spelling.data());
48 #define TOK_KEYWORD(SPELLING) \
51 #include "FIRTokenKinds.def"
65 StringRef bytes =
spelling.drop_front().drop_back();
68 result.reserve(bytes.size());
69 for (
size_t i = 0, e = bytes.size(); i != e;) {
76 assert(i + 1 <= e &&
"invalid string should be caught by lexer");
85 result.push_back(
'\b');
88 result.push_back(
'\n');
91 result.push_back(
'\t');
94 result.push_back(
'\f');
97 result.push_back(
'\r');
104 assert(i + 1 <= e &&
"invalid string should be caught by lexer");
105 auto c2 = bytes[i++];
107 assert(llvm::isHexDigit(c1) && llvm::isHexDigit(c2) &&
"invalid escape");
108 result.push_back((llvm::hexDigitValue(c1) << 4) | llvm::hexDigitValue(c2));
124 StringRef bytes =
spelling.drop_front().drop_back();
127 result.reserve(bytes.size());
128 for (
size_t i = 0, e = bytes.size(); i != e;) {
135 assert(i + 1 <= e &&
"invalid string should be caught by lexer");
136 auto c1 = bytes[i++];
140 result.push_back(c1);
151 MLIRContext *context) {
152 auto mainBuffer = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
153 StringRef bufferName = mainBuffer->getBufferIdentifier();
154 if (bufferName.empty())
155 bufferName =
"<unknown>";
160 : sourceMgr(sourceMgr),
163 sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID())->getBuffer()),
164 curPtr(curBuffer.begin()),
166 curToken(lexTokenImpl()) {}
170 Location FIRLexer::translateLocation(llvm::SMLoc loc) {
172 unsigned mainFileID =
sourceMgr.getMainFileID();
173 auto lineAndColumn =
sourceMgr.getLineAndColumn(loc, mainFileID);
175 lineAndColumn.second);
189 auto isHorizontalWS = [](
char c) ->
bool {
return c ==
' ' || c ==
'\t'; };
190 auto isVerticalWS = [](
char c) ->
bool {
191 return c ==
'\n' || c ==
'\r' || c ==
'\f' || c ==
'\v';
195 const auto *ptr = (
const char *)tok.
getSpelling().data();
196 while (ptr != bufStart && isHorizontalWS(ptr[-1]))
200 if (ptr != bufStart && !isVerticalWS(ptr[-1]))
212 const char *tokStart =
curPtr;
216 if (llvm::isAlpha(
curPtr[-1]))
220 return emitError(tokStart,
"unexpected character");
226 return formToken(FIRToken::eof, tokStart);
243 return formToken(FIRToken::period, tokStart);
245 return formToken(FIRToken::comma, tokStart);
247 return formToken(FIRToken::colon, tokStart);
249 return formToken(FIRToken::l_paren, tokStart);
251 return formToken(FIRToken::r_paren, tokStart);
255 return formToken(FIRToken::l_brace, tokStart);
257 return formToken(FIRToken::r_brace, tokStart);
259 return formToken(FIRToken::l_square, tokStart);
261 return formToken(FIRToken::r_square, tokStart);
265 return formToken(FIRToken::less, tokStart);
267 return formToken(FIRToken::greater, tokStart);
271 return formToken(FIRToken::equal, tokStart);
273 return formToken(FIRToken::question, tokStart);
278 return emitError(tokStart,
"unexpected character");
282 return emitError(tokStart,
"unexpected character following '%'");
287 return emitError(tokStart,
"unexpected character");
323 return formToken(FIRToken::fileinfo, tokStart);
338 return emitError(tokStart,
"unterminated file info specifier");
352 bool stringMode =
false;
356 stringMode = !stringMode;
362 return formToken(FIRToken::inlineannotation, tokStart);
376 return emitError(tokStart,
"unterminated inline annotation");
393 bool isLiteralId = *tokStart ==
'`';
403 return emitError(tokStart,
"unterminated literal identifier");
407 StringRef spelling(tokStart,
curPtr - tokStart);
412 FIRToken::Kind kind = llvm::StringSwitch<FIRToken::Kind>(spelling)
413 #define TOK_LPKEYWORD(SPELLING) .Case(#SPELLING, FIRToken::lp_##SPELLING)
414 #include "FIRTokenKinds.def"
415 .Default(FIRToken::identifier);
416 if (kind != FIRToken::identifier) {
423 FIRToken::Kind kind = llvm::StringSwitch<FIRToken::Kind>(spelling)
424 #define TOK_KEYWORD(SPELLING) .Case(#SPELLING, FIRToken::kw_##SPELLING)
425 #include "FIRTokenKinds.def"
426 .Default(FIRToken::identifier);
431 if (isLiteralId && kind == FIRToken::identifier)
432 kind = FIRToken::literal_identifier;
469 return formToken(FIRToken::string, tokStart);
473 return formToken(FIRToken::verbatim_string, tokStart);
479 return emitError(tokStart,
"unicode escape not supported in string");
491 return emitError(tokStart,
"unterminated string");
494 return emitError(tokStart,
"string characters must be 7-bit ASCII");
516 if (!llvm::isDigit(*
curPtr) && !llvm::isDigit(
curPtr[-1]))
517 return emitError(tokStart,
"unexpected character after sign");
522 const char *oldPtr =
curPtr;
531 return formToken(FIRToken::radix_specified_integer, tokStart);
536 return formToken(FIRToken::radix_specified_integer, tokStart);
539 while (llvm::isDigit(*
curPtr))
541 return formToken(FIRToken::radix_specified_integer, tokStart);
544 while (llvm::isHexDigit(*
curPtr))
546 return formToken(FIRToken::radix_specified_integer, tokStart);
553 while (llvm::isDigit(*
curPtr))
559 if (*tokStart ==
'-' || *tokStart ==
'+')
560 return formToken(FIRToken::signed_integer, tokStart);
561 return formToken(FIRToken::integer, tokStart);
566 while (llvm::isDigit(*
curPtr))
575 while (llvm::isDigit(*
curPtr))
582 if (*
curPtr !=
'.' || !llvm::isDigit(
curPtr[1]) || hasE)
583 return formToken(FIRToken::floatingpoint, tokStart);
587 while (llvm::isDigit(*
curPtr))
589 return formToken(FIRToken::version, tokStart);
assert(baseType &&"element must be base type")
static StringAttr getMainBufferNameIdentifier(const llvm::SourceMgr &sourceMgr, MLIRContext *context)
FIRToken lexFileInfo(const char *tokStart)
Lex a file info specifier.
FIRToken lexIdentifierOrKeyword(const char *tokStart)
Lex an identifier or keyword that starts with a letter.
const llvm::SourceMgr & sourceMgr
FIRToken formToken(FIRToken::Kind kind, const char *tokStart)
FIRToken lexNumber(const char *tokStart)
Lex a number literal.
FIRToken lexString(const char *tokStart, bool isVerbatim)
StringLit ::= '"' UnquotedString? '"' VerbatimStringLit ::= '\'' UnquotedString? '\'' UnquotedString ...
std::optional< unsigned > getIndentation(const FIRToken &tok) const
Return the indentation level of the specified token or None if this token is preceded by another toke...
void skipComment()
Skip a comment line, starting with a ';' and going to end of line.
FIRToken emitError(const char *loc, const Twine &message)
Emit an error message and return a FIRToken::error token.
FIRLexer(const llvm::SourceMgr &sourceMgr, mlir::MLIRContext *context)
mlir::Location translateLocation(llvm::SMLoc loc)
Encode the specified source location information into a Location object for attachment to the IR or e...
FIRToken lexInlineAnnotation(const char *tokStart)
Lex a non-standard inline Annotation file.
const mlir::StringAttr bufferNameIdentifier
This represents a specific token for .fir files.
std::string getVerbatimStringValue() const
Given a token containing a verbatim string, return its value, including removing the quote characters...
StringRef getSpelling() const
StringRef spelling
A reference to the entire token contents; this is always a pointer into a memory buffer owned by the ...
llvm::SMRange getLocRange() const
std::string getStringValue() const
Given a token containing a string literal, return its value, including removing the quote characters ...
Kind kind
Discriminator that indicates the sort of token this is.
llvm::SMLoc getEndLoc() const
llvm::SMLoc getLoc() const
bool isKeyword() const
Return true if this is one of the keyword token kinds (e.g. kw_wire).
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.