2020-10-29

实验一 TINY语言的词法分析

一、实验目的
(评价依据,描述是否准确到位)
利用第三方的lex工具构造tiny语言的词法分析器(扫描器)并使得构造出的扫描器能够读入教材样例中给出的tiny语言的示例代码,分解成token输出。
学习如何使用flex,配置它的环境并使用。
学习如何编写正则表达式和tiny语法结构。
学习如何使用工具获取tokens。

二、实验设计
(评价依据实验方案设计是否合理)

由词法分析器的工作方式可以知道,实验需要做到:理解并使用tiny语言,使用构造出的扫描器,能够读入教材样例中给出的tiny语言的示例代码,分解成token输出。,经编译后在c编译器上使用和调用。
三、内容和步骤
1.配置环境:
配置环境变量:右击此电脑->属性->高级系统设置->“高级”一栏下的环境变量 在系统变量Path中增加win_flex_bison的路径。直接在桌面新建一个test文件夹,里面创建文本文件后改名lex.l打开cmd,同样方法获得路径,输入cd :路径,比如我cd C:\Users\Administrator\Desktop\test 回车后进入。没有报错,文件夹出现新文件,说明配置成功

2.代码:

%{
#include "stdio.h"
#include "stdlib.h"
%}

INT_DEX [1-9][0-9]*|[0]
INT_HEX [0][Xx]([1-9][0-9]*|[0])
INT_OCT [0][0-7]
FLOAT [0-9]*[.][0-9]+([eE][+-]?[0-9]*|[0])?f?
SEMI [;]
COMMA [,]
ASSIGNOP [=]
RELOP [>]|[<]|[>][=]|[<][=]|[=][=]|[!][=](^[=])
PLUS [+]
MINUS [-]
STAR [*]
DIV [/]
AND [&][&]
OR [|][|]
DOT [.]
NOT [!]
TYPE int|float
LP \(
RP \)
LB \[
RB \]
LC \{
RC \}
STRUCT struct
RETURN return
IF if
ELSE else 
WHILE while
SPACE [ \n\t]
ID [a-zA-Z_][a-zA-Z_0-9]*
/*end of definition*/
%%
{SEMI} {
    printf("get semmi : %s\n", yytext);

}

{COMMA} {
    printf("get comma : %s\n", yytext);
}
{ASSIGNOP} {
    printf("get assignop : %s\n", yytext);
}

{INT_DEX} |
{INT_HEX} |
{INT_OCT} {
    printf("get an integer: %s\n", yytext);
}

{FLOAT} {
    printf("get a float: %s\n", yytext);
}

{PLUS} | 
{MINUS} |
{DIV} |
{STAR} {
    printf("get an operator: %s\n", yytext);
}

{RELOP} {
    printf("get a relop: %s\n", yytext);
}

{AND} |
{OR} |
{NOT} {
    printf("get a logic operator: %s\n", yytext);
}

{DOT} {
    printf("get a dot: %s\n", yytext);
}
{STRUCT} |
{RETURN} |
{IF} |
{ELSE} |
{WHILE} {
    printf("get keyword: %s\n", yytext);
}

{TYPE} {
    printf("get type: %s\n", yytext);
}

{LP} |
{RP} |
{LB} |
{RB} |
{LC} |
{RC} {
    printf("get brackets : %s\n", yytext);
}

{SPACE} |
. {
/*ABANDON THESE CHARACTORS*/
}

{ID} {
    printf("get an ID: %s\n", yytext);
}
%%
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;
}

3.结果:

测试如下案例(书本23页):
{ sample progarm
in tiny language -
computer factorial
}
read x;{ input an integer }
if x < 0 then { don’t compute if x <= 0}
fact := 1;
repeat
fact := fact * x;
x := x - 1
until x = 0;
write fact {output factorial of x}
End

四、实验结论:
1 理论基础(评价依据 理论知识非常清楚)
TINY的程序结构是一个由分号分隔开的语句序列。另外,它既无过程也无声明。所有的变量都是整型变量,通过对其赋值可较轻易地声明变量(类似FORTRAN或BASIC)。它只有两个控制语句:i f语句和repea语句,这两个控制语句本身也可包含语句序列。If语句有一个可选的else部分且必须由关键字end结束。除此之外,read语句和write语句完成输入/输出。在花括号中可以有注释,但注释不能嵌套。
TINY的表达式也局限于布尔表达式和整型算术表达式。布尔表达式由对两个算术表达式的比较组成,该比较使用<与=比较算符。算术表达式可以包括整型常数、变量、参数以及4个整型算符+、-、*、/,此外还有一般的数学属性。布尔表达式可能只作为测试出现在控制语句中——而没有布尔型变量、赋值或I / O。
本次书上的测试案例:
{ sample progarm
in tiny language -
computer factorial
}
read x;{ input an integer }
if x < 0 then { don’t compute if x <= 0}
fact := 1;
repeat
fact := fact * x;
x := x - 1
until x = 0;
write fact {output factorial of x}
End

flex的语法被分为三个部分:
{definitions}/定义段
%%
{rules}/规则段
%%
{user subroutines}/代码段

definitions:LABEL REGULAR_EXPRESSION
LABEL是这里类字符串的名称,REGULAR_EXPRESSION则是匹配这种字符串的正则表达式。
正则表达式的语法:
| 或
[] 括号中的字符取其一

  • a-z表示ascii码中介于a-z包括a.z的字符
    \ 转义(flex不能识别除字母外的字符)
  • 0或多个字符
    ? 0或1个字符
  • 1或多个字符
    ^ 除此之外的其余字符
    . 除\n外的所有字符,等价于^\n

2、分析和总结(评价依据:是否能够对实验结果作出完整和准确的描述,是否能够捕捉到实验中的各种现象,是否有强的信息综合能力,是否能得出正确的结论。)
整个实验的流程其实很清楚:
(1)环境配置
(2)编写.l文件,并利用flex,devc++编译
(3)运行并输入tiny例子,完成分析
本实验的唯一难点在于编写.l文件,文件分为定义段,规则段,代码段三部分。
{definitions}/定义段
%%
{rules}/规则段
%%
{user subroutines}/代码段
规则段用于提取,代码段用于c程序的运行。
在正则表达式上会有些难度,规则段其实按照例子来就很简单,代码段搞不懂说明c语言没有掌握透彻。
3、对工具的评价(优缺点及其局限性的总结)
lex是一个产生词法分析器, Lex常常与yacc语法分析器产生程序。
Lex读进一个代表词法分析器规则的输入字符串流,然后输出以C语言实做的词法分析器源代码。有名的Lex公开源代码版本是flex,代表"快速的词法分析器"。因此优点在于速度快,但是必然会失去部分稳定性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值