实验要求
读懂exam1.l和exam2.l两个例子,使用flex工具将exam1.l和exam2.l编译并调试通过。并且修改exam2.l,在其基础上增加如下记号:
左右大小括号:{ } ( )
将关系算符改写成C中的形式
分号、赋值号:; =
关键字:if else
双斜线表示的注释://
算术运算符号:+ - * /
将标识符改为可含有下划线,并且可以以下划线开头
将注释内容忽略
核心代码
%{
#include <stdio.h>
#define LT 1
#define LE 2
#define GT 3
#define GE 4
#define EQ 5
#define NE 6
#define WHILE 18
#define DO 19
#define ID 20
#define NUMBER 21
#define RELOP 22
#define NEWLINE 23
#define ERRORCHAR 24
#define LEFTPARENTHESIS 25 /*小括号*/
#define RIGHTPARENTHESIS 26 /*小括号*/
#define LEFTBRACE 27 /*大括号*/
#define RIGHTBRACE 28 /*大括号*/
#define SEMICOLON 29 /*分号*/
#define ASSIGNMENT 30 /*赋值号*/
#define IF 31
#define ELSE 32
#define ARITHMETIC 33 /*算术运算*/
#define STRING 34 /*字符串*/
%}
delim [ \t \n]
ws {delim}+
letter [A-Za-z]
digit [0-9]
id ({letter}|_)({letter}|{digit}|_)*
number {digit}+(\.{digit}+)?(E[+-]?{digit}+)?
escchar \\({letter}|{digit}|[\\"'])
string \"([^\\"']|{escchar})*\"
/*匹配的字符:非特况;是特况?是\,是转义*/
/* 状态(或条件)定义可以定义在这里
* INITIAL是一个默认的状态,不需要定义
*/
%s COMMENT
%s LINECOMMENT
%%
<INITIAL>"/*" { BEGIN COMMENT;}
<COMMENT>.|\n { ;}
<COMMENT>"*/" { BEGIN INITIAL;}
<INITIAL>"//" { BEGIN LINECOMMENT;}
<LINECOMMENT>. { ;}
<LINECOMMENT>\n { BEGIN INITIAL;}
/* ECHO是一个宏,相当于 fprintf(yyout, "%s", yytext)*/
<INITIAL>{string} { return (STRING);}
<INITIAL>{ws} {;}
<INITIAL>while { return (WHILE);}
<INITIAL>do { return (DO);}
<INITIAL>if { return (IF);}
<INITIAL>else { return (ELSE);}
<INITIAL>{id} { return (ID);}
<INITIAL>{number} { return (NUMBER);}
<INITIAL>"<" { return (RELOP);}
<INITIAL>"<=" { return (RELOP);}
<INITIAL>"==" { return (RELOP);}
<INITIAL>"!=" { return (RELOP);}
<INITIAL>">" { return (RELOP);}
<INITIAL>">=" { return (RELOP);}
<INITIAL>"(" { return (LEFTPARENTHESIS);}
<INITIAL>")" { return (RIGHTPARENTHESIS);}
<INITIAL>"{" { return (LEFTBRACE);}
<INITIAL>"}" { return (RIGHTBRACE);}
<INITIAL>";" { return (SEMICOLON);}
<INITIAL>"=" { return (ASSIGNMENT);}
<INITIAL>"+"|"-"|"*"|"/" { return (ARITHMETIC);}
<INITIAL>. { return ERRORCHAR;}
%%
int yywrap (){
return 1;
}
void writeout(int c){
switch(c){
case ERRORCHAR: fprintf(yyout, "(ERRORCHAR, \"%s\") ", yytext);break;
case RELOP: fprintf(yyout, "(RELOP, \"%s\") ", yytext);break;
case WHILE: fprintf(yyout, "(WHILE, \"%s\") ", yytext);break;
case DO: fprintf(yyout, "(DO, \"%s\") ", yytext);break;
case NUMBER: fprintf(yyout, "(NUM, \"%s\") ", yytext);break;
case ID: fprintf(yyout, "(ID, \"%s\") ", yytext);break;
case NEWLINE: fprintf(yyout, "\n");break;
case LEFTPARENTHESIS: fprintf(yyout, "(LEFTPARENTHESIS, \"%s\") ", yytext);break;
case RIGHTPARENTHESIS: fprintf(yyout, "(RIGHTPARENTHESIS, \"%s\") ", yytext);break;
case LEFTBRACE: fprintf(yyout, "(LEFTBRACE, \"%s\") ", yytext);break;
case RIGHTBRACE: fprintf(yyout, "(RIGHTBRACE, \"%s\") ", yytext);break;
case SEMICOLON: fprintf(yyout, "(SEMICOLON, \"%s\") ", yytext);break;
case ASSIGNMENT: fprintf(yyout, "(ASSIGNMENT, \"%s\") ", yytext);break;
case IF: fprintf(yyout, "(IF, \"%s\") ", yytext);break;
case ELSE: fprintf(yyout, "(ELSE, \"%s\") ", yytext);break;
case ARITHMETIC: fprintf(yyout, "(ARITHMETIC, \"%s\") ", yytext);break;
case STRING: fprintf(yyout, "(STRING, %s) ", yytext);break;
default:break;
}
return;
}
int main (int argc, char ** argv){
int c,j=0;
if (argc>=2){
if ((yyin = fopen(argv[1], "r")) == NULL){
printf("Can't open file %s\n", argv[1]);
return 1;
}
if (argc>=3){
yyout=fopen(argv[2], "w");
}
}
while (c = yylex()){
writeout(c);
j++;
if (j%5 == 0) writeout(NEWLINE);
}
if(argc>=2){
fclose(yyin);
if (argc>=3) fclose(yyout);
}
return 0;
}