文章目录
- 一、词法分析器设计思路说明
- 1.全局状态图
- 2.识别单词的状态转换图
- 3.识别注释与除号状态转换图
- 4.识别字符字符串状态转换图
- 5.识别关键字与常量的状态转换图
- 6.识别界符与运算符的状态转换图
- 二、TinyScript的词法要求
- 1.TinyScript的字符集
- 2.TinyScript中的关键字
- 3.TinyScript中的运算符
- 三、词法分析器代码分析
- 1.common包
- 2.lexer包
- 四、测试执行过程分析
一、词法分析器设计思路说明
该词法分析器基于状态转换图进行设计。首先画出识别特定单词的状态转换图并编写对应的单词识别程序,然后把不同的状态转换图合并为完整的状态转换图,并编写对应的完整的识别程序。完整的识别程序中,根据输入字符的不同调用识别不同单词的程序。
1.全局状态图
“扫描程序”是将源程序文件从文件中读取存在内存,读到一个字符串缓冲区中了。识别单词就是识别这个字符串中每个字符的类型,然后产找对应的token值插入到token表中。如果在识别单词时,识别结果非单词,则进入异常处理状态,进行报错。在分状态转换图中识别非单词进入异常处理状态都存在且重复,就省略。
2.识别单词的状态转换图
首先识别一个非空字符串,进入首字符类型判断状态,根据不同的类,调用不同的“处理机”,然后查找token表,找到对应的token值,最后添加到集合中。
3.识别注释与除号状态转换图
在识别注释与除号的过程中,先进入识别状态识别字符串第一个字符为‘/’,则进入处理注释与除号的“处理机”,并开始识别下一个字符,如果下一个字符是‘/’,则进行迭代,直接读取下一个的内容,如果是‘’,则就行迭代读取,直到读取到前一个字符为‘’,后面接着‘/’,则开始识别下一个字符,处理注释与除号的“处理机”
4.识别字符字符串状态转换图
在识别字符与字符串的过程中,第一个字符为‘’’或‘”’则进入字符与字符串的“处理机”,先存进缓存栈,然后删除此字符开始识别下一个字符(第一个字符为‘’’),如果识别的字符为非‘’’则进行循环识别并连接字符,直到识别到‘’’表示识别结束,返回字符的token值,字符串处理类似于字符处理;开始识别下一个字符(第一个字符为‘’’’),则进行循环识别并连接字符,直到识别到‘’’’表示识别结束,返回字符串的token值。
5.识别关键字与常量的状态转换图
在识别关键词和变量名的过程中,先识别第一个单词如果是字母,则进入关键词和变量名“处理机”,如果就一个单词则直接返回token值,如果后面还有则继续识别,直到识别结束,返回token值,然后查字典,如果在字典中,则说明是一个字符,不在则说明是一个自定义变量。
6.识别界符与运算符的状态转换图
在识别界定符和运算符的过程中,先进行识别字符,如果字符为界符,则创建token对象。进行下一次识别,如果为运算符则记录此符号之前的符号,并识别此符号下一个字符,如果还有其他字符,则进出处理机处理状态,否则删除缓存队列,进行下一次识别。然后开始自循环遍历缓存栈中所有元素,直到遍历到终结界符,然后返回。
先进性识别字符状态,如果识别下一个字符如果是0或1,并自循环判断此数中只出现0和1则返回二进制的token值,同理只存在0到7之间的数可能是八进制,十进制,十六进制,进行下一次判断。如果出现字母A~F则返回十六进制,如出现9但不出现字母,则返回八进制。
例如:识别”//asdeaaq\true”
因为第一个第二个字符为’/’则调用注释与除号的处理机,直到读取到换行符‘\’,然后进入识别单词的处理机,识别单词true。
查表,返回token值为24。
二、TinyScript的词法要求
1.TinyScript的字符集
TinyScript的字符集由英文大写字母,小写字母,数字,下划线和空白符号,以及下述特殊符号构成的:
2.TinyScript中的关键字
3.TinyScript中的运算符
TinyScript的运算符包括算数运算符、逻辑运算符和关系运算符
三、词法分析器代码分析
词法分析器包括commom和lexer两个包,分别分析如下。
1.common包
common包内的类分析如下。
(1)AlphabetHelper类
AlphabetHelper类的主要作用是定义TinyScript语言的字母表,包含以下4个属性和4个方法。
·ptnLetter属性
ptnLetter是Pattern类型的模式串,用于匹配单个字母,可以是大写字母或小写字母。
·ptnNumber属性
ptnNumber是Pattern类型的模式串,用于匹配0-9中的单个数字。
·ptnLiteral属性
ptnLiteral是Pattern类型的模式串,用于匹配单个大写字母或小写字母或0-9中的单个数字
·ptnOperator属性
ptnOperator是Pattern类型的模式串,用于匹配算数运算符、逻辑运算符、关系运算符等统称为运算符、操作符。
·isLetter()方法
isLetter(char c)返回boolean类型的结果,用于判断参数c是否为字母。
·isNumber()方法
isNumber(char c)返回boolean类型的结果,用于判断参数c是否为数字。
·isLiteral()方法
isLiteral(char c)返回boolean类型的结果,用于判断参数c是否为字母或数字。
·isOperator()方法
isOperator(char c)返回boolean类型的结果,用于判断参数c是否为运算符、操作符。
(2)PeekIterator类
PeekIterator类的主要作用是定义缓存流队列,包含以下5个属性和7个方法。
·It属性
It是Iterator<T>类型定义的一个迭代器.来访问一个容器对象中各个元素。
·queueCache属性
queueCache是LinkedList<T>类型定义的链表数据结构,表示缓存队列作为正在处理的字符执行窗口
·stackPutBacks属性
stackPutBacks是LinkedList<T>类型定义的链表数据结构,表示缓存栈存已经处理过的n字符。
·CACHE_SIZE属性
CACHE_SIZE是int类型定义的变量,表示缓存窗口的大小。
·_endToken属性
_endToken是T类型(即任意类型)定义的变量,表示结束符。
·PeekIterator(Stream<T> stream)方法
PeekIterator(Stream<T> stream)初始化构造迭代器,用其缓存元素。
·PeekIterator(Iterator<T> _it, T endToke)方法
PeekIterator(Iterator<T> _it, T endToke)初始化构造迭代器,并初始化结束符号。
·PeekIterator(Stream<T> stream, T endToken)方法
PeekIterator(Stream<T> stream, T endToken)初始化构造流对象,并初始化结束符号。
·peek()方法
peek()方法用于实现获得数据头,不提取仅获得。
·putBack()方法
putBack()方法回退数据操作,从缓存中拿到最后一个数据放到回退栈中
·hasNext()方法
重写实现类Iterator的hasNext()方法,返回boolean类型的结果,判断是否存在下一个值
·next()方法
重写实现类Iterator 的next()方法,返回下一个值,优先从回退栈中取,栈为空的话从迭代器里拿。
2.lexer包
lexer包内的类分析如下:
(1)Keywords类
Keywords的主要作用是定义TinyScript语言的的保留关键字,实现关键词字典。包含以下2个属性和1个方法。
·keywords属性
keywords是String[]类型定义的字符数组,内包含TinyScript语言的的保留关键字。
·set属性
set是HashSet<String>类型定义的包含keywords的数组。
·isKeyword()方法
isKeyword(String word)返回boolean类型的结果,用于判断参数word中是否与keywords中的保留关键字重复。
(2)Lexer类
Lexer类主要作用是进行词法分析.包含了以下3个方法.
·analyse(PeekIterator<Character> it)方法
analyse(PeekIterator<Character> it)对缓存队列中的元素进行词法分析,主要进行以下操作:
1.读一非空字符
2.首字符分类: 如果首字符为’/’进入删除注释处理;
如果是",'开头交给字符串状态机处理; 如果是字母交给变量或关键字状态机处理;
如果是数字交给数字状态机处理; 如果是运算符交给运算符状态机处理
·analyse(Stream source)方法
analyse(Stream source)初始化流和结束符号,将词法分析后的单词token值以集合形式返回.
·fromFile(String src)方法
fromFile(String src)从源代码文件加载并解析文件内容.即解析代码程序文件.
(3)Lexical Exception类
LexicalException的主要作用是进行词法分析的异常显示,包含以下1个属性和3个方法。
·msg属性
msg是String类型定义的字符串,用于表示错误信息。
·LexicalException(char c)方法
LexicalException(char c)方法用于将传入的错误的字符c表示为一个句子"Unexpected character %c"。
·LexicalException(String _msg)方法
LexicalException(String _msg)方法用于对传参
·getMessage()方法
重写String类型的getMessage()方法,返回获取的msg的内容。
(4)Token类
Token类的主要作用是保存代码中的Token,
其中包括关键字/标识符/操作符/字符串/数字等定义的TokenType,以及对词语的提取。
包含以下2个属性和15个方法。
·_type属性
_type是TokenType类型定义的,表示字符类型
·_value属性
_value是 String类型定义的,表示字符值
·Token()方法
Token(TokenType type, String value)方法用于初始化字符类型和字符值
·getType()方法
getType()方法用于返回type的值
·getValue()方法
getValue()方法用于返回value的值
·toString()方法
重写String类型的toString方法,用于输出type和value的值
·isVariable()方法
isVariable()返回boolean类型的结果,用于判断是否为变量。
·isScalar()方法
isScalar()返回boolean类型的结果,用于判断是否为规范的类型。
·isOperator()方法
isOperator()返回boolean类型的结果,用于判断是否为操作符。
·isPostUnaryOperato()方法
isPostUnaryOperator()返回boolean类型的结果,用于判断是否为后置一元运算符
·isType()
isType()返回boolean类型的结果,用于判断是否为定义类型
·isValue()方法
isValue()返回boolean类型的结果,用于判断是否为变量
·isNumber()方法
isNumber()返回boolean类型的结果,用于判断是否为数字
·makeVarOrKeyword(Peeklterator<Character>)方法
用于提取关键字与变量名
·makeString(Peeklterator <Character>)方法
用于提取字符串
·makeOp(Peeklterator<Character>)方法
用于提取操作符
·makeNumber(Peeklterator<Character>)方法
用于提取数字,其中涉及到小数以及正负数的判断
(5)TokenType类
TokenType类的主要作用是实现符号类型枚举。
四、测试执行过程分析
词法分析器的测试代码位于src/test/java目录下,包括commom和lexer两个包,分别分析如下。
1.common包
common包内的类分析如下。
(1)AlphabetHelperTests类
AlphabetHelperTests类的主要作用是对AlphabetHelper类的4个方法进行测试,通过test()方法验证其能否正确区分是否为相应类型的字符。
经测试,AlphabetHelper类的4个方法实现了相应功能。
(2)PeekIteratorTests类
PeekIteratorTests类的主要作用是对PeekIterator类的3个方法进行测试,通过
test_peek()方法测试迭代器是否能够正常读取字符.
test_lookahead2()方法测试检索并删除此列表的最后一个元素,如果此列表为空,则返回 null 。即测试新插入的元素.
test_endToken()方法测试结束符相关方法是否奏效.
经测试PeekIterator类的3个方法均实现相应功能.
2.lexer包
lexer包内的类分析如下。
(1)LexerTests类
LexerTests类主要的作用是对Lexer类7个方法的测试.
test_expression()方法测试字符串是否能够被单词识别系统正确识别.
test_function()方法测试对方法体的识别检测.
test_deleteComment()方法主要测试对注释的删除屏蔽功能, 之后是否不影响正常代码
test_deleteErrorComment()方法主要测试对错误注释/*/的异常处理
test_deleteOneLine()方法主要测试对单行注释的删除屏蔽,之后是否不影响正常代码
minus()方法主要测试对运算符号’-’的测试,是否成功识别.
test_loadFile方法主要对加载源文件代码的提取识别进行测试.
经测试LexerTests类的7个方法均实现相应功能.
(2)TokenTests类
TokenTests类主要的作用是对Token类4个方法的测试.
test_varOrKeyword()方法主要对提取的关键字与变量名进行测试
test_makeString()方法主要对提取的进行字符串判断测试
test_makeOperator()方法主要对提取进行操作符判断测试
test_makeNumber()方法主要对提取的进行数字判断测试
经测试TokenTests类的7个方法均实现相应功能.