深入研究Clang(七) Clang Lexer代码阅读笔记之Lexer

简介: 作者:史宁宁(snsn1984)源码位置:clang/lib/Lexer.cpp源码网络地址:http://clang.llvm.org/doxygen/Lexer_8cpp_source.htmlLexer.cpp这个文件,是Clang这个前端的词法分析器的主要文件,它的内容是对Lexer这个类的具体实现,原文件的注释中:“This file implements the Lexer and Token interfaces.” 这么解释这个文件的,但是Token只有两个简单函数的实现,剩下的都是Lexer的实现。

作者:史宁宁(snsn1984)

源码位置:clang/lib/Lexer.cpp

源码网络地址:http://clang.llvm.org/doxygen/Lexer_8cpp_source.html


Lexer.cpp这个文件,是Clang这个前端的词法分析器的主要文件,它的内容是对Lexer这个类的具体实现,原文件的注释中:“This file implements the Lexer and Token interfaces.” 这么解释这个文件的,但是Token只有两个简单函数的实现,剩下的都是Lexer的实现。所以要想搞清楚Clang的词法分析器是怎么实现的,那么必须对这个文件有着深入的理解。


从Lexer的初始化函数开始入手:

void Lexer::InitLexer(const char *BufStart, const char *BufPtr,
   56                       const char *BufEnd) {
   57   BufferStart = BufStart;
   58   BufferPtr = BufPtr;
   59   BufferEnd = BufEnd;
   60 
   61   assert(BufEnd[0] == 0 &&
   62          "We assume that the input buffer has a null character at the end"
   63          " to simplify lexing!");
   64 
   65   // Check whether we have a BOM in the beginning of the buffer. If yes - act
   66   // accordingly. Right now we support only UTF-8 with and without BOM, so, just
   67   // skip the UTF-8 BOM if it's present.
   68   if (BufferStart == BufferPtr) {
   69     // Determine the size of the BOM.
   70     StringRef Buf(BufferStart, BufferEnd - BufferStart);
   71     size_t BOMLength = llvm::StringSwitch<size_t>(Buf)
   72       .StartsWith("\xEF\xBB\xBF", 3) // UTF-8 BOM
   73       .Default(0);
   74 
   75     // Skip the BOM.
   76     BufferPtr += BOMLength;
   77   }
   78 
   79   Is_PragmaLexer = false;
   80   CurrentConflictMarkerState = CMK_None;
   81 
   82   // Start of the file is a start of line.
   83   IsAtStartOfLine = true;
   84   IsAtPhysicalStartOfLine = true;
   85 
   86   HasLeadingSpace = false;
   87   HasLeadingEmptyMacro = false;
   88 
   89   // We are not after parsing a #.
   90   ParsingPreprocessorDirective = false;
   91 
   92   // We are not after parsing #include.
   93   ParsingFilename = false;
   94 
   95   // We are not in raw mode.  Raw mode disables diagnostics and interpretation
   96   // of tokens (e.g. identifiers, thus disabling macro expansion).  It is used
   97   // to quickly lex the tokens of the buffer, e.g. when handling a "#if 0" block
   98   // or otherwise skipping over tokens.
   99   LexingRawMode = false;
  100 
  101   // Default to not keeping comments.
  102   ExtendedTokenMode = 0;
  103 }

这个初始化函数,是在Lexer类的两个构造函数里被调用的,具体代码如下:


  104 
  105 /// Lexer constructor - Create a new lexer object for the specified buffer
  106 /// with the specified preprocessor managing the lexing process.  This lexer
  107 /// assumes that the associated file buffer and Preprocessor objects will
  108 /// outlive it, so it doesn't take ownership of either of them.
  109 Lexer::Lexer(FileID FID, const llvm::MemoryBuffer *InputFile, Preprocessor &PP)
  110   : PreprocessorLexer(&PP, FID),
  111     FileLoc(PP.getSourceManager().getLocForStartOfFile(FID)),
  112     LangOpts(PP.getLangOpts()) {
  113 
  114   InitLexer(InputFile->getBufferStart(), InputFile->getBufferStart(),
  115             InputFile->getBufferEnd());
  116 
  117   resetExtendedTokenMode();
  118 }
  119 
  120 void Lexer::resetExtendedTokenMode() {
  121   assert(PP && "Cannot reset token mode without a preprocessor");
  122   if (LangOpts.TraditionalCPP)
  123     SetKeepWhitespaceMode(true);
  124   else
  125     SetCommentRetentionState(PP->getCommentRetentionState());
  126 }
  127 
  128 /// Lexer constructor - Create a new raw lexer object.  This object is only
  129 /// suitable for calls to 'LexFromRawLexer'.  This lexer assumes that the text
  130 /// range will outlive it, so it doesn't take ownership of it.
  131 Lexer::Lexer(SourceLocation fileloc, const LangOptions &langOpts,
  132              const char *BufStart, const char *BufPtr, const char *BufEnd)
  133   : FileLoc(fileloc), LangOpts(langOpts) {
  134 
  135   InitLexer(BufStart, BufPtr, BufEnd);
  136 
  137   // We *are* in raw mode.
  138   LexingRawMode = true;
  139 }

这两个构造函数各有不同,从输入参数上就可以看出。也有相同的地方,就是对一些参数只是引用的关系,并没有获取这些参数的所有权。


Lexer的构造函数,在自己的类内部,分别被以下的函数所调用:

Create_PragmaLexer: Lexer constructor - Create a new lexer object for _Pragma expansion.
http://clang.llvm.org/doxygen/classclang_1_1Lexer.html#ac7f3b1ce4f2eeaec8d787d22bf197cd0


getSpelling - This method is used to get the spelling of a token into a preallocated buffer, instead of as an std::string.

http://clang.llvm.org/doxygen/classclang_1_1Lexer.html#a94f2c5710332ae19d7955c609ac37adb


getRawToken

http://clang.llvm.org/doxygen/classclang_1_1Lexer.html#adac8b8cf001621ec3b109d82a7074f05


 getBeginningOfFileToken

http://clang.llvm.org/doxygen/Lexer_8cpp.html#a4845396d18432c436e605303b057dbb4


findLocationAfterToken

http://clang.llvm.org/doxygen/classclang_1_1Lexer.html#a099b99b2d19ef5cdd8fcb80d8cf4064e



目录
相关文章
|
6月前
|
机器学习/深度学习 人工智能 自然语言处理
《打破黑箱:深度学习模型可解释性的攻坚之路》
深度学习模型在图像识别、自然语言处理等领域取得了显著成果,但其“黑箱”特性引发了可靠性、安全性和透明度的担忧。这种不可解释性在医疗、金融和自动驾驶等场景中可能导致不确定性或信任危机。为解决这一问题,研究者从模型可视化、特征重要性分析、设计可解释模型架构及事后解释方法等方向展开探索。然而,现有方法仍面临局部解释性、计算成本高及缺乏统一评估标准等问题。实现深度学习模型的可解释性是AI走向成熟与广泛应用的关键,未来需学术界与产业界共同努力,推动技术进步以造福社会。
354 9
|
4月前
|
传感器 自然语言处理 搜索推荐
通义灵码 2.5 版体验报告:智能编程助手的全新升级
通义灵码2.5版通过Qwen3模型和智能体模式,显著提升了编程效率与体验。智能体可自主决策,快速完成应用开发;MCP工具广场提供3000+工具,一键安装便捷高效;记忆能力让工具越用越懂用户需求;Qwen3强大的自然语言处理能力助力复杂任务解析。界面友好、性能稳定,为开发者带来高效个性化体验,未来潜力巨大。
|
10月前
|
存储 持续交付 开发工具
clang-format
clang-format
687 7
|
11月前
|
机器学习/深度学习 人工智能 算法
【算法】最长公共子序列(C/C++)
【算法】最长公共子序列(C/C++)
|
安全 编译器 Go
Go 1.21: 泛型函数的全面回顾
Go 1.21: 泛型函数的全面回顾
|
存储 Go
带你入门 Go 语言中的泛型编程
带你入门 Go 语言中的泛型编程
145 0
|
SQL NoSQL 前端开发
大厂如何解决订单幂等问题
本文探讨了分布式系统中接口幂等性的重要性和实现方法,特别是在防止重复下单的场景中。首先介绍了通过数据库事务处理创建订单时的原子性需求。接着分析了服务间调用时可能遇到的重复请求问题,提出每个请求需具备唯一标识,并记录处理状态以识别并阻止重复操作。具体实践包括生成全局唯一的订单ID,利用数据库主键唯一性约束来防止重复插入,以及使用Redis存储订单支付状态。此外,文章还讨论了解决ABA问题(即数据在两次检查之间被修改的问题)的方法,引入版本号机制来确保数据更新的原子性和一致性。这些技术方案不仅限于订单服务,也可广泛应用于需要实现幂等性的其他业务场景中。
|
Shell Java
shell编程之转义和引用
shell中有两类字符,一类是普通字符,在Shell中除了本身的字面意思外没有其他特殊意义,即普通纯文本;另一类即元字符,是Shell的保留字符,在Shell中有着特殊的含义。 一、转义 转义是指使用转义符引用单个字符,从而使其表达单纯的字符的字面含义。
1988 0
|
iOS开发 开发者
iOS iPhone手机弱网环境配置
iOS iPhone手机弱网环境配置
iOS iPhone手机弱网环境配置
|
jenkins 测试技术 持续交付
Python测试框架之pytest详解
Python测试框架之pytest详解
826 0
 Python测试框架之pytest详解

热门文章

最新文章