当前位置:文档之家› 实验_语义分析器

实验_语义分析器

实验_语义分析器
实验_语义分析器

实验三语义分析和中间代码生成器设计与实现

实验类型:设计性实验学时: 2 实验要求:必修

一、实验目的

通过上机实习,加深对语法制导翻译原理的理解,掌握将语法分析所识别的语法成分变换为中间代码的语义翻译方法。

二、实验内容

1、设置语义过程。

(1)emit(char *result,char *ag1,char *op,char *ag2)

该函数的功能是生成一个三地址语句送到四元式表中。

四元式表的结构如下:

struct

{ char result[8];

char ag1[8];

char op[8];

char ag2[8];

}quad[20];

(2) char *newtemp()

该函数回送一个新的临时变量名,临时变量名产生的顺序为T1,T2,…

char *newtemp(void)

{ char *p;

char m[8];

p=(char *)malloc(8);

k++;

itoa(k,m,10);

strcpy(p+1,m);

p[0]=’t’;

return(p);

}

2、函数lrparser 在原来语法分析的基础上插入相应的语义动作:将输入串翻译成四元式序列。在实验中我们只对表达式、赋值语句进行翻译。

三、仪器设备

计算机,VC++6.0软件环境。

四、所需耗材

五、实验原理、方法和手段

采用递归下降语法制导翻译法,对算术表达式、赋值语句进行语义分析并生成四元式序列。

六、实验步骤

阅读实验说明,做好实验准备,然后进行编辑调试。

七、实验结果处理

演示结果并保存相关文件。

八、实验注意事项

注意中间变量产生,四元式输出格式。

九、预习与思考题

预习:阅读课本相关内容,分析相关算法设计思想,熟悉VC++6.0使用方式。

思考题:类C语言程序的语义分析和中间代码生成。

十、实验报告要求

1、实验报告中应包括相关操作步骤和程序代码,。

2.书写实验报告时要结构合理,层次分明,在分析描述的时候,需要注意语言的流畅。

附源代码:

#include

#include

#include

#include

#include

using namespace std;

string s;

//s储存输入的字符串

int p, row, syn = -1, sum, flag;

//p作为指针,用来扫描输入的字符串;row记录出现错误的行数;syn用于记录种别码;sum记录识别出的数字的值;flag 用来标记是否出错

char ch;

char token[12];

//token用于临时储存scanner每次分析的词

string tab[6] = {"begin", "if", "then", "while", "do", "end"};

//全部关键字

int q,k = 1;

//q:产生四元式的个数,k:用于产生四元式的下标

struct

{//四元式表

char result[12];

char ag1[12];

char op[12];

char ag2[12];

}quad[100];

//语义分析函数

char *newtemp();

void emit(char *result, char *ag1, char*op, char *ag2); //出错退出

void error();

//递归下降子函数

void scanner();

char *factor();

char *term();

char *expression();

void statement();

void sentance();

//产生新的临时变量

char *newtemp()

{

char *p;

p=(char *)malloc(12);

char *m;

m=(char *)malloc(12);

itoa(k, m, 10);

strcpy(p + 1, m);

p[0] = 'T';

k++;

// cout<

return p;

}

//生成四元式

void emit(char *result, char *ag1, char*op, char *ag2) {

strcpy(quad[q].result, result);

strcpy(quad[q].ag1, ag1);

strcpy(quad[q].op, op);

strcpy(quad[q].ag2, ag2);

//printf("%s = %s %s %s\n",quad[q].result,quad[q].ag1,quad[q].op,quad[q].ag2);

q++;

}

//词法分析函数

void scanner()

{

int i;

//初始化

for(i = 0;i < 12;i++) token[i] = '\0';

//开始分析

ch = s[p++];

//如果是空格,跳过

while(ch == ' ' || ch == '\n')

{

if(ch == '\n') row++;

ch = s[p++];

}

//可能是标识符或者关键字

if((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_')

{

i = 0;

while((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_')

{

token[i++] = ch;

ch = s[p++];

}

token[i++] = '\0';

//因为上面while出循环时,ch实际上为下一个字符,但该字符不符合以上规则,所以要到回去以便下次识别。

p--;

syn = 10;

//判断是否是关键字

for(i = 0;i < 6;i++)

{

if(strcmp(token, tab[i].c_str()) == 0)

{

syn = i + 1;

break;

}

}

}

//整形数据

else if((ch >= '0' && ch <= '9'))

{

sum = 0;

while((ch >= '0' && ch <= '9'))

{

sum = sum * 10 + ch - '0';

ch = s[p++];

}

p--;

syn = 11;

}

//其他符号

else switch(ch)

{

case '<':

{

i = 0;

token[i++] = ch;

ch = s[p++];

if(ch == '>')//'<>'

{

syn = 21;

token[i++] = ch;

}

else if(ch == '=')//'<='

{

syn = 22;

token[i++] = ch;

}

else//'<'

{

syn = 20;

//下一个字符不是和<一起的,退回,下次识别

p--;

}

break;

}

case '>':

{

i = 0;

token[i++] = ch;

ch = s[p++];

if(ch == '=')//'>='

{

syn = 24;

token[i++] = ch;

else//'>'

{

syn = 23;

p--;

}

break;

}

case ':':

{

i = 0;

token[i++] = ch;

ch = s[p++];

if(ch == '=')//':='

{

syn = 18;

token[i++] = ch;

}

else//':'

{

syn = 17;

p--;

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:

{

flag = 0;syn = -1;

break;

}

}

if(flag == 0)

{

error();

}

}

// factor分析函数

char *factor()

{

char *fplace;

fplace = (char *)malloc(12);

strcpy(fplace, "");

if(syn == 10)//标识符

{

strcpy(fplace, token);

scanner();

}

else if(syn == 11)//常整数

{

itoa(sum, fplace, 10);//将数据以十进制转换为字符串保存在fplace字符数组内

scanner();

}

else if(syn == 27)//"("

{

scanner();

fplace = expression();

if(syn == 28)//")"

{

scanner();

}

else

{

error();

}

}

else

{

error();

}

return fplace;

}

// term分析函数

char *term()

{

char *eplace1, *eplace2, *op, *temp;

//eplace1:第一个因子, eplace2:第二个因子, op:运算符, temp:临时变量eplace1 = (char *)malloc(12);

eplace2 = (char *)malloc(12);

op = (char *)malloc(12);

temp = (char *)malloc(12);

strcpy(eplace1, factor());

while(syn == 15 ||syn == 16)//'*'、'/'

{

if(syn == 15) strcpy(op, "*");

else strcpy(op, "/");

// cout<

scanner();

strcpy(eplace2, factor());

strcpy(temp, newtemp());

emit(temp, eplace1, op, eplace2);

strcpy(eplace1, temp);

}

return eplace1;

}

// expression表达式分析函数

char *expression()

{

char *eplace1, *eplace2, *op, *temp;

//eplace1:第一个因子, eplace2:第二个因子, op:运算符, temp:临时变量eplace1 = (char *)malloc(12);

op = (char *)malloc(12);

temp = (char *)malloc(12);

strcpy(eplace1, term());

while(syn == 13 || syn == 14)//'+'、'-'

{

if(syn == 13) strcpy(op, "+");

else strcpy(op, "-");

scanner();

strcpy(eplace2, term());

strcpy(temp, newtemp());

emit(temp, eplace1, op ,eplace2);

strcpy(eplace1,temp);

//cout<

//cout<

}

return eplace1;

}

// statement语句分析函数

void statement()

{

char *eplace, *temp;

temp = (char *)malloc(12);

// int schain = 0;

if(syn == 10)//是标识符

{

strcpy(temp, token);//把标识符存进temp

scanner();//读下一个单词符号

if(syn == 18)//':='是赋值语句

{

scanner();

strcpy(eplace, expression());

emit(temp, eplace, "", "");//赋值语句只有一个因子:temp := eplace }

else//出错

{

error();

}

}

else//出错

{

error();

}

}

//语句串分析程序

void sentance()

{

statement();

while(syn == 26)//';'

{

scanner();

statement();

}

}

//递归下降分析程序

void lrparser()

{

if(strcmp(token, "begin") == 0)//开始

{

scanner();

sentance();

if(strcmp(token, "end") == 0)//结束

{

scanner();

if(syn == 0 && flag == -1)//字符串遇到'#'且没有语法错误,成功

{

flag = 1;

}

else//出错

{

error();

}

}

else//出错

{

error();

}

}

else//出错

{

error();

}

}

//出错

void error()

{

cout<<"Error in line "<

cout<<"请按任意键退出程序。。。";

getch();

cout<

exit(0);

}

int main()

{

p = 0;

flag = -1;

cout<<"input:"<

do

{

ch = cin.get();

//ch = getchar(); //不能保留换行符

s[p++] = ch;

//cout<

}while(ch != '#');

p = 0;

q = 0;

k = 1;

row = 1; //判断出错所在行数

cout<<"output:"<

//开始分析

scanner();

lrparser();

//结束分析

if(flag != 1)

{

error();

}

if(flag == 1)

{

cout<<"Success!"<

cout<<"产生的四元式为:"<

for(int i = 0;i < q;i++)

{

printf("%s = %s %s %s\n",quad[i].result,quad[i].ag1,quad[i].op,quad[i].ag2);

}

}

return 0; }

编译原理语义分析实验报告——免费!

语义分析实验报告 一、实验目的: 通过上机实习,加深对语法制导翻译原理的理解,掌握将语法分析所识别的语法成分变换为中间代码的语义翻译方法。 二、实验要求: 采用递归下降语法制导翻译法,对算术表达式、赋值语句进行语义分析并生成四元式序列。 三、算法思想: 1、设置语义过程。 (1)emit(char *result,char *ag1,char *op,char *ag2) 该函数的功能是生成一个三地址语句送到四元式表中。 四元式表的结构如下: struct { char result[8]; char ag1[8]; char op[8]; char ag2[8]; }quad[20]; (2) char *newtemp() 该函数回送一个新的临时变量名,临时变量名产生的顺序为T1,T2,… char *newtemp(void) { char *p; char m[8]; p=(char *)malloc(8); k++; itoa(k,m,10); strcpy(p+1,m); p[0]=’t’; return(p); } 2、函数lrparser 在原来语法分析的基础上插入相应的语义动作:将输入串翻译成四元式序列。在实验中我们只对表达式、赋值语句进行翻译。

四、源程序代码: #include #include #include #include struct { char result[12]; char ag1[12]; char op[12]; char ag2[12]; }quad; char prog[80],token[12]; char ch; int syn,p,m=0,n,sum=0,kk; //p是缓冲区prog的指针,m是token的指针char *rwtab[6]={"begin","if","then","while","do","end"}; void scaner(); char *factor(void); char *term(void); char *expression(void); int yucu(); void emit(char *result,char *ag1,char *op,char *ag2); char *newtemp(); int statement(); int k=0; void emit(char *result,char *ag1,char *op,char *ag2) { strcpy(quad.result,result); strcpy(quad.ag1,ag1); strcpy(quad.op,op); strcpy(quad.ag2,ag2);

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

编译技术 班级网络0802 学号3080610052姓名叶晨舟 指导老师朱玉全2011年 7 月 4 日

一、目的 编译技术是理论与实践并重的课程,而其实验课要综合运用一、二年级所学的多门课程的内容,用来完成一个小型编译程序。从而巩固和加强对词法分析、语法分析、语义分析、代码生成和报错处理等理论的认识和理解;培养学生对完整系统的独立分析和设计的能力,进一步培养学生的独立编程能力。 二、任务及要求 基本要求: 1.词法分析器产生下述小语言的单词序列 这个小语言的所有的单词符号,以及它们的种别编码和内部值如下表: 单词符号种别编码助记符内码值 DIM IF DO STOP END 标识符 常数(整)= + * ** , ( )1 2 3 4 5 6 7 8 9 10 11 12 13 14 $DIM $IF $DO $STOP $END $ID $INT $ASSIGN $PLUS $STAR $POWER $COMMA $LPAR $RPAR - - - - - - 内部字符串 标准二进形式 - - - - - - 对于这个小语言,有几点重要的限制: 首先,所有的关键字(如IF﹑WHILE等)都是“保留字”。所谓的保留字的意思是,用户不得使用它们作为自己定义的标示符。例如,下面的写法是绝对禁止的: IF(5)=x 其次,由于把关键字作为保留字,故可以把关键字作为一类特殊标示符来处理。也就是说,对于关键字不专设对应的转换图。但把它们(及其种别编码)预先安排在一张表格中(此表叫作保留字表)。当转换图识别出一个标识符时,就去查对这张表,确定它是否为一个关键字。 再次,如果关键字、标识符和常数之间没有确定的运算符或界符作间隔,则必须至少用一个空白符作间隔(此时,空白符不再是完全没有意义的了)。例如,一个条件语句应写为

NC数据加工做语义模型(DOC)

报表语义模型(数据加工:返回结果集方式) 数据加工方式:1.返回查询SQL ; 2.返回结果集DataSet;3.返回数据表。 实现方式基本一致,可以参照系统原有报表语义模型 一、新建报表查询入口类,初始化报表字段 1.数据加工查询业务处理接口的定义: package nc.itf.fbm.paperbill.query; import nc.pub.smart.data.DataSet; import nc.vo.pub.BusinessException; import com.ufida.dataset.IContext; /**票据信息查询/票据池额度查询接口 * * @author 温燕荣WYR * @date 2014-04-15 */ public interface IFbmQueryPaperBillService { /** * 票据信息查询 * @param context * @return * @throws BusinessException */ public DataSet queryPaperBillInfo(IContext context) throws Exception; /** * 票据池额度查询接口 * @param context * @return * @throws BusinessException */ public DataSet queryPaperBillPoolLimit(IContext context) throws Exception; }

2.数据加工入口类,初始化报表字段 package nc.itf.fbm.paperbill.query; import java.util.ArrayList; import java.util.List; import https://www.doczj.com/doc/ed13111950.html,mon.NCLocator; import nc.pub.smart.data.DataSet; import nc.pub.smart.metadata.DataTypeConstant; import nc.pub.smart.metadata.Field; import nc.pub.smart.metadata.MetaData; import nc.vo.obm.paperbill.query.PaperBillPoolVO; import com.ufida.dataset.IContext; /**票据池额度查询入口类 * * @author 温燕荣WYR * @date 2014-04-15 */ public class QueryPaperPoolLimitService { private static final MetaData metaData; public QueryPaperPoolLimitService(){ super(); } /** * 获得结果集 * * @param context 报表界面查询传进来的参数(查询条件=值,系统一些默认参数等)* @return */ public static DataSet queryPJCAmt(IContext context)throws Exception { //调用报表查询业务处理接口, IFbmQueryPaperBillService gatherservice=(IFbmQueryPaperBillService) NCLocator.getInstance().lookup(IFbmQueryPaperBillService.class.getName()); DataSet resultDataSet = gatherservice.queryPaperBillPoolLimit(context); setPrecision(resultDataSet); return resultDataSet; } //初始化报表要显示的字段,包括查询条件字段也在内

实验二 编译 词法分析器的构造

实验二词法分析器的构造 一、实验目的 掌握词法分析器的构造原理,掌握手工编程或LEX编程方法之一。 二、实验内容 编写一个词法分析器,能够将输入的源程序转换为单词序列输出。 三、实验指南 1.源语言定义见教材附录A.1,其中的终结符即词法分析需要得到的tokens。 (1)该语言的关键字:if while do break real true false int char bool float (其中,int、char、bool、float在产生式中为basic) 所有的关键字都是保留字,并且必须是小写。 (2)id和num的正则表达式定义; (3)专用符号:+ - * / < <= > >= == != = ; , ( ) [ ] { } /* */ (4)空格由空白、换行符和制表符组成。空格通常被忽略,除了它必须分开I D、N U M关键字。 (5)考虑注释。注释由/*和*/包含。注释可以放在任何空白出现的位置,且可以超过一行。注释不能嵌套。 2.实现词法分析器的注意要点: (1)关键字和标识符名的区别; (2)数字的转换处理; (3)“>=”和“>”这类单词的处理; 3.源程序测试示例 要求应自行准备多个源程序片段,运行并测试输出是否合符要求。 示例1: 源程序输入: { int i; if ( i >= 0) i = i + 1; } 输出token序列如下:

{, int, (id, i) ;, if, (, (id, i) >=, (num, 0) (id, i) =, (id, i) +, (num, 1) 示例2: 源程序片段: { int i; int j; float v; float x; float[100] a; while ( true) { do i = i + 1; while ( a[i] < v); do j = j - 1; while ( a[j] > v); if ( i >= j ) break; x = a[i]; a[i] = a[j]; a[j] = x; } } 四、实验结果

词法分析实验报告

编译原理实验一 姓名:朱彦荣 学号:20132184 专业:软件工程2 实验题目:词法分析完成语言:C/C++ 上级系统:VC++6.0 日期:2015/11/7

词法分析 设计题目:手工设计c语言的词法分析器 (可以是c语言的子集) 设计容: 处理c语言源程序,过滤掉无用符号,判断源程序中单词的合法性,并分解出正确的单词,以二元组形式存放在文件中。 设计目的: 了解高级语言单词的分类,了解状态图以及如何表示并识别单词规则,掌握状态图到识别程序的编程。 结果要求:课程设计报告。 完成日期:第十五周提交报告

一.分析 要想手工设计词法分析器,实现C语言子集的识别,就要明白什么是词法分析器,它的功能是什么。词法分析是编译程序进行编译时第一个要进行的任务,主要是对源程序进行编译预处理(去除注释、无用的回车换行找到包含的文件等)之后,对整个源程序进行分解,分解成一个个单词,这些单词有且只有五类,分别是标识符、保留字、常数、运算符、界符。以便为下面的语法分析和语义分析做准备。可以说词法分析面向的对象是单个的字符,目的是把它们组成有效的单词(字符串);而语法的分析则是利用词法分析的结果作为输入来分析是否符合语法规则并且进行语法制导下的语义分析,最后产生四元组(中间代码),进行优化(可有可无)之后最终生成目标代码。可见词法分析是所有后续工作的基础,如果这一步出错,比如明明是‘<=’却被拆分成‘<’和‘=’就会对下文造成不可挽回的影响。因此,在进行词法分析的时候一定要定义好这五种符号的集合。下面是我构造的一个C语言子集。 第一类:标识符 letter(letter | digit)* 无穷集 第二类:常数 (digit)+ 无穷集 第三类:保留字(32) auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while 第四类:界符‘/*’、‘//’、 () { } [ ] " " ' 等 第五类:运算符 <、<=、>、>=、=、+、-、*、/、^、等 对所有可数符号进行编码:

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

. 编译原理实验专业:13级网络工程

语法分析器1 一、实现方法描述 所给文法为G【E】; E->TE’ E’->+TE’|空 T->FT’ T’->*FT’|空 F->i|(E) 递归子程序法: 首先计算出五个非终结符的first集合follow集,然后根据五个产生式定义了五个函数。定义字符数组vocabulary来存储输入的句子,字符指针ch指向vocabulary。从非终结符E函数出发,如果首字符属于E的first集,则依次进入T函数和E’函数,开始递归调用。在每个函数中,都要判断指针所指字符是否属于该非终结符的first集,属于则根据产生式进入下一个函数进行调用,若first集中有空字符,还要判断是否属于该非终结符的follow集。以分号作为结束符。 二、实现代码 头文件shiyan3.h #include #include

#include using namespace std; #define num 100 char vocabulary[num]; char *ch; void judge_E(); void judge_EE(); void judge_T(); void judge_TT(); void judge_F(); 源文件 #include"shiyan3.h" void judge_E() { if(*ch==';') { cout<<"该句子符合此文法!"<

int a=0; cout<<"按1结束程序"<>a; if(a==1) exit(0); } else if(*ch=='('||*ch=='i') { judge_T(); judge_EE(); } else { cout<<"该句子不匹配此文法!"<>a; if(a==1) exit(0); }

实验一 词法分析器的设计

实验一词法分析器的设计 (2) 1.1 词法分析器的结构和主要任务 (2) 1.1.1 输入输出接口 (2) 1.1.2 条件限制 (2) 1.2 词法分析程序的总体设计 (3) 1.3 词法分析程序的详细设计 (4) 1.4实验步骤 (5) 1.5输入数据 (15) 1.6结果输出 (15)

实验一词法分析器的设计 实验目的:掌握词法分析的概念,设计方法,熟悉高级语言中词法的定义,词法分析程序的编写。 实验要求:在8学时内实现SAMPLE语言的词法分析器,要求用VC窗口界面实现。 实验内容:分为4次实验完成。 1.1 词法分析器的结构和主要任务 1.1.1 输入输出接口 图1-1词法分析器的输入输出界面 词法分析程序的主要任务是从左到右扫描每行源程序,拼成单词,换成统一的内部表示(token)输出,送给语法分析器。具体包括: 1.组织源程序的输入; 2.按规则拼单词,并转换成二元形式; 3.滤掉空白符,跳过注释、换行符及一些无用的符号(如字符常数的引号) 4.进行行列计数,用于指出出错的行列号,并复制出错部分; 5.列表打印源程序; 6.发现并定位词法错误; 7.生成符号表。 token文件和符号表用作语法分析的输入部分。 1.1.2 条件限制 本实验可以作如下假定: (1) 假定SAMPLE语言采用自由格式书写; (2) 可以使用注解,用/*……*/或者{……}标识,但注解不能插在单词内部,注解要在一行内结束,若一行结束,没有遇到注释后面的结束标记,自动认为注释也结束; (3) 一行可以有多个语句,一个语句也可以分布在多行中,单词之间和语句之间可以插入任意空格,单词中间不能有空白符号,单词中间也不能有回车换行符,即单词不能跨行书写; (4) 关键字都是保留字。

词法分析器实验报告

词法分析器实验报告 词法分析器设计 一、实验目的: 对C语言的一个子集设计并实现一个简单的词法分析器,掌握利用状 态转换图设计词法分析器的基本方法。利用该词法分析器完成对源程 序字符串的词法分析。输出形式是源程序的单词符号二元式的代码, 并保存到文件中。 二、实验内容: 1. 设计原理 词法分析的任务:从左至右逐个字符地对源程序进行扫描,产生一个个单词符号。 理论基础:有限自动机、正规文法、正规式 词法分析器(Lexical Analyzer) 又称扫描器(Scanner):执行词法分析的程序 2. 词法分析器的功能和输出形式 功能:输入源程序、输出单词符号 程序语言的单词符号一般分为以下五种:关键字、标识符、常数、运算符,界符 3. 输出的单词符号的表示形式: 单词种别用整数编码,关键字一字一种,标识符统归为一种,常数一种,各种符号各一种。 4. 词法分析器的结构 单词符号 5. 状态转换图实现

三、程序设计 1.总体模块设计 /*用来存储目标文件名*/ string file_name; /*提取文本文件中的信息。*/ string GetText(); /*获得一个单词符号,从位置i开始查找。并且有一个引用参数j,用来返回这个单词最后一个字符在str的位置。*/ string GetWord(string str,int i,int& j); /*这个函数用来除去字符串中连续的空格和换行 int DeleteNull(string str,int i); /*判断i当前所指的字符是否为一个分界符,是的话返回真,反之假*/ bool IsBoundary(string str,int i); /*判断i当前所指的字符是否为一个运算符,是的话返回真,反之假*/ bool IsOperation(string str,int i);

概率潜在语义模型综述

概率潜在语义模型综述 信息检索本质上是语义检索, 而传统信息检索系统都是基于独立词索引, 因此检索效果并不理想. 概率潜在语义索引是一种新型的信息检索模型, 它在潜在语义索引模型思想的基础上, 通过EM迭代算法将词向量和文档向量投影到一个低维空间, 消减了词和文档之间的语义模糊度, 使得文档之间的语义关系更为明晰。论述了概率潜在语义索引的理论基础, 探讨了隐含语义索引在信息处理处理中的应用。 标签:信息检索;潜在语义索引;SVD分解;概率潜在语义索引 1 简介 传统的信息检索模型可归为三类:布尔模型、向量空间模型和概率模型。它们都分别把文本和查询表示为索引词的集合,尽管使用了不同的方法,但本质上均为某种形式的索引词的匹配,而没有进一步做语义上的分析。自然语言中存在大量的同义词、多义词,这分别对传统检索模型的召回率和准确率有不利的影响。检索系统要求用户提供足够多精确、无歧义的关键词才有可能得到所需要的信息,这大大增加了系统使用的难度。为了进行更自然更人性化的查询,检索系统必须能够处理自然语言中的同义、多义现象,进行语义上的分析。 潜在语义分析(LSA)是一种发现潜在语义并分析文档、词和语义三者之间关系的方法。其主要思想是通过统计分析来发现文档中词与词之间存在的某种潜在的语义结构,并且使用这些潜在的语义结构来表示词和文本。 虽然潜在语义分析在信息检索领域取得了令人满意的效果,但是它存在几个缺陷:首先由于潜在语义分析过程中奇异值分解的物理意义不够明确,较难控制词义聚类的效果;此外这个算法的空间和时间复杂度太大,在目前的计算机硬件条件下很难实际适应实际应用。 针对潜在语义分析的这些缺陷,Hoffmann 提出了一种新的方法-概率潜在语义分析(PLSA),该方法使用概率模型来表示“文档—潜在语义—关键词”三者之间的关系,文档和关键词都可以映射到同一个语义空间,这样,文档和文档以及文档和关键词之间的相似度都可以通过计算语义空间上的夹角而得以量化。 2 潜在语义索引(LSI) 潜在语义索引(Latent Semantic Indexing) 是S. T. Dumais)等人提出的。其基本思想是文本中的词与词之间存在某种联系,即存在某种潜在的语义结构,因此采用统计的方法来寻找该语义结构,并且用语义结构来表示词和文本。这样的结果可以达到消除词之间的相关性,化简文本向量的目的。潜在语义索引的算法基于矩阵的奇异值分解

词法分析器实验报告

词法分析器实验报告 词法分析器实验报告实验目的: 设计、编制、调试一个词法分析子程序,识别单词,加深对词法分析原理的理 解。 实验要求: 该程序要实现的是一个读单词过程,从输入的源程序中,识别出各个具有独立 意义的单词,即基本保留字、标识符、常数、运算符、分界符五大类。并依次输出 各个单词的内部编码及单词符号自身值。 (一)实验内容 (1)功能描述:对给定的程序通过词法分析器弄够识别一个个单词符号,并以二 元式(单词种别码,单词符号的属性值)显示。而本程序则是通过对给定路径的文件 的分析后以单词符号和文字提示显示。 (2)程序结构描述: 函数调用格式: 函数调用格式函数名(实在参数表 ) Switch(m)、 isKey(String string)、isLetter(char c)、实参 isDigit(char c)、isOperator(char c) isKey(String string)、isLetter(char c)、调作为表达式 isDigit(char c)、isOperator(char c) 用 方 作为语句 getChar()、judgement()、 法 函数的递归调用 isOperator(char c) 、isLetter(char c)、isDigit(char c)

参数含义: 1 String string;存放读入的字符串 String str; 存放暂时读入的字符串 char ch; 存放读入的字符 int rs 判断读入的文件是否为空 char []data 存放文件中的数据 int m;通过switch用来判断字符类型, 函数之间的调用关系图: main Complier..judgement isOperate() M=0 getChar( ) isDigit() M=4 For(ch ) isLet ter() M=2 Switch(m) isKey() M=3 函数功能: Judgement()判断输入的字符并输出单词符号,返回值为空; getChar() 读取文件的,返回值为空; isLetter(char c) 判断读入的字符是否为字母的,返回值为Boolean类型; switch (m) 判断跳转输出返回值为空; isOperator(char c)判断是否为运算符的,返回值为Boolean类型; isKey(String string)判断是否为关键字的,返回值为Boolean类型; isDigit(char c) 判断读入的字符是否为数字的,返回值为Boolean类型。测试结果:

编译原理实验--词法分析器

编译原理实验--词法分析器 实验一词法分析器设计 【实验目的】 1(熟悉词法分析的基本原理,词法分析的过程以及词法分析中要注意的问题。 2(复习高级语言,进一步加强用高级语言来解决实际问题的能力。 3(通过完成词法分析程序,了解词法分析的过程。 【实验内容】 用C语言编写一个PL/0词法分析器,为语法语义分析提供单词,使之能把输入的字符 串形式的源程序分割成一个个单词符号传递给语法语义分析,并把分析结果(基本字, 运算符,标识符,常数以及界符)输出。 【实验流程图】

【实验步骤】 1(提取pl/0文件中基本字的源代码 while((ch=fgetc(stream))!='.') { int k=-1; char a[SIZE]; int s=0; while(ch>='a' && ch<='z'||ch>='A' && ch<='Z') { if(ch>='A' && ch<='Z') ch+=32; a[++k]=(char)ch; ch=fgetc(stream); } for(int m=0;m<=12&&k!=-1;m++) for(int n=0;n<=k;n++) {

if(a[n]==wsym[m][n]) ++s; else s=0; if(s==(strlen(wsym[m]))) {printf("%s\t",wsym[m]);m=14;n=k+1;} } 2(提取pl/0文件中标识符的源代码 while((ch=fgetc(stream))!='.') { int k=-1; char a[SIZE]=" "; int s=0; while(ch>='a' && ch<='z'||ch>='A' && ch<='Z') { if(ch>='A' && ch<='Z') ch+=32; a[++k]=(char)ch; ch=fgetc(stream); } for(int m=0;m<=12&&k!=-1;m++) for(int n=0;n<=k;n++) { if(a[n]==wsym[m][n]) ++s; else s=0; if(s==(strlen(wsym[m]))) {m=14;n=k+1;} } if(m==13) for(m=0;a[m]!=NULL;m++) printf("%c ",a[m]);

PL 0 语言编译器分析实验报告

PL/0 语言编译器分析实验 一、实验目的 通过阅读与解析一个实际编译器(PL/0语言编译器)的源代码,加深对编译阶段(包括词法分析、语法分析、语义分析、中间代码生成等)和编译系统软件结构的理解,并达到提高学生学习兴趣的目的。 二、实验要求 (1)要求掌握基本的程序设计技巧(C语言)和阅读较大规模程序源代码的能力; (2)理解并掌握编译过程的逻辑阶段及各逻辑阶段的功能; (3)要求能把握整个系统(PL/0语言编译器)的体系结构,各功能模块的功能,各模块之间的接口; (4)要求能总结出实现编译过程各逻辑阶段功能采用的具体算法与技 三、实验报告 pl/0语言是pascal语言的一个子集,我们这里分析的pl/0的编译程序包括了对pl/0语言源程序进行分析处理、编译生成类pcode代码,并在虚拟机上解释运行生成的类pcode代码的功能。 pl/0语言编译程序采用以语法分析为核心、一遍扫描的编译方法。词法分析和代码生成作为独立的子程序供语法分析程序调用。语法分析的同时,提供了出错报告和出错恢复的功能。在源程序没有错误编译通过的情况下,调用类pcode 解释程序解释执行生成的类pcode代码。 词法分析子程序分析: 词法分析子程序名为getsym,功能是从源程序中读出一个单词符号(token),把它的信息放入全局变量sym、id和num中,语法分析器需要单词时,直接从这三个变量中获得。(注意!语法分析器每次用完这三个变量的值就立即调用getsym 子程序获取新的单词供下一次使用。而不是在需要新单词时才调用getsym过程。)getsym过程通过反复调用getch子过程从源程序过获取字符,并把它们拼成单词。getch过程中使用了行缓冲区技术以提高程序运行效率。 词法分析器的分析过程: 调用getsym时,它通过getch过程从源程序中获得一个字符。如果这个字符是字母,则继续获取字符或数字,最终可以拼成一个单词,查保留字表,如果查到为保留字,则把sym变量赋成相应的保留字类型值;如果没有查到,则这个单词应是一个用户自定义的标识符(可能是变量名、常量名或是过程的名字),把sym 置为ident,把这个单词存入id变量。查保留字表时使用了二分法查找以提高效率。如果getch获得的字符是数字,则继续用getch获取数字,并把它们拼成一个整数,然后把sym置为number,并把拼成的数值放入num变量。如果识别出其它合

东南大学编译原理词法分析器实验报告

词法分析设计 1. 实验目的 通过本实验的编程实践,了解词法分析的任务,掌握词法分析程序设计的原理和构造方法,对编译的基本概念、原理和方法有完整的和清楚的理解,并能正确地、熟练地运用。 2. 实验内容 用C++语言实现对C++语言子集的源程序进行词法分析。通过输入源程序从左到右对字符串进行扫描和分解,依次输出各个单词的内部编码及单词符号自身值;若遇到错误则显示“Error”,然后跳过错误部分继续显示;同时进行标识符登记符号表的管理。 3. 实验原理 本次实验采用NFA->DFA->DFA0的过程: 对待分析的简单的词法(关键词/id/num/运算符/空白符等)先分别建立自己的FA,然后将他们用产生式连接起来并设置一个唯一的开始符,终结符不合并。 待分析的简单的词法 (1)关键字: "asm","auto","bool","break","case","catch","char","class","

const","const_cast"等 (2)界符(查表) ";",",","(",")","[","]","{","}" (3)运算符 "*","/","%","+","-","<<","=",">>","&","^","|","++","--"," +=","-=","*=","/=","%=","&=","^=","|=" relop: (4)其他单词是标识符(ID)和整型常数(SUM),通过正规式定义。 id/keywords: digit: (5)空格有空白、制表符和换行符组成。空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。

词法分析器实验报告

词法分析器实验报告 一、实验目的及要求 本次实验通过用C语言设计、编制、调试一个词法分析子程序,识别单词,实现一个C语言词法分析器,经过此过程可以加深对编译器解析单词流的过程的了解。 运行环境: 硬件:windows xp 软件:visual c++6.0 二、实验步骤 1.查询资料,了解词法分析器的工作过程与原理。 2.分析题目,整理出基本设计思路。 3.实践编码,将设计思想转换用c语言编码实现,编译运行。 4.测试功能,多次设置包含不同字符,关键字的待解析文件,仔细察看运行结果,检测该分析器的分析结果是否正确。通过最终的测试发现问题,逐渐完善代码中设置的分析对象与关键字表,拓宽分析范围提高分析能力。 三、实验内容 本实验中将c语言单词符号分成了四类:关键字key(特别的将main说明为主函数)、普通标示符、常数和界符。将关键字初始化在一个字符型指针数组*key[]中,将界符分别由程序中的case列出。在词法分析过程中,关键字表和case列出的界符的内容是固定不变的(由程序中的初始化确定),因此,从源文件字符串中识别出现的关键字,界符只能从其中选取。标识符、常数是在分析过程中不断形成的。 对于一个具体源程序而言,在扫描字符串时识别出一个单词,若这个单词的类型是关键字、普通标示符、常数或界符中之一,那么就将此单词以文字说明的形式输出.每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直到整个源程序全部扫描完毕,从而形成相应的单词串。 输出形式例如:void $关键字

流程图、程序流程图:

程序: #include #include #include #include //定义关键字 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);

语义分析实验报告

实验三语法分析 309 科3 李君林 一.实验目的: 通过使用、剖析和扩充TINY语言的语义分析程序,掌握编译器的语义分析程序的构造方法。 二.实验内容 (一)运行TINY的语义分析程序 (二)扩充TINY的语法分析程序 提示: 考虑作用域(如:函数)和数组时可能需要修改符号表。 三.实验步骤 1.先读懂TINY语义程序(相关联的文件:) (1)buildSymtab(syntaxTree); 充TINY的语法分析程序 本次实验我首先将源程序实现的功能改成符合C_MINUS的符号表与类型检测 然后加入没申明调用与数组调用错误即数组没申明而调用数组类型。 四.实验结果 1.正确的测试程序 /**/ int gcd (int u,int v[]) { if(v==0) return u; else return gcd(v,u); } void main(void) { int x;int y; read x; x=y=2; while(x>0) y=y-1; write y; return (gcd(x,y)); }

/**/ 运行结果: 经检验测试程序代码无语义错误2.错误测试程序 /**/ int gcd (int u,int v[]) { if(v==0) return u; else return gcd(v,u); } void main(void) { int x;int y; read x; t=1; x=y=2; x[2]=2; while(x>0) y=y-1; write y; return (gcd(x,y)); } /**/ 实验结果:

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

编译原理语法分析器实验报告 班级: 学号: 姓名:

实验名称语法分析器 一、实验目的 1、根据某一文法编制调试LL(1)分析程序,以便对任意输入的符号串进行分析。 2、本次实验的目的主要是加深对自上而下分析法的理解。 二、实验内容 [问题描述] 递归下降分析法: 0.定义部分:定义常量、变量、数据结构。 1.初始化:从文件将输入符号串输入到字符缓冲区中。 2.利用递归下降分析法分析,对每个非终结符编写函数,在主函数中调用文法开始符号的函数。 LL(1)分析法: 模块结构: 1、定义部分:定义常量、变量、数据结构。 2、初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体等); 3、运行程序:让程序分析一个text文件,判断输入的字符串是否符合文法定义的规则; 4、利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式 符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示简 单的错误提示。 [基本要求] 1. 对数据输入读取 2. 格式化输出分析结果 2.简单的程序实现词法分析 public static void main(String args[]) { LL l = new LL(); l.setP(); String input = ""; boolean flag = true;

while (flag) { try { InputStreamReader isr = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(isr); System.out.println(); System.out.print("请输入字符串(输入exit退出):"); input = br.readLine(); } catch (Exception e) { e.printStackTrace(); } if(input.equals("exit")){ flag = false; }else{ l.setInputString(input); l.setCount(1, 1, 0, 0); l.setFenxi(); System.out.println(); System.out.println("分析过程"); System.out.println("----------------------------------------------------------------------"); System.out.println(" 步骤| 分析栈 | 剩余输入串| 所用产生式"); System.out.println("----------------------------------------------------------------------"); boolean b = l.judge(); System.out.println("----------------------------------------------------------------------"); if(b){ System.out.println("您输入的字符串"+input+"是该文法的一个句子"); }else{ System.out.println("您输入的字符串"+input+"有词法错误!");

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

(此文档为word格式,下载后您可任意编辑修改!) 编译技术 班级网络0802 学号 姓名叶晨舟 指导老师朱玉全 2011年 7 月 4 日

一、目的 编译技术是理论与实践并重的课程,而其实验课要综合运用一、二年级所学的多门课程的内容,用来完成一个小型编译程序。从而巩固和加强对词法分析、语法分析、语义分析、代码生成和报错处理等理论的认识和理解;培养学生对完整系统的独立分析和设计的能力,进一步培养学生的独立编程能力。 二、任务及要求 基本要求: 1.词法分析器产生下述小语言的单词序列 这个小语言的所有的单词符号,以及它们的种别编码和内部值如下表: 单词符号种别编码助记符内码值 DIM IF DO STOP END 标识符 常数(整)= + * ** , ( )1 2 3 4 5 6 7 8 9 10 11 12 13 14 $DIM $IF $DO $STOP $END $ID $INT $ASSIGN $PLUS $STAR $POWER $COMMA $LPAR $RPAR - - - - - - 内部字符串 标准二进形式 - - - - - - 对于这个小语言,有几点重要的限制: 首先,所有的关键字(如IF﹑WHILE等)都是“保留字”。所谓的保留字的意思是,用户不得使用它们作为自己定义的标示符。例如,下面的写法是绝对禁止的: IF(5)=x 其次,由于把关键字作为保留字,故可以把关键字作为一类特殊标示符来处理。也就是说,对于关键字不专设对应的转换图。但把它们(及其种别编码)预先安排在一张表格中(此表叫作保留字表)。当转换图识别出一个标识符时,就去查对这张表,确定它是否为一个关键字。 再次,如果关键字、标识符和常数之间没有确定的运算符或界符作间隔,则必须至少用一个空白符作间隔(此时,空白符不再是完全没有意义的了)。例如,一个条件语句应写为 IF i>0 i= 1;

编译原理 实验2 词法分析器

编译原理实验2 词法分析器 一、实验目的 1. 通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。 2. 掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。 3. 编制一个读单词的程序,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符和分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值。(遇到错误时可显示“Error”,然后跳过错误部分继续显示) 二、词法分析的基础知识 1. 词法分析器的功能和输出格式 词法分析器的功能是输入源程序,输出单词符号。词法分析器的单词符号常常表示成以下的二元式(单词种别码,单词符号的属性值)。在本实验中,采用的是一类符号一种别码的方式。 标识符的BNF表示: <标识符>-> <字母><字母数字串> ) <字母数字串>-><字母><字母数字串>|<数字><字母数字串>|ε 无符号整数的BNF表示: <无符号整数>-> <数字><数字串> <数字串>-> <数字><数字串> |ε 运算符的BNF表示: <加法运算符>-> + <减法运算符>-> - <大于关系运算符>-> > <大于等于关系运算符>-> >= 2. 超前搜索 ; 词法分析时,常常会用到超前搜索方法。如当前待分析字符串为“a > i”,当前字符为“>”,此时,分析器到底是将其分析为大于关系运算符还是大于等于关系运算符呢显然,只有知道下一个字符是什么才能下结论。于是分析器读入下一个字符“+”,这时可知应将“>”解释为大于运算符。但此时,超前读了一个字符“i”,所以要回退一个字符,词法分析器才能正常运行。在分析标识符,无符号整数等时也有类似情况。 三、程序要求 1. 程序输入示例: 如源程序为C语言,输入如下一段: main() { int a, b; a = 10; b = a+20; } ; 2. 程序输出示例:

相关主题
文本预览
相关文档 最新文档