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>.动作伪代码
无
