C语言语法分析器

合集下载

llvm编译c-概述说明以及解释

llvm编译c-概述说明以及解释

llvm编译c-概述说明以及解释1.引言1.1 概述LLVM(Low Level Virtual Machine)是一个开源的编译器基础设施,它提供了广泛的编译技术和工具。

通过LLVM,我们可以实现高效的代码生成、优化和分析,从而实现跨平台的编译。

LLVM已经成为许多编程语言的编译器后端,如C、C++、Objective-C等。

在本文中,我们将重点讨论LLVM编译C语言的过程。

我们将介绍LLVM的基本结构和原理,探讨如何使用LLVM将C代码编译成机器代码,并深入研究LLVM在编译优化中的应用。

通过本文的学习,读者将能够更深入地了解编译器技术和LLVM在其中的作用。

1.2 文章结构文章结构部分主要介绍了整篇文章的组织和安排,包括引言、正文和结论三个部分。

具体内容如下:引言部分包括概述、文章结构和目的三个小节。

在概述中,会对整个文章的主题进行简要介绍,引出文章的主要内容。

文章结构部分则是本节所在的部分,介绍了整篇文章的框架和组成部分。

而目的部分则会说明为什么要撰写这篇文章,读者可以在这里了解到文章的写作意图和期望达到的效果。

正文部分则包括LLVM简介、LLVM编译C语言的过程和LLVM在编译优化中的应用三个小节。

在这三个小节中,会详细介绍LLVM技术的背景和原理,以及在实际编译C语言过程中的应用和优化效果。

结论部分包括总结、未来展望和结束语三个小节。

在总结部分,会对整篇文章的内容进行概括和总结,重点强调文章的主要观点和结论。

未来展望部分则会展望LLVM技术在未来的发展方向和应用领域,为读者提供展望和思考的角度。

结束语则是文章的结尾部分,可以对读者提出反思或启发,激发读者的思考和讨论。

1.3 目的:本文旨在介绍使用LLVM编译器进行C语言编译的过程,并探讨LLVM 在编译优化中的应用。

通过深入了解LLVM编译器的工作原理和优化技术,读者可以更好地理解现代编译器的工作机制,并学习如何利用LLVM提供的优化功能提高代码执行效率和性能表现。

简单C语言编译器

简单C语言编译器

简单C语言编译器编译器是一种将高级语言转换为机器语言的软件工具。

它是编译原理中的一个重要概念,负责将程序源代码转换成可执行文件。

在这个过程中,编译器会对源代码进行词法分析、语法分析、语义分析和代码优化等操作。

一个简单的C语言编译器包含以下主要组件:1. 词法分析器(Lexer):词法分析器将源代码分割成一个个词素(token),例如关键字、标识符、运算符和常量等。

它可以通过有限自动机(DFA)来实现,也可以使用现有的词法分析工具如Lex。

2. 语法分析器(Parser):语法分析器根据对应的语法规则,将一系列的词素组合成语法树。

它可以通过上下文无关文法(CFG)来实现,例如使用自顶向下的递归下降分析法或自底向上的移入-规约分析法。

3. 语义分析器(Semantic Analyzer):语义分析器对语法树进行语义检查,例如检查变量的声明和使用是否匹配、类型转换是否合法、函数调用是否正确等。

它还可以生成符号表,用于存储程序中的变量、函数和类型等信息。

4. 中间代码生成器(Intermediate Code Generator):中间代码生成器将语法树转换成一种中间表示形式,通常是三地址码、虚拟机指令或者抽象语法树。

该中间表示形式能够方便后续的代码优化和目标代码生成。

5. 代码优化器(Code Optimizer):代码优化器对中间代码进行优化,以提高目标代码的性能。

常见的优化技术包括常量折叠、复写传播、循环展开、函数内联等。

优化器的目标是在不改变程序行为的前提下,尽可能地减少执行时间和存储空间。

6. 目标代码生成器(Code Generator):目标代码生成器将优化后的中间代码转换成机器语言代码。

它可以根据目标平台的特点选择合适的指令集和寻址方式,并生成可以被计算机硬件执行的程序。

7. 符号表管理器(Symbol Table Manager):符号表管理器负责管理程序中的符号表,其中包含了变量、函数和类型等信息。

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

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

函数 int f(char c) 和 int g(char c) , 判断运算符之间的优先关系 , 根据不同情况作各种不同操作 。 流程
图如下 :
word 完美格式
专业资料
输入算数表达式,以 #结束 初始化 loptr[1]= ’#’ 用 get()取一个待分析字符 s
Optr[1] 和 s 是否同时为 #

2 、而且对词法分析和语法分析在实践中的应用有了深入的掌握

3 、 更加熟悉了构造词法分析程序和语法分析程序的手工方式的相关原理
, 能够实现对词
法分析程序所提供的单词符号序列进行相应的语法检查和结构分析
,达到了学以致用的目的 。
word 完美格式
word 完美格式
专业资料
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)
-
9
*
10
<=
11
<
11
==
11
=
12
;
13
word 完美格式
助记符 while
if else switch case

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

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

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

4、状态转换图:字符a包括:= , & , | , + , --字符b包括:-- , < , > , | , *字符c包括:, , : , ( , ) , { , } , [ , ] , ! ,# , % , ” , / , * , + , -- , > , <, .三、源代码如下:#include <stdio.h>#include <string.h>char set[1000],str[500],strtoken[20];char sign[50][10],constant[50][10];char ch;int sr,to,id=0,st=0;typedef struct keytable /*放置关键字*/{char name[20];int kind;}KEYTABLE;KEYTABLE keyword[]={ /*设置关键字*/{"main",0},{"int",1},{"float",2},{"char",3},{"if",4},{"else",5},{"for",6},{"while",7},{"do",8},{"switch",9},{"case",10},{"break",11},{"default",12},};openfile() /*打开文件*/{FILE *fp;char a,filename[10];int n=0;printf("Input the filename:");gets(filename);if((fp=fopen(filename,"r"))==NULL){printf("cannot open file.\n");exit(0);}elsewhile(!feof(fp)) /*文件不结束,则循环*/{a=getc(fp); /*getc函数带回一个字符,赋给a*/set[n]=a; /*文件的每一个字符都放入set[]数组中*/n++;}fclose(fp); /*关闭文件*/set[n-1]='\0';printf("\n\n-------------------Source Code--------------------------\n\n");puts(set);printf("\n--------------------------------------------------------\n");}reflesh() /*清空strtoken数组*/{to=0; /*全局变量to是strtoken的指示器*/strcpy(strtoken," ");}prearrange1() /*预处理程序1*/{int i,a,b,n=0;do{if(set[n]=='/' && set[n+1]=='*'){a=n; /*记录第一个注释符的位置*/while(!(set[n]=='*' && set[n+1]=='/'))n++;b=n+1; /*记录第二个注释符的位置*/for(i=a;i<=b;i++) /**/set[i]=' '; /*把注释的内容换成空格,等待第二步预处理*/ }n++;}while(set[n]!='\0');}prearrange2() /*预处理程序2*/{int j=0;sr=0; /*全局变量sr是str[]的指示器*/do{if(set[j]==' ' || set[j]=='\n'){while(set[j]==' ' || set[j]=='\n') /*扫描到有连续的空格或换行符*/j++;str[sr]=' '; /*用一个空格代替扫描到的连续空格和换行符放入str[]*/sr++;}else{str[sr]=set[j]; /*若当前字符不为空格或换行符就直接放入str[]*/sr++;j++;}}while(set[j]!='\0');str[sr]='\0';}char GetChar() /*把字符读入全局变量ch中,指示器sr前移*/{ch=str[sr];sr++;return(str[sr-1]);}void GetBC() /*开始读入符号,直至第一个不为空格*/{while(ch==' '){ch=GetChar();}}Concat() /*把ch中的字符放入strtoken[]*/{strtoken[to]=ch;to++; /*全局变量to是strtoken的指示器*/strtoken[to]='\0';}int IsLetter() /*判断是否为字母*/{if((ch>=65 && ch<=90)||(ch>=97 && ch<=122))return(1);else return(0);}int IsDigit() /*判断是否为数字*/{if(ch>=48 && ch<=57)return(1);else return(0);}int Reserve() /*对strtoken中的字符串查找保留字表,若是则返回它的编码,否则返回-1*/ {int i,k=0;for(i=0;i<=20;i++){if(strcmp(strtoken,keyword[i].name)==0){ k=1;return(keyword[i].kind);}}if(k!=1)return(-1);}void Retract() /*指示器sr回调一个字符位置,把ch置为空*/{sr--;}int InsertId(){int i,k;for(i=0;i<id;i++){k=strcmp(strtoken,sign[i]);if(k==0)return(i);}strcpy(sign[id],strtoken); /*插入标识符*/id++;return(id-1);}int InsertConst(){int i,k;for(i=0;i<st;i++){k=strcmp(strtoken,constant[i]);if(k==0)return(i);}strcpy(constant[st],strtoken); /*插入常数*/st++;return(st-1);}void analysis(){int value;reflesh(); /*清空strtoken数组*/prearrange1(); /*预处理,使注释内容换成单个空格,放回set[]中*/prearrange2(); /*预处理,使set[]中连续的空格置换成单个空格,并把set[]的内容放到str[]中*/GetChar();GetBC(); /*读取第一个字符*/while(ch!='\0') /*当不等于结束符,继续执行*/{if(IsLetter()){while(IsLetter() || IsDigit()) /*若第一个是字符,继续读取,直到出现空格*/{Concat();GetChar();}Retract(); /*指示器sr回调一个字符位置,把ch置为空*/value=Reserve(); /*对strtoken中的字符串查找保留字表,若是则返回它的编码,否则返回-1*/ if(value==-1) /*如果返回值是-1,那就是变量,把它输出*/{InsertId(); /*插入标识符*/printf("\n%s",strtoken);getch();}else /*否则就是关键字,也输出*/{printf("\n%s",strtoken);getch();}reflesh();}else if(IsDigit()){while(IsDigit()) /*否则,若第一个是数字,继续读取,知道出现空格*/{Concat();GetChar();}Retract();InsertConst(); /*插入常数*/printf("\n%s",strtoken);getch();reflesh();}elseswitch(ch) /*否则,若是下面的符号,就直接把它输出*/{case ',':case ';':case '(':case ')':case '{':case '}':case '[':case ']':case '!':case '#':case '%':case '"':case '/':case '*':Concat();printf("\n'%s'",strtoken);getch();reflesh();break;default:if(ch=='=' || ch=='&' || ch=='|' || ch=='+' || ch=='-') /*如果是这些符号,继续读取下一个*/ {Concat(); /*判断是否为==,&&,||,++,--的情况*/GetChar();if(ch==strtoken[0])Concat();elseRetract();printf("\n'%s'",strtoken);getch();reflesh();break;}else if(ch=='+' || ch=='-' || ch=='<' || ch=='>' || ch=='!' || ch=='*'){Concat(); /*判断是否为+=,-=,<=,>=,!=,*=的情况*/GetChar();if(ch=='=')Concat();elseRetract();printf("\n'%s'",strtoken);getch();reflesh();break;}else{printf("Error!");getch();break;}}GetChar();GetBC();}}main(){clrscr();openfile();analysis();printf(“analysis is over!”);}五、测试结果:1、分析文件test1.c中的程序:Input the filename:test.c*****************Original Code************************/* HELLO.C -- Hello, world */#include "stdio.h"#include "conio.h"main(){printf("Hello, world\n");getch();}*****************************************************'#'include'"'stdio'.'h'"''#'include'"'conio'.'h'"'main'('')''{'printf'(''"'Hello','worldError!n'"'')'';'getch'('')'';''}'Analysis is over!六、实验总结:这个程序主要参考书上关于词法分析器的设计。

语法分析器文档

语法分析器文档
这里我们采用递归下降分析方法:直接以程序的方式模拟产生式产生语言的过程。它的基本设计思想是:为每一个非终结符构造一个子程序,每一个子程序的过程体中按该产生式的候选项分情况展开,遇到终结符直接匹配,而遇到非终结符就调用相应非终结符的子程序。该分析从调用文法开始符号的子程序开始,直到所有非终结符都展开为终结符并得到匹配为止。若分析过程中达到这一步则表明分析成功,否则表明输入中有语法错误。递归下降分析对文法的限制是不能有公共左因子和左递归。由于文法是递归定义的,因此子程序也是递归的。
初使化词法分析器
识别出具有独立意义的最小语法单位
辅助性模块
②重要数据结构
·语法树节点类型
struct ExprNode { //语法树节点类型
enum Token_Type OpCode;
union {
struct {
ExprNode *Left, *Right;
} CaseOperator;
struct {
重复此过程,直到所有A产生式的候选项中均不再有公共前缀。
·构造递归下降子程序的方法:
①构造文法的状态转换图并且简化;
②将转换图转化为EBNF表示;
③从EBNmain.cpp)
#include <stdio.h>
#include "parser.h"
·消除左递归算法
输入:无回路文法G
输出:无左递归的等价文法G’
方法:将非终结符合理排序:A1,A2,…,An,然后运用下述过程:
for i in 2..n
loop for j in 1..i-1
loop用AjQ1|Q2|…|Qk的右部替换每个形如AiAj产生式中的Aj,得到新产生式:

语法分析器

语法分析器

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

可以编译c语言的基本结构,包括循环嵌套和条件嵌套。

二.实验的输入输出(1)执行程序时,可输入源程序的路径,如果输入为空的话,将会编译默认的源程序“./input.dat”(2)如果编译发现有错误,则会输出错误行数,并在结束编译时输出“Complete!”三.语法结构程序:=main()<语句块>语句块:=’{’ <赋值语句> ’}’赋值语句valueStatement: = <int|char> id = expression{,id = expression};循环语句的分析recycleStatement := while(condition){statementBlock}条件语句conditionStatement := if(condition)"{"statementBlock"}"{else if conditionStatement} | else statementBlock条件的分析condition := expression(>= | <= | == | > | < | !=)expression因子的分析factor := (expression)|id|number项的分析term := facto人{*factor|/factor)}表达式的分析expression := term{+term|-term}四.分析器主要代码/** 表达式的分析 expression = term{+term|-term}*/private void expression() {this.term();this.scanNext();while (this.match("+") || this.match("-")) {this.term();this.scanNext();}this.scanBack();}/** 项的分析 term = facto人{*factor|/factor)}*/private void term() {this.factor();this.scanNext();while (this.match("*") || this.match("\\")) {this.factor();this.scanNext();}this.scanBack();}/** 因子的分析 factor = (expression)|id|number*/private void factor() {this.scanNext();if (this.match("id") || this.match("number")) {// ---------------------------------------------------} else if (this.match("(")) {this.expression();this.matchNext(")");} else {System.out.println(row + " Error: factor error!");}}/** 条件的分析 condition = expression(>= | <= | == | > | < | !=)expression */private void condition() {this.expression();this.scanNext();if (this.match("<=") || this.match("==") || this.match(">=") || this.match(">") || this.match("<") || this.match("!=")) {} else {System.out.println(row + " ERROR: condition error!");}this.expression();}/** 条件语句 conditionStatement =if(condition)"{"statementBlock"}"{else* conditionStatement}|else statementBlock*/private void conditionStatement() {this.matchNext("if");this.matchNext("(");this.condition();this.matchNext(")");this.statementBlock();this.scanNext();if (this.match("else")) {this.scanNext();if (this.match("{")) {this.scanBack();this.statementBlock();} else if (this.match("if")) {this.scanBack();this.conditionStatement();} else {System.out.println(row + " ERROR: conditionStatement error!");}} else {this.scanBack();}}/** 循环语句的分析 recycleStatement = while(condition){statementBlock} */private void recycleStatement() {this.matchNext("while");this.matchNext("(");this.condition();this.matchNext(")");this.statementBlock();}/** 赋值语句分析 valueStatement = <int|char> id = expression{,id = expression};*/private void intValueStatement() {int nowRow = this.row;this.matchNext("int");this.matchNext("id");this.scanNext();if (this.match("=")) {this.expression();} else {this.scanBack();}this.scanNext();while (this.match(",")) {this.matchNext("id");this.scanNext();if (this.match("=")) {this.expression();} else {this.scanBack();}if (this.row != nowRow) {System.out.println(row + " ERROR: intValueStatement error!");}this.scanNext();}this.scanBack();}private void charValueStatement() {int nowRow = this.row;this.matchNext("char");this.matchNext("id");this.scanNext();if (this.match("=")) {this.expression();} else {this.scanBack();}this.scanNext();while (this.match(",")) {this.matchNext("id");this.scanNext();if (this.match("=")) {this.expression();} else {this.scanBack();}if (this.row != nowRow) {System.out.println(row + " ERROR: intValueStatement error!");}this.scanNext();}this.scanBack();}/** 语句块的分析*/private void statementBlock() {this.matchNext("{");this.statementSequence();this.matchNext("}");}/** 语句串的分析*/private void statementSequence() {this.scanNext();while (this.match("if") || this.match("while") ||this.match("id")|| this.match(";") || this.match("int") ||this.match("char")) {if (this.match("if")) {this.scanBack();this.conditionStatement();} else if (this.match("while")) {this.scanBack();this.recycleStatement();} else if (this.match("id")) {this.matchNext("=");this.expression();this.matchNext(";");} else if (this.match("int")) {this.scanBack();this.intValueStatement();} else if (this.match("char")) {this.scanBack();this.charValueStatement();} else if (this.match(";")) {}this.scanNext();}this.scanBack();}public void parseMain() {this.matchNext("main");this.matchNext("(");this.matchNext(")");this.statementBlock();System.out.println("Complete!");}五.小结通过此次语法分析器的编写,不仅使我更清楚的熟悉了语法分析文法,同时也再次巩固了词法分析的知识。

用C语言实现简单的词法分析器

用C语言实现简单的词法分析器

⽤C语⾔实现简单的词法分析器词法分析器⼜称扫描器。

词法分析是指将我们编写的⽂本代码流解析为⼀个⼀个的记号,分析得到的记号以供后续语法分析使⽤。

词法分析器的⼯作是低级别的分析:将字符或者字符序列转化成记号.。

要实现的词法分析器单词符号及种别码对照表:单词符号#begin if then while do End+-*/:: =种别码0123456131415161718单词符号<<><=>>==;()Letter(letter|digit)digit digit*种别码2021222324252627281011#include<stdio.h>#include<string.h>char input[200];//存放输⼊字符串char token[5];//存放构成单词符号的字符串char ch; //存放当前读⼊字符int p; //input[]下标int fg; //switch标记int num; //存放整形值//⼆维字符数组,存放关键字char index[6][6]={"begin","if","then","while","do","end"};main(){p=0;printf("please intput string(End with '#'):\n");do{ch=getchar();input[p++]=ch;}while(ch!='#');p=0;do{scaner();switch(fg){case 11:printf("( %d,%d ) ",fg,num);break;case -1:printf("input error\n"); break;default:printf("( %d,%s ) ",fg,token);}}while(fg!=0);getch(); //⽤于让程序停留在显⽰页⾯}/*词法扫描程序:*/scaner(){int m=0;//token[]下标int n;//清空token[]for(n=0;n<5;n++)token[n]=NULL;//获取第⼀个不为0字符ch=input[p++];while(ch==' ')ch=input[p++];//关键字(标识符)处理流程if((ch<='z'&&ch>='a')||(ch<='Z'&&ch>='A')){while((ch<='z'&&ch>='a')||(ch<='Z'&&ch>='A')||(ch<='9'&&ch>='0')){token[m++]=ch;ch=input[p++];}token[m++]='\0';ch=input[--p];fg=10;for(n=0;n<6;n++)if(strcmp(token,index[n])==0)//strcmp()⽐较两个字符串,相等返回0{fg=n+1;break;}}//数字处理流程else if((ch<='9'&&ch>='0')){num=0;while((ch<='9'&&ch>='0')){num=num*10+ch-'0';ch=input[p++];}ch=input[--p];fg=11;}//运算符界符处理流程elseswitch(ch){case '<':m=0;token[m++]=ch;ch=input[p++];if(ch=='>') //产⽣<>{fg=21;token[m++]=ch;}else if(ch=='=') //产⽣<={fg=22;token[m++]=ch;}else{fg=20;ch=input[--p];}break;case '>':token[m++]=ch;ch=input[p++];if(ch=='=') //产⽣>={fg=24;token[m++]=ch;}else //产⽣>{fg=23;ch=input[--p];}break;case ':':token[m++]=ch;ch=input[p++];if(ch=='=') //产⽣:={fg=18;token[m++]=ch;}else //产⽣:{fg=17;ch=input[--p];}break;case '+':fg=13;token[0]=ch;break; case '-':fg=14;token[0]=ch;break; case '*':fg=15;token[0]=ch;break; case '/':fg=16;token[0]=ch;break; case ':=':fg=18;token[0]=ch;break; case '<>':fg=21;token[0]=ch;break; case '<=':fg=22;token[0]=ch;break; case '>=':fg=24;token[0]=ch;break; case '=':fg=25;token[0]=ch;break; case ';':fg=26;token[0]=ch;break; case '(':fg=27;token[0]=ch;break; case ')':fg=28;token[0]=ch;break; case '#':fg=0;token[0]=ch;break; default:fg=-1;}}。

语法分析器生成器YACC

语法分析器生成器YACC

E : num num
再分析3++5
5
分析器动作 移进 num,转向state 3 按(2)“E : num”归约,goto State 1 移进 +,转向State 4 移进error,转向 state 2 按(3)“E : error”归约,goto State 5, 按(1)“E : E‘+’E”归约,goto State 1 移进 +,转向State 4 移进 num,转向 State 3 按(2)“E : num”归约,goto State 5 按(1)“E : E‘+’E”归约,goto State 1 接受
2.2.3.2 YACC对语义的支持
分析器工作原理:
记号流 归约前栈顶 归约后栈顶 $3 E $2 + $1($$) E ... ... 驱动器 分析表 输出
语义栈对语法制导翻译提供直接支持。语义栈的 类型决定了文法符号的属性,语义栈类型表示能力的 强弱决定了YACC的能力。
<1> YACC默认的语义值类型 YACC语义栈与yylval同类型,并以终结符的yylval 值作为栈中的初值。因为yylval的默认类型为整型,所 以,当用户所需文法符号的语义类型是整型时,无需定 义它的类型。如在下述表达式的产生式中: E :E '+' E | E '*' E | num ; { $$=$1+$3;} { $$=$1*$3;}
2.2.1 YACC概述
利用YACC进行语法分析器设计的关键,也是如何编写 YACC源程序。 下边首先介绍YACC源程序的基本结构,然后着重讨论 YACC的产生式、YACC解决产生式冲突的方法、以及YACC对语 义的支持和对错误的处理等。

C语言编译原理词法分析和语法分析

C语言编译原理词法分析和语法分析

C语言编译原理词法分析和语法分析编程语言的编写和使用离不开编译器的支持,而编译器的核心功能之一就是对代码进行词法分析和语法分析。

C语言作为一种常用的高级编程语言,也有着自己的词法分析和语法分析规则。

一、词法分析词法分析是编译器的第一阶段,也是将源代码拆分为一个个独立单词(token)的过程。

在C语言中,常见的单词包括关键字(如if、while等)、标识符(如变量名)、常量(如数字、字符常量)等。

词法分析器会根据预定义的规则对源代码进行扫描,并将扫描到的单词转化为对应的符号表示。

词法分析的过程可以通过有限自动机来实现,其中包括各种状态和状态转换规则。

词法分析器通常会使用正则表达式和有限自动机的方法来进行实现。

通过词法分析,源代码可以被分解为一个个符号,为后续的语法分析提供基础。

二、语法分析语法分析是编译器的第二阶段,也是将词法分析得到的单词序列转换为一棵具有语法结构的抽象语法树(AST)的过程。

在C语言中,语法分析器会根据C语言的文法规则,逐句解析源代码,并生成相应的语法树。

C语言的语法规则相对复杂,其中包括了各种语句、表达式、声明等。

语法分析的过程主要通过递归下降分析法、LR分析法等来实现。

语法分析器会根据文法规则建立语法树的分析过程,对每个语法结构进行逐步推导和分析,最终生成一棵完整的语法树。

三、编译器中的词法分析和语法分析在编译器中实现词法分析和语法分析是一项重要的技术任务。

编译器通常会将词法分析和语法分析整合在一起,形成一个完整的前端。

在C语言编译器中,词法分析和语法分析器会根据C语言的词法规则和文法规则,对源代码进行解析,并生成相应的中间表示形式,如语法树或者中间代码。

词法分析和语法分析的结果会成为后续编译器中各个阶段的输入,如语义分析、中间代码生成、目标代码生成等。

编译器的优化和错误处理也与词法分析和语法分析有密切关系。

因此,对词法分析和语法分析的理解和实现对于编译器开发者而言是非常重要的。

C语言编译原理编译过程和编译器的工作原理

C语言编译原理编译过程和编译器的工作原理

C语言编译原理编译过程和编译器的工作原理C语言是一种广泛使用的计算机编程语言,它具有高效性和可移植性的特点。

在C语言程序的运行之前,需要通过编译器将源代码翻译成机器可以执行的目标代码。

编译器是一种专门用于将高级语言源代码转换为机器语言的程序。

编译过程分为四个主要阶段,包括词法分析、语法分析、语义分析和代码生成。

下面我们逐一介绍这些阶段的工作原理。

1. 词法分析词法分析是编译过程的第一步,它将源代码分解成一系列的词法单元,如标识符、常量、运算符等。

这些词法单元存储在符号表中,以便后续的分析和转换。

2. 语法分析语法分析的目标是将词法单元按照语法规则组织成一个语法树,以便进一步的分析和优化。

语法分析器使用文法规则来判断输入的字符串是否符合语法规范,并根据语法规则生成语法树。

3. 语义分析语义分析阶段对语法树进行分析并在合适的地方插入语义动作。

语义动作是一些与语义相关的处理操作,用于检查和修正代码的语义错误,并生成中间代码或目标代码。

4. 代码生成代码生成是编译过程的最后一个阶段,它将中间代码或语法树翻译为目标代码,使得计算机可以直接执行。

代码生成阶段涉及到指令的选择、寄存器分配、数据位置的确定等一系列的优化操作,以提高程序的性能和效率。

编译器是实现编译过程的工具。

它接收源代码作为输入,并将其转换为目标代码或可执行文件作为输出。

编译器工作原理可以简单概括为:读取源代码、进行词法分析和语法分析、生成中间代码、进行优化、生成目标代码。

编译器在编译过程中还涉及到符号表管理、错误处理、优化算法等方面的工作。

符号表用于管理程序中的标识符、常量、变量等信息;错误处理机制用于检测和纠正程序中的错误;优化算法用于提高程序的性能和效率,例如常量折叠、无用代码删除等。

总结起来,C语言编译过程涉及到词法分析、语法分析、语义分析和代码生成等阶段,每个阶段都有特定的工作原理和任务。

编译器作为实现编译过程的工具,负责将源代码转换为机器可以执行的目标代码。

编译原理词法分析器和语法分析器(急急急!!!)

编译原理词法分析器和语法分析器(急急急!!!)

编译原理实验报告词法分析器实验目的1.熟练掌握词法分析程序的基本原理2.掌握词法分析程序的设计和实现实验内容1.针对一个简化的C语言子集完成对它的词法分析程序的设计与实现2.C语言子集的单词符号挤内码值程序代码:#include "stdio.h"#include "string.h"int i,j,k;char s;char a[20],token[20];int letter(){if((s>=97)&&(s<=122))return 1;else return 0;}int digit(){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(){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("输入源程序,结束用'#':\n");i=0;do{i++;scanf("%c",&a[i]);}while(a[i]!='#');i=1;memset(token,0,sizeof(char)*20);j=0;get();while(s!='#'){if(s==' ')get();else{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++;get();}retract();k=lookup();if(k==0)printf("(%d,%s)\n",6,token); else printf("(%d,unll)\n",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)\n",7,token); break;case'+':printf("(+,null)\n"); break;case'-':printf("(-,null)\n");break;case'*':printf("(*,null)\n");break;case'<':get();if(s=='=')printf("(relop,LE)\n");else {retract();printf("(relop,LT)\n");}break;case'=':get();if(s=='=')printf("(relop,EQ)\n");else{retract();printf("(=,null)\n");}break;case';':printf("(;,null)\n");break;default:printf("(%c,error)\n",s);break;}memset(token,0,sizeof(char)*10);j=0;get();}}}运行结果:编译原理实验报告语法分析器实验目的1.熟练掌握语法分析程序的基本原理2.掌握用算符优先分析法来构造,设计优先函数3.掌握语法分析程序的设计与实现实验内容1.针对一个简单文法完成对它的语法分析程序的设计与实现2.通过语法分析程序来完成多输入的算数表达式进行计算并相应得到的对应四元式程序代码:#include <stdio.h>char a[20],optr[10],s,op;int i,j,k,opnd[10],x1,x2,x3;int operand(char s){if((s>='0')&&(s<='9'))return 1;elsereturn 0;}int f(char s){switch(s){case'+':return 6;case'-':return 8;case'*':return 10;case'/':return 12;case'(':return 2;case')':return 12;case'#':return 2;default:printf("error!\n");}}int g(char s){switch(s){case'+':return 5;case'-':return 7;case'*':return 9;case'/':return 11;case'(':return 13;case')':return 2;case'#':return 2;default:printf("error!\n");}}void get(){i=i+1;s=a[i];}void main(){printf("请输入算数表达式,以'#'结束:\n");i=0;do{i=i+1;scanf("%c",&a[i]);}while(a[i]!='#');i=0;j=0;k=0;optr[j]='#';get();while((optr[j] != '#')||(s != '#')){if(operand(s)){opnd[k]=s-'0';k=k+1;get();}else if(f(optr[j])>g(s)){op=optr[j];j=j-1;x2=opnd[k-1];x1=opnd[k-2];k=k-2;switch(op){case'+':x3=x1+x2;break;case'-':x3=x1-x2;break;case'*':x3=x1*x2;break;case'/':x3=x1/x2;break;}opnd[k]=x3;k=k+1;printf("(%c,%d,%d,%d)\n",op,x1,x2,x3);}else if(f(optr[j]) < g(s)){j=j+1;optr[j]=s;get();}else if(f(optr[j]) == g(s)){j=j-1;get();}elseprintf("error!");}}运行结果:。

Simple C语言词法分析器的探讨与实践

Simple C语言词法分析器的探讨与实践
号> =。
> < > = =
G T L T G E L E
EQ
NE
[ ] ( )
/卑
年/
[ ] { )
[ zE _ A— r
][ -Za— A zO-9]
id

号 项
}l
向 符
表 表
请 注 意 . 果按 照 从 s r状 态 到 达 接 受状 态 如 tt a 3的边 的顺 序 . 意 味着 > 则 和一 个 与 之无 关 的字 符 已经 被读 过 。 由于这 个无 关字 符 不是关 系操作 符> 的一 部 分 .而是 下 一 个词 素 的一 部 分 .所 以 f - 0 r W r 针 必 须 回滚 一 个 字 符 。状 态 上 的 水表 示 ad指
wh i e 1 v i o d
( )
( )
符 , 果 该 字 符 是 > 则 转 向状 态 1 否 则 便 告 识 如 , , 别 > : 败 。到达 状 态 1时 。 下 一 个 字符 , 或> 失 遇 如
果 它 是=。 转 向状 态 2 否 则 标 有 o e 的边 表 明 则 . tr h 已经 转 向状态 3 。在 状态 2上 有双 圈 . 示它 是接 表 受状 态 。 当进 入这 个 状态 时 . 态转 换 图识别 了记 状
+ 一 木/ < < > >= == != = =
;, { ) 【 ]() 厂 水 水 /
图 31状态 转 换 图 .
( 下转 第 15页 ) 6
21 0 2年第 4期
福 建 电

15 6
界 面 和遥 控逻 辑 .实 现一 个通 用 遥 控器 遥 控 多个 间的服 务发 现 问题 .这 些将 在后 续 的工作 中展 开 不 同类 型 的受 控 应 用 , 图 2 图 3所 示 。在 系统 研 究 。 如 ,

用C语言编写的简单编译器

用C语言编写的简单编译器

用C语言编写的简单编译器编译器是软件开发中不可或缺的工具,它可以将高级语言编写的源代码转换成计算机能够理解和执行的机器码。

在本文中,我们将介绍如何用C语言编写一个简单的编译器,让读者了解编译器的基本原理和实现方法。

一、概述编译器是由多个模块组成的,每个模块负责完成不同的任务。

在我们的简单编译器中,我们将实现以下几个基本模块:1. 词法分析器(Lexer):将源代码分解成一个个的词法单元,比如标识符、关键字和运算符等。

词法分析器是编译器的第一个模块,它会读取源代码,并生成一个个的词法单元序列供后续处理。

2. 语法分析器(Parser):根据词法单元序列构建语法分析树,通过语法规则判断源代码是否符合语法规范。

语法分析器会进行递归下降或者使用其他算法进行语法分析,并将结果存储在语法分析树中。

3. 语义分析器(Semantic Analyzer):对语法分析树进行分析,并进行语义检查,比如类型检查、符号表管理等。

语义分析器负责捕捉源代码中可能存在的语义错误,并提供错误提示和修复建议。

4. 中间代码生成器(Intermediate Code Generator):将语法分析树转换成中间代码表示,比如三地址代码、虚拟机代码等。

中间代码生成器是连接语义分析和目标代码生成的桥梁。

5. 目标代码生成器(Codegen):将中间代码转换成目标机器的机器码,并生成可执行文件。

目标代码生成器负责将中间代码翻译成目标机器能够执行的代码,并进行优化以提高执行效率。

二、实现步骤下面以一个简单的四则运算表达式为例,介绍我们的编译器的实现步骤:1. 首先,我们需要定义词法分析器,它会从源代码中逐个读取字符,并根据一定的规则进行词法单元的生成。

在这个例子中,我们可以定义的词法单元有:数字、加号、减号、乘号和除号等。

2. 接下来,我们定义语法分析器,在这个例子中,我们可以使用递归下降的方法来进行语法分析。

我们需要定义一个函数来处理每个非终结符,比如表达式、项和因子等,并根据定义的语法规则进行递归调用。

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

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

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

词法分析器负责将源代码转化为一个个标记(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语言编译器开发理解编译原理和过程

C语言编译器开发理解编译原理和过程编译器是一种将高级语言转化为机器代码的软件工具。

在C语言编程中,编译器是非常重要的,它将我们编写的C代码转化为计算机能够理解和执行的机器语言指令。

了解编译原理和过程对于C语言编译器的开发非常重要。

一、编译原理概述编译原理是计算机科学的一个重要分支,它研究编程语言的词法分析、语法分析、语义分析、中间代码生成和目标代码生成等方面的问题。

编译原理的主要目标是将高级程序设计语言转化为低级机器语言。

二、编译过程1. 词法分析(Lexical Analysis)词法分析是将源代码拆分成符号的过程。

编译器会根据编程语言的语法规则,将源代码转化为一系列的token(标记)。

每个token表示程序中的一个指令或者数据单元。

2. 语法分析(Syntax Analysis)语法分析是将词法分析得到的token序列按照语言的语法规则进行分析和处理。

语法分析器通过构建抽象语法树(Abstract Syntax Tree,AST),确定代码的结构和层次关系。

3. 语义分析(Semantic Analysis)语义分析是在语法分析的基础上,对语法上正确的代码进行语义检查和修正。

它会对变量使用、类型检查、函数调用等进行检查,确保程序的语义正确。

4. 中间代码生成(Intermediate Code Generation)在中间代码生成阶段,编译器会将语法分析器生成的抽象语法树转化为中间代码。

中间代码是一种介于源代码和机器代码之间的表示形式,它更加抽象,能够提供更好的优化和跨平台的能力。

5. 优化(Optimization)编译器在生成目标代码之前,会对中间代码进行一系列的优化操作,以提高程序的性能和效率。

这包括常量折叠、循环展开、无用代码消除等一系列技术。

6. 目标代码生成(Code Generation)目标代码生成是将中间代码转化为目标计算机的机器语言代码的过程。

编译器会将中间代码中的每条指令转化为对应目标机器的指令,包括寄存器分配、指令选择、代码填充等。

语法分析器构造

语法分析器构造

语法分析器构造(总8页)--本页仅作为文档封面,使用时请直接删除即可----内页可以根据需求调整合适字体及大小--编译原理实验报告实验题目:语法分析器构造指导教师:姓名:班级:学号:实验成绩:实验题目语法分析器构造实验目的和要求借助于词法分析程序提供的分析结果,编写一个算符优先语法分析程序,程序能进行语法结构分析和错误检查并产生相应的归约信息。

同时给出出错信息和错误类型,从而加深对语法分析的理解。

设计思想与框架main函数:算术表达式函数:算符优先算法:核心算法主要数据结构说明:符号栈:stack[N]栈顶指针:top记录归约步骤号:No[N]输入字符串:strings[N]算术表达式:old_strings[N]记录下一个输入符号:a可归约字符串:*word[6]手动生成的算符优先表:x[9][9]查找算符表达式:expression(char *str)入栈:push(char ch)出栈:pop(char ch)printf(" # < < < < < e3 < =\n");if((fp=fopen("预处理.txt","r"))==NULL){printf("文件打开失败!");exit(0);}char ch[4048]={'\0'};int i=0,j=0;ch[0]=fgetc(fp);while(ch[i]!='#')//将预处理文件的内容读入至数组ch中ch[++i]=fgetc(fp);ch[++i]='\0';fclose(fp);i=0;while(ch[i]!='#'){memset(strings,0,sizeof(strings));//输入表达式strings初始化memset(old_strings,0,sizeof(old_strings));expression(ch);//查找算术表达式if(ch[sr]=='\0')break;printf("算术表达式%d为:%s\n",id,old_strings);printf("转换为输入串:%s\n",strings);printf(" 步骤号符号栈优先关系当前分析符剩余输入串动作\n");analysis();//算符优先分析int n=0;printf("\n算术表达式%d的归约产生式步骤号为:",id++);while(No[n]){printf("%d ",No[n]);n++;}printf("\n");while(stack[0]!='\0')pop();while(No[--n])No[n]='\0';top=-1;a='\0';k=0;step=1;n=0;}printf("算符优先语法分析结束!\n");getch();return 0;}问题及处理问题:对算符优先分析算法不熟悉,不知道如何下手,从算符优先文法到算符优先表构造再到利用算符优先分析法进行归约,都不清楚。

编译原理课程(词法分析器及语法分析器)

编译原理课程(词法分析器及语法分析器)

编译原理实验报告词法分析器与语法分析器I. 问题描述设计、编制并调试一个词法分析子程序,完成识别语言单词的任务;设计、编制、调试一个语法分析程序,并用它对词法分析程序所提供的单词序列进行语法检查和结构分析。

ii. 设计简要描述界面需求:为了更加形象的模拟过程,此实验使用图形界面。

要求从图形界面上输入输入串,点击词法分析,可以将词法分析后识别的单词符号显示,点击语法分析,可以将语法分析的堆栈过程显示,并且显示结果(是否是符合文法的句子),清空则可以将所有置空。

功能分析:1、由用户输入输入串;2、用户点击“词法分析”,可以将词法分析后识别的单词符号显示。

3、用户点击语法分析,可以将语法分析的堆栈过程显示,并且显示结果(是否是符合文法的句子)4、用户点击清空,则将界面所有组件置为空思路描述:一、设计构想:本实验决定编写一个简易C语言的词法分析器和语法分析器。

使其能够识别while,if等关键字,可以判断赋值语句、条件语句、循环语句。

二、文法分析1、需要识别的关键字及其识别码有:关键字识别码关键字识别码关键字识别码main 0 - 11 ;22int 1 * 12 > 23char 2 / 13 < 24if 3 ( 14 >= 25else 4 ) 15 <= 26for 5 [ 16 == 27while 6 ] 17 != 28ID 7 { 18 ERROR -1NUM 8 } 19= 9 , 20+ 10 : 212、文法〈程序〉→ main()〈语句块〉〈语句块〉→{〈语句串〉}〈语句串〉→〈语句〉;〈语句串〉|〈语句〉;〈语句〉→〈赋值语句〉|〈条件语句〉|〈循环语句〉〈赋值语句〉→ ID =〈表达式〉;〈条件语句〉→ if〈条件〉〈语句块〉〈循环语句〉→ while〈条件〉〈语句块〉〈条件〉→(〈表达式〉〈关系符〉〈表达式〉)〈表达式〉→〈表达式〉〈运算符〉〈表达式〉|(〈表达式〉)|ID|NUM〈运算符〉→+|-|*|/〈关系符〉→<|<=|>|>=|=|!>转化为符号表示:S→ main() K|空K→ { C }C→Y;C |空Y→F | T | XF→ ID = BT→ if J KX→ while J KJ→( B G B )B→ B Z B |( B )| ID | NUMZ→ + | - | * | /G→< | <= | > | >= | == | !>表示含义:S:程序 K:语句块 C:语句串 Y:语句 F :赋值语句T:条件语句 X:循环语句 J:条件 B:表达式 I:项 Z :运算符G:关系符3、LL(1)分析表(1),求出first集及follow集:FIRST(S)={mian}FIRST(K)={{}FIRST(C)= FIRST(Y)= {ID,if,while,空};FIRST(Y)= FIRST(F)+ FIRST(T)+ FIRST(X)={ID,if,while};FIRST(F)={ID};FIRST(T)={if};FIRST(X)={while};FIRST(J)= FIRST(B)={};FIRST(B)={(,ID,NUM };FIRST(Z)={+,-,*,/}FIRST(G)={<,<= ,>,>=,==,!= };FOLLO W(S)={#};FOLLO W(K)={;};FOLLO W(C)={}};FOLLO W(Y)={;}FOLLO W(F)={;};FOLLO W(T)={;};FOLLO W(X)={;};FOLLO W(J)={{,;};FOLLO W(B)={+,-,*,/,),<,<= ,>,>=,==,!=,;};FOLLO W(B’)={+,-,*,/,),<,<= ,>,>=,==,!=,;};FOLLO W(Z)={(,ID,NUM };FOLLO W(G)={(,ID,NUM };(2)消除左递归,拆分文法关系并编号0、S→ 空1、S→ main() K2、K→ { C }3、C→Y;C4、C→空5、Y→ F6、Y→ T7、Y→ X8、F→ ID = B9、T→ if J K10、X→ while J K11、J→( B G B )12、 B→( B )B'13、B→ ID B'14、B→ NUM B'15、B'→ BZB B'16、B'→空17、Z→ +18、Z→ -19、Z→ *20、Z→ /21、 G→ <22、 G→ <=23、 G→ >24、 G→ >=25、 G→ ==26、 G→ !=(3)构造LL(1)分析表(注:在表中用上一步的编号表示所需要的产生式)main 空( ) { } ; = if while ID num + - * / < <= > >= == != #iii. 详细设计描述 项目构架:各函数功能介绍:1、word.wordList 包(存储了关键字):word :此类是定义了存储关键字的结构:包括String 型的关键字,和int 型的识别符。

编译原理课程设计_词法语法分析器

编译原理课程设计_词法语法分析器

编译原理课程设计Course Design of Compiling(课程代码3273526)半期题目:词法和语法分析器实验学期:大三第二学期学生班级:2014级软件四班学生学号:2014112218学生姓名:何华均任课教师:丁光耀信息科学与技术学院2017.6课程设计1-C语言词法分析器1.题目C语言词法分析2.内容选一个能正常运行的c语言程序,以该程序出现的字符作为单词符号集,不用处理c语言的所有单词符号。

将解析到的单词符号对应的二元组输出到文件中保存可以将扫描缓冲区与输入缓冲区合成一个缓冲区,一次性输入源程序后就可以进行预处理了3.设计目的掌握词法分析算法,设计、编制并调试一个词法分析程序,加深对词法分析原理的理解4.设计环境(电脑语言环境)语言环境:C语言CPU:i7HQ6700内存:8G5.概要设计(单词符号表,状态转换图)5.1 词法分析器的结构词法分析程序的功能:输入:所给文法的源程序字符串。

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

词法分析程序可以单独为一个程序;也可以作为整个编译程序的一个子程序,当需要一个单词时,就调用此法分析子程序返回一个单词.为便于程序实现,假设每个单词间都有界符或运算符或空格隔开,并引入下面的全局变量及子程序:1) ch 存放最新读进的源程序字符2) strToken 存放构成单词符号的字符串3) Buffer 字符缓冲区4)struct keyType 存放保留字的符号和种别5.3 状态转换图6.详细设计(数据结构,子程序)算法思想:首先设置3个变量:①strToken用来存放构成单词符号的字符串;②ch 用来字符;③struct keyType用来存放单词符号的种别码。

扫描子程序主要部分流程如下图所示。

7.程序清单// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。

//#include"stdafx.h"#include"stdio.h"#include"stdlib.h"#include"conio.h"#include"string.h"#define N 47char ch;char strToken[20];//存放构成单词符号的字符串char buffer[1024]; //字符缓冲区struct keyType {char keyname[256];int value;}Key[N] = { { "$ID",0 },{ "$INT",1 },{ "auto",2 },{ "break",3 },{ "case",4 }, { "char",5 },{ "const",6 },{ "continue",7 },{ "default",8 },{ "do",9 }, { "double",10 },{ "else",11 },{ "enum",12 },{ "extern",13 },{ "float",14 }, { "for",15 },{ "goto",16 },{ "if",17 },{ "int",18 },{ "long",19 },{ "register",20 }, { "return",21 },{ "short",22 },{ "signed",23 },{ "sizeof",24 },{ "static",25 }, { "struct",26 },{ "switch",27 },{ "typedef",28 },{ "union",29 },{ "unsigned",30 }, { "void",31 },{ "volatile",32 },{ "while",33 },{ "=",34 },{ "+",35 },{ "-",36 },{ "*",37 }, { "/",38 },{ "%",39 },{ ",",40 },{ ";",41 },{ "(",42 },{ ")",43 },{ "?",44 },{ "clear", 45 },{ "#",46 } };void GetChar() //读一个字符到ch中{int i;if (strlen(buffer)>0) {ch = buffer[0];for (i = 0; i<256; i++)buffer[i] = buffer[i + 1];}elsech = '\0';}void GetBC()//读一个非空白字符到ch中{int i;while (strlen(buffer)) {i = 0;ch = buffer[i];for (; i<256; i++) buffer[i] = buffer[i + 1];if (ch != ' '&&ch != '\n'&&ch != '\0') break;}}void ConCat()//把ch连接到strToken之后{char temp[2];temp[0] = ch;temp[1] = '\0';strcat(strToken, temp);}bool Letter()//判断ch是否为字母{if (ch >= 'A'&&ch <= 'Z' || ch >= 'a'&&ch <= 'z')return true;elsereturn false;}bool Digit()//判断ch是否为数字{if (ch >= '0'&&ch <= '9')return true;elsereturn false;}int Reserve()//用strToken中的字符查找保留字表,并返回保留字种别码,若返回0,则非保留字{int i;for (i = 0; i<N; i++)if (strcmp(strToken, Key[i].keyname) == 0)return Key[i].value;return 0;}void Retract()//把ch中的字符回送到缓冲区{int i;if (ch != '\0') {buffer[256] = '\0';for (i = 255; i>0; i--)buffer[i] = buffer[i - 1];buffer[0] = ch;}ch = '\0';}keyType ReturnWord(){strcpy(strToken, "\0");int c;keyType tempkey;GetBC();if (ch >= 'A'&&ch <= 'Z' || ch >= 'a'&&ch <= 'z') { ConCat();GetChar();while (Letter() || Digit()) {ConCat();GetChar();}Retract();c = Reserve();strcpy(tempkey.keyname, strToken);if (c == 0)tempkey.value = 0;elsetempkey.value = Key[c].value;}else if (ch >= '0'&&ch <= '9') {ConCat();GetChar();while (Digit()) {ConCat();GetChar();}Retract();strcpy(tempkey.keyname, strToken);tempkey.value = 1;}else {ConCat();strcpy(tempkey.keyname, strToken);tempkey.value = Reserve();}return tempkey;}/*主函数*/int main() {//文件操作FILE *fp;if ((fp = fopen("E:\\作业\\编译原理\\Ccode.txt", "r")) == NULL) { printf("cannot open file/n"); exit(1);}while (!feof(fp)) {if (fgets(buffer, 250, fp) != NULL){printf("E:\\作业\\编译原理\\Ccode.txt\n");}}keyType temp;printf("单词\t种别号\n");while (strlen(buffer)) {temp = ReturnWord();printf("%s\t %d\n\n", temp.keyname, temp.value);}printf("the end!\n");getch();return 0;}8.运行结果E:/作业/编译原理/Code.txt运行结果九、 实验体会通过本次次法分析设计实验,我加深了对词法分析过程的理解。

语法分析器实验报告

语法分析器实验报告

杭州电子科技大学班级: 12052312 专业: 计算机科学与技术实验报告【实验名称】实验二语法分析一. 实验目的编写一个语法分析程序, 实现对词法分析程序所提供的单词序列的语法检查和结构分析。

二. 实验内容利用编程语言实现语法分析程序, 并对简单语言进行语法分析。

2.1 待分析的简单语言的语法用扩充的BNF表示如下:⑴<程序>: : =begin<语句串>end⑵<语句串>: : =<语句>{;<语句>}⑶<语句>: : =<赋值语句>⑷<赋值语句>: : =ID: =<表达式>⑸<表达式>: : =<项>{+<项> | -<项>}⑹<项>: : =<因子>{*<因子> | /<因子>⑺<因子>: : =ID | NUM | (<表达式>)2.2 实验要求说明输入单词串, 以“#”结束, 如果是文法正确的句子, 则输出成功信息, 打印“success”, 否则输出“error”。

例如:输入begin a:=9; x:=2*3; b:=a+x end #输出success!输入x:=a+b*c end #输出error测试以上输入的分析, 并完成实验报告。

2.3 语法分析程序的算法思想(1)主程序示意图如图2-1所示。

图2-1 语法分析主程序示意图(2)递归下降分析程序示意图如图2-2所示。

(3)语句串分析过程示意图如图2-3所示。

图2-3 语句串分析示意图图2-2 递归下降分析程序示意图(4)statement 语句分析程序流程如图2-4.2-5.2-6.2-7所示。

图2-4 statement 语句分析函数示意图 图2-5 expression 表达式分析函数示意图图2-7 factor 分析过程示意图三.个人心得一、 通过该实验, 主要有以下几方面收获: 二、 对实验原理有更深的理解。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

郑州轻工业学院编译原理课程设计总结报告设计题目:词法分析器(语法分析器)学生姓名:系别:专业:班级:学号:指导教师:20013年6 月2日目录一、设计题目 (3)二、运行环境(软、硬件环境) (3)三、算法设计的思想 (3)四、算法流程图 (5)五、算法设计分析 (5)六、源代码 (6)七、运行结果 (11)八、收获及体会 (12)(一)设计题目词法分析器(二)运行环境Visual C++.6.0(三)算法设计的思想各种单词符号对应的种别码:算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。

1.主程序示意图:主程序示意图如下;其中初值包括如下两个方面:(1)关键字表的初值。

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

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

关键字表为一个字符串数组,其描述如下:Char*rwtab[6]={“begin”,”if”,”then”,”while”,”do”,”end”};(2)程序需要用到的主要变量为syn,token和sum。

2.扫描子程序的算法思想首先设置3个变量:(1)token用来存放构成单词符号的字符串;(2)sum 用来存放整型单词(3)syn用来存放单词符号的种别码。

(五)算法设计分析算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。

其中初值包括如下两个方面:(一)关键字表的初值。

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

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

关键字表为一个字符串数组,其描述如下:Char*rwtab[6]={“begin”,”if”,”then”,”while”,”do”,”end”};(2)程序需要用到的主要变量为syn,token和sum。

2.扫描子程序的算法思想首先设置3个变量:(1)token用来存放构成单词符号的字符串;(2)sum 用来存放整型单词(3)syn用来存放单词符号的种别码。

(六)源代码#include<stdio.h>#include<iostream.h>#include<string.h>#define MAX 150 //词法分析表的最大容量#define MAXBUF 255//缓冲区的最大缓冲量char prog[MAXBUF],token[MAX];char ch;int syn,p,m,n,sum;char *rwtab[6]={"begin","if","then","while","do","end"};/////////////////////////////////////////////////词法分析程序///////////////////////////////////////////////void scaner(){for(m=0;m<MAX;m++)token[m]=NULL;m=0;sum=0;ch=prog[p++];while(ch==' ')ch=prog[p++];//读取下一个字符;if(ch>=65&&ch<=122 /*是字母字符*/){while(ch>=65&&ch<=122||ch>=48&&ch<=57)/*为字母字符或数字字符*/{token[m++]=ch;ch=prog[p++];//读取下一个字符;}token[m++]='\0';p=p-1;syn=10;for(n=0;n<6;n++)if(strcmp(token,rwtab[n])==0){syn=n+1;//给出syn值;break;}}else if(ch>=48&&ch<=57/*ch为数字字符*/){while(ch>=48&&ch<=57/*ch为数字字符*/){sum=sum*10+ch-'0';ch=prog[p++];//读取下一个字符;}p=p-1;//回退一个字符;syn=11;}else switch(ch){case '<': m=0;token[m++]=ch;ch=prog[p++];//读取下一个字符;if(ch=='>'){syn=21;token[m++]=ch;}else if(ch=='='){syn=22;token[m++]=ch;}else{syn=20;p=p-1;//回退一个字符;}break;case'>': token[m++]=ch;;ch=prog[p++];//读取下一个字符;if(ch=='='){syn=24;//将>=的中别码=>syn;token[m++]=ch;;}else{syn=23;p=p-1;//回退一个字符;}break;case':': token[m++]=ch;;ch=prog[p++];//读取下一个字符;if(ch=='='){syn=18;token[m++]=ch;;}else{syn=17;p=p-1;//回退一个字符;}break;case'+': syn=13;token[0]=ch;break;case'-': syn=14;token[0]=ch;break;case'*': syn=15;token[0]=ch;break;case'/': syn=16;token[0]=ch;break;case'=': syn=25;token[0]=ch;break;case';': syn=26;token[0]=ch;break;case'(': syn=27;token[0]=ch;break;case')': syn=28;token[0]=ch;break;case'#': syn=0;token[0]=ch;break;default: syn=-1;break;}}/////////////////////////////////////////////主函数///////////////////////////////////////////void main(){char A;cout<<"*****************************************"<<endl;loop:p=0;cout<<"*****************************************"<<endl;printf("please input string (以#结束):\n");do{scanf("%c",&ch);prog[p++]=ch;//输入源程序字符串,送到缓冲区prog[p++]中;}while(ch!='#');p=0;do{scaner();switch(syn){case 11:cout<<"( "<<syn<<","<<sum<<" )"<<endl;//输出(数的二元组);break;case -1:cout<<"error"<<endl;break;default:cout<<"( "<<syn<<","<<token<<" )"<<endl;//输出(其他单词二元组);}}while(syn!=0);cout<<"*****************************************"<<endl;cout<<"请确定是否继续使用程序:S为继续;其它为退出;"<<endl;cout<<"是否继续:";cin>>A;switch(A){case 'S': goto loop;default:cout<<"*****************************************"<<endl;cout<<"Thank you ! Bye Bye !"<<endl;cout<<"*****************************************"<<endl;break;}}(七)运行结果分析(八)收获及体会为期一周的编译原理课程设计结束了,我们这次的任务是做一个编译器。

这次课程设计我做的是用C++编写词法分析器,编译程序是在单词的级别上来分析和翻译源程序的,因此词法分析是编译的基础。

通过此次实验,我基本上了解了词法分析器的工作原理和功能以及实现方法。

进一步学习了C语言的知识。

此次实验,遇到的最大的一个问题就是用了C++语言里的cin输入字符串,结果空格符号直接给预处理掉了,导致开始的关键字与字母连接时会不识别,最后通过查阅,终于找到了这个问题的所在,最后通过C语言里的Scanf函数来输入,就解决了这个问题。

总而言之,本程序实现了所要求的全部功能。

美中不足的是程序中没有运用文件,对文件的掌握不是很到位,相信经过以后的程序训练,会熟练的运用文件来编程。

相关文档
最新文档