任务描述
经过上个任务的磨砺,相信大家已经熟悉了lex/flex的使用。这一次我们将利用flex工具生成PL语言的词法分析器,要求输入一个PL语言源程序文件demo.pl,输出一个文件tokens.txt,该文件包括每一个单词及其种别枚举值,每行一个单词。
编程要求
根据提示,在右侧编辑器补充代码,设计识别PL语言单词符号的词法分析器。
PL语言单词符号及其种别值
注意,这里还有一个类别ERROR,包括不是出现在字符串中的非法字符,有~!@#$%^&_\ 当词法分析器读到非法字符时,应该输出ERROR作为种别值。
测试说明
平台会对你编写的代码进行测试:
一共有5个测试集。
测试输入1:Test2_1.PLS;
这个测试集主要测试对算术运算符的识别。
需要完成的种别有:IDENT,INTCON,PLUS,MINUS,TIMES,DIVSYM,BECOME。
测试输入2:Test2_2.PLS
这个测试集主要测试对字符常量的识别。
需要完成的种别有:CHARCON。
测试输入3:Test2_3.PLS
这个测试集主要测试对比较运算符的识别。
需要完成的种别有:IDENT,EQL,NEQ,LSS,LEQ,GTR,GEQ。
测试输入4:Test2_4.PLS
这个测试集是一个完整PL源程序。
需要完成的种别有:所有PL可以识别的种别。
测试输入5:Test2_5.PLS
这个测试集是一个完整PL源程序中间插入了非法字符,需要将其识别出来。
需要完成的种别有:所有PL可以识别的种别+ERROR。
/* PL词法分析器 */
/* 功能:能够识别出PL支持的所有单词符号并给出种别值 */
/* 说明:在下面的begin和end之间添加代码,已经实现了标识符和整常量的识别,你需要完成剩下的部分,加油吧! */
/* 提示:因为是顺序匹配,即从上至下依次匹配规则,所以需要合理安排顺序~ */
%{
#include <stdio.h>
%}
/* begin */
OFSYM of
ARRAYSYM array
PROGRAMSYM program
MODSYM mod
ANDSYM and
NOTSYM not
ORSYM or
BEGINSYM begin
ENDSYM end
IFSYM if
THENSYM then
ELSESYM else
WHILESYM while
DOSYM do
CALLSYM call
CONSTSYM const
VARSYM var
TYPESYM type
PROCSYM procedure
CHARCON \'[^\']*\'
INTCON [\-]?[1-9][0-9]*|0
IDENT [A-Za-z][A-Za-z0-9]*
PLUS \+
MINUS \-
TIMES \*
DIVSYM \/
EQL =
NEQ <>
LSS <
LEQ <=
GTR >
GEQ >=
LBRACK \[
RBRACK \]
LPAREN \(
RPAREN \)
COMMA ,
SEMICOLON ;
COLON :
PERIOD \.
BECOME :=
ERROR [^ \t\n]
/* end */
%%
{CHARCON} {printf("%s: CHARCON\n", yytext);}
{PLUS} {printf("%s: PLUS\n", yytext);}
{MINUS} {printf("%s: MINUS\n", yytext);}
{TIMES} {printf("%s: TIMES\n", yytext);}
{DIVSYM} {printf("%s: DIVSYM\n", yytext);}
{EQL} {printf("%s: EQL\n", yytext);}
{NEQ} {printf("%s: NEQ\n", yytext);}
{LSS} {printf("%s: LSS\n", yytext);}
{LEQ} {printf("%s: LEQ\n", yytext);}
{GTR} {printf("%s: GTR\n", yytext);}
{GEQ} {printf("%s: GEQ\n", yytext);}
{LBRACK} {printf("%s: LBRACK\n", yytext);}
{RBRACK} {printf("%s: RBRACK\n", yytext);}
{LPAREN} {printf("%s: LPAREN\n", yytext);}
{RPAREN} {printf("%s: RPAREN\n", yytext);}
{COMMA} {printf("%s: COMMA\n", yytext);}
{SEMICOLON} {printf("%s: SEMICOLON\n", yytext);}
{COLON} {printf("%s: COLON\n", yytext);}
{PERIOD} {printf("%s: PERIOD\n", yytext);}
{BECOME} {printf("%s: BECOME\n", yytext);}
{OFSYM} {printf("%s: OFSYM\n", yytext);}
{ARRAYSYM} {printf("%s: ARRAYSYM\n", yytext);}
{PROGRAMSYM} {printf("%s: PROGRAMSYM\n", yytext);}
{MODSYM} {printf("%s: MODSYM\n", yytext);}
{ANDSYM} {printf("%s: ANDSYM\n", yytext);}
{NOTSYM} {printf("%s: NOTSYM\n", yytext);}
{ORSYM} {printf("%s: ORSYM\n", yytext);}
{BEGINSYM} {printf("%s: BEGINSYM\n", yytext);}
{ENDSYM} {printf("%s: ENDSYM\n", yytext);}
{IFSYM} {printf("%s: IFSYM\n", yytext);}
{THENSYM} {printf("%s: THENSYM\n", yytext);}
{ELSESYM} {printf("%s: ELSESYM\n", yytext);}
{WHILESYM} {printf("%s: WHILESYM\n", yytext);}
{DOSYM} {printf("%s: DOSYM\n", yytext);}
{CALLSYM} {printf("%s: CALLSYM\n", yytext);}
{CONSTSYM} {printf("%s: CONSTSYM\n", yytext);}
{VARSYM} {printf("%s: VARSYM\n", yytext);}
{TYPESYM} {printf("%s: TYPESYM\n", yytext);}
{PROCSYM} {printf("%s: PROCSYM\n", yytext);}
{INTCON} {printf("%s: INTCON\n", yytext);}
{IDENT} {printf("%s: IDENT\n", yytext);}
{ERROR} {printf("%s: ERROR\n", yytext);}
\n {}
. {}
%%
int yywrap() { return 1; }
int main(int argc, char **argv)
{
if (argc > 1) {
if (!(yyin = fopen(argv[1], "r"))) {
perror(argv[1]);
return 1;
}
}
while (yylex());
return 0;
}