这个对象就包含了已经转换好的DFA和各种词法分析器运转所需要的参数。下一步,我们就可以用ScannerInfo对象创建出Scanner对象,请看下面的代码:

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Scanner scanner = new Scanner(info); string source = "asdf04a 1107 else"; StringReader sr = new StringReader(source); scanner.SetSource(new SourceReader(sr)); scanner.SetSkipTokens(WHITESPACE.Index); Lexeme l1 = scanner.Read(); Console.WriteLine(l1.TokenIndex); //等于ID.Index Console.WriteLine(l1.Value); //等于 asdf04a Lexeme l2 = scanner.Read(); Console.WriteLine(l2.TokenIndex); //等于NUM.Index Console.WriteLine(l2.Value); //等于 1107 Lexeme l3 = scanner.Read(); Console.WriteLine(l3.TokenIndex); //等于ELSE.Index Console.WriteLine(l3.Value); //等于 else Lexeme l4 = scanner.Read(); Console.WriteLine(l4.TokenIndex); //等于info.EndOfStreamTokenIndex Console.WriteLine(l4.Value); //等于 null |

创建Scanner对象时,需要传入上一步生成的ScannerInfo对象,接下来可以指定输入的源代码。这里我们用StringReader来读取一段字符串源代码。注意Scanner的SetSkipTokens方法,可以设定词法扫描器自动跳过的单词。比如我们不希望词法分析器返回空白字符的词素,就设定跳过WHITESPACE单词。在操作Scanner类的时候,所有与Token相关的操作都是通过Token.Index(一个整数)来完成的,因为Scanner内部仅仅保存了Token在Lexicon内部的索引值,这样可以减小内存使用并且提高效率。

一切准备就绪之后就可以调用scanner.Read()方法来进行词法分析了!每次调用scanner.Read()会返回下一个词素(Lexeme对象),从Lexeme的属性中我们可以拿到该词素对应的单词类型(仍然是以Token.Index整数形式),词素的字符串表示(Value属性)以及词素在源代码中位置等丰富的信息。当扫描到文件或字符串尾部时,scanner.Read()会返回一个特殊的词素表示End Of Stream。这个特殊词素的TokenIndex可以从ScannerInfo对象查询到(每个ScannerInfo的EndOfStreamTokenIndex会不一样)。大家可以试着运行一下上述代码,并且修改自己的词法定义或源代码,来观察Scanner类的各种行为。另外VBF.Compilers.Scanner库还提供了两种具有特殊能力的Scanner------分别是PeekableScanner和ForkableScanner,未来的篇章中我们会用到它们的特殊能力。

相关推荐
悠仁さん11 小时前
【C++】vector 类
开发语言·c++
_upupup11 小时前
智能指针的原理及简单模拟实现(C++)
开发语言·c++
en.en..11 小时前
C语言---宏
c语言·开发语言
郝学胜-神的一滴12 小时前
C++ Templates 01:拨开迷雾,读懂C++模板经典著作
开发语言·c++·程序人生·游戏·游戏引擎·软件构建
言乐612 小时前
Python实现关税自动计算模型
开发语言·python·django·virtualenv·pygame
朝朝辞暮i12 小时前
C++ 第 14 课:引用 &
开发语言·c++·算法
梅雅达编程笔记12 小时前
04-Python CSV数据保存与翻页抓取
开发语言·爬虫·python·pandas·数据采集·csv
C++ 老炮儿的技术栈13 小时前
有符号变量与无符号变量的区别
服务器·开发语言·前端·数据结构·c++·算法·c
估值探索者13 小时前
【Python量化策略实战 #04】Donchian 通道假突破太多?用 ATR 阈值过滤跑通真实突破信号
开发语言·python·接口·api接口·数据api接口·股票数据api接口
个 人 练 习 生13 小时前
C++:模板初阶详解
开发语言·c++·经验分享·学习