例如,有一个cpp源代码,例如:
#include<iostream>
using namespace std;
int main()
{
int counta=0;
int countb=0;
while(cin.get()!='*')
count++;
cout<<count<<" char";
}
令牌,例如:
head_iostream
namesp_std
begin_main
var_int
var_int
begin_while,cin_char,var_char!=’*’
assign,var_int++
end_while
你怎么能做到?有可用的相关工具或开源软件吗?
基本上,您要做的是编写一个处理来自源文件的输入字符流的有限状态机(FSM)的代码。每个状态都会根据从流中读取的各个字符进行转换。
FSM的开始状态是“不知道接下来会出现什么令牌”。中间状态是“根据自开始状态以来已看到的字符,当前令牌可以是X,Y,Z ...(特定于该状态)集合中的任何一个”。叶子状态为“当前令牌是完整的X”或“自开始以来的字符不对应任何有效令牌”。请注意,具有“完整的X”并不意味着无法读取更多字符来扩展X或成为Y。
人们可能会将空白/注释作为FSM开始状态的其他分支来处理,这些分支只是在空白序列结束时返回到FSM开始状态。
您可以很容易地手动为有限字符集(例如ASCII)编写这样的有限语句机器。这通常是针对编译器执行的,因为此类FSM可以非常快速地处理输入流,并且编译器会看到很多源代码字符。加快速度往往有助于使编译器更快。
对于各种状态而言,将转换后的字符存储到令牌缓冲区中通常很有用,因此,当达到叶子状态时,就已捕获了令牌内容。可以根据当前的中间状态有条件地执行此操作;例如,如果当前状态只能导致关键字,则无需存储此类字符。
您可以使用称为“词法生成器”的各种工具(Lex,Yacc,Flex等许多工具)生成此类FSM。通常,这些工具会列出一对
<token_name, regular_expression>
并构建一个统一的FSM,其中集成了正则表达式的效果,并为每个token_name生成叶子状态。这样生成的词法分析器可能非常快。手工生成的词法分析器几乎总是可以更快,因为人们可以将更多的知识带到餐桌上。
机器生成的词法分析器对于带有大量令牌集且每个令牌具有复杂正则表达式的语言(C ++ 11和COBOL符合此类别)或涉及Unicode的语言(因为从每个状态的转换数量可能很大且类别确实很乱,谢谢Unicode)。Unicode成为首选的字符集,这表明机器生成的词法分析器将成为长期的自然选择。(令人惊讶的是,许多词法分析器生成器似乎都不处理Unicode。[我有一个生成器]。)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句