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 {
190 return c ==
' ' || c ==
'\t' || c ==
',';
192 auto isVerticalWS = [](
char c) ->
bool {
193 return c ==
'\n' || c ==
'\r' || c ==
'\f' || c ==
'\v';
197 const auto *ptr = (
const char *)tok.
getSpelling().data();
198 while (ptr != bufStart && isHorizontalWS(ptr[-1]))
202 if (ptr != bufStart && !isVerticalWS(ptr[-1]))
214 const char *tokStart =
curPtr;
218 if (llvm::isAlpha(
curPtr[-1]))
222 return emitError(tokStart,
"unexpected character");
228 return formToken(FIRToken::eof, tokStart);
246 return formToken(FIRToken::period, tokStart);
248 return formToken(FIRToken::colon, tokStart);
250 return formToken(FIRToken::l_paren, tokStart);
252 return formToken(FIRToken::r_paren, tokStart);
256 return formToken(FIRToken::l_brace, tokStart);
258 return formToken(FIRToken::r_brace, tokStart);
260 return formToken(FIRToken::l_square, tokStart);
262 return formToken(FIRToken::r_square, tokStart);
268 return formToken(FIRToken::less, tokStart);
270 return formToken(FIRToken::greater, tokStart);
274 return formToken(FIRToken::equal, tokStart);
276 return formToken(FIRToken::question, tokStart);
281 return emitError(tokStart,
"unexpected character");
285 return emitError(tokStart,
"unexpected character following '%'");
290 return emitError(tokStart,
"unexpected character");
329 return formToken(FIRToken::fileinfo, tokStart);
344 return emitError(tokStart,
"unterminated file info specifier");
358 bool stringMode =
false;
365 stringMode = !stringMode;
371 return formToken(FIRToken::inlineannotation, tokStart);
382 return emitError(tokStart,
"unterminated inline annotation");
399 bool isLiteralId = *tokStart ==
'`';
409 return emitError(tokStart,
"unterminated literal identifier");
413 StringRef spelling(tokStart,
curPtr - tokStart);
418 FIRToken::Kind kind = llvm::StringSwitch<FIRToken::Kind>(spelling)
419 #define TOK_LPKEYWORD(SPELLING) .Case(#SPELLING, FIRToken::lp_##SPELLING)
420 #include "FIRTokenKinds.def"
421 .Default(FIRToken::identifier);
422 if (kind != FIRToken::identifier) {
429 FIRToken::Kind kind = llvm::StringSwitch<FIRToken::Kind>(spelling)
430 #define TOK_KEYWORD(SPELLING) .Case(#SPELLING, FIRToken::kw_##SPELLING)
431 #include "FIRTokenKinds.def"
432 .Default(FIRToken::identifier);
437 if (isLiteralId && kind == FIRToken::identifier)
438 kind = FIRToken::literal_identifier;
475 return formToken(FIRToken::string, tokStart);
479 return formToken(FIRToken::verbatim_string, tokStart);
485 return emitError(tokStart,
"unicode escape not supported in string");
497 return emitError(tokStart,
"unterminated string");
500 return emitError(tokStart,
"string characters must be 7-bit ASCII");
522 if (!llvm::isDigit(*
curPtr) && !llvm::isDigit(
curPtr[-1]))
523 return emitError(tokStart,
"unexpected character after sign");
528 const char *oldPtr =
curPtr;
537 return formToken(FIRToken::radix_specified_integer, tokStart);
542 return formToken(FIRToken::radix_specified_integer, tokStart);
545 while (llvm::isDigit(*
curPtr))
547 return formToken(FIRToken::radix_specified_integer, tokStart);
550 while (llvm::isHexDigit(*
curPtr))
552 return formToken(FIRToken::radix_specified_integer, tokStart);
559 while (llvm::isDigit(*
curPtr))
565 if (*tokStart ==
'-' || *tokStart ==
'+')
566 return formToken(FIRToken::signed_integer, tokStart);
567 return formToken(FIRToken::integer, tokStart);
572 while (llvm::isDigit(*
curPtr))
581 while (llvm::isDigit(*
curPtr))
588 if (*
curPtr !=
'.' || !llvm::isDigit(
curPtr[1]) || hasE)
589 return formToken(FIRToken::floatingpoint, tokStart);
593 while (llvm::isDigit(*
curPtr))
595 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.
This file defines an intermediate representation for circuits acting as an abstraction for constraint...