词法分析器结构学习

最近正在研究JS动态解析的基本结构,希望自己能够将研究成果前前后后总结出来。

以方便自己复习,也希望能够和大家分享这样一套拥有悠久历史的编译技术实现。

 

按照编译原理的运行特点,一套解释系统最前面也是最简单的就是词法分析。

 

这里首先研究的是V8引擎的词法分析结构,头文件定义在 src/scanner.h中,具体实现在对应的src/scanner.cc中。

所有的构件

  • Scanner [v8::internal]
  • UC16CharacterStream [v8::internal]
  • UnicodeCache [v8::internal]
  • LiteralBuffer [v8::internal]
  • LiteralScope [v8::internal::Scanner]

在头文件中共声明有五个类,但是对外提供词法分析服务的就是Scanner类。其他四个类为词法分析提供基本基础服务:譬如字符流编码、结果存取、输入流缓冲等。

 

UC16CharacterStream [v8::internal]

对外主要提供三个接口:

  •     Advance [v8::internal::UC16CharacterStream] 向前扫描一个字符,并返回扫描到的字符,如果到文件尾部则返回一个负数。
  •     pos [v8::internal::UC16CharacterStream] 返回当前字符流扫描到的位置
  •     SeekForward [v8::internal::UC16CharacterStream] 向前N步步进
  •     PushBack      [v8::internal::UC16CharacterStream] 回溯一个字符

其是一个抽象类,与其相关的子类如图:


 

UnicodeCache [v8::internal]

用于对Unicode字符进行类型分析。其内部专门实现了用于支持Unicode的相关类包。主要是便于词法分析器在扫描到当前字符时可以进行当前字符状态的查询。

其内部含有各种类型分辨数据单元:

  •   unibrow::Predicate<IdentifierStart, 128> kIsIdentifierStart;
  •   unibrow::Predicate<IdentifierPart, 128> kIsIdentifierPart;
  •   unibrow::Predicate<unibrow::LineTerminator, 128> kIsLineTerminator;
  •   unibrow::Predicate<unibrow::WhiteSpace, 128> kIsWhiteSpace;

例如IndentifierStart数据题用于判断是否为起始字符:

struct IdentifierStart {
  static inline bool Is(uc32 c) {
    switch (c) {
      case '$': case '_': case '\\': return true;
      default: return unibrow::Letter::Is(c);
    }
  }
};

 

LiteralBuffer [v8::internal]

当前分析结果的字符流存储缓存结构。

内部用  Vector<byte> backing_store_ 保存扫描的字符流数据。

 

LiteralScope [v8::internal::Scanner]

用于记录在完成词法扫描后的词法分析状态

 

Scanner [v8::internal]

词法分析主体类,原先感觉是否会使用lex等自动生成器,没想到时完全手写版本。

字符流的基本分析方法时DFA,如果有时间,我考虑把分析器的DFA逆向画出来。

Scanner内部主要维护了current_,next_两步的token,具体的维护策略需要看语法分析的维护。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
java编程 含有界面 以及完整代码 〈程序〉→ main()〈语句块〉 〈语句块〉→{〈语句串〉} 〈语句串〉→〈语句〉;〈语句串〉|〈语句〉; 〈语句〉→〈赋值语句〉|〈条件语句〉|〈循环语句〉 〈赋值语句〉→ ID =〈表达式〉; 〈条件语句〉→ if〈条件〉〈语句块〉 〈循环语句〉→ while〈条件〉〈语句块〉 〈条件〉→(〈表达式〉〈关系符〉〈表达式〉) 〈表达式〉→〈表达式〉〈运算符〉〈表达式〉|(〈表达式〉)|ID|NUM 〈运算符〉→+|-|*|/ 〈关系符〉→<|<=|>|>=|=|!> word.wordList包(存储了关键字): word:此类是定义了存储关键字的结构:包括String型的关键字,和int型的识别符。 wordList:此类存储了29个关键字,在构造函数中初始化。 2、word包(进行词法分析)中: basicFunction:此类定义了做词法分析的基本函数: GetChar()将下一输入字符读到ch中,搜索知识器前移一个字符位置 GetBC();检查ch中的字符是否为空白。若是,则调用GetChar直至不 是字符为止 Concat();将ch中的字符连接到strToken之后 IsLetter();判断ch中的字符是否为字母 IsDigit();判断ch中的字符是否为数字 Reserve();对strToken中的字符创查找保留字表,若是则返回它的编码,否则返回0 Retract();将搜索指示器回调一个字符位置 RetractStr();将strToken置空 lexAnalysis:此类是用来进行词法分析,将分析后的单词存入word数组中,(注:在词法分析中,若是一串字母,则认为是ID,若是数字,则认为是NUM。存储的时候识别符分别存ID与NUM的识别符,但是内容仍然是自己的内容) 其中的wordAnalysis函数就是词法分析函数(具体实现请看后面的重要函数分析) 3、stack包(定义栈)中: 栈是通过链表来定义的,因此 StringListElement:次类定义了链表的每一个节点 StringStrack:此类定义了栈,其中有长度属性,有函数: Top();用来取得栈顶 Push();压栈 Pop();出栈 4、sentence包(语法分析)中: juzi :定义了文法的句子的结构:key(左边部分) content[](右边推出的部分) lo(长度) grammar :存储了文法的27个关系式 AnalysisFB :定义了分析表的存储结构 AnalysisF :存储分析表 SentenceAnalysis :语法分析 JuProduction(word w):此函数是用来判断在当前栈与输入串的情况下,用哪一个产生式,返回产生式在数组中的下标 若输入串的第一个字符与栈顶字符相同则表示可以规约,则返回-1; 若不能过用产生式,则返回-2; AnalysisBasic(word w):此函数是分布进行语法分析,对栈操作 * 根据所需要的产生式对符号栈进行操作 * 返回0表示规约;返回1表示移进;否则表示输入串不是文法的句子 5.Main包(主界面)中 Main:此类定义了图形界面
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值