1.9规则动作详细设计
1.9.1 概述
该部分,除了包括{loc}中提到的单词的识别,还将介绍如何匹配、缓存并返还下一行;如何处理字符常量识别的各种情况;如何处理遇到文件尾的各种情况;如何处理单行注释;如何处理多行注释等;如何处理非法字符等情况。
PASCAL-S的单行注释以//开始,多行注释由一对花括号包括。
1.9.2 环境介绍
名称 | 描述 | 进入条件 | 离开条件 |
---|---|---|---|
INITIAL | 初始环境(默认环境) | lex开始运行,或从CH、SCOM、MCOM返回 | 遇到单引号、双斜杠、左花括号 |
CH | 字符常量识别环境 | 在INITIAL中遇到单引号 | 遇到单引号、换行符 |
SCOM | 单行注释识别环境 | 在INITIAL中遇到双斜杠 | 遇到换行符 |
MCOM | 多行注释识别环境 | 在INITIAL中遇到左花括号 | 遇到右花括号 |
1.9.3 INITIAL环境
1.9.3.1 空白符
正则表达式
{blank_chars}
动作伪代码
无
说明
遇到空白符,无需采取任何动作。
1.9.3.2 缓存下一行
正则表达式
{line}
动作伪代码
{ if(检测当前行长度超过限制)//CheckAndAddLengthTooLargeErrorInformation return 0; 将当前行保存到lineBuffer中; yycolumn初始化为1; 将当前行全部退回到输入区,只保留一开始的换行符; }
说明
下一行的起始标志是换行符,因此为了识别第一行,在预处理中,我们在整个源程序的第一行之前加入了一个换行符;另外加入换行符也会影响到yylineno及行号,真正的行号应为yylineno-1。<br /> 缓存下一行的主要目的是为了输出更加详细的词法错误信息。可以先指明错误类型,然后输出错误所在行,最后用”^”符号指出错误的具体位置。
1.9.3.3 各种单词通用设计
正则表达式
program | const | var | array |
---|---|---|---|
of | procedure | function | begin |
if | then | for | to |
do | else | repeat | until |
while | {_type} | not | {relop} |
{addop} | {mulop} | - | = |
:= | \.\. | {delimiter} |
动作伪代码
{ yylval指向新创建的节点; 根据当前的单词种类,对yylval的记号和属性域进行赋值; yylval的行号域赋值为当前行号; return 当前记号; }
说明
各单词的记号和属性信息在{loc}中已详细说明,不再赘述。
1.9.3.4 单引号,进入CH环境
正则表达式
‘
动作伪代码
{ 进入CH环境; charRec初始化为空字符串; }
1.9.3.5 双斜杠,进入SCOM环境
正则表达式
\/\/
动作伪代码
{ 进入SCOM环境; }
1.9.3.6 左花括号,进入MCOM环境
正则表达式
\{
动作伪代码
{ 进入MCOM环境; }
1.9.3.7 非法字符
正则表达式
.
动作伪代码
{ 添加非法字符错误;//错误3 }
1.9.4 CH环境
1.9.4.1 文件尾
正则表达式
<CH><<EOF>>
动作伪代码
{ 添加读取字符常量时遇到文件尾的错误;//错误4 }
1.9.4.2 单引号或换行符,进入INITIAL环境
正则表达式
<CH>("'"|"\n")
动作伪代码
{ len=charRec记录的字符串的长度; if(当前识别的是单引号 && len==0) { 添加字符常量为空的错误信息; //错误5 返回到初始环境; yylval指向新创建的节点; yylval的属性为"\0"; yylval的记号为CHAR; yylval的行号域赋值为当前行号; return CHAR; } else if(当前识别的是单引号 && len==1) { yylval指向新创建的节点; 返回到初始环境; yylval的属性为charRec[0]; yylval的记号为CHAR; yylval的行号域赋值为当前行号; return CHAR; } else if(当前识别的是单引号 && len>1) { 添加字符常量过长的错误信息; //错误6 yylval指向新创建的节点; 返回到初始环境; yylval的属性为charRec[0]; yylval的记号为CHAR; yylval的行号域赋值为当前行号; return CHAR; } else { //当前识别的是换行符 添加右单引号缺失的错误信息; //错误7 yylval指向新创建的节点; 返回到初始环境; if(len==0) yylval的属性为"\0"; else yylval的属性为charRec[0]; yylval的记号为CHAR; yylval的行号域赋值为当前行号; return CHAR; } }
1.9.4.3 其它字符
正则表达式
<CH>.
动作伪代码
{ charRec后面拼上yytext[0]; }
1.9.5 SCOM环境
1.9.5.1 文件尾
正则表达式
<SCOM><<EOF>>
动作伪代码
{ return 0;//表示分析结束 }
说明
单行注释遇到文件尾是很正常的情况。
1.9.5.2 换行符,进入INITIAL环境
正则表达式
<SCOM>"\n"
动作伪代码
{ 返回到初始环境; 将换行符退回; 当前行号减1; }
1.9.5.3 其它字符
正则表达式
<SCOM>.
动作伪代码
无
1.9.6 MCOM环境
1.9.6.1 文件尾
正则表达式
<MCOM><<EOF>>
动作伪代码
{ 添加多行注释遇到文件尾的错误信息; return 0; //词法分析终止 }
1.9.6.2 缓存下一行
正则表达式
<MCOM>{line}
动作伪代码
{ if(检测当前行长度超过限制)//CheckAndAddLengthTooLargeErrorInformation return 0; 将当前行保存到lineBuffer中; yycolumn初始化为1; 将当前行全部退回到输入区,只保留一开始的换行符; }
1.9.6.3 右花括号,进入INITIAL环境
正则表达式
<MCOM>"\}"
动作伪代码
{ 返回到初始环境; }
1.9.6.4 其它字符
正则表达式
<MCOM>.
动作伪代码
无