106f32e7eSjoerg //===- llvm/MC/MCAsmLexer.h - Abstract Asm Lexer Interface ------*- C++ -*-===// 206f32e7eSjoerg // 306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information. 506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 606f32e7eSjoerg // 706f32e7eSjoerg //===----------------------------------------------------------------------===// 806f32e7eSjoerg 906f32e7eSjoerg #ifndef LLVM_MC_MCPARSER_MCASMLEXER_H 1006f32e7eSjoerg #define LLVM_MC_MCPARSER_MCASMLEXER_H 1106f32e7eSjoerg 1206f32e7eSjoerg #include "llvm/ADT/ArrayRef.h" 1306f32e7eSjoerg #include "llvm/ADT/SmallVector.h" 1406f32e7eSjoerg #include "llvm/MC/MCAsmMacro.h" 1506f32e7eSjoerg #include <algorithm> 1606f32e7eSjoerg #include <cassert> 1706f32e7eSjoerg #include <cstddef> 1806f32e7eSjoerg #include <cstdint> 1906f32e7eSjoerg #include <string> 2006f32e7eSjoerg 2106f32e7eSjoerg namespace llvm { 2206f32e7eSjoerg 2306f32e7eSjoerg /// A callback class which is notified of each comment in an assembly file as 2406f32e7eSjoerg /// it is lexed. 2506f32e7eSjoerg class AsmCommentConsumer { 2606f32e7eSjoerg public: 2706f32e7eSjoerg virtual ~AsmCommentConsumer() = default; 2806f32e7eSjoerg 2906f32e7eSjoerg /// Callback function for when a comment is lexed. Loc is the start of the 3006f32e7eSjoerg /// comment text (excluding the comment-start marker). CommentText is the text 3106f32e7eSjoerg /// of the comment, excluding the comment start and end markers, and the 3206f32e7eSjoerg /// newline for single-line comments. 3306f32e7eSjoerg virtual void HandleComment(SMLoc Loc, StringRef CommentText) = 0; 3406f32e7eSjoerg }; 3506f32e7eSjoerg 3606f32e7eSjoerg 3706f32e7eSjoerg /// Generic assembler lexer interface, for use by target specific assembly 3806f32e7eSjoerg /// lexers. 3906f32e7eSjoerg class MCAsmLexer { 4006f32e7eSjoerg /// The current token, stored in the base class for faster access. 4106f32e7eSjoerg SmallVector<AsmToken, 1> CurTok; 4206f32e7eSjoerg 4306f32e7eSjoerg /// The location and description of the current error 4406f32e7eSjoerg SMLoc ErrLoc; 4506f32e7eSjoerg std::string Err; 4606f32e7eSjoerg 4706f32e7eSjoerg protected: // Can only create subclasses. 4806f32e7eSjoerg const char *TokStart = nullptr; 4906f32e7eSjoerg bool SkipSpace = true; 5006f32e7eSjoerg bool AllowAtInIdentifier; 51*da58b97aSjoerg bool AllowHashInIdentifier = false; 5206f32e7eSjoerg bool IsAtStartOfStatement = true; 53*da58b97aSjoerg bool LexMasmHexFloats = false; 5406f32e7eSjoerg bool LexMasmIntegers = false; 55*da58b97aSjoerg bool LexMasmStrings = false; 56*da58b97aSjoerg bool LexMotorolaIntegers = false; 57*da58b97aSjoerg bool UseMasmDefaultRadix = false; 58*da58b97aSjoerg unsigned DefaultRadix = 10; 59*da58b97aSjoerg bool LexHLASMIntegers = false; 60*da58b97aSjoerg bool LexHLASMStrings = false; 6106f32e7eSjoerg AsmCommentConsumer *CommentConsumer = nullptr; 6206f32e7eSjoerg 6306f32e7eSjoerg MCAsmLexer(); 6406f32e7eSjoerg 6506f32e7eSjoerg virtual AsmToken LexToken() = 0; 6606f32e7eSjoerg SetError(SMLoc errLoc,const std::string & err)6706f32e7eSjoerg void SetError(SMLoc errLoc, const std::string &err) { 6806f32e7eSjoerg ErrLoc = errLoc; 6906f32e7eSjoerg Err = err; 7006f32e7eSjoerg } 7106f32e7eSjoerg 7206f32e7eSjoerg public: 7306f32e7eSjoerg MCAsmLexer(const MCAsmLexer &) = delete; 7406f32e7eSjoerg MCAsmLexer &operator=(const MCAsmLexer &) = delete; 7506f32e7eSjoerg virtual ~MCAsmLexer(); 7606f32e7eSjoerg 7706f32e7eSjoerg /// Consume the next token from the input stream and return it. 7806f32e7eSjoerg /// 7906f32e7eSjoerg /// The lexer will continuously return the end-of-file token once the end of 8006f32e7eSjoerg /// the main input file has been reached. Lex()8106f32e7eSjoerg const AsmToken &Lex() { 8206f32e7eSjoerg assert(!CurTok.empty()); 8306f32e7eSjoerg // Mark if we parsing out a EndOfStatement. 8406f32e7eSjoerg IsAtStartOfStatement = CurTok.front().getKind() == AsmToken::EndOfStatement; 8506f32e7eSjoerg CurTok.erase(CurTok.begin()); 8606f32e7eSjoerg // LexToken may generate multiple tokens via UnLex but will always return 8706f32e7eSjoerg // the first one. Place returned value at head of CurTok vector. 8806f32e7eSjoerg if (CurTok.empty()) { 8906f32e7eSjoerg AsmToken T = LexToken(); 9006f32e7eSjoerg CurTok.insert(CurTok.begin(), T); 9106f32e7eSjoerg } 9206f32e7eSjoerg return CurTok.front(); 9306f32e7eSjoerg } 9406f32e7eSjoerg UnLex(AsmToken const & Token)9506f32e7eSjoerg void UnLex(AsmToken const &Token) { 9606f32e7eSjoerg IsAtStartOfStatement = false; 9706f32e7eSjoerg CurTok.insert(CurTok.begin(), Token); 9806f32e7eSjoerg } 9906f32e7eSjoerg isAtStartOfStatement()10006f32e7eSjoerg bool isAtStartOfStatement() { return IsAtStartOfStatement; } 10106f32e7eSjoerg 10206f32e7eSjoerg virtual StringRef LexUntilEndOfStatement() = 0; 10306f32e7eSjoerg 10406f32e7eSjoerg /// Get the current source location. 10506f32e7eSjoerg SMLoc getLoc() const; 10606f32e7eSjoerg 10706f32e7eSjoerg /// Get the current (last) lexed token. getTok()10806f32e7eSjoerg const AsmToken &getTok() const { 10906f32e7eSjoerg return CurTok[0]; 11006f32e7eSjoerg } 11106f32e7eSjoerg 11206f32e7eSjoerg /// Look ahead at the next token to be lexed. 11306f32e7eSjoerg const AsmToken peekTok(bool ShouldSkipSpace = true) { 11406f32e7eSjoerg AsmToken Tok; 11506f32e7eSjoerg 11606f32e7eSjoerg MutableArrayRef<AsmToken> Buf(Tok); 11706f32e7eSjoerg size_t ReadCount = peekTokens(Buf, ShouldSkipSpace); 11806f32e7eSjoerg 11906f32e7eSjoerg assert(ReadCount == 1); 12006f32e7eSjoerg (void)ReadCount; 12106f32e7eSjoerg 12206f32e7eSjoerg return Tok; 12306f32e7eSjoerg } 12406f32e7eSjoerg 12506f32e7eSjoerg /// Look ahead an arbitrary number of tokens. 12606f32e7eSjoerg virtual size_t peekTokens(MutableArrayRef<AsmToken> Buf, 12706f32e7eSjoerg bool ShouldSkipSpace = true) = 0; 12806f32e7eSjoerg 12906f32e7eSjoerg /// Get the current error location getErrLoc()13006f32e7eSjoerg SMLoc getErrLoc() { 13106f32e7eSjoerg return ErrLoc; 13206f32e7eSjoerg } 13306f32e7eSjoerg 13406f32e7eSjoerg /// Get the current error string getErr()13506f32e7eSjoerg const std::string &getErr() { 13606f32e7eSjoerg return Err; 13706f32e7eSjoerg } 13806f32e7eSjoerg 13906f32e7eSjoerg /// Get the kind of current token. getKind()14006f32e7eSjoerg AsmToken::TokenKind getKind() const { return getTok().getKind(); } 14106f32e7eSjoerg 14206f32e7eSjoerg /// Check if the current token has kind \p K. is(AsmToken::TokenKind K)14306f32e7eSjoerg bool is(AsmToken::TokenKind K) const { return getTok().is(K); } 14406f32e7eSjoerg 14506f32e7eSjoerg /// Check if the current token has kind \p K. isNot(AsmToken::TokenKind K)14606f32e7eSjoerg bool isNot(AsmToken::TokenKind K) const { return getTok().isNot(K); } 14706f32e7eSjoerg 14806f32e7eSjoerg /// Set whether spaces should be ignored by the lexer setSkipSpace(bool val)14906f32e7eSjoerg void setSkipSpace(bool val) { SkipSpace = val; } 15006f32e7eSjoerg getAllowAtInIdentifier()15106f32e7eSjoerg bool getAllowAtInIdentifier() { return AllowAtInIdentifier; } setAllowAtInIdentifier(bool v)15206f32e7eSjoerg void setAllowAtInIdentifier(bool v) { AllowAtInIdentifier = v; } 15306f32e7eSjoerg setAllowHashInIdentifier(bool V)154*da58b97aSjoerg void setAllowHashInIdentifier(bool V) { AllowHashInIdentifier = V; } 155*da58b97aSjoerg setCommentConsumer(AsmCommentConsumer * CommentConsumer)15606f32e7eSjoerg void setCommentConsumer(AsmCommentConsumer *CommentConsumer) { 15706f32e7eSjoerg this->CommentConsumer = CommentConsumer; 15806f32e7eSjoerg } 15906f32e7eSjoerg 160*da58b97aSjoerg /// Set whether to lex masm-style binary (e.g., 0b1101) and radix-specified 161*da58b97aSjoerg /// literals (e.g., 0ABCh [hex], 576t [decimal], 77o [octal], 1101y [binary]). setLexMasmIntegers(bool V)16206f32e7eSjoerg void setLexMasmIntegers(bool V) { LexMasmIntegers = V; } 163*da58b97aSjoerg 164*da58b97aSjoerg /// Set whether to use masm-style default-radix integer literals. If disabled, 165*da58b97aSjoerg /// assume decimal unless prefixed (e.g., 0x2c [hex], 077 [octal]). useMasmDefaultRadix(bool V)166*da58b97aSjoerg void useMasmDefaultRadix(bool V) { UseMasmDefaultRadix = V; } 167*da58b97aSjoerg getMasmDefaultRadix()168*da58b97aSjoerg unsigned getMasmDefaultRadix() const { return DefaultRadix; } setMasmDefaultRadix(unsigned Radix)169*da58b97aSjoerg void setMasmDefaultRadix(unsigned Radix) { DefaultRadix = Radix; } 170*da58b97aSjoerg 171*da58b97aSjoerg /// Set whether to lex masm-style hex float literals, such as 3f800000r. setLexMasmHexFloats(bool V)172*da58b97aSjoerg void setLexMasmHexFloats(bool V) { LexMasmHexFloats = V; } 173*da58b97aSjoerg 174*da58b97aSjoerg /// Set whether to lex masm-style string literals, such as 'Can''t find file' 175*da58b97aSjoerg /// and "This ""value"" not found". setLexMasmStrings(bool V)176*da58b97aSjoerg void setLexMasmStrings(bool V) { LexMasmStrings = V; } 177*da58b97aSjoerg 178*da58b97aSjoerg /// Set whether to lex Motorola-style integer literals, such as $deadbeef or 179*da58b97aSjoerg /// %01010110. setLexMotorolaIntegers(bool V)180*da58b97aSjoerg void setLexMotorolaIntegers(bool V) { LexMotorolaIntegers = V; } 181*da58b97aSjoerg 182*da58b97aSjoerg /// Set whether to lex HLASM-flavour integers. For now this is only [0-9]* setLexHLASMIntegers(bool V)183*da58b97aSjoerg void setLexHLASMIntegers(bool V) { LexHLASMIntegers = V; } 184*da58b97aSjoerg 185*da58b97aSjoerg /// Set whether to "lex" HLASM-flavour character and string literals. For now, 186*da58b97aSjoerg /// setting this option to true, will disable lexing for character and string 187*da58b97aSjoerg /// literals. setLexHLASMStrings(bool V)188*da58b97aSjoerg void setLexHLASMStrings(bool V) { LexHLASMStrings = V; } 18906f32e7eSjoerg }; 19006f32e7eSjoerg 19106f32e7eSjoerg } // end namespace llvm 19206f32e7eSjoerg 19306f32e7eSjoerg #endif // LLVM_MC_MCPARSER_MCASMLEXER_H 194