实验一词法分析
班级:计科12-3 学号:08123282 姓名:樊鑫 实验目的
学会针对DFA转换图实现相应的高级语言源程序。 深刻领会状态转换图的含义,逐步理解有限自动机。
掌握手工生成词法分析器的方法,了解词法分析器的内部工作原理。 实验内容
TINY计算机语言的编译程序的词法分析部分实现。
从左到右扫描每行该语言源程序的符号,拼成单词,换成统一的内部表示(token)送给语法分析程序。
为了简化程序的编写,有具体的要求如下: 数仅仅是整数。
空白符仅仅是空格、回车符、制表符。 代码是自由格式。
注释应放在花括号之内,并且不允许嵌套
实验要求
要求实现编译器的以下功能:
按规则拼单词,并转换成二元式形式 删除注释行
删除空白符 (空格、回车符、制表符)
列表打印源程序,按照源程序的行打印,在每行的前面加上行号,并且打印出每行包含的记号的二元形式 发现并定位错误
,词法分析进行具体的要求:
记号的二元式形式中种类采用枚举方法定义;其中保留字和特殊字符是每个都一个种类,标示符自己是一类,数字是一类;单词的属性就是表示的字符串值。
词法分析的具体功能实现是一个函数GetToken(),每次调用都对剩余的字符串分析得到一个单词或记号识别其种类,收集该记号的符号串属性,当识别一个单词完毕,采用返回值的形式返回符号的种类,同时采用程序变量的形式提供当前识别出记号的属性值。这样配合语法分析程序的分析需要的记号及其属性,生成一个语法树。
标示符和保留字的词法构成相同,为了更好的实现,把语言的保留字建立一个表格存储,这样可以把保留字的识别放在标示符之后,用识别出的标示符对比该表格,如果存在该表格中则是保留字,否则是一般标示符。 实验程序
#include #include #include #include #include using namespace std;enum WordType {WRONG, NUMBER, BIAOSHI, IF, THEN, ELSE, END, REPEAT, UNTIL, //9
READ, WRITE, PLUS, SUBTRACT, MULTIPLY, DIVIDEY, EQUAL, LESSTHAN, COLON,//18 ASSIGNMENT, LINE_FEED, SPACE, TAB, BRACKET_L, BRACKET_R}; //24 enum CharType {ALPHABET, OTHER};
enum WrongType {ZERO, ALP_NUM, NUM_ALP, UNLEAGL_S, NO_MATCH, UNKNOW};
char *Words [] = {\"wrong\\"read\\":=\\ typedef struct { char *str; int wordtype; }Two;
char ArrayChar[100], cbuffer; int i=-1, numline = 1, wordtype; string LineChar; Two T;
ifstream fp(\"source.txt\int main () { void HandleAlphabet(); void HandleNumber (); void HandleOther (); if (!fp) cout<<\"文件打开错误!\"<if(cbuffer == '\\n')//忽略换行符 { cout << \"第\" << numline << \" 行所有字符:\" << LineChar << endl; numline++; LineChar = \"\"; fp.get(cbuffer); }else if (cbuffer == ' ')//忽略空字符 { LineChar += \" \"; fp.get(cbuffer); }
else if (cbuffer == ' ')//忽略制表符 { LineChar += \" \"; fp.get(cbuffer); }
else if (isalpha(cbuffer))//判断是否是字母 { HandleAlphabet (); }
else if (isdigit(cbuffer))//判断是否是数字 { HandleNumber (); }
else //其他字符 HandleOther (); i = -1; } }
cout << \"第\" << numline << \" 行所有字符:\" << LineChar << endl; fp.close (); system (\"pause\"); return 0; }
int Match(char str[], int chartype)//查找匹配的字符 { int i; switch (chartype) { case ALPHABET: for (i = IF; i <= WRITE; i++) { if (strcmp(Words[i],str) == 0) return i; } case OTHER: for (i = PLUS; i <= ASSIGNMENT; i++) { if (strcmp(Words[i],str) == 0) return i; } } return WRONG; }
void TypeWrong (int wrongtype, int line)
{
switch (wrongtype) {
case ZERO: break; case ALP_NUM: cout << \"字母后面不能紧跟数字!\"; break; case NUM_ALP:
cout << \"数字后面不能紧跟字母!\"; case UNLEAGL_S: break;
cout << \"非法特殊符号!\"; break; case NO_MATCH: cout << \"没有与第\" << line << \"行\"\"匹配的\"\"!\"; break; default: cout << \"其它类型错误!\"; break; } }
Two ConvertTwo (char str[], int wordtype, int wrongtype, int numline, int line)//进行二元转换 { Two T; T.wordtype = wordtype; T.str = str; cout << setiosflags (ios::left) << setw (6) << numline << \"(\"; cout << setiosflags (ios::left) << setw (10) << T.wordtype << \ cout << setiosflags (ios::left) << setw (20) << T.str << \")\"; if (T.wordtype == WRONG) TypeWrong (wrongtype, line); cout << endl; return T; }
void HandleAlphabet ()//首字符为字母时的处理 { bool mark = true; while(!fp.eof() && isalpha(cbuffer)) { ArrayChar[++i]=cbuffer; fp.get(cbuffer); } if (isdigit (cbuffer))
{ mark = false; while(!fp.eof() && (isalpha(cbuffer)||isdigit(cbuffer))) { ArrayChar[++i]=cbuffer; fp.get(cbuffer); } } ArrayChar[i+1]='\\0'; LineChar += ArrayChar; if (mark) { wordtype = Match(ArrayChar, ALPHABET); T = ConvertTwo(ArrayChar,(BIAOSHI > wordtype ? BIAOSHI : numline, numline); } else T = ConvertTwo(ArrayChar,WRONG, ALP_NUM, numline, numline); }
void HandleNumber ()//首字符为数字时的处理 { bool mark = true; while (!fp.eof() && isdigit(cbuffer)) { ArrayChar[++i]=cbuffer; fp.get(cbuffer); } if (isalpha(cbuffer)) { mark = false; while(!fp.eof() && (isalpha(cbuffer)||isdigit(cbuffer))) { ArrayChar[++i]=cbuffer; fp.get(cbuffer); } } ArrayChar[i+1]='\\0'; LineChar += ArrayChar; if (mark) T = ConvertTwo(ArrayChar, NUMBER, ZERO, numline, numline); else T = ConvertTwo(ArrayChar,WRONG, NUM_ALP, numline, numline); }
void DeleteNote ()//删除注释
wordtype), ZERO, { { }
int record = numline;
while (!fp.eof() && cbuffer != '}') { fp.get(cbuffer); while (!fp.eof() && cbuffer != '}') { if (cbuffer == '\\n') ArrayChar [i + 1] = '\\0'; LineChar += ArrayChar; cout << \"第\" << numline << \" 行所有字符:\" << LineChar << endl; LineChar = \"\"; numline++; i = -1; fp.get(cbuffer); } ArrayChar[++i]=cbuffer; fp.get(cbuffer); } ArrayChar[i + 1]='\\0'; if (cbuffer == '}') { ArrayChar [++i] = '}'; ArrayChar[i + 1]='\\0'; T = ConvertTwo(\BRACKET_R, ZERO, numline, numline); } else { T = ConvertTwo(\"\ } }
LineChar += ArrayChar; fp.get(cbuffer);
void HandleOther ()//字符为特殊字符时的处理 { ArrayChar [++i] = cbuffer; if (ArrayChar [i] == '{')//删除注释 { ConvertTwo(\"{\ DeleteNote (); } else//其他字符
{ fp.get(cbuffer); while (!fp.eof() && cbuffer != '\\n' && cbuffer != ' ' && cbuffer != ' ' && !isalpha(cbuffer) && !isdigit(cbuffer)) { ArrayChar [++i] = cbuffer; fp.get(cbuffer); } ArrayChar[i + 1]='\\0'; wordtype = Match(ArrayChar, OTHER); LineChar += ArrayChar; T = ConvertTwo(ArrayChar, wordtype, (wordtype > 0 ? 0: UNLEAGL_S), numline, numline); } }
实验结果
实验体会
通过本次实验学会了针对DFA转换图实现相应的高级语言源程序,并且深刻领会了状态转换图的含义,逐步理解有限自动机,同时掌握手工生成词法分析器的方法,了解词法分析器的内部工作原理。