CS143_PA2

基本说明

PA2中运行make lexer,会在目录下产生一个可执行文件lexer,运行./lexer test.cl,即可对test.cl中的代码进行词法分析。

.flex文件定义了语法分析的规则,在本次PA中,我们需要完成cool.flex文件, 在其中设置正确的正则表达式。从而使得我们的lexer能产生正确的词法分析结果。

具体实现

.flex文件中,definitions区包含了定义全局变量、定义宏等内容;rules区中设置各个正则表达式和对应的代码处理,每当匹配到一个正则表达式,就会执行对应的代码块;下面分别介绍definitions区和rules区的具体实现。

definitions区

除了已有定义,在definition区我们还做了以下定义:

  • 两个全局变量,comment_layer保存注释的层数,用于后续处理嵌套循环,stringArray用于存储字符串;
  • 对于cool语言中的简单关键字也在这里做flex定义,供后续代码中使用

具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
static int comment_layer=0;
static std::vector<char> stringArray;

DARROW =>
CLASS class
ELSE else
FI fi
IF if
IN in
INHERITS inherits
LET let
LOOP loop
POOL pool
THEN then
WHILE while
CASE case
ESAC esac
OF of
NEW new
ISVOID isvoid
NOT not

DIGIT [0-9]
TYPEID [A-Z][A-Za-z0-9_]*
OBJECTID [a-z][A-Za-z0-9_]*
INVALID [\[\]\'>]
BOOL_TRUE t[Rr][Uu][Ee]
BOOL_FALSE f[Aa][Ll][Ss][Ee]

rules区

rules区主要对以下几类语句进行处理:

  1. 注释
  2. 关键字(固定字符)
  3. 单个字符
  4. 字符串

下面分别进行介绍。

注释处理

cool有两种注释格式,分别是使用(*的多行注释和使用--的单行注释,并且支持嵌套循环,在这使用一个全局变量comment_layer来记录嵌套数量,具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<INITIAL,COMMENTS>"(*"	{   ++comment_layer; BEGIN(COMMENTS);}

<COMMENTS>[^\n(*]* {}

<COMMENTS>[()*] {}

<COMMENTS>"*)" { --comment_layer;
if(comment_layer==0){
BEGIN(INITIAL);
}
}

<COMMENTS><<EOF>> {
cool_yylval.error_msg="EOF in comment";
BEGIN(INITIAL);
return (ERROR);
}

<COMMENTS>\n { ++curr_lineno; }

"*)" { cool_yylval.error_msg = "Unmatched *)";
BEGIN(INITIAL);
return (ERROR); }

<INITIAL>"--" { BEGIN(INLINE_COMMENTS); }

<INLINE_COMMENTS>[^\n]* {}

<INLINE_COMMENTS>\n { ++curr_lineno; BEGIN(INITIAL); }

固定字符、单个字符

这类字符的处理比较简单,借用一些之前的定义一一对应即可。

具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
"<-"			{ return ASSIGN;}
"<=" { return LE; }
"+" { return int('+'); }
"-" { return int('-'); }
"*" { return int('*'); }
"/" { return int('/'); }
"<" { return int('<'); }
"=" { return int('='); }
"." { return int('.'); }
";" { return int(';'); }
"~" { return int('~'); }
"{" { return int('{'); }
"}" { return int('}'); }
"(" { return int('('); }
")" { return int(')'); }
":" { return int(':'); }
"@" { return int('@'); }
"," { return int(','); }

{DARROW} { return DARROW; }
{CLASS} { return (CLASS); }
{ELSE} { return (ELSE); }
{FI} { return (FI); }
{IF} { return (IF); }
{IN} { return (IN); }
{INHERITS} { return (INHERITS); }
{LET} { return (LET); }
{LOOP} { return (LOOP); }
{POOL} { return (POOL); }
{THEN} { return (THEN); }
{WHILE} { return (WHILE); }
{CASE} { return (CASE); }
{ESAC} { return (ESAC); }
{OF} { return (OF); }
{NEW} { return (NEW); }
{ISVOID} { return (ISVOID); }
{NOT} { return (NOT); }

{TYPEID} { cool_yylval.symbol=idtable.add_string(yytext);
return TYPEID;
}

{OBJECTID} { cool_yylval.symbol=idtable.add_string(yytext);
return OBJECTID;
}

[ \f\r\t\v]+ { }

{DIGIT}+ { cool_yylval.symbol=inttable.add_string(yytext);
return INT_CONST;
}

{INVALID} { cool_yylval.error_msg=yytext;
return ERROR;
}

{BOOL_TRUE} { cool_yylval.boolean=true;
return BOOL_CONST;
}

{BOOL_FALSE} {
cool_yylval.boolean=false;
return BOOL_CONST;
}

字符串处理

字符串处理主要需要注意的是转义字符和一些不合法状态的处理,具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
"\n"			{	curr_lineno++;	}

<INITIAL>\" { stringArray.clear(); BEGIN(STRING); }

<STRING>[^\\\"\n]* { stringArray.insert(stringArray.end(),yytext,yytext+yyleng); }

<STRING>\\ { BEGIN(STRING_TEMP); }

<STRING>\\\n { stringArray.push_back('\n'); ++curr_lineno; }

<STRING_TEMP>n { stringArray.push_back('\n'); BEGIN(STRING); }

<STRING_TEMP>b { stringArray.push_back('\b'); BEGIN(STRING); }

<STRING_TEMP>t { stringArray.push_back('\t'); BEGIN(STRING); }

<STRING_TEMP>f { stringArray.push_back('\f'); BEGIN(STRING); }

<STRING_TEMP>[^nbtf0] { stringArray.push_back(yytext[0]); BEGIN(STRING); }

<STRING_TEMP>0 { cool_yylval.error_msg="String contains null character.";
BEGIN(INITIAL);
return(ERROR);
}

<STRING>\n { cool_yylval.error_msg="Unterminated string constant.";
++curr_lineno;
BEGIN(INITIAL);
return(ERROR);
}

<STRING>\" { stringArray.insert(stringArray.end(),yytext,yytext+yyleng-1);
if(stringArray.size()>1024){
yylval.error_msg="String constant too long.";
BEGIN(INITIAL);
return (ERROR);
}
cool_yylval.symbol=stringtable.add_string(&stringArray[0],stringArray.size());
BEGIN(INITIAL);
return(STR_CONST);
}

<STRING,STRING_TEMP><<EOF>> { cool_yylval.error_msg="EOF in string constant";
BEGIN(INITIAL);
return(ERROR);
}

结果测试

运行make dotest,编译lexer并将当前目录下cool文件test.cl传递给这个lexer,得到测试的输出。为了判断结果是否正确,我们需要把我们的cool.flex结果和标准lexer的输出结果进行比较,通过checker工具检查,可以发现结果是一致的。

除了test.cl中的例子,还需要对其他情况进行测试,这部分写在test1.cl中,如下,测试了没有、字符串中包含\0、字符串长度超出限制(cool.flex中将长度限制为1024位)、EOF等情况,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(* my test *)  
*)
class Main inherits IO {
myString1 : String;
myString2: String;
myString3: String;

main() : SELF_TYPE {
myString1<-"fsgd
myString2<-"dfad \0 dfad";
myString3<-"vdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitoj vdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitojvdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitoj vdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitojvdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitoj vdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitojvdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitoj vdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitojvdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitoj vdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitojvdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitoj vdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitojvdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitoj vdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitojvdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitoj vdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitojvdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitoj vdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitojvdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitoj vdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitojvdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitoj vdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitojvdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitoj vdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitojvdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitoj vdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitojvdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitoj vdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitojvdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitoj vdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitojvdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitoj vdskhv jsdslkhlb elfjldasjv aljaljdvlk lkdvjsldkvjsad dlkhfaj reitoj";
}
myString1<-"123\0"
myString2<-"123\\0"
myString3

};
""

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!