永发信息网

词法扫描器 c c++

答案:1  悬赏:0  手机版
解决时间 2021-05-05 06:18

题2: 设计一个词法扫描器。词法扫描器的功能是输入源程序,输出单词符号。写出关键字集合和程序流程图。例如源程序为C语言。输入如下一段:
main() {
int a,b;
a = 10;
b = a + 20;
}
输出如图:
(2,”main”)
(5,”(“)
(5,”)“)
(5,”{“)
(1,”int”)
(2,”a”)
(5,”,”)
(2,”b”)
(5,”;”)
(2,”a”)
(4,”=”)
(3,”10”)
(5,”;”)
(2,”b”)
(4,”=”)
(2,”a”)
(4,”+”)
(3,”20”)
(5,”;”)
(5,” ) “ )

最佳答案
类似的词法分析器,你可以在这基础上加上一些功能。mlex.c内容如下:#include <stdio.h>#include <stdlib.h>#include <string.h>#include <conio.h>#include <assert.h>#include "lex.h"
char strToken[30]; //字符数组,存放构成单词符号的字符串。int lvalue; //单词的内码值keyword keywords[]={ "switch",$SWITCH, "case",$CASE, "if",$IF, "else",$ELSE, "do",$DO, "while",$WHILE, "stop",$STOP, "end",$END, "var",$VAR, "dim",$DIM, "char",$CHAR, 0,0,}; //关键字表symbol ctable[200]; //常数表symbol vtable[200]; //符号表(标识符)char inbuf[300]; //扫描缓冲区int sp; //起点指示器int ep; //扫描指示器int lineno; //行计数器FILE *fsrc;
char GetChar(){ //从扫描缓冲区第一个缓冲区从inbuf中读一个字符,实现双输入缓冲。 //[0]到inbuf[149],第二个缓冲区从inbuf[150]到inbuf[299], //每次从源文件读一个缓冲区大小的内容,分析完当前工作缓冲区内容时把源文件读入 //另一个缓冲区,另一个缓冲区成为工作缓冲区 int i = 0; char ch; if ((ep == 150)||(ep == 300)) { ep = ep%300; while (((inbuf[i+ep]=fgetc(fsrc))!=NULL) && (i<150)) i++; } ch = inbuf[ep]; ep++; return ch;}char GetBC(){ //从扫描缓冲区读字符,过滤空格、制表和回车符号 char ch = GetChar(); while ((ch==' ') || (ch=='\n') || (ch=='\t')) { if (ch=='\n') lineno++; ch = GetChar(); } return ch;}void Concat(char str[], char ch){ //将字符ch添加到符号串str的尾部 str[strlen(str)] = ch;}bool isLetter(char ch){ //判断ch是否字母 if (((ch>='A')&&(ch<='Z')) || ((ch>='a')&&(ch<='z'))) return true; return false;}bool isDigit(char ch){ //判断ch是否数字 if ((ch>='0')&&(ch<='9')) return true; return false;}
int Reserve(char* str){ //如str是保留字,返回保留字种别号 //否则返回0 int i = 0; while (keywords[i].code != 0) { if (strcmp(str,keywords[i].name) == 0) return keywords[i].code; i++; } return 0;}void Retract(){ //从扫描输入缓冲区回退一个字符 if (ep==0) ep = 299; else ep--;}
int InsertID(char *str){ //如符号表中已有str标识符,返回记录号, //否则将str加到符号表中,返回记录号 int i = 0; while ((vtable[i].number!=0) && (i<200)) { if (strcmp(str,vtable[i].name) == 0) return vtable[i].number; i++; } if (i<200) { vtable[i].number = i+1; strcpy(vtable[i].name, str); return vtable[i].number; } return 0;}int InsertConst(char *str){ //如常数表中已有str常数,返回记录号, //否则将str加到常数表中,返回记录号 int i = 0; while ((ctable[i].number!=0) && (i<200)) { if (strcmp(str,ctable[i].name) == 0) return ctable[i].number; i++; } if (i<200) { ctable[i].number = i+1; strcpy(ctable[i].name, str); return ctable[i].number; } return 0;}void ProcError(){ printf("%i 行有错误\n", lineno);}int Lex(){ //从扫描缓冲区中识别出一个单词,返回单词种别号, //构成的单词的符号串保留在strToken中, //单词的值保留在lvalue中。strToken和lvalue为全局变量。 int code; char ch;
memset(strToken, 0, 30); ch = GetBC(); sp = ep-1; lvalue = 0; if (isLetter(ch)) { while (isLetter(ch) || isDigit(ch)) { Concat(strToken, ch); ch = GetChar(); } Retract(); code = Reserve(strToken); if (code == 0) { lvalue = InsertID(strToken); return $ID; } return code; } else if (isDigit(ch)) { while (isDigit(ch)) { Concat(strToken, ch);ch = GetChar(); } if (ch == '.' ) { Concat(strToken, ch); if(!isDigit(GetChar())) {ProcError(); return $END;} Retract(); while(isDigit(GetChar())) { Retract(); Concat(strToken,GetChar()); Retract(); GetChar(); } InsertConst(strToken); return $FLOAT; } Retract(); lvalue = InsertConst(strToken); return $INT; }

else if (ch == '=') { ch = GetChar(); if (ch == '=') return $EQ; Retract(); return $ASSIGN; } else if (ch == '+') return $PLUS; else if (ch == ';') return $SEMICOLON; else if (ch == '(') return $LPAR; else if (ch == ')') return $RPAR; else if (ch == '{') return $LBRACE; else if (ch == '}') return $RBRACE;
else if (ch == '*') { ch = GetChar(); if (ch == '*') return $POWER; Retract(); return $STAR; } else if (ch == EOF) return $END; else { ProcError(); return $END; }}void main(){ token aToken; int i = 0; char strName[256]; FILE *fcon = fopen("const.txt","w+"); FILE *ftoken = fopen("token.txt","w+"); FILE *fsym = fopen("symbol.txt","w+"); printf("请输入源文件名(enter结束):\n"); scanf("%s",strName); fsrc = fopen(strName,"r"); if (fsrc == NULL) { printf("找不到源文件src.txt\n"); exit(1); } if ((ftoken == NULL) || (fcon == NULL) || \ (fsym == NULL)) { printf("不能创建输出文件const.txt,token.txt,symbol.txt\n"); exit(1); } while ((i<150) && ((inbuf[i]=fgetc(fsrc)) != EOF)) i++;
ep = 0; lineno = 1; aToken.label = 0; aToken.code = Lex(); aToken.addr = lvalue; printf("单词序列:\n"); while (aToken.code != $END) { //单词输出到文件 fprintf(ftoken, "(%3d,%3d)", aToken.code, aToken.addr); //单词输出到屏幕 printf("(%3d,%3d) ", aToken.code, aToken.addr); aToken.label++; aToken.code = Lex(); aToken.addr = lvalue; } i = 0; printf("\n符号表:\n"); while (vtable[i].number != 0) { fprintf(fsym, "(%3d,%s)", vtable[i].number, vtable[i].name); printf("(%3d,%s)", vtable[i].number, vtable[i].name); i++; } i = 0; printf("\n常数表:\n"); while (ctable[i].number != 0) { fprintf(fcon, "(%3d,%s)", ctable[i].number, ctable[i].name); printf("(%3d,%s)", ctable[i].number, ctable[i].name); i++; } fclose(fsrc); fclose(fsym); fclose(fcon); fclose(ftoken); printf("\n词法分析结束,按任意键\n"); getch();}

lex.h头文件内容如下:typedef struct token{ int label; char name[30];//组成单词的字符串 int code; int addr;}token;
typedef struct symbol{ int number; char name[30];//组成标识符或常数的字符串} symbol;
typedef struct keyword{ char name[30]; //组成关键字的字符串 int code;} keyword;
//定义一些常量enum TVAL {$WHILE=1,$IF,$ELSE,$SWITCH,$CASE,$DO,$STOP,$END,$ID,$INT,$EQ,$ASSIGN,$PLUS, \ $STAR,$POWER,$COMMA,$LPAR,$RPAR,$SEMICOLON,$LBRACE, \ $RBRACE,$VAR,$DIM,$FLOAT,$CHAR};
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
学堂怎么得积分
关于识别天气的谚语
有没有较好的初中习题网,谢谢哦。
最后一段跳舞的音乐叫什么
推荐一些好听的日韩歌曲
怎样祛除身上或脸上的黑痣?
谁知道常州2010年7月30日的最高气温和最低气
男友的家人对我很不是很满意,怎么办。?
安庆医药高等专科学校室内车库这个地址在什么
17天送戒指?
自己有一点点白发,想买染发膏到发廓染,大概
你给的美好的明天 什么歌
为什么最近家里的无线网络总是不稳定?
DNF魔法师武器哪些有光,火,冰属性的啊?
吃结核药以后我的皮肤变黑了,都说是吡嗪酰胺
推荐资讯
当你看见你女朋友和他前男朋友说些伤你心的话
描写陪伴的古诗词
和亲人相聚开心的句
天域生物我想知道这个在什么地方
心律失常怎么彻底根治?
看图这是什么钱!!!
本人寻6个字的情侣网名,要求含义深点,悲伤
空心方阵是什么样子
两根绳子怎么连在一起打死结
江苏宜兴移动宽带套餐资费是怎样的?知道的和
看看这电脑具体值多少钱才配的
yeswhatyou的英语是什么
正方形一边上任一点到这个正方形两条对角线的
阴历怎么看 ?