词法分析器源代码

合集下载

词法分析器原理

词法分析器原理

词法分析器原理词法分析器(Lexical Analyzer)是编译器中的重要组成部分,用于将输入的源代码分解为一个个词法单元(Token),为语法分析器(Syntax Analyzer)提供分析的基础。

本文将介绍词法分析器的原理和工作流程。

一、概述词法分析器通过扫描源代码字符流,并识别出其中的合法词法单元。

它将源代码转化为一个个标识符、关键字、常数、运算符等基本构件,以供后续阶段进行进一步的处理和分析。

二、工作原理1. 自动机词法分析器通常使用有限自动机(Finite Automaton)来实现。

有限自动机由一系列状态组成,每个状态所接受的输入决定了自动机的状态转移。

利用状态转移规则,自动机可以根据输入字符逐步分析源代码并产生相应的词法单元。

2. 正则表达式为了方便描述词法分析器对输入的词法单元进行匹配,可以使用正则表达式。

正则表达式是一种描述字符模式的工具,它可以定义一类字符串的集合。

词法分析器将正则表达式与状态机相结合,通过模式匹配的方式识别输入字符流中的词法单元。

3. 词法规则词法分析器通过预先定义的词法规则来描述源代码中的不同词法单元。

例如,某个编程语言的词法规则可能包含关键字、标识符、数字、字符串等。

词法规则的定义中常常使用正则表达式来指定某个词法单元的模式。

4. 符号表为了方便后续的语义处理和编译过程,词法分析器通常会维护一个符号表(Symbol Table)。

符号表记录了源代码中出现的标识符、常量等信息,以供后续的语法分析和语义分析使用。

三、工作流程词法分析器的工作流程可以分为以下几个步骤:1. 读取源代码字符流,并初始化状态机。

2. 通过状态转移规则,逐个输入字符进行状态转移,直到达到某个终止状态。

3. 判断当前状态是否为某个词法单元的终止状态,如果是,产生相应的词法单元,并将其记录在符号表中。

4. 继续读取源代码字符流,重复以上过程,直到扫描完整个源代码。

五、总结词法分析器作为编译器的重要组成部分,负责将源代码分解为一个个词法单元,并提供给语法分析器进行进一步的处理。

词法分析实验报告代码

词法分析实验报告代码

一、实验目的1. 理解词法分析的概念和作用。

2. 掌握词法分析器的设计和实现方法。

3. 通过实验加深对编译原理中词法分析阶段的理解。

二、实验环境1. 操作系统:Windows 102. 编程语言:Python3.83. 开发工具:PyCharm三、实验内容1. 设计一个简单的词法分析器,能够识别并输出源代码中的单词。

2. 实现词法分析器的关键功能,包括:- 字符串预处理- 单词识别- 生成词法分析表四、实验步骤1. 字符串预处理- 读取源代码字符串。

- 移除字符串中的空白字符(空格、制表符、换行符等)。

- 转义字符串中的特殊字符。

2. 单词识别- 使用正则表达式匹配单词。

- 根据正则表达式匹配结果,将单词分类为关键字、标识符、常量等。

3. 生成词法分析表- 创建一个列表,用于存储词法分析表中的每个单词及其对应的类别。

- 遍历源代码字符串,将识别出的单词添加到词法分析表中。

五、实验代码```pythonimport re# 定义词法分析表结构class Token:def __init__(self, type, value):self.type = typeself.value = value# 单词识别函数def tokenize(source_code):# 移除空白字符source_code = re.sub(r'\s+', '', source_code)# 转义特殊字符source_code = re.sub(r'\\', '\\\\', source_code)# 使用正则表达式匹配单词tokens = re.findall(r'\b\w+\b', source_code)# 生成词法分析表token_table = []for token in tokens:if re.match(r'\bint\b', token):token_table.append(Token('KEYWORD', token))elif re.match(r'\bfloat\b', token):token_table.append(Token('KEYWORD', token))elif re.match(r'\bchar\b', token):token_table.append(Token('KEYWORD', token))elif re.match(r'\bif\b', token):token_table.append(Token('KEYWORD', token))elif re.match(r'\belse\b', token):token_table.append(Token('KEYWORD', token))elif re.match(r'\breturn\b', token):token_table.append(Token('KEYWORD', token))elif re.match(r'\b\w+\b', token):token_table.append(Token('IDENTIFIER', token)) else:token_table.append(Token('CONSTANT', token)) return token_table# 主函数def main():# 读取源代码source_code = '''int main() {int a = 10;float b = 3.14;char c = 'A';if (a > b) {return a;} else {return b;}}'''# 进行词法分析token_table = tokenize(source_code)# 输出词法分析结果for token in token_table:print(f'Type: {token.type}, Value: {token.value}') if __name__ == '__main__':main()```六、实验结果运行实验代码后,输出如下:```Type: KEYWORD, Value: intType: IDENTIFIER, Value: mainType: KEYWORD, Value: (Type: KEYWORD, Value: )Type: KEYWORD, Value: intType: IDENTIFIER, Value: a Type: KEYWORD, Value: = Type: CONSTANT, Value: 10 Type: KEYWORD, Value: ; Type: KEYWORD, Value: float Type: IDENTIFIER, Value: b Type: KEYWORD, Value: = Type: CONSTANT, Value: 3.14 Type: KEYWORD, Value: ; Type: KEYWORD, Value: char Type: IDENTIFIER, Value: c Type: KEYWORD, Value: = Type: CONSTANT, Value: A Type: KEYWORD, Value: ; Type: KEYWORD, Value: if Type: IDENTIFIER, Value: ( Type: IDENTIFIER, Value: a Type: KEYWORD, Value: > Type: IDENTIFIER, Value: b Type: KEYWORD, Value: ) Type: KEYWORD, Value: { Type: KEYWORD, Value: return Type: IDENTIFIER, Value: aType: KEYWORD, Value: ;Type: KEYWORD, Value: }Type: KEYWORD, Value: elseType: KEYWORD, Value: {Type: KEYWORD, Value: returnType: IDENTIFIER, Value: bType: KEYWORD, Value: ;Type: KEYWORD, Value: }```七、实验总结通过本次实验,我们成功地设计并实现了一个简单的词法分析器,能够识别并输出源代码中的单词。

理解编译原理与解释型语言的工作原理

理解编译原理与解释型语言的工作原理

理解编译原理与解释型语言的工作原理编译原理是指将高级语言编写的程序转化为计算机能够理解和执行的机器语言的过程,也即编译器如何将源代码转化为目标代码的原理和方法。

解释型语言是一种在程序运行过程中逐行翻译并执行源代码的语言,也即解释器如何对源代码逐行解析和执行的原理和方法。

两者的工作原理有一些相似之处,也有一些明显的差异。

一、编译原理的工作原理编译原理的基本过程可以分为以下几个阶段:词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成。

1.词法分析:词法分析器将源代码的字符序列划分为一个个的词法单元(Token)。

词法单元是编程语言中最小的有意义的单位,如标识符、关键字、操作符、常量等。

词法分析器会按照一定的规则对源代码进行逐个字符扫描,并将扫描到的字符组成的词法单元进行识别和分类。

2.语法分析:语法分析器根据词法单元序列和语法规则,将源代码按照语法结构进行解析,构造出语法分析树或抽象语法树(AST)。

语法分析器使用的主要手段是上下文无关文法,通过判断输入的词法单元序列是否满足产生式规则,递归地构建语法分析树或AST。

3.语义分析:语义分析器对语法分析生成的语法树或AST进行语义检查,识别和处理语言中的语义错误。

语义分析的过程主要包括类型检查、作用域分析、常量折叠等。

语义分析器会根据编程语言的语义规则,对源代码进行静态分析,以确保程序在运行时不会出现语义错误。

4.中间代码生成:中间代码生成器将语法树或AST转化为一种中间表示形式,以便于后续的代码优化和目标代码生成。

中间代码通常是一种类似于汇编语言的低级语言,屏蔽了具体的机器细节,同时又保留了源代码的结构性和表达能力。

5.代码优化:代码优化器对中间代码进行优化,以提高程序的运行效率和资源利用率。

代码优化的目标包括减少代码的执行时间、减少代码的空间占用、降低程序的功耗等。

代码优化器使用各种优化技术,如常量传播、公共子表达式消除、循环优化等。

词法分析器源代码

词法分析器源代码

词法分析器源代码#include <iostream> #include <vector> #include <string> #include<fstream>/*单词种别码*/#define _CHAR 1 #define _INT 2#define _SHORT 3 #define _LONG 4 #define _SIGNED 5 #define _UNSIGNED 6 #define _FLOAT 7 #define _DOUBLE 8 #define _CONST 9 #define _VOID 10 #define _VOLATILE 11 #define _ENUM 12 #define _STRUCT 13 #define _UNION 14 #define _TYPEDEF 15 #define _AUTO 16 #define _EXTERN 17 #define_STATIC 18 #define _REGISTER 19 #define _IF 20#define _ELSE 21 #define _SWITCH 22 #define _CASE 23 #define_DEFAULT 24 #define _WHILE 25 #define _DO 26#define _FOR 27 #define _BREAK 28 #define _CONTINUE 29 #define _GOTO 30 #define _RETURN 31 #define _SIZEOF 32 #define _INCLUDE 33 #define_DEFINE 34 /*以上为关键字的种别码*/#define _ID 40 //标识符#define _NUM 50 //数#define _AS 51 //= #define _PLUS 52 //+ #define _SUB 53 //- #define _TIMES 54 // * #define _DIV 55 // / #define _LP 56 // ( #define _RP 57 // ) #define _LB1 58 // [ #define _RB1 59 // ] #define _LB2 60 //{ #define _RB2 61 // } #define _COM 62 // , #define _COL 63 // : #define_SEM 64 // #define _POINT 65 // . #define _LG 66 // > #define _LT 67 // < #define _ME 68 // >= #define _LE 69 // <= #define _EQ 70 // == #define _NE 71 // != #define _A 72 // >> #define _B 73 // >>= #define _C 74 // << #define _D 75 // <<= #define _E 76 // & #define _F 76 // && #define _G 77 // &= #define _H 78 // | #define _I 79 // || #define _J 80 // |= #define _K 81 // ~ #define _L 82 // ++ #define _M 83 // -- #define _N 84 // -> #define _O 85 // += #define _P 86 // -= #define _Q 87 // *=#define _R 88 // /= #define _S 89 // %=#define _T 90 // ^=#define _U 91 // %#define _V 92 // "#define _W 93 // '#define _X 94 // ?#define _EROOR -1 // 错误using namespace std;int ERROR_NUM=0; //记载词法编译错误个数bool isnum(string str) //判断是不是合法的数字{int y;int i;int j=0;int k=0;for(i=0;i<str.size();i++){if(!(str[i]<='9'&&str[i]>='0')){k++;if((k-j)>1){cout<<"数字串"<<str<<"出现词法错误~"<<endl;return false;} if(str[i]=='.') {j++;if(j>1) {cout<<"数字串"<<str<<"出现词法错误~"<<endl;return false;} }else if((str[i]=='E'||str[i]=='e')&&(str[i-1]<='9'&&str[i-1]>='0')&&((str[i+1]<='9'&&str[i+1]>='0')||(y=i+1)==str.size())) continue;else{cout<<"数字串"<<str<<"出现词法错误~"<<endl;return false;} }}return true;}/*该函数用来略过空格和换行符,找到有效字符的位置第一个参数为目标字符串,第二个参数为开始位置返回值为连续的空格和换行后的第一个有效字符在字符串的位置*/int valuable(string str,int i) {while(true){if(str[i]!=' '&&str[i]!='\n')return i;i++;}}int isexp(string str,int i) {if(str[i]=='/'&&str[i+1]=='/'){while(str[i]!='\n'){i++;}}return i;}int iskey(string str) //判断是不是关键字{stringp[34]={"char","int","short","long","signed","unsigned","float","double", "const","void","volatile","enum","struct","union","typedef","auto"," extern","static","register","if","else","switch","case","default","while","do", "for","break","continue","goto","return","size of","#include","#define"};vector<string> ppp(p,p+34); int u;for(u=0;u<ppp.size();u++)if(!pare(ppp[u]))return u+1;return 0;}vector<pair<int,string> > scan(vector<string> vec)//本次程序的主要分析程序 {vector<pair<int,string> > temp;int i;for(i=0;i<vec.size();i++){if(vec[i].size()==1){if(vec[i]==">"){if(vec[i+1]=="="){string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_ME,jk);temp.push_back(pp);continue;}else if(vec[i+1]==">"&&vec[i+2]!="=") { string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_A,jk);temp.push_back(pp);continue; }else if(vec[i+1]==">"&&vec[i+2]=="="){ string jk=vec[i];jk.append(vec[++i],0,1);jk.append(vec[++i],0,1);pair<int,string> pp(_B,jk);temp.push_back(pp);continue;}else {pair<int,string> pp(_LG,vec[i]);//标识符temp.push_back(pp);}}else if(vec[i]=="<") {if(vec[i+1]=="=") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_LE,jk);temp.push_back(pp);continue; }else if(vec[i+1]=="<"&&vec[i+2]!="=") { string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_C,jk);temp.push_back(pp);continue;}else if(vec[i+1]=="<"&&vec[i+2]=="=") { string jk=vec[i];jk.append(vec[++i],0,1);jk.append(vec[++i],0,1);pair<int,string> pp(_D,jk);temp.push_back(pp);continue; }else {pair<int,string> pp(_LT,vec[i]);//标识符temp.push_back(pp);}}else if(vec[i]=="!") {if(vec[i+1]=="=") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_LE,jk);temp.push_back(pp);continue;}else {pair<int,string> pp(_NE,vec[i]);//标识符temp.push_back(pp);}else if(vec[i]=="=") {if(vec[i+1]=="="){string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_EQ,jk);temp.push_back(pp);continue; }else {pair<int,string> pp(_AS,vec[i]);//标识符temp.push_back(pp); }}else if(vec[i]=="&") {if(vec[i+1]=="&") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_F,jk);temp.push_back(pp);continue;}else if(vec[i+1]=="=") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_G,jk);temp.push_back(pp);continue;}else {pair<int,string> pp(_E,vec[i]);//标识符temp.push_back(pp);}}else if(vec[i]=="|"){if(vec[i+1]=="|") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_I,jk);temp.push_back(pp);continue;}else if(vec[i+1]=="="){string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_J,jk);temp.push_back(pp);continue;}else {pair<int,string> pp(_H,vec[i]);//标识符temp.push_back(pp);}}else if(vec[i]=="(") {{pair<int,string> pp(_LP,vec[i]);//标识符temp.push_back(pp);}}else if(vec[i]==")"){{pair<int,string> pp(_RP,vec[i]);//标识符temp.push_back(pp); }}else if(vec[i]=="["){{pair<int,string> pp(_LB1,vec[i]);//标识符temp.push_back(pp); } }else if(vec[i]=="]") {{pair<int,string> pp(_RB1,vec[i]);//标识符temp.push_back(pp); } }else if(vec[i]=="~") {{pair<int,string> pp(_K,vec[i]);//标识符temp.push_back(pp); } }else if(vec[i]==",") {{pair<int,string> pp(_COM,vec[i]);//标识符temp.push_back(pp); } }else if(vec[i]=="{") {{pair<int,string> pp(_LB2,vec[i]);//标识符temp.push_back(pp);} }else if(vec[i]==":") {{pair<int,string> pp(_COL,vec[i]);//标识符temp.push_back(pp); } }else if(vec[i]==";") {{pair<int,string> pp(_SEM,vec[i]);//标识符temp.push_back(pp); } }else if(vec[i]=="}") {{pair<int,string> pp(_RB2,vec[i]);//标识符temp.push_back(pp); } }else if(vec[i]=="*") {if(vec[i+1]=="="){string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_Q,jk);temp.push_back(pp);continue; }else {pair<int,string> pp(_TIMES,vec[i]);//标识符temp.push_back(pp); } }else if(vec[i]=="/") {if(vec[i+1]=="=") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_R,jk);temp.push_back(pp);continue; }else if(vec[i+1]=="*") {i=i+4;while(i<vec.size()&&(vec[i-1]!="*"||vec[i]!="/"))i++; cont inue; }else {pair<int,string> pp(_DIV,vec[i]);//标识符temp.push_back(pp); }}else if(vec[i]=="%") {if(vec[i+1]=="=") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_S,jk);temp.push_back(pp);continue; }else {pair<int,string> pp(_U,vec[i]);//标识符temp.push_back(pp); } }else if(vec[i][0]=='"') {pair<int,string> pp(_V,vec[i]);//标识符temp.push_back(pp);}else if(vec[i][0]=='\'') {pair<int,string> pp(_W,vec[i]);//标识符temp.push_back(pp);}else if(vec[i][0]=='?'){pair<int,string> pp(_X,vec[i]);//标识符temp.push_back(pp); }else if(vec[i]=="+") {if(vec[i+1]=="=") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_O,jk);temp.push_back(pp);continue; }else if(vec[i+1]=="+") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_L,jk);temp.push_back(pp);continue; }else if((vec[i-1]=="="||vec[i-1]=="(")&&isnum(vec[i+1])) {string jk=vec[i]; jk.append(vec[++i]);pair<int,string> pp(_NUM,jk);temp.push_back(pp);continue; }else{pair<int,string> pp(_PLUS,vec[i]);//标识符temp.push_back(pp); } }else if(vec[i]=="-"){if(vec[i+1]=="=") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_P,jk);temp.push_back(pp);continue;}else if(vec[i+1]=="-") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_M,jk);temp.push_back(pp);continue; }else if(vec[i+1]==">") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_N,jk);temp.push_back(pp);continue;} else if((vec[i-1]=="="||vec[i-1]=="(")&&isnum(vec[i+1])) { string jk=vec[i]; jk.append(vec[++i]);pair<int,string> pp(_NUM,jk);temp.push_back(pp);continue; }else {pair<int,string> pp(_SUB,vec[i]);//标识符temp.push_back(pp);}}else if(vec[i][0]<='9'&&vec[i][0]>='0'){pair<int,string> pp(_NUM,vec[i]);temp.push_back(pp);}else{pair<int,string> pp(_ID,vec[i]);//标识符temp.push_back(pp);}}else if((vec[i][0]<='9'&&vec[i][0]>='0')||vec[i][0]=='.'){if(!isnum(vec[i]))ERROR_NUM++;else if((vec[i+1][0]=='+'||vec[i+1][0]=='-')&&isnum(vec[i+2])) { string jk=vec[i];jk.append(vec[++i]);jk.append(vec[++i]);pair<int,string> pp(_NUM,jk);temp.push_back(pp);continue;}else{pair<int,string> pp(_NUM,vec[i]);temp.push_back(pp);}}else if(iskey(vec[i])){pair<int,string> pp(iskey(vec[i]),vec[i]);temp.push_back(pp);}else{pair<int,string> pp(_ID,vec[i]);temp.push_back(pp);}}return temp;}void OutFile(vector<pair<int,string> > v) {int i;for(i=0;i<v.size();i++)outfile<<"<"<<v[i].first<<" , \""<<v[i].second<<"\">"<<endl; return;}。

实验一、词法分析器(含源代码)

实验一、词法分析器(含源代码)

词法分析器实验报告一、实验目的及要求本次实验通过用C语言设计、编制、调试一个词法分析子程序,识别单词,实现一个C语言词法分析器,经过此过程可以加深对编译器解析单词流的过程的了解。

运行环境:硬件:windows xp软件:visual c++6.0二、实验步骤1.查询资料,了解词法分析器的工作过程与原理。

2.分析题目,整理出基本设计思路。

3.实践编码,将设计思想转换用c语言编码实现,编译运行。

4.测试功能,多次设置包含不同字符,关键字的待解析文件,仔细察看运行结果,检测该分析器的分析结果是否正确。

通过最终的测试发现问题,逐渐完善代码中设置的分析对象与关键字表,拓宽分析范围提高分析能力。

三、实验内容本实验中将c语言单词符号分成了四类:关键字key(特别的将main说明为主函数)、普通标示符、常数和界符。

将关键字初始化在一个字符型指针数组*key[]中,将界符分别由程序中的case列出。

在词法分析过程中,关键字表和case列出的界符的内容是固定不变的(由程序中的初始化确定),因此,从源文件字符串中识别出现的关键字,界符只能从其中选取。

标识符、常数是在分析过程中不断形成的。

对于一个具体源程序而言,在扫描字符串时识别出一个单词,若这个单词的类型是关键字、普通标示符、常数或界符中之一,那么就将此单词以文字说明的形式输出.每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直到整个源程序全部扫描完毕,从而形成相应的单词串。

输出形式例如:void $关键字流程图、程序流程图:程序:#include<string.h>#include<stdio.h>#include<stdlib.h>#include<ctype.h>//定义关键字char*Key[10]={"main","void","int","char","printf","scanf","else","if","return"}; char Word[20],ch; // 存储识别出的单词流int IsAlpha(char c) { //判断是否为字母if(((c<='z')&&(c>='a'))||((c<='Z')&&(c>='A'))) return 1;else return 0;}int IsNum(char c){ //判断是否为数字if(c>='0'&&c<='9') return 1;else return 0;}int IsKey(char *Word){ //识别关键字函数int m,i;for(i=0;i<9;i++){if((m=strcmp(Word,Key[i]))==0){if(i==0)return 2;return 1;}}return 0;}void scanner(FILE *fp){ //扫描函数char Word[20]={'\0'};char ch;int i,c;ch=fgetc(fp); //获取字符,指针fp并自动指向下一个字符if(IsAlpha(ch)){ //判断该字符是否是字母Word[0]=ch;ch=fgetc(fp);i=1;while(IsNum(ch)||IsAlpha(ch)){ //判断该字符是否是字母或数字Word[i]=ch;i++;ch=fgetc(fp);}Word[i]='\0'; //'\0' 代表字符结束(空格)fseek(fp,-1,1); //回退一个字符c=IsKey(Word); //判断是否是关键字if(c==0) printf("%s\t$普通标识符\n\n",Word);//不是关键字else if(c==2) printf("%s\t$主函数\n\n",Word);else printf("%s\t$关键字\n\n",Word); //输出关键字 }else //开始判断的字符不是字母if(IsNum(ch)){ //判断是否是数字Word[0]=ch;ch=fgetc(fp);i=1;while(IsNum(ch)){Word[i]=ch;i++;ch=fgetc(fp);}Word[i]='\0';fseek(fp,-1,1); //回退printf("%s\t$无符号实数\n\n",Word);}else //开始判断的字符不是字母也不是数字{Word[0]=ch;switch(ch){case'[':case']':case'(':case')':case'{':case'}':case',':case'"':case';':printf("%s\t$界符\n\n",Word); break;case'+':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word);//运算符“+=”}else if(ch=='+'){printf("%s\t$运算符\n\n",Word); //判断结果为“++”}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word); //判断结果为“+”}break;case'-':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word); }else if(ch=='-'){printf("%s\t$运算符\n\n",Word); //判断结果为“--”}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word); //判断结果为“-”}break;case'*':case'/':case'!':case'=':ch=fgetc(fp);if(ch=='='){printf("%s\t$运算符\n\n",Word);}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word);}break;case'<':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word); //判断结果为运算符“<=”}else if(ch=='<'){printf("%s\t$运算符\n\n",Word); //判断结果为“<<”}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word); //判断结果为“<”}break;case'>':ch=fgetc(fp);Word[1]=ch;if(ch=='=') printf("%s\t$运算符\n\n",Word);else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word);}break;case'%':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word);}if(IsAlpha(ch)) printf("%s\t$类型标识符\n\n",Word);else {fseek(fp,-1,1);printf("%s\t$取余运算符\n\n",Word);}break;default:printf("无法识别字符!\n\n"); break;}}}main(){char in_fn[30]; //文件路径FILE *fp;printf("\n请输入源文件名(包括路径和后缀名):");while(1){gets(in_fn);//scanf("%s",in_fn);if((fp=fopen(in_fn,"r"))!=NULL) break; //读取文件内容,并返回文件指针,该指针指向文件的第一个字符else printf("文件路径错误!请重新输入:");}printf("\n******************* 词法分析结果如下 *******************\n");do{ch=fgetc(fp);if(ch=='#') break; //文件以#结尾,作为扫描结束条件else if(ch==' '||ch=='\t'||ch=='\n'){} //忽略空格,空白,和换行else{fseek(fp,-1,1); //回退一个字节开始识别单词流scanner(fp);}}while(ch!='#');return(0);}4.实验结果解析源文件:void main(){int a=3;a+=b;printf("%d",a);return;}#解析结果:5.实验总结分析通过本次实验,让再次浏览了有关c语言的一些基本知识,特别是对文件,字符串进行基本操作的方法。

词法分析器的实验报告

词法分析器的实验报告

词法分析器的实验报告词法分析器的实验报告引言:词法分析器是编译原理中的重要组成部分,它负责将源代码中的字符序列转换为有意义的词法单元,为后续的语法分析提供基础。

本实验旨在设计和实现一个简单的词法分析器,并对其进行测试和评估。

实验设计:1. 词法规则设计:在开始实验之前,我们首先需要设计词法规则,即定义源代码中的合法词法单元。

例如,对于一门类C的语言,我们可以定义关键字(如if、while、int等)、标识符、运算符(如+、-、*等)、分隔符(如()、{}等)等。

2. 有限自动机(DFA)的设计:基于词法规则,我们可以设计一个有限自动机,用于识别和分析源代码中的词法单元。

有限自动机是一个状态转换图,其中每个状态代表一种词法单元,而边表示输入字符的转换关系。

3. 实现代码:根据有限自动机的设计,我们可以使用编程语言(如Python、C++等)实现词法分析器的代码。

代码的主要功能包括读取源代码文件、逐个字符进行词法分析、识别和输出词法单元。

实验过程:1. 词法规则设计:我们以一门简单的算术表达式语言为例,设计了以下词法规则:- 数字:由0-9组成的整数或浮点数。

- 运算符:包括+、-、*、/等。

- 分隔符:包括括号()和逗号,。

- 标识符:以字母开头,由字母和数字组成的字符串。

2. 有限自动机(DFA)的设计:我们基于词法规则,设计了一个简单的有限自动机。

该自动机包含以下状态:- 初始状态:用于读取和识别源代码中的字符。

- 数字状态:用于识别和输出数字。

- 运算符状态:用于识别和输出运算符。

- 分隔符状态:用于识别和输出分隔符。

- 标识符状态:用于识别和输出标识符。

3. 实现代码:我们使用Python编程语言实现了词法分析器的代码。

代码主要包括以下功能:- 读取源代码文件。

- 逐个字符进行词法分析,根据有限自动机的设计进行状态转换。

- 识别和输出词法单元。

实验结果:我们对几个测试样例进行了词法分析,并对结果进行了评估。

编译程序的前端 名词解释

编译程序的前端 名词解释

编译程序的前端名词解释编译程序是一种将高级语言转换为机器语言的工具。

它由两个主要的组成部分组成:前端和后端。

前端负责将用户编写的源代码进行词法分析、语法分析和语义分析,生成一个称为中间代码的表示形式。

而后端则负责将中间代码翻译成目标机器可执行的机器代码。

前端在编译程序中起着至关重要的作用。

它主要包括词法分析器、语法分析器和语义分析器。

词法分析器将源代码分解为一个个的标识符(如变量名、函数名等)和关键字,形成一个记号流。

语法分析器则负责根据语法规则检查记号流的结构,并将其转换为一棵语法树。

语义分析器则进一步验证源代码的语义正确性,并生成中间代码。

词法分析器将源代码转换为一个个记号,这些记号是编译器理解和处理源代码所必需的基本元素。

例如,在C语言中,标识符和关键字是记号的一种。

标识符指的是由字母、数字和下划线组成的变量名或函数名,而关键字则是由编程语言定义的特殊单词,具有特定的意义。

语法分析器会根据语法规则检查记号流的结构,并将其转换为一棵语法树。

语法规则定义了语言中合法的语法结构,例如条件语句、循环语句等。

语法分析器可以根据这些规则来分析源代码,判断其是否符合语法规范。

如果不符合规范,语法分析器将抛出一个语法错误。

语义分析器的主要任务是验证源代码的语义正确性。

它会检查变量的声明和使用是否一致,函数调用的参数是否匹配等。

例如,在C语言中,如果一个变量在使用之前没有声明,语义分析器将发出一个错误提示。

语义分析器还可以执行类型推导,将编译器自动推断出表达式中的数据类型。

词法、语法和语义分析器紧密合作,它们共同构建了编译程序的前端。

通过这些分析,编译程序可以根据源代码生成中间代码,中间代码是一个与具体机器无关的表示形式。

它通常采用一种称为三地址码的形式,其中每个语句最多包含三个操作数。

生成中间代码是编译程序的一项重要工作,因为它将源代码转换成了更加抽象和独立于机器的形式。

这样一来,即使计算机架构发生变化,后端只需要负责将中间代码翻译成新架构的机器代码,而无需对前端进行修改。

词法分析器源代码

词法分析器源代码

#include<stdio.h>#include<cstring>#include<stdlib.h>#define MaxSize1 17//关键字的个数#define MaxSize2 20//运算符的个数#define MaxSize3 4//结束符的个数//数据结构struct TNode{char value[20]; //存放标识符的值int number; //存放标识符的种别码char description[20];//描述}KeyWords[MaxSize1],Operation[MaxSize2],EndOperation[MaxSize3];//存放关键字的数组char*WordsBuff[MaxSize1]={"const","long","float","double","void","main","if","else","then", "break","int","char","include","for","while","printf","scanf"};//存放运算符的数组char*OperationBuff[MaxSize2]={"+","-","*","/","+=","-=","*=","++","--","<","<=",">",">="," <>","=","(",")","#","{","}"};char EndOperationBuff[MaxSize3]={' ',';','\n','\t'};//存放词法分析程序输出的结果TNode Table1[500];TNode Variable[100];//标识符表TNode Const[100];//关键字数组初始化void inputKeyWords(char * buff[],int size){//关键字编码从1-sizefor(int i=0;i<size;i++){strcpy(KeyWords[i].value,buff[i]);KeyWords[i].number=i+1;strcpy(KeyWords[i].description,"关键字");}}//运算符数组初始化void inputOperation(char * buff[],int size){//运算符编码从50-(50+size)for(int i=0;i<size;i++){strcpy(Operation[i].value,buff[i]);Operation[i].number=i+50;strcpy(Operation[i].description,"运算符");}}//结束符数组初始化void inputEndOperation(char buff[],int size){//结束符编码从100-(100+size);for(int i=0;i<size;i++){EndOperation[i].value[0]=buff[i];EndOperation[i].value[1]='\0';EndOperation[i].number=i+100;strcpy(EndOperation[i].description,"结束符"); }}//输出数据结构数组中的信息void outputInfo(TNode a[],int size){for(int i=0;i<size;i++){printf("(%d",a[i].number);printf("\t");printf("%s)",a[i].value);printf("\t");printf(a[i].description);printf("\n");}}void outInfoToFile(TNode a[],int size,FILE *out) {//将词法分析程序的结果输出到文件中去for(int i=0;i<size;i++){fprintf(out,"(%d",a[i].number);fprintf(out,"\t");fprintf(out,"%s)",a[i].value);fprintf(out,"\t");fprintf(out,a[i].description);fprintf(out,"\n");}//从文件中读取一个字符//返回文件中读取的字符char getChar(FILE *fp){char ch=fgetc(fp);return ch;}//判读是否是运算符int isOperation(char a[]){//返回i表示是运算符在运算符数组中的位置//返回-1表示不是运算符int result;for(int i=0;i<MaxSize2;i++){result=strcmp(a,Operation[i].value);if(result==0){return i;break;}}return -1;}//判读是否是关键字int isKeyWords(char a[]){//返回i表示在关键字表中的位置//返回-1表示不是关键字int result;for(int i=0;i<MaxSize1;i++){result=strcmp(a,KeyWords[i].value);if(result==0){return i;break;}}return -1;//判读是否是结束符int isEndOperation(char a){//返回i表示是结束符在结束符表中的位置//返回-1表示不是结束符for(int i=0;i<MaxSize3;i++){if(a==EndOperation[i].value[0]){return i;break;}}return -1;}//判读是否是字符int isChar(char a){//返回1表示是字符//返回0表示不是字符if(a>='a'&&a<='z')return 1;else if(a>'A'&&a<='Z')return 1;elsereturn 0;}//判读是否是数字int isDigit(char a){//返回1表示是数字//返回0表示不是数字if(a>='0'&&a<='9')return 1;elsereturn 0;}int count=0;//记录结果表中的关键字及运算符等表项个数,用于返回int count1=0;//记录标识符的表项个数int count2=0;//记录常量的表项的个数//从屏幕上面获得字符并解析,返回在结果表中的表项int start1(FILE *in){char buff[20];//用于保存单词的缓冲区char nextchar[2];char temp[20];//用于保存变量或常量的类型数组int i=0;//缓冲区指针int a;//比较的结果指针char op[3];//用于保存第一个运算符op[2]='\0';nextchar[0]=fgetc(in);nextchar[1]='\0';while(nextchar[0]!=EOF){if(isChar(nextchar[0])){buff[i]=nextchar[0];i++;nextchar[0]=fgetc(in);}else if(isDigit(nextchar[0])){buff[i]=nextchar[0];i++;nextchar[0]=fgetc(in);}else if(nextchar[0]=='\r'||nextchar[0]=='\n'){buff[i]='\0';a=isKeyWords(buff);if(a!=-1&&i>0){strcpy(Table1[count].value,KeyWords[a].value);Table1[count].number=KeyWords[a].number;strcpy(Table1[count].description,KeyWords[a].description);count++;//计数器加一i=0;//清空缓冲区}else if(i>0){if(isChar(buff[0])){//是标识符strcpy(Variable[count1].value,buff);Variable[count1].number=count1;strcpy(Variable[count1].description,"标识符");count1++;//计数器加一i=0;//清空缓冲区}else if(isDigit(buff[0])){//是常量strcpy(Const[count2].value,buff);Const[count2].number=count2;strcpy(Const[count2].description,"常量");count2++;//计数器加一i=0;//清空缓冲区}}else{//缓冲区为空!}//处理回车符与换行符nextchar[0]=fgetc(in);}else if(isEndOperation(nextchar[0])!=-1){buff[i]='\0';a=isKeyWords(buff);if(a!=-1&&i>0){strcpy(Table1[count].value,KeyWords[a].value);Table1[count].number=KeyWords[a].number;strcpy(Table1[count].description,KeyWords[a].description);strcpy(temp,KeyWords[a].value);count++;//计数器加一i=0;//清空缓冲区}else if(i>0){if(isChar(buff[0])){//是标识符strcpy(Variable[count1].value,buff);Variable[count1].number=count1;strcpy(Variable[count1].description,"标识符");count1++;//计数器加一i=0;//清空缓冲区}else if(isDigit(buff[0])){//是常量strcpy(Const[count2].value,buff);Const[count2].number=count2;strcpy(Const[count2].description,"常量");count2++;//计数器加一i=0;//清空缓冲区}}else{//缓冲区为空!}nextchar[0]=fgetc(in);}else if((a=isOperation(nextchar))!=-1){//首先输出缓冲区中的数据buff[i]='\0';a=isKeyWords(buff);if(a!=-1&&i>0){strcpy(Table1[count].value,KeyWords[a].value);Table1[count].number=KeyWords[a].number;strcpy(Table1[count].description,KeyWords[a].description);count++;//计数器加一i=0;//清空缓冲区}else if(i>0){if(isChar(buff[0])){//是标识符strcpy(Variable[count1].value,buff);Variable[count1].number=count1;strcpy(Variable[count1].description,"标识符");count1++;//计数器加一i=0;//清空缓冲区}else if(isDigit(buff[0])){//是常量strcpy(Const[count2].value,buff);Const[count2].number=count2;strcpy(Const[count2].description,"常量");count2++;//计数器加一i=0;//清空缓冲区}}else{//缓冲区为空!}//处理运算符op[0]=nextchar[0];nextchar[0]=fgetc(in);if(nextchar[0]!='@'){if(isOperation(nextchar)!=-1){op[1]=nextchar[0];if((a=isOperation(op))!=-1){//输出双目运算符strcpy(Table1[count].value,Operation[a].value);Table1[count].number=Operation[a].number;strcpy(Table1[count].description,Operation[a].description);count++;//计数器加一//读取下一个字符nextchar[0]=fgetc(in);}else{//错误的双目运算符strcpy(Table1[count].value,op);Table1[count].number=-1;strcpy(Table1[count].description,"未定义的运算符");count++;//计数器加一//读取下一个字符nextchar[0]=fgetc(in);}}else{//输出一元运算符op[1]='\0';a=isOperation(op);strcpy(Table1[count].value,Operation[a].value);Table1[count].number=Operation[a].number;strcpy(Table1[count].description,Operation[a].description);count++;//计数器加一}}}}return count;}void main(){inputKeyWords(WordsBuff,MaxSize1);inputOperation(OperationBuff,MaxSize2);inputEndOperation(EndOperationBuff,MaxSize3);FILE *in,*out;bool Flag=true;while(Flag){printf("源文件的位置:C:\\input.txt\n");if((in=fopen("C:\\input.txt","r"))==NULL){printf("读取源文件失败!\n");exit(0);}if((out=fopen("C:\\out.txt","w"))==NULL){printf("打开文件失败!\n");exit(0);}int MaxSize=start1(in);printf("关键字及运算符\n");fprintf(out,"关键字及运算符\n");outputInfo(Table1,MaxSize);outInfoToFile(Table1,MaxSize,out);printf("标识符表:\n");fprintf(out,"标识符表:\n");outputInfo(Variable,count1);outInfoToFile(Variable,count1,out);printf("常量表:\n");fprintf(out,"常量表:\n");outputInfo(Const,count2);outInfoToFile(Const,count2,out);Flag=false;fclose(in);fclose(out);}getchar(); }。

编译原理实验词法分析器与语法分析器实现

编译原理实验词法分析器与语法分析器实现

编译原理实验词法分析器与语法分析器实现词法分析器与语法分析器是编译器的两个重要组成部分,它们在编译过程中扮演着至关重要的角色。

词法分析器负责将源代码转化为一个个标记(token)序列,而语法分析器则根据词法分析器生成的标记序列构建语法树,验证源代码的语法正确性。

本实验旨在实现一个简单的词法分析器和语法分析器。

实验一:词法分析器实现在实现词法分析器之前,需要定义所需词法项的规则。

以C语言为例,常见的词法项包括关键字(如int、if、for等)、标识符、运算符(如+、-、*、/等)、常量(如整数、浮点数等)和分隔符(如括号、逗号等)。

接下来,我们来实现一个简单的C语言词法分析器。

1. 定义词法项的规则在C语言中,关键字和标识符由字母、数字和下划线组成,且首字符不能为数字。

运算符包括各种数学运算符和逻辑运算符。

常量包括整数和浮点数。

分隔符包括括号、逗号等。

2. 实现词法分析器的代码下面是一个简单的C语言词法分析器的实现代码:```pythondef lexer(source_code):keywords = ['int', 'if', 'for'] # 关键字列表operators = ['+', '-', '*', '/'] # 运算符列表separators = ['(', ')', '{', '}', ',', ';'] # 分隔符列表tokens = [] # 标记序列列表current_token = '' # 当前标记for char in source_code:if char.isspace(): # 如果是空格,则忽略continueelif char.isalpha(): # 如果是字母,则可能是关键字或标识符的一部分current_token += charelif char.isdigit(): # 如果是数字,则可能是常量的一部分current_token += charelif char in operators or char in separators: # 如果是运算符或分隔符,则当前标记结束if current_token:tokens.append(current_token)current_token = ''tokens.append(char)else: # 如果是其他字符,则当前标记结束if current_token:tokens.append(current_token)current_token = ''return tokens```以上代码通过遍历源代码的字符,根据定义的规则生成一个个标记,存储在`tokens`列表中。

编译原理词法分析和语法分析报告+代码[C语言版]

编译原理词法分析和语法分析报告+代码[C语言版]

词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。

二、实验要求2.1 待分析的简单的词法(1)关键字:begin if then while do end所有的关键字都是小写。

(2)运算符和界符:= + - * / < <= <> > >= = ; ( ) #(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*(4)空格有空白、制表符和换行符组成。

空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。

2.2 各种单词符号对应的种别码:表2.1 各种单词符号对应的种别码2.3 词法分析程序的功能:输入:所给文法的源程序字符串。

输出:二元组(syn,token或sum)构成的序列。

其中:syn为单词种别码;token为存放的单词自身字符串;sum为整型常数。

例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列:(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)……三、词法分析程序的算法思想:算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。

3.1 主程序示意图:主程序示意图如图3-1所示。

其中初始包括以下两个方面:⑴关键字表的初值。

关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。

如能查到匹配的单词,则该单词为关键字,否则为一般标识符。

关键字表为一个字符串数组,其描述如下:Char *rwtab[6] = {“begin”, “if”, “then”, “while”, “do”, “end”,};是图3-1(2)程序中需要用到的主要变量为syn,token和sum3.2 扫描子程序的算法思想:首先设置3个变量:①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。

C语言词法分析器构造实验报告(1)1

C语言词法分析器构造实验报告(1)1

C 语言词法分析器构造实验报告02计算机(2) 2002374203 冯绍欣一、题目要求:完成一个C 语言的词法分析器的构造。

此词法分析器能识别附值语句、循环语句、条件语句、并能处理注释。

二、设计方案:这个词法分析器分析的主要关键字有:main, int, float, char, if, else, for, while, do, switch, case, break; default 。

选择要分析的c 文件,首先对其去掉注释和与空格处理,再根据字符的不同类型分析。

1、全局数据结构:字符数组 set[ ]:存放从文件中读到的所有字符;str[ ]:存放经过注释处理和预空格处理的字符;strtoken[ ]:存放当前分析的字符;结构体 KEYTABLE :存放关键字及其标号;全局字符变量 ch :当前读入字符;全局整型变量 sr, to :数组str, strtoken 的指针。

2、以层次图形式描述模块的组成及调用关系3、主要函数的设计要求(功能、参数、返回值):openfile :打开文件;GetChar :将下一个输入字符读到ch 中,搜索指示器前移一字符位置;GetBC :检查ch 中的字符是否为空白。

若是,则调用GetChar 直至ch 中进入一个非空白字符; Main ( )Openfile ( ) Analysis ( )Reflesh() Process()Set32()GetChar() GetBC()Concat()Reserve()IsLetter() IsDigit()Retract()GetChar()Concat :将ch 中的字符连接到strtoken 之后;IsLetter 和IsDigit :布尔函数过程,分别判断ch 中的字符是否为字母和数字;Reserve :整型函数过程,对strtoken 中的字符串查找关键字表,若是关键字则返回编码,否则返回-1;Retract :将搜索指示器回调一个字符位置,将ch 置为空白字符;reflesh :刷新,把strtoken 数组置为空;prearrange1:将注释部分置为空格;prearrange2:预处理空格,去掉多余空格;analysis:词法分析;main :主函数。

编译原理名词解释

编译原理名词解释

编译原理名词解释1. 词法分析器(Lexer):也称为扫描器(Scanner),用于将源代码分割成一个个单词(Token)。

2. 语法分析器(Parser):将词法分析器生成的单词序列转换成语法树(Parse Tree)或抽象语法树(Abstract Syntax Tree)。

3. 语法树(Parse Tree):表示源代码的语法结构的树状结构,它由语法分析器根据语法规则生成。

4. 抽象语法树(Abstract Syntax Tree):比语法树更加简化和抽象的树状结构,用于表示源代码的语义结构。

5. 语义分析器(Semantic Analyzer):对抽象语法树进行语义检查,并生成中间代码或目标代码。

6. 中间代码(Intermediate code):一种介于源代码和目标代码之间的中间表示形式,可以被不同的优化器和代码生成器使用。

7. 目标代码生成器(Code Generator):将中间代码转换成特定目标平台的机器代码。

8. 优化器(Optimizer):用于对中间代码进行优化,以提高代码的执行效率和资源利用率。

9. 符号表(Symbol Table):用于存储程序中的标识符(变量、函数等)的信息,包括名称、类型等。

10. 语言文法(Grammar):定义了一种语言的语法规则,常用的形式包括上下文无关文法和正则文法。

11. 上下文无关文法(Context-free Grammar):一种形式化的语法表示方法,由产生式和非终结符组成,描述一种语言的句子结构。

12. 语言解释器(Interpreter):将源代码逐行解释执行的程序,不需要生成目标代码。

13. 回溯法(Backtracking):一种递归式的算法,用于在语法分析过程中根据产生式进行选择。

14. 正则表达式(Regular Expression):用于描述一类字符串的表达式,可以用于词法分析中的模式匹配。

15. 自顶向下分析(Top-down Parsing):从文法的起始符号开始,按照语法规则逐步构建语法树的过程。

词法分析器(lex实现)

词法分析器(lex实现)

院系:计算机学院实验课程:编译原理实验项目:C++源代码单词扫描程序(词法分析)指导老师:陈寅开课时间:2014~2015年度第1学期专业:数据库班级:2班学生:雷楚楚学号:20122100158C++源代码单词扫描程序(词法分析)一、实验目的设计并实现一个词法分析器,深刻理解编译原理中词法分析器的原理。

二、实验内容1、C++源代码扫描程序识别C++记号。

C++语言包含了几种类型的记号:标识符,关键字,数(包括整数、浮点数),字符串,注释,特殊符号(分解符)和运算符号等。

2、打开一个C++源文件,打印出所有以上的记号。

3、选作部分:为了提高C++源程序的可读性,C++程序在书写过程中加入了空行、空格、缩进、注释等。

假设你想牺牲可读性,以节省磁盘空间,那么你可以存贮一个删除了所有不必要空格和注释的C++源程序的压缩文本。

因此,程序中还看可以有这样的压缩功能。

4、进一步实现减少源文件大小的压缩功能。

5、完善软件文档。

二、实验过程1、对C++文法中的各类单词分类(1)保留字:asm、do、if、return、typedef、auto、double、inline、short、typeid、bool、try、include、long、sizeof、union、case、enum、mutable、static、unsigned、long、sizeof、union、case、enum、mutable、static、unsigned、catch、explicit、namespace、using、char、export、int、signed、break、else、new、struct、virtual、class、extern、operator、switch、void、const、false、private、template、volatile、float、protected、this、continue、for、public、throw、while、default、friend、register、true、delete、goto、try、include、std、iomanip、setw、setprecision、endl、setiosflags、ios (2)数字:包括整数和浮点数(3)标识符:由字母打头的字母和数字的字符串,可包含下划线(4)运算符:"&="、"^="、"、="、"<<="、">>="、"*="、"/="、"%="、"+="、"-="、"="、"?:"、"、、"、"&&"、"、"、"^"、"&"、"=="、"!="、">"、">="、"<"、"<="、"<<"、">>"、"+"、"-"、"*"、"/"、"%"、".*"、"->*"、"&"、"+"、"-"、"++"、"--"、"->"、"::"(5)界符:"{"、"}"、"("、")"、"#"、","、":"、";"、"."、"\""(6)注释:包括//和/**/两种类型的注释(7)字符串:包含在“”里面的内容2、将各类单词对应到Flex中:(1)保留字:asm|do|if|return|typedef|auto|double|inline|short|typeid|bool|try|include|long|sizeof|union|case|enum|mutable|static|unsigned|long|sizeof|union|case|enum|mutable|static|unsigned|catch|explicit|namespace|using|char|export|int|signed|break|else|new|struct|virtual|class|extern|operator|switch|void|const|false|private|template|volatile|float|protected|this|continue|for|public|throw|while|default|friend|register|true|delete|goto|try|include|std|iomanip|setw|setprecision|endl|setiosflags|ios(2)数字:包括整数和浮点数(正负)[+-]?([0-9]*|0|([0-9]*\.[0-9]*))(3)标识符:由字母打头的字母和数字的字符串,包含下划线[A-Za-z]([A-Za-z]|[0-9]|_)*(4)运算符:"&="|"^="|"|="|"<<="|">>="|"*="|"/="|"%="|"+="|"-="|"="|"?:"|"||"|"&&"|"|"|"^"|"&"|"=="|"!="|">"|">="|"<"|"<="|"<<"|">>"|"+"|"-"|"*"|"/"|"%"|".*"|"->*"|"&"|"+"|"-"|"++"|"--"|"->"|"::"(5)界符:"{"|"}"|"("|")"|"#"|","|":"|";"|"."|"\""(6)注释:包括//和/**/两种类型的注释\/\*(\s|.)*?\*\/(/**/)\/\/[^\n]*(//)(7)字符串:包含在“”里面的内容'[^'\n]*'|\"[^\"]*\"(8)除其他情况之外判断为出错3、跳过空行和空格[\t]+{}/*空格*/ \n|.{}/*空行*/4、为lex制定一些规则5、写子程序让用户输入要进行词法扫描的文件,当lex读完输入文件之后就会调用函数yywrap。

词法分析程序(c语言版)

词法分析程序(c语言版)

源代码:1、词法分析/*cifa fenxi chengxu*/#include <stdio.h>#include <ctype.h>#include <alloc.h>#include <stdlib.h>#include <string.h>#define NULL 0FILE *fp;char cbuffer;char*key[8]={"if","else","for","while","do","return","break","continue"}; char *border[6]={",",";","{","}","(",")"};char *arithmetic[4]={"+","-","*","/"};char *relation[6]={"<","<=","=",">",">=","<>"};char *consts[20];char *label[20];int constnum=0,labelnum=0;int search(char searchchar[],int wordtype){int i=0;switch (wordtype) {case 1:for (i=0;i<=7;i++){if (strcmp(key[i],searchchar)==0)return(i+1);}case 2:{for (i=0;i<=5;i++){if (strcmp(border[i],searchchar)==0)return(i+1);} return(0);}case 3:{for (i=0;i<=3;i++){if (strcmp(arithmetic[i],searchchar)==0){return(i+1);}}return(0);}case 4:{for (i=0;i<=5;i++){if (strcmp(relation[i],searchchar)==0){return(i+1);}}return(0);}case 5:{for (i=0;i<=constnum;i++){if (strcmp(consts[i],searchchar)==0){return(i+1);}}consts[i-1]=(char *)malloc(sizeof(searchchar));strcpy(consts[i-1],searchchar);constnum++;return(i);}case 6:{for (i=0;i<=labelnum;i++){if (strcmp(label[i],searchchar)==0){return(i+1);}}label[i-1]=(char *)malloc(sizeof(searchchar));strcpy(label[i-1],searchchar);labelnum++;return(i);}}}char alphaprocess(char buffer){int atype;int i=-1;char alphatp[20];while ((isalpha(buffer))||(isdigit(buffer))) {alphatp[++i]=buffer;buffer=fgetc(fp);}alphatp[i+1]='\0';if (atype=search(alphatp,1))printf("%s (1,%d)\n",alphatp,atype-1);else{atype=search(alphatp,6);printf("%s (6,%d)\n",alphatp,atype-1);}return(buffer);}char digitprocess(char buffer){int i=-1;char digittp[20];int dtype;while ((isdigit(buffer))){digittp[++i]=buffer;buffer=fgetc(fp);}digittp[i+1]='\0';dtype=search(digittp,5);printf("%s (5,%d)\n",digittp,dtype-1);return(buffer);}char otherprocess(char buffer){int i=-1;char othertp[20];int otype,otypetp;othertp[0]=buffer;othertp[1]='\0';if (otype=search(othertp,3)){printf("%s (3,%d)\n",othertp,otype-1);buffer=fgetc(fp);goto out;}if (otype=search(othertp,4)){buffer=fgetc(fp);othertp[1]=buffer;othertp[2]='\0';if (otypetp=search(othertp,4)){printf("%s (4,%d)\n",othertp,otypetp-1);goto out;}elseothertp[1]='\0';printf("%s (4,%d)\n",othertp,otype-1);goto out;}if (buffer==':'){buffer=fgetc(fp);if (buffer=='=')printf(":= (2,2)\n");buffer=fgetc(fp);goto out;}else{if (otype=search(othertp,2)){printf("%s (2,%d)\n",othertp,otype-1);buffer=fgetc(fp);goto out;}}if ((buffer!='\n')&&(buffer!=' '))printf("%c error,not a word\n",buffer);buffer=fgetc(fp);out: return(buffer);}void main(){int i;for (i=0;i<=20;i++){label[i]=NULL;consts[i]=NULL;};if ((fp=fopen("c:\\example.c","r"))==NULL)printf("error");else{cbuffer = fgetc(fp);while (cbuffer!=EOF){if (isalpha(cbuffer))cbuffer=alphaprocess(cbuffer);else if (isdigit(cbuffer))cbuffer=digitprocess(cbuffer);else cbuffer=otherprocess(cbuffer);}printf("over\n");getchar();}}2、递归向下分析#include <stdio.h>#include<dos.h>#include<stdlib.h>#include<string.h>char a[50] ,b[50],d[200],e[10];char ch;int n1,i1=0,flag=1,n=5;int E();int E1();int T();int G();int S();int F();void input();void input1();void output();void main() /*递归分析*/{int f,p,j=0;char x;d[0]='E';d[1]='=';d[2]='>';d[3]='T';d[4]='G';d[5]='#';printf("请输入字符串(长度<50,以#号结束)\n");do{scanf("%c",&ch);a[j]=ch;j++;}while(ch!='#');n1=j;ch=b[0]=a[0];printf("文法\t分析串\t\t分析字符\t剩余串\n");f=E1();if (f==0) return;if (ch=='#'){ printf("accept\n");p=0;x=d[p];while(x!='#') {printf("%c",x);p=p+1;x=d[p]; /*输出推导式*/}}else {printf("error\n");printf("回车返回\n");getchar();getchar();return;}printf("\n");printf("回车返回\n");getchar();getchar();}int E1(){ int f,t;printf("E TG\t");flag=1;input();input1();f=T();if (f==0) return(0);t=G();if (t==0) return(0);else return(1);}int E(){ int f,t;printf("E→TG\t");e[0]='E';e[1]='=';e[2]='>';e[3]='T';e[4]='G';e[5]='#';output();flag=1;input();input1();f=T();if (f==0) return(0);t=G();if (t==0) return(0);else return(1);}int T(){ int f,t;printf("T→FS\t");e[0]='T';e[1]='=';e[2]='>';e[3]='F';e[4]='S';e[5]='#';output();flag=1;input();input1();f=F();if (f==0) return(0);t=S();if (t==0) return(0);else return(1);}int G(){ int f;if(ch=='+') {b[i1]=ch;printf("G→+TG\t");e[0]='G';e[1]='=';e[2]='>';e[3]='+';e[4]='T';e[5]='G';e[6]='#';output();flag=0;input();input1();ch=a[++i1];f=T();if (f==0) return(0);G();return(1);}printf("G→^\t");e[0]='G';e[1]='=';e[2]='>';e[3]='^';e[4]='#';output();flag=1;input();input1();return(1);}int S(){int f,t;if(ch=='*') {b[i1]=ch;printf("S→*FS\t");e[0]='S';e[1]='=';e[2]='>';e[3]='*';e[4]='F';e[5]='S';e[6]='#';output();flag=0;input();input1();ch=a[++i1];f=F();if (f==0) return(0);t=S();if (t==0) return(0);else return(1);}printf("S→^\t");e[0]='S';e[1]='=';e[2]='>';e[3]='^';e[4]='#';output();flag=1;a[i1]=ch;input();input1();return(1);}int F(){ int f;if(ch=='(') {b[i1]=ch;printf("F→(E)\t");e[0]='F';e[1]='=';e[2]='>';e[3]='(';e[4]='E';e[5]=')';e[6]='#';output();flag=0;input();input1();ch=a[++i1];f=E();if (f==0) return(0);if(ch==')') {b[i1]=ch;printf("F→(E)\t");flag=0;input();input1();ch=a[++i1];}else {printf("error\n");return(0);}}else if(ch=='i') {b[i1]=ch;printf("F→i\t");e[0]='F';e[1]='=';e[2]='>';e[3]='i';e[4]='#';output();flag=0;input();input1();ch=a[++i1];}else {printf("error\n");return(0);}return(1);}void input(){int j=0;for (;j<=i1-flag;j++)printf("%c",b[j]); /*输出分析串*/printf("\t\t");printf("%c\t\t",ch); /*输出分析字符*/ }void input1(){int j;for (j=i1+1-flag;j<n1;j++)printf("%c",a[j]); /*输出剩余字符*/ printf("\n");void output(){ /*推导式计算*/ int m,k,j,q;int i=0;m=0;k=0;q=0;i=n;d[n]='=';d[n+1]='>';d[n+2]='#';n=n+2;i=n;i=i-2;while(d[i]!='>'&&i!=0) i=i-1;i=i+1;while(d[i]!=e[0]) i=i+1;q=i;m=q;k=q;while(d[m]!='>') m=m-1;m=m+1;while(m!=q) {d[n]=d[m];m=m+1;n=n+1;}d[n]='#';for(j=3;e[j]!='#';j++){d[n]=e[j];n=n+1;}k=k+1;while(d[k]!='=') {d[n]=d[k];n=n+1;k=k+1;}d[n]='#';}3、LL(1)/*LL(1)分析法源程序,只能在VC++中运行 */#include<stdio.h>#include<stdlib.h>#include<string.h>#include<dos.h>char A[20];/*分析栈*/char B[20];/*剩余串*/char v1[20]={'i','+','*','(',')','#'};/*终结符 */char v2[20]={'E','G','T','S','F'};/*非终结符 */int j=0,b=0,top=0,l;/*L为输入串长度 */typedef struct type/*产生式类型定义 */ {char origin;/*大写字符 */char array[5];/*产生式右边字符 */int length;/*字符个数 */}type;type e,t,g,g1,s,s1,f,f1;/*结构体变量 */ type C[10][10];/*预测分析表 */void print()/*输出分析栈 */{int a;/*指针*/for(a=0;a<=top+1;a++)printf("%c",A[a]);printf("\t\t");}/*print*/void print1()/*输出剩余串*/{int j;for(j=0;j<b;j++)/*输出对齐符*/printf(" ");for(j=b;j<=l;j++)printf("%c",B[j]);printf("\t\t\t");}/*print1*/void main(){int m,n,k=0,flag=0,finish=0;char ch,x;type cha;/*用来接受C[m][n]*//*把文法产生式赋值结构体*/e.origin='E';strcpy(e.array,"TG");e.length=2;t.origin='T';strcpy(t.array,"FS");t.length=2;g.origin='G';strcpy(g.array,"+TG");g.length=3;g1.origin='G';g1.array[0]='^';g1.length=1;s.origin='S';strcpy(s.array,"*FS");s.length=3;s1.origin='S';s1.array[0]='^';s1.length=1;f.origin='F';strcpy(f.array,"(E)");f.length=3;f1.origin='F';f1.array[0]='i';f1.length=1;for(m=0;m<=4;m++)/*初始化分析表*/for(n=0;n<=5;n++)C[m][n].origin='N';/*全部赋为空*//*填充分析表*/C[0][0]=e;C[0][3]=e;C[1][1]=g;C[1][4]=g1;C[1][5]=g1;C[2][0]=t;C[2][3]=t;C[3][1]=s1;C[3][2]=s;C[3][4]=C[3][5]=s1;C[4][0]=f1;C[4][3]=f;printf("提示:本程序只能对由'i','+','*','(',')'构成的以'#'结束的字符串进行分析,\n");printf("请输入要分析的字符串:");do/*读入分析串*/{scanf("%c",&ch);if ((ch!='i') &&(ch!='+')&&(ch!='*')&&(ch!='(')&&(ch!=')')&&(ch!='#')){printf("输入串中有非法字符\n");exit(1);}B[j]=ch;j++;}while(ch!='#');l=j;/*分析串长度*/ch=B[0];/*当前分析字符*/A[top]='#'; A[++top]='E';/*'#','E'进栈*/printf("步骤\t\t分析栈 \t\t剩余字符 \t\t所用产生式 \n"); do{x=A[top--];/*x为当前栈顶字符*/printf("%d",k++);printf("\t\t");for(j=0;j<=5;j++)/*判断是否为终结符*/if(x==v1[j]){flag=1;break;}if(flag==1)/*如果是终结符*/{if(x=='#'){finish=1;/*结束标记*/printf("acc!\n");/*接受 */getchar();getchar();exit(1);}/*if*/if(x==ch){print();print1();printf("%c匹配\n",ch);ch=B[++b];/*下一个输入字符*/flag=0;/*恢复标记*/}/*if*/else/*出错处理*/{print();print1();printf("%c出错\n",ch);/*输出出错终结符*/exit(1);}/*else*/}/*if*/else/*非终结符处理*/{for(j=0;j<=4;j++)if(x==v2[j]){m=j;/*行号*/break;}for(j=0;j<=5;j++)if(ch==v1[j]){n=j;/*列号*/break;}cha=C[m][n];if(cha.origin!='N')/*判断是否为空*/{print();print1();printf("%c->",cha.origin);/*输出产生式*/for(j=0;j<cha.length;j++)printf("%c",cha.array[j]);printf("\n");for(j=(cha.length-1);j=0;j--)/*产生式逆序入栈*/A[++top]=cha.array[j];if(A[top]=='^')/*为空则不进栈*/top--;}/*if*/else/*出错处理*/{print();print1();printf("%c出错\n",x);/*输出出错非终结符*/exit(1);}/*else*/}/*else*/}while(finish==0);}/*main*/4、LL(2)/*LL(1)分析法源程序,只能在VC++中运行 */#include<stdio.h>#include<stdlib.h>#include<string.h>#include<dos.h>char A[20];/*分析栈*/char B[20];/*剩余串*/char v1[20]={'i','+','*','(',')','#'};/*终结符 */ char v2[20]={'E','G','T','S','F'};/*非终结符 */int j=0,b=0,top=0,l;/*L为输入串长度 */typedef struct type/*产生式类型定义 */{char origin;/*大写字符 */char array[5];/*产生式右边字符 */int length;/*字符个数 */}type;type e,t,g,g1,s,s1,f,f1;/*结构体变量 */type C[10][10];/*预测分析表 */void print()/*输出分析栈 */{int a;/*指针*/for(a=0;a<=top;a++)printf("%c",A[a]);printf("\t\t");}/*print*/void print1()/*输出剩余串*/{int j;for(j=0;j<b;j++)/*输出对齐符*/printf(" ");for(j=b;j<=l;j++)printf("%c",B[j]);printf("\t\t\t");}/*print1*/void main(){int m,n,k=0,flag=0;char ch,x;type cha;/*用来接受C[m][n]*//*把文法产生式赋值结构体*/e.origin='E';strcpy(e.array,"TG");e.length=2;t.origin='T';strcpy(t.array,"FS");t.length=2;g.origin='G';strcpy(g.array,"+TG");g.length=3;g1.origin='G';g1.array[0]='^';g1.length=1;s.origin='S';strcpy(s.array,"*FS");s.length=3;s1.origin='S';s1.array[0]='^';s1.length=1;f.origin='F';strcpy(f.array,"(E)");f.length=3;f1.origin='F';f1.array[0]='i';f1.length=1;for(m=0;m<=4;m++)/*初始化分析表*/for(n=0;n<=5;n++)C[m][n].origin='N';/*全部赋为空*/ /*填充分析表*/C[0][0]=e;C[0][3]=e;C[1][1]=g;C[1][4]=g1;C[1][5]=g1;C[2][0]=t;C[2][3]=t;C[3][1]=s1;C[3][2]=s;C[3][4]=C[3][5]=s1;C[4][0]=f1;C[4][3]=f;printf("提示:本程序只能对由'i','+','*','(',')'构成的以'#'结束的字符串进行分析,\n");printf("请输入要分析的字符串:");do/*读入分析串*/{scanf("%c",&ch);if ((ch!='i') &&(ch!='+')&&(ch!='*')&&(ch!='(')&&(ch!=')')&&(ch!='#')){printf("输入串中有非法字符\n");exit(1);}B[j]=ch;j++;}while(ch!='#');l=j;/*分析串长度*/ch=B[0];/*当前分析字符*/A[top]='#';A[++top]='E';/*'#','E'进栈*/x=A[top];/*x为当前栈顶字符*/printf("步骤\t\t分析栈 \t\t剩余字符 \t\t所用产生式 \n");loop: printf("%d",k++);printf("\t\t");for(j=0;j<=5;j++)/*判断是否为终结符*/if(x==v1[j]) flag=1;if(flag==1)/*如果是终结符*/{if(x=='#'){printf("acc!\n");/*接受 */getchar();getchar();exit(1);}/*if*/if(x==ch){print();print1();printf("%c匹配\n",ch);top--;/*栈顶出栈*/ch=B[++b];/*下一个输入字符*/x=A[top];flag=0;/*恢复标记*/goto loop;}/*if*/else/*出错处理*/{print();print1();printf("%c出错\n",ch);/*输出出错终结符*/exit(0);}/*else*/}/*if*/else/*非终结符处理*/{for(j=0;j<=4;j++)if(x==v2[j])m=j;/*行号*/for(j=0;j<=5;j++)if(ch==v1[j])n=j;/*列号*/cha=C[m][n];if(cha.origin!='N')/*判断是否为空*/{print();print1();printf("%c-",cha.origin);/*输出产生式*/for(j=0;j<cha.length;j++)printf("%c",cha.array[j]);printf("\n");top--;for(j=(cha.length-1);j=0;j--)/*产生式逆序入栈*/A[++top]=cha.array[j];if(A[top]=='^')/*为空则不进栈*/top--;x=A[top];goto loop;}/*if*/else/*出错处理*/{print();print1();printf("%c出错\n",x);/*输出出错非终结符*/exit(0);}/*else*/}/*else*/}/*main*/5、逆波兰式include<stdio.h>#include<math.h>#define max 100char ex[max]; /*存储后缀表达式*/void trans(){ /*将算术表达式转化为后缀表达式*/char str[max]; /*存储原算术表达式*/char stack[max]; /*作为栈使用*/char ch;int sum,i,j,t,top=0;printf("*****************************************\n");printf("*输入一个求值的表达式,以#结束。

词法分析器(含完整源码)

词法分析器(含完整源码)

词法分析实验报告一、实验目的与要求:1、了解字符串编码组成的词的内涵,感觉一下字符串编码的方法和解读2、了解和掌握自动机理论和正规式理论在词法分析程序和控制理论中的应用二、实验内容:构造一个自己设计的小语言的词法分析器:1、这个小语言能说明一些简单的变量识别诸如begin,end,if,while等保留字;识别非保留字的一般标识符(有下划线、字符、数字,且第一个字符不能是数字)。

识别数字序列(整数和小数);识别:=,<=,>=之类的特殊符号以及;,(,)等界符。

2、相关过程(函数):Scanner()词法扫描程序,提取标识符并填入display表中3、这个小语言有顺序结构的语句4、这个小语言能表达分支结构的语句5、这个小语言能够输出结果总之这个小语言词法分析器能提供以上所说明到的语法描述的功能……三、实验步骤:1、测试评价(1)、测试1:能说明一些简单的变量,如关键字、一般标识符、界符等;(2)、测试2:能输出结果:单词符号(内码形式)、各种信息表(如符号表、常量表等);(3)、测试程序:var x,y,z;beginx:=2;y:=3;if (x+5>=y*y) thenbeginz:=y*y-x;z:=z+x*x;endelsez:=x+y;prn z;end.(4)、结果:①、从键盘读入;部分结果如下:(类型:该标识符所属的类型,如关键字,变量等;下标:该标识符所对应表(如变量标识符表,常量标识符表等)中其相应的位置,下同)②、从文件读入,输出到文件;部分结果如下:其他测试及结果如下:③、出错处理;注:若有错误,则只指出错误,不输出各个表;(5)、评价:这个小语言程序基本上能完成词法分析阶段的工作,识别诸如begin,if等保留字;识别非保留字的一般标识符(有下划线、字符、数字,且第一个字符不能是数字)。

识别数字序列(整数和小数);识别:=,<=,>=之类的特殊符号以及;,(,)等界符。

编译原理课程设计-词法分析器(附含源代码)精选.

编译原理课程设计-词法分析器(附含源代码)精选.

编译原理-词法分析器的设计一.设计说明及设计要求一般来说,编译程序的整个过程可以划分为五个阶段:词法分析、语法分析、中间代码生成、优化和目标代码生成。

本课程设计即为词法分析阶段。

词法分析阶段是编译过程的第一个阶段。

这个阶段的任务是从左到右一个字符一个字符地读入源程序,对构成源程序的字符流进行扫描和分解,从而识别出一个个单词(也称单词符号或符号)。

如保留字(关键字或基本字)、标志符、常数、算符和界符等等。

二.设计中相关关键字说明1.基本字:也称关键字,如C语言中的if , else , while , do ,for,case,break,return 等。

2.标志符:用来表示各种名字,如常量名、变量名和过程名等。

3.常数:各种类型的常数,如12,6.88,和“ABC”等。

4.运算符:如+ ,- , * , / ,%, < , > ,<= , >= 等。

5.界符,如逗点,冒号,分号,括号,# ,〈〈,〉〉等。

三、程序分析词法分析是编译的第一个阶段,它的主要任务是从左到右逐个字符地对源程序进行扫描,产生一个个单词序列,用以语法分析。

词法分析工作可以是独立的一遍,把字符流的源程序变为单词序列,输出在一个中间文件上,这个文件做为语法分析程序的输入而继续编译过程。

然而,更一般的情况,常将词法分析程序设计成一个子程序,每当语法分析程序需要一个单词时,则调用该子程序。

词法分析程序每得到一次调用,便从源程序文件中读入一些字符,直到识别出一个单词,或说直到下一个单词的第一个字符为止。

四、模块设计下面是程序的流程图五、程序介绍在程序当前目录里建立一个文本文档,取名为infile.txt,所有需要分析的程序都写在此文本文档里,程序的结尾必须以“@”标志符结束。

程序结果输出在同一个目录下,文件名为outfile.txt,此文件为自动生成。

本程序所输出的单词符号采用以下二元式表示:(单词种别,单词自身的值)如程序输出结果(57,"#")(33,"include")(52,"<")(33,"iostream") 等。

(完整)编译原理实验报告(词法分析器 语法分析器)

(完整)编译原理实验报告(词法分析器 语法分析器)

编译原理实验报告实验一一、实验名称:词法分析器的设计二、实验目的:1,词法分析器能够识别简单语言的单词符号2,识别出并输出简单语言的基本字。

标示符。

无符号整数.运算符.和界符。

三、实验要求:给出一个简单语言单词符号的种别编码词法分析器四、实验原理:1、词法分析程序的算法思想算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号.2、程序流程图(1)主程序(2)扫描子程序3、各种单词符号对应的种别码五、实验内容:1、实验分析编写程序时,先定义几个全局变量a[]、token[](均为字符串数组),c,s( char型),i,j,k(int型),a[]用来存放输入的字符串,token[]另一个则用来帮助识别单词符号,s用来表示正在分析的字符.字符串输入之后,逐个分析输入字符,判断其是否‘#’,若是表示字符串输入分析完毕,结束分析程序,若否则通过int digit(char c)、int letter(char c)判断其是数字,字符还是算术符,分别为用以判断数字或字符的情况,算术符的判断可以在switch语句中进行,还要通过函数int lookup(char token[])来判断标识符和保留字。

2 实验词法分析器源程序:#include 〈stdio.h〉#include <math.h>#include <string。

h>int i,j,k;char c,s,a[20],token[20]={’0’};int letter(char s){if((s〉=97)&&(s〈=122)) return(1);else return(0);}int digit(char s){if((s〉=48)&&(s<=57)) return(1);else return(0);}void get(){s=a[i];i=i+1;}void retract(){i=i-1;}int lookup(char token[20]){if(strcmp(token,"while")==0) return(1);else if(strcmp(token,"if")==0) return(2);else if(strcmp(token,"else”)==0) return(3);else if(strcmp(token,"switch”)==0) return(4);else if(strcmp(token,"case")==0) return(5);else return(0);}void main(){printf(”please input string :\n");i=0;do{i=i+1;scanf("%c",&a[i]);}while(a[i]!=’#’);i=1;j=0;get();while(s!=’#'){ memset(token,0,20);switch(s){case 'a':case ’b':case ’c':case ’d':case ’e’:case ’f’:case 'g’:case ’h':case 'i':case ’j':case 'k’:case ’l':case 'm’:case 'n':case ’o':case ’p':case ’q’:case 'r’:case 's’:case 't’:case ’u’:case ’v’:case ’w’:case ’x':case ’y':case ’z’:while(letter(s)||digit(s)){token[j]=s;j=j+1;get();}retract();k=lookup(token);if(k==0)printf("(%d,%s)”,6,token);else printf("(%d,—)",k);break;case ’0':case ’1’:case ’2':case ’3':case '4’:case '5’:case ’6':case ’7’:case ’8’:case '9’:while(digit(s)){token[j]=s;j=j+1;get();}retract();printf(”%d,%s",7,token);break;case '+':printf(”(’+',NULL)”);break;case ’-':printf("(’-',null)");break;case ’*':printf(”('*’,null)");break;case '<':get();if(s=='=’) printf(”(relop,LE)”);else{retract();printf("(relop,LT)");}break;case ’=':get();if(s=='=’)printf("(relop,EQ)");else{retract();printf(”('=',null)”);}break;case ’;':printf(”(;,null)");break;case ' ’:break;default:printf("!\n”);}j=0;get();} }六:实验结果:实验二一、实验名称:语法分析器的设计二、实验目的:用C语言编写对一个算术表达式实现语法分析的语法分析程序,并以四元式的形式输出,以加深对语法语义分析原理的理解,掌握语法分析程序的实现方法和技术.三、实验原理:1、算术表达式语法分析程序的算法思想首先通过关系图法构造出终结符间的左右优先函数f(a),g(a)。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
};
/*****************************重要数据结构的声明结束*************************/
/*********************************全局变量声明开始**************************/
int place=1;
/*26*/{999,12,999,999,999,999,999,9,999,999,999,11,13,999,999,999,33,10,999,999},
/*27*/{999,999,68,999,999,68,68,999,999,20,21,999,999,999,999,999,999,999,999,999},
#define op_add 9 //+
#define op_mul 10 //*
#define op_2star 11 //**
#define div_fenhao 12 //;
#define syl_ls 13 //(
#define syl_rs 14 //)
#define syl_lb 15 //{
/*4*/{999,999,999,999,7,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999},
/*5*/{999,999,999,999,999,999,999,999,999,999,999,999,999,61,999,999,999,999,999,999},
/*30*/{999,999,72,72,999,72,72,999,72,72,72,999,999,72,999,999,999,999,999,999},
/*31*/{999,999,999,75,999,999,999,999,999,999,999,999,999,63,999,999,999,999,999,34},
/*12*/{999,12,999,999,999,999,999,999,999,999,999,11,13,999,999,999,999,23,999,999},
/*13*/{999,999,73,73,999,73,73,999,73,73,73,999,999,73,999,999,999,999,999,999},
/*6*/{999,12,999,999,999,999,999,9,999,999,999,11,13,999,999,999,8,10,999,999},
/*7*/{999,12,999,999,999,999,999,999,999,999,999,11,13,999,999,999,999,14,999,999},
#define ELSE 3 //else
#define shishu 4 //float
#define PRINT 5 //print
#define ID 6 //identify
#define CONSTANT 7 //constant
#define op_fuzhi 8 //=
/*18*/{999,999,67,999,999,67,67,999,999,999,999,999,999,999,999,999,999,999,999,999},
/*19*/{999,12,999,999,999,999,999,999,999,999,999,11,13,999,999,999,999,27,999,999},
/*16*/{74,999,999,999,999,999,999,999,999,999,999,999,74,74,999,999,999,999,999,25},
/*17*/{74,999,999,999,999,999,999,999,999,999,999,999,74,74,999,999,999,999,999,26},
/*8*/{999,999,15,999,999,16,17,999,999,999,999,999,999,999,999,999,999,999,999,999},
/*9*/{999,12,999,999,999,999,999,9,999,999,999,11,13,999,999,999,18,10,999,999},
/*28*/{999,999,69,69,999,69,69,999,69,69,21,999,999,69,999,999,999,999,999,999},
/*29*/{999,999,70,70,999,70,70,999,70,70,70,999,999,70,999,999,999,999,999,999},
#define op_or 23 //||
#define rop_fei 24 //!
#define rop_equal 25 //==
#define rop_dayu 26 //>
#define rop_xiaoyu 27 //<
#define rop_buxiaoyu 28 //>=
/*2*/{74,999,999,999,999,999,999,999,999,999,999,999,74,74,999,999,999,999,5,999},
/*3*/{999,6,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999},
int nextpos=1;
stack<list *> stknext;
stack<list *> stktrue;
stack<list *> stkfalse;
stack<int> stkpos;
stack<delos> stktemp;//常量,变量,临时变量
delos temp;
//条件语句的LR(1)分析表,110表示接受,999表示出错
int table[38][20]={
/*0*/{3,999,999,999,999,999,999,999,999,999,999,999,4,999,1,2,999,999,999,999},
/*1*/{999,999,999,999,999,999,999,999,999,999,999,999,999,110,999,999,999,999,999,999},
/*14*/{999,999,999,64,999,999,999,999,999,20,21,999,999,64,999,999,999,999,999,999},
/*15*/{74,999,999,999,999,999,999,999,999,999,999,999,74,74,999,999,999,999,24,999},
/*36*/{3,999,999,999,999,999,999,999,999,999,999,999,4,999,999,37,999,999,999,999},
/*37*/{999,999,999,62,999,999,999,999,999,999,999,999,999,62,999,999,999,999,999,999}
/*34*/{999,999,999,35,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999},
/*35*/{74,999,999,999,999,999,999,999,999,999,999,999,74,74,999,999,999,999,36,999},
#def sbl_lm 17 //[
#define sbl_rm 18 //]
#define op_sub 19 //-
#define op_div 20 // /
#define div_douhao 21 //,
#define rop_yu 22 //&&
/*20*/{999,12,999,999,999,999,999,999,999,999,999,11,13,999,999,999,999,28,999,999},
/*21*/{999,12,999,999,999,999,999,999,999,999,999,11,13,999,999,999,999,29,999,999},
struct delos
{
int code,value;
}*result; //结果
//变量表
struct analyse
{
int state;
char sign;
};
struct list
{
int value;
list *next;
};
"==",">","<",">=","<=","!="};
//变量
string *var;
int varlen=0,nowvar=1;
/*24*/{3,999,999,999,999,999,999,999,999,999,999,999,4,999,999,31,999,999,999,999},
/*25*/{999,12,999,999,999,999,999,9,999,999,999,11,13,999,999,999,32,10,999,999},
/*32*/{999,999,65,999,999,65,65,999,999,999,999,999,999,999,999,999,999,999,999,999},
相关文档
最新文档