编译原理课程设计报告C-语言词法与语法分析器的实现
编译原理课程设计报告
课题名称:编译原理课程设计
C-语言词法与语法分析器的实现
提交文档学生姓名:
提交文档学生学号:
同组成员名单:
指导教师姓名:
指导教师评阅成绩:
指导教师评阅意见:
.
.
提交报告时间:年月日
C-词法与语法分析器的实现
1.课程设计目标
(1)题目实用性
C-语言拥有一个完整语言的基本属性,通过编写C-语言的词法分析和语法分析,对于理解编译原理的相关理论和知识有很大的作用。通过编写C-语言词法和语法分析程序,能够对编译原理的相关知识:正则表达式、有限自动机、语法分析等有一个比较清晰的了解和掌握。(2)C-语言的词法说明
①语言的关键字:
else if int return void while
所有的关键字都是保留字,并且必须是小写。
②专用符号:
+ - * / < <= > >= == != = ; , ( ) [ ] { } /* */
③其他标记是ID和NUM,通过下列正则表达式定义:
ID = letter letter*
NUM = digit digit*
letter = a|..|z|A|..|Z
digit = 0|..|9
注:ID表示标识符,NUM表示数字,letter表示一个字母,digit表示一个数字。
小写和大写字母是有区别的。
④空格由空白、换行符和制表符组成。空格通常被忽略。
⑤注释用通常的c语言符号/ * . . . * /围起来。注释可以放在任何空白出现的位置(即注释不能放在标记内)上,且可以超过一行。注释不能嵌套。
(3)程序设计目标
能够对一个程序正确的进行词法及语法分析。
2.分析与设计
(1)设计思想
a.词法分析
词法分析的实现主要利用有穷自动机理论。有穷自动机可用作描述在输入串中识别模式的过程,因此也能用作构造扫描程序。通过有穷自动机理论能够容易的设计出词法分析器。b.语法分析
语法分析采用递归下降分析。递归下降法是语法分析中最易懂的一种方法。它的主要原理是,对每个非终结符按其产生式结构构造相应语法分析子程序,其中终结符产生匹配命令,而非终结符则产生过程调用命令。因为文法递归相应子程序也递归,所以称这种方法为递归子程序下降法或递归下降法。其中子程序的结构与产生式结构几乎是一致的。
(2)程序流程图
程序主流程图:
词法分析: 语法分析:
3.程序代码实现
整个词法以及语法的程序设计在一个工程里面,一共包含了8个文件,分别为main.cpp、parse.cpp、scan.cpp、util.cpp、scan.h、util.h、globals.h、parse.h,其中scan.cpp和scan.h为词法分析程序。
以下仅列出各个文件中的核心代码:
Main.cpp
#include "globals.h"
#define NO_P ARSE FALSE
#include "util.h"
#if NO_PARSE
#include "scan.h"
#else
#include "parse.h"
#endif
int lineno=0;
FILE * source;
FILE * listing;
FILE * code;
int EchoSource = TRUE;
int TraceScan=TRUE;
int TraceParse=TRUE;
int Error = FALSE;
int main(int argc,char * argv[])
{
TreeNode * syntaxTree;
char pgm[120];
scanf("%s",pgm);
source=fopen(pgm,"r");
if(source==NULL)
{
fprintf(stderr,"File %s not found\n",pgm);
exit(1);
}
listing = stdout;
fprintf(listing,"\nC COMPILA TION: %s\n",pgm); #if NO_PARSE
while(getToken()!=ENDFILE);
#else
syntaxTree = parse();
if(TraceParse){
fprintf(listing,"\nSyntaxtree:\n");
printTree(syntaxTree);
}
#endif
fclose(source);
return 0;
}
Parse.cpp
#include "globals.h"
#include "util.h"
#include "scan.h"
#include "parse.h"
static TokenType token; /* holds current token */
/* function prototypes for recursive calls */
static TreeNode * declaration_list(void);
static TreeNode * declaration(void);
static TreeNode * params(void);
static TreeNode * param_list(void);
static TreeNode * param(void);
static TreeNode * compound_stmt(void);
static TreeNode * local_declarations(void);
static TreeNode * statement_list(void);
static TreeNode * statement(void);
static TreeNode * expression_stmt(void);
static TreeNode * if_stmt(void);
static TreeNode * while_stmt(void);
static TreeNode * return_stmt(void);
static TreeNode * expression(void);
static TreeNode * var(void);
static TreeNode * simple_exp(void);
static TreeNode * additive_expression(void);
static TreeNode * term(void);
static TreeNode * factor(void);
static TreeNode * args(void);
static TreeNode * arg_list(void);
static void syntaxError(char * message)
{ fprintf(listing,"\n>>> ");
fprintf(listing,"Syntax error at line %d: %s",lineno,message); Error = TRUE;
}
/*判断读取的字符*/
static void match(TokenType expected)
{
if(token==expected)
{
token=getToken( );
}
else
{
syntaxError("unexpected token -> ");
printToken(token,tokenString);
fprintf(listing," ");
}
}
/*进行语法分析,构建语法树*/
TreeNode * declaration_list(void)
{
TreeNode * t= declaration();
TreeNode * p= t;
while ((token==INT) || (token==VOID) )
{
TreeNode *q = declaration();
if (q!=NULL) {
if (t==NULL) t = p = q;
else /* now p cannot be NULL either */
{
p->sibling = q;
p = q;
}
}
}
return t;
}
TreeNode * declaration(void)
{ TreeNode * t = NULL;
switch (token)
{
case VOID :
case INT :
t = newStmtNode(DecK);
if(token == INT)
t->type =Integer;
else
t->type = V oid;
match(token);
switch (token)
{
case ID:
t->https://www.360docs.net/doc/474855467.html, = copyString(tokenString);
t->kind.stmt = V arDK;
match(ID);
switch (token)
{
case LZKH:
t->kind.stmt = V arDK;
t->type = IntArray;
match(LZKH);
match(NUM);
match(RZKH);
match(SEMI);
break;
case LPAREN:
t->kind.stmt = FunDK;
match(LPAREN);
t->child[0] = params();
match(RP AREN);
t->child[1] = compound_stmt();
break;
default: match(SEMI);break;
}
break;
default:syntaxError("unexpected token -> ");
printToken(token,tokenString);
token = getToken();
break;
}
break;
default : syntaxError("unexpected token -> ");
printToken(token,tokenString);
token = getToken();
break;
} /* end case */
return t;
}
TreeNode * params(void)
{
TreeNode * t = NULL;
if(token == VOID)
{
match(token);
t = newStmtNode(ParamList);
t->child[0] = newStmtNode(ParamK);
t->child[0]->type = V oid;
}
else if(token == RP AREN)
t=NULL;
else
{
t = param_list();
}
return t;
}
TreeNode * param_list(void)
{
TreeNode * t = newStmtNode(ParamList);
int i = 1;
t->child[0] = param();
while(token != RP AREN)
{
match(DOT);
t->child[i] = param();
i++;
}
return t;
}
TreeNode * param(void)
{
TreeNode * t = NULL;
match(INT);
t= newStmtNode(ParamK);
t->type=Integer;
t->https://www.360docs.net/doc/474855467.html,=copyString(tokenString);
match(ID);
if(token == LZKH)
{
t->type=IntArray;
match(LZKH);
match(RZKH);
}
return t;
}
TreeNode * compound_stmt(void)
{
TreeNode * t = newStmtNode(ComK);
match(LDKH);
t->child[0] = local_declarations();
t->child[1] = statement_list();
match(RDKH);
return t;
}
TreeNode * local_declarations(void)
{
TreeNode * t = newStmtNode(LocalDecK);
int i=0;
while(token == INT || token == VOID)
{
t->child[i] = declaration();
i++;
}
return t;
}
TreeNode * statement_list(void)
{
TreeNode * t = newStmtNode(StmtList);
int i=0;
while(token != RDKH)
{
t->child[i] =statement();
i++;
}
return t;
}
TreeNode * statement(void)
{
TreeNode * t ;
switch (token) {
case IF : t = if_stmt(); break;
case WHILE : t = while_stmt(); break;
case ID :
case SEMI:
t = expression_stmt(); break;
case RETURN : t = return_stmt(); break;
case LDKH : t=compound_stmt();break;
default : syntaxError("unexpected token -> ");
printToken(token,tokenString);
token = getToken();
break;
} /* end case */
return t;
}
TreeNode * expression_stmt(void)
{
TreeNode * t = newStmtNode(ExpstmtK);
if(token == SEMI)
match(SEMI);
else
{
t = expression();
match(SEMI);
}
return t;
}
TreeNode * if_stmt(void)
{
TreeNode * t = newStmtNode(IfK);
if(t!=NULL)
{
match(IF);
match(LPAREN);
t->child[0] = expression();
match(RP AREN);
t->child[1] = statement();
if (token==ELSE)
{
match(ELSE);
if (t!=NULL) t->child[2] = newStmtNode(ElseK);
t->child[2]->child[0] = statement();
} }
return t;
}
TreeNode * while_stmt(void)
{
TreeNode * t = newStmtNode(WhileK);
match(WHILE);
match(LPAREN);
if (t!=NULL) t->child[0] = expression();
match(RP AREN);
if (t!=NULL) t->child[1] = statement();
return t;
}
TreeNode * return_stmt(void)
{
TreeNode * t = newStmtNode(RetK);
if(token == RETURN)
match(RETURN);
if(token == SEMI)
match(SEMI);
else
{
t->child[0] = expression();
match(SEMI);
}
return t;
}
TreeNode * expression(void)
{
TreeNode * t = simple_exp();
return t;
}
TreeNode* var(void)
{
TreeNode* t = newExpNode(IdK);
if ((t!=NULL) && (token==ID))
t->https://www.360docs.net/doc/474855467.html, = copyString(tokenString);
match(ID);
if(token == LZKH)
{
match(token);
t->type = ArrayUnit;
t->child[0] = expression();
match(RZKH);
}
return t;
}
TreeNode * simple_exp(void)
{
TreeNode * t = additive_expression();
if(t!=NULL){
if (token == L T || token == LE|| token == MT || token == ME||token ==EQ||token ==NEQ) {
TreeNode * p = newExpNode(OpK);
if(p!=NULL)
{
p->attr.op = token;
p->child[0] = t;
match(token);
p->child[1] = additive_expression();
t=p;
}
}
}
return t;
}
TreeNode* additive_expression(void)
{
TreeNode * t = term();
while(token == PLUS || token == MINUS)
{
TreeNode * p = newExpNode(OpK);
p->attr.op = token;
p->child[0] = t;
match(token);
p->child[1] = term();
t = p;
}
return t;
}
TreeNode * term(void)
{
TreeNode * t = factor();
while ((token==TIMES)||(token==OVER))
{
TreeNode * p = newExpNode(OpK);
if (p!=NULL) {
p->child[0] = t;
p->attr.op = token;
match(token);
p->child[1] = factor();
t = p;
}
}
return t;
}
TreeNode * factor(void)
{
TreeNode * t = NULL;
switch (token)
{
case NUM :
t = newExpNode(ConstK);
if ((t!=NULL) && (token==NUM))
t->attr.val = atoi(tokenString);
match(NUM);
break;
case ID :
t = var();
if (token == ASSIGN)
{
TreeNode* p = newStmtNode(AssignK);
p->https://www.360docs.net/doc/474855467.html, = t->https://www.360docs.net/doc/474855467.html,;
match(token);
p->child[0] = expression();
t = p;
}
if (token == LP AREN )
{
TreeNode * p = newStmtNode(CallK);
p->https://www.360docs.net/doc/474855467.html, = t->https://www.360docs.net/doc/474855467.html,;
t=p;
match(token);
p->child[0] = args();
match(RP AREN);
}
break;
case LPAREN :
match(LPAREN);
t = expression();
match(RP AREN);
break;
default:
syntaxError("unexpected token -> ");
printToken(token,tokenString);
token = getToken();
break;
}
return t;
}
TreeNode * args(void)
{
TreeNode * t = newStmtNode(ArgList);
if(token != RPAREN)
{
t->child[0] = arg_list();
return t;
}else
return NULL;
}
TreeNode * arg_list(void)
{
TreeNode * t = newStmtNode(ArgK);
int i = 1;
if(token != RPAREN)
t->child[0] = expression();
while(token!=RP AREN)
{
match(DOT);
t->child[i] = expression();
i++;
}
return t;
}
TreeNode * parse(void)
{ TreeNode * t;
token = getToken();
t =declaration_list();
if (token!=ENDFILE)
syntaxError("Code ends before file\n");
return t;
}
scan.cpp
#include "globals.h"
#include "util.h"
#include "scan.h"
/*对扫描的字符进行匹配判断*/ TokenType getToken(void)
{ /* index for storing into tokenString */ int tokenStringIndex = 0;
/* holds current token to be returned */
TokenType currentToken;
/* current state - always begins at START */ StateType state = ST ART;
/* flag to indicate save to tokenString */
int save;
while (state != DONE)
{ int c = getNextChar();
save = TRUE;
switch (state)
{ case START:
if (isdigit(c))
state = INNUM;
else if (isalpha(c))
state = INID;
else if (c == '=')
state = INEQUAL;
else if (c == '<')
state = INLE;
else if (c == '>')
state = INME;
else if ((c == ' ') || (c == '\t') || (c == '\n')) save = FALSE;
else if (c== '!')
state = INNEQ;
else if (c == '/')
{
if(getNextChar()!='*')
{
ungetNextChar();
state = DONE;
currentToken = OVER;
break;
}
else
{
save = FALSE;
state = INCOMMENT;
}
}
else
{ state = DONE;
switch (c)
{ case EOF:
save = FALSE;
currentToken = ENDFILE;
break;
case '+':
currentToken = PLUS;
break;
currentToken = MINUS;
break;
case '*':
currentToken = TIMES;
break;
case '(':
currentToken = LP AREN;
break;
case ')':
currentToken = RP AREN;
break;
case ';':
currentToken = SEMI;
break;
case '[':
currentToken=LZKH;
break;
case ']':
currentToken=RZKH;
break;
case '{':
currentToken=LDKH;
break;
case '}':
currentToken=RDKH;
break;
case ',':
currentToken=DOT;
break;
default:
currentToken = ERROR;
break;
}
}
break;
case INCOMMENT:
save = FALSE;
编译原理C语言词法分析器
编译原理 C语言词法分析器 一、实验题目 编制并调试C词法分析程序。 a.txt源代码: ?main() { int sum=0 ,it=1;/* Variable declaration*/ if (sum==1) it++; else it=it+2; }? 设计其词法分析程序,能识别出所有的关键字、标识符、常数、运算符(包括复合运算符,如++)、界符;能过滤掉源程序中的注释、空格、制表符、换行符;并且能够对一些词法规则的错误进行必要的处理,如:标识符只能由字母、数字与下划线组成,且第一个字符必须为字母或下划线。实验要求:要给出所分析语言的词法说明,相应的状态转换图,单词的种别编码方案,词法分析程序的主要算法思想等。 二、实验目的 1、理解词法分析在编译程序中的作用; 2、掌握词法分析程序的实现方法与技术; 3、加深对有穷自动机模型的理解。 三、主要函数 四、设计 1、主函数void main ( ) 2 3
4、整数类型判断函数 char *key1[]={" ","(",")","[","]","{","}",",",";","'"}; /*分隔符表*/
char *key2[]={" ","+","-","*","/","%","<",">","==",">=","<=","!=","!","&&","||","<<",">>","~","|","^","&","=","?:","->","++","--","、","+=","-=","*=","/="}; /*运算符表*/ int xx0[35],xx1[10],xx2[31]; int temp_key3=0,temp_c40=0,temp_c41=0,temp_c42=0,temp_c43=0; /******* 初始化函数*******/ void load() { int mm; for (mm=0;mm<=34;mm++) { xx0[mm]=0; } for (mm=0;mm<=9;mm++) { xx1[mm]=0; } for (mm=0;mm<=30;mm++) { xx2[mm]=0; } FILE *floading; if ((floading=fopen("key0、txt","w"))==NULL) { printf("Error! Can't create file : key0、txt"); return; } fclose (floading); /*建立保留字表文件:key0、txt*/ if ((floading=fopen("key1、txt","w"))==NULL) { printf("Error! Can't create file : key1、txt"); return; } /*建立分隔符表文件:key1、txt*/ if ((floading=fopen("key2、txt","w"))==NULL) { printf("Error! Can't create file : key2、txt"); return; } fclose(floading); /*建立运算符表文件:key2、txt*/ if ((floading=fopen("key3、txt","w"))==NULL) { printf("Error! Can't create file : key3、txt");
c语言语法分析器详解
#include
C语言编译器的设计与实现.
C语言编译器的设计与实现 01计算机4班18号任春妍2号陈俊我们设计的编译程序涉及到编译五个阶段中的三个,即词法分析器、语法分析器和中间代码生成器。编译程序的输出结果包括词法分析后的二元式序列、变量名表、状态栈分析过程显示及四元式序列程序,整个编译程序分为三部分: (1) 词法分析部分 (2) 语法分析处理及四元式生成部分 (3) 输出显示部分 一.词法分析器设计 由于我们规定的程序语句中涉及单词较少,故在词法分析阶段忽略了单词输入错误的检查,而将编译程序的重点放在中间代码生成阶段。词法分析器的功能是输入源程序,输出单词符号。我们规定输出的单词符号格式为如下的二元式:(单词种别,单词自身的值) #define ACC -2 #define syl_if 0 #define syl_else 1 #define syl_while 2 #define syl_begin 3 #define syl_end 4 #define a 5 #define semicolon 6 #define e 7 #define jinghao 8 #define s 9 #define L 10 #define tempsy 11 #define EA 12 #define EO 13 #define plus 14 #define times 15 #define becomes 16 #define op_and 17 #define op_or 18 #define op_not 19 #define rop 20 #define lparent 21 #define rparent 22 #define ident 23 #define intconst 24
编译原理课程设计 C语言编译器的实现
编译原理课程设计报告 设计题目编译代码生成器设计 学生姓名 班级 学号 指导老师 成绩
一、课程设计的目的 编译原理课程兼有很强的理论性和实践性,是计算机专业的一门非常重要的专业基础课程,它在系统软件中占有十分重要的地位,是计算机专业学生的一门主修课。为了让学生能够更好地掌握编译原理的基本理论和编译程序构造的基本方法和技巧,融会贯通本课程所学专业理论知识,提高他们的软件设计能力,特设定该课程的课程设计,通过设计一个简单的PASCAL语言(EL语言)的编译程序,提高学生设计程序的能力,加深对编译理论知识的理解与应用。 二、课程设计的要求 1、明确课程设计任务,复习编译理论知识,查阅复印相关的编译资料。 2、按要求完成课程设计内容,课程设计报告要求文字和图表工整、思路清晰、算法正 确。 3、写出完整的算法框架。 4、编写完整的编译程序。 三、课程设计的内容 课程设计是一项综合性实践环节,是对平时实验的一个补充,课程设计内容包括课程的主要理论知识,但由于编译的知识量较复杂而且综合性较强,因而对一个完整的编译程序不适合平时实验。通过课程设计可以达到综合设计编译程序的目的。本课程的课程设计要求学生编写一个完整的编译程序,包括词法分析器、语法分析器以及实现对简单程序设计语言中的逻辑运算表达式、算术运算表达式、赋值语句、IF语句、While语句以及do…while语句进行编译,并生成中间代码和直接生汇编指令的代码生成器。 四、总体设计方案及详细设计 总体设计方案: 1.总体模块 主程序 词法分析程序语法分析 程序 中间代码 生成程序
2. 表2.1 各种单词符号对应的种别码 单词符号种别码单词符号种别码bgin 1 :17 If 2 := 18 Then 3 < 20 wile 4 <> 21 do 5 <= 22 end 6 > 23 lettet(letter|digit)* 10 >= 24 dight dight* 11 = 25 + 13 ;26 —14 ( 27 * 15 ) 28 / 16 # 0 详细设计: 4.1界面导入设计 (1)一共三个选项: ①choice 1--------cifafenxi ②choice 2--------yufafenxi ③choice 3--------zhongjiandaima (2)界面演示 图一
编译原理课程设计报告C语言词法与语法分析器的实现
编译原理课程设计报告 课题名称:编译原理课程设计 C-语言词法与语法分析器的实现
C-词法与语法分析器的实现 1.课程设计目标 (1)题目实用性 C-语言拥有一个完整语言的基本属性,通过编写C-语言的词法分析和语法分析,对于理解编译原理的相关理论和知识有很大的作用。通过编写C-语言词法和语法分析程序,能够对编译原理的相关知识:正则表达式、有限自动机、语法分析等有一个比较清晰的了解和掌握。(2)C-语言的词法说明 ①语言的关键字: else if int return void while 所有的关键字都是保留字,并且必须是小写。 ②专用符号: + - * / < <= > >= == != = ; , ( ) [ ] { } /* */ ③其他标记是ID和NUM,通过下列正则表达式定义: ID = letter letter* NUM = digit digit* letter = a|..|z|A|..|Z digit = 0|..|9 注:ID表示标识符,NUM表示数字,letter表示一个字母,digit表示一个数字。 小写和大写字母是有区别的。 ④空格由空白、换行符和制表符组成。空格通常被忽略。 ⑤注释用通常的c语言符号/ * . . . * /围起来。注释可以放在任何空白出现的位置(即注释不能放在标记)上,且可以超过一行。注释不能嵌套。
(3)程序设计目标 能够对一个程序正确的进行词法及语法分析。 2.分析与设计 (1)设计思想 a.词法分析 词法分析的实现主要利用有穷自动机理论。有穷自动机可用作描述在输入串中识别模式的过程,因此也能用作构造扫描程序。通过有穷自动机理论能够容易的设计出词法分析器。b.语法分析 语法分析采用递归下降分析。递归下降法是语法分析中最易懂的一种方法。它的主要原理是,对每个非终结符按其产生式结构构造相应语法分析子程序,其中终结符产生匹配命令,而非终结符则产生过程调用命令。因为文法递归相应子程序也递归,所以称这种方法为递归子程序下降法或递归下降法。其中子程序的结构与产生式结构几乎是一致的。 (2)程序流程图 程序主流程图: 词法分析: 语法分析:
C语言词法分析器和C语言语法分析器编译原理课程设计报告书
《编译原理课程设计》课程报告题目 C语言词法分析器和C-语言语法分析器 学生 学生学号 指导教师 提交报告时间 2019 年 6 月 8 日
C语言词法分析器 1 实验目的及意义 1.熟悉C语言词法 2.掌握构造DFA的过程 3.掌握利用DFA实现C语言的词法分析器 4.理解编译器词法分析的工作原理 2 词法特点及正则表达式 2.1词法特点 2.1.1 保留字 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, 2.1.2 符号 + - * / ++ -- += -= *= < <= > >= == != = ; , ( ) [ ] { } /* */ : 2.2 正则表达式 whitespace = (newline|blank|tab|comment)+ digit=0|..|9 nat=digit+ signedNat=(+|-)?nat NUM=signedNat(“.”nat)? letter = a|..|z|A|..|Z ID = letter(letter|digit|“_”)+ CHAR = 'other+' STRING = “other+”
语法分析代码2(LR分析器 C语言实现)
#include"status_stack.h" #include"symbol_instr_stack.h" #include"lr.h" //打印LR分析器的工作过程 void print(status *status_p,symbol_instr *symbol_p,symbol_instr *instr_p) { int i; out_stack(status_p); for(i=0;i<20-status_p->top;i++) printf(" "); out_stack1(symbol_p); for(i=0;i<20;i++) printf(" "); out_stack2(instr_p); printf("\n"); } //状态转换函数 int goto_char(status *status_p,symbol_instr *instr_p) { char x; int y,z; x = get_top(instr_p); y = get_top(status_p); z = get_index_char(x); return table[y][z]; } //移进--规约函数 void action(status *status_p,symbol_instr *symbol_p,symbol_instr *instr_p) { int i,j,x; char a; i = goto_char(status_p,instr_p); //规约出错 if(i == -1) printf("\n===============规约出错!================\n"); //规约成功 if(i == 12) printf("\n===============规约成功!================\n"); //移进动作 if(i>=0 && i<=11) { push(status_p,i); a = pop(instr_p); push(symbol_p,a);
实验三 语法分析的C语言实现
实验三语法分析的C语言实现 一、实验目的 加深对语法分析器工作过程的理解;能够采用一种编程语言实现简单的语法分析程序;能够使用自己编写的分析程序对简单的程序段进行语法分析。 二、实验要求 1、在实验一(用C语言实现词法分析的程序)的基础上,实现编写语法分析程序,语法 分析程序的实现可以采用任何一种编程工具。 2、对语法规则有明确的定义; 3、编写的分析程序能够对实验一的结果进行正确的语法分析; 4、对于遇到的语法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利 完成语法分析过程; 三、实验指导1(实现算术表达式的运算) (一)准备 1.阅读课本有关章节,参考P63的表6.3优先关系表。 2.初步编制程序。 3.准备一组测试数据。 (二)程序要求 1.程序输入/输出示例: 输入如下一段C语言源程序: 3+2*(5.5-5) 输出:输出运算的结果4.0。 2. 建议:实验一的词法分析结果保存到文件input.c,实验二直接从input.c读取一个token,将用到的文法规则输出并保存到文件output.c。(注:NUM由词法分析器返回) 3.可选功能:可以根据自身的情况完善语法分析程序的错误处理功能,如对遇到的语法错误给出准确的位置和错误类型提示。 三、实验指导2(用递归下降分析器实现语法分析) (一)准备 1.阅读课本有关章节,特别是P49的代码,明确语言的语法。 2.初步编制程序。 3.准备一组测试数据。 (二)程序要求 1.程序输入/输出示例: 输入如下一段C语言源程序(实现赋值语句或者if语句或者while语句,或者都实现):main() { a = 10*(b+2); if (a>b) a=b else a=c; while (a!=0) a=3+21*a; }
实验5 LL(1)语法分析程序的设计与实现(C语言)教学文稿
实验五LL(1)文法识别程序设计 一、实验目的 通过LL(1)文法识别程序的设计理解自顶向下的语法分析思想。 二、实验重难点 FIRST集合、FOLLOW集合、SELECT集合元素的求解,预测分析表的构造。 三、实验内容与要求 实验内容: 1.阅读并理解实验案例中LL(1)文法判别的程序实现; 2.参考实验案例,完成简单的LL(1)文法判别程序设计。 四、实验学时 4课时 五、实验设备与环境 C语言编译环境 六、实验案例 1.实验要求 参考教材93页预测分析方法,94页图5.11 预测分析程序框图,编写表达式文法的识别程序。要求对输入的LL(1)文法字符串,程序能自动判断所给字符串是否为所给文法的句子,并能给出分析过程。 表达式文法为: E→E+T|T T→T*F|F F→i|(E) 2.参考代码
为了更好的理解代码,建议将图5.11做如下标注:
/* 程序名称:LL(1)语法分析程序*/ /* E->E+T|T */ /* T->T*F|F */ /* F->(E)|i */ /*目的: 对输入LL(1)文法字符串,本程序能自动判断所给字符串是否为所给文法的句子,并能给出分析过程。 /********************************************/ /* 程序相关说明*/ /* A=E' B=T' */ /* 预测分析表中列号、行号*/ /* 0=E 1=E' 2=T 3=T' 4=F */ /* 0=i 1=+ 2=* 3=( 4=) 5=# */ /************************************/ #include"iostream" #include "stdio.h" #include "malloc.h" #include "conio.h" /*定义链表这种数据类型参见: https://www.360docs.net/doc/474855467.html,/link?url=_owQzf8PRZOt9H-5oXIReh4X0ClHo6zXtRdWrdSO5YBLpKl NvkCk0qWqvFFxjgO0KzueVwEQcv9aZtVKEEH8XWSQCeVTjXvy9lxLQ_mZXeS###*/ struct Lchar{ char char_ch; struct Lchar *next; }Lchar,*p,*h,*temp,*top,*base; /*p指向终结符线性链表的头结点,h指向动态建成的终结符线性链表节点,top和base分 别指向非终结符堆栈的顶和底*/
c语言实现语法分析器
实验报告 姓名:张静学号:13031121 【实验名称】一种绘图语言的词法分析器 【实验目的】采用c语言完成词法分析器,练习使用。 【实验内容】 一、问题描述 设计一种简单的函数绘图语言的词法分析器,该绘图语言可以提供一条循环绘图语句,图形变换语句,注释语句,他的词法分析器部分是读取源程序——字符序列,并根据构词规则将其转换为记号流。它可以完成三个任务:(1)滤掉源程序中的注释和无用的成分(如空格,TAB等);(2)输出记号,供语法分析器使用;(3)识别非法输入,并将非法输入作为出错记号提供给语法分析器,以便进行出错处理。 二、问题分析 词法分析器的构造步骤:正规式——NFA——DFA——最小DFA ——编写程序——测试。 1、记号的设计 记号一般有两部分组成:极好的类别,记号的属性。根据 函数绘图语言的特点,可以将记号设计为如下的数据结构: Struct Token
{ Token_Type type;----------类别 char* lexeme;--------------属性,原是输入的字符串double value;----------属性,若记号是常数则是常数的值 double (*FuncPtr)(double);--属性,若记号是函数则是函数指针 }; 函数绘图语言的记号类别划分如下: Enum Token_Type { ORGIN, SCALE, ROT, IS, ------------保留字 TO, STEP, DRAW, FOR, FROM,---------保留字 T,--------------------------------参数 SEMICO, L_BRACKET, R_BRACKET, COMMA--分隔符 PLUS, MINUS, MUL, DIV, POWER,------运算符 FUNC,--------------------------函数 CONST_ID,-------------------常数 NONTOKEN,-----------------空记号 ERRTOKEN-------------------出错记号 }; 2、模式的正规式表示 函数绘图语言的此法可用下是正规式集合表示,其中的letter 和digit是辅助定义 描述词法的正规式
编译原理C语言词法分析器
编译原理C语言词法分析器 一、实验题目 编制并调试C词法分析程序。 a.txt源代码: ?main() { int sum=0 ,it=1;/* Variable declaration*/ if (sum==1) it++; else it=it+2; }? 设计其词法分析程序,能识别出所有的关键字、标识符、常数、运算符(包括复合运算符,如++)、界符;能过滤掉源程序中的注释、空格、制表符、换行符;并且能够对一些词法规则的错误进行必要的处理,如:标识符只能由字母、数字和下划线组成,且第一个字符必须为字母或下划线。实验要求:要给出所分析语言的词法说明,相应的状态转换图,单词的种别编码方案,词法分析程序的主要算法思想等。 二、实验目的 1、理解词法分析在编译程序中的作用; 2、掌握词法分析程序的实现方法和技术; 3、加深对有穷自动机模型的理解。 三、主要函数
四、设计 1.主函数void main ( ) 2. 初始化函数void load ( ) 3. 保留字及标识符判断函数void char_search(char *word) 4. 整数类型判断函数void inta_search(char *word)
5. 浮点类型判断函数void intb_search(char *word) 6. 字符串常量判断函数void cc_search(char *word) 7. 字符常量判断函数void c_search(char *word) 同4、5函数图 8.主扫描函数void scan ( )
五、关键代码 #include
c语言语法分析器
#include<> #include<> #include<> /*******************************************/ int count=0; /*分解的产生式的个数*/ int number; /*所有终结符和非终结符的总数*/ char start; /*开始符号*/ char termin[50]; /*终结符号*/ char non_ter[50]; /*非终结符号*/ char v[50]; /*所有符号*/ 、 char left[50]; /*左部*/ char right[50][50]; /*右部*/ char first[50][50],follow[50][50]; /*各产生式右部的FIRST和左部的FOLLOW集合*/ char first1[50][50]; /*所有单个符号的FIRST集合*/ char select[50][50]; /*各单个产生式的SELECT集合*/ char f[50],F[50]; /*记录各符号的FIRST和FOLLOW是否已求过*/ char empty[20]; /*记录可直接推出@的符号*/ char TEMP[50]; /*求FOLLOW时存放某一符号串的FIRST集合*/ int validity=1; /*表示输入文法是否有效*/ int ll=1; /*表示输入文法是否为LL(1)文法*/ — int M[20][20]; /*分析表*/ char choose; /*用户输入时使用*/ char empt[20]; /*求_emp()时使用*/ char fo[20]; /*求FOLLOW集合时使用*/ /******************************************* 判断一个字符是否在指定字符串中 ********************************************/ int in(char c,char *p) { @ int i; if(strlen(p)==0) return(0); for(i=0;;i++) { if(p[i]==c) return(1); /*若在,返回1*/ if(i==strlen(p)) return(0); /*若不在,返回0*/ } [
c语言基本简单语法分析器
输入一个表达式,输出结果,不包括() 例如可以输入的形式: 3*3-6/2+70+1/3 代码: #include 郑州轻工业学院 编译原理课程设计总结报告 设计题目:词法分析器(语法分析器) 学生姓名: 系别: 专业: 班级: 学号: 指导教师: 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.扫描子程序的算法思想 集美大学计算机工程学院 编译原理课程设计报告 选题名称:LL(1)文法分析 院(系):计算机工程学院 专业:计算机科学与技术 班级:计算1412 指导教师:付永刚 学年学期:2016~2017 学年第2学期 2017 年 06 月29 日 摘要:选题要求:根据某一文法编制调试LL(1)文法语法分分析程序,以便对任意输入的符号串进行分析。本次课程设计的目的主要是加深对预测分析LL(1)文法语法分析法的理解。具体如下:1、对语法规则有明确的定义;2、编写的分析程序能够对给定文 法进行正确的语法分析;3、对输入给定的文法,手工计算FIRST、FOLLOW集合和select 集合,应能判断识别是否为给定文法的句子,并给出推导过程。4、对输入给定的文法,由程序自动构造FIRST、FOLLOW集合。5、对于遇到的语法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成语法分析过程。? 关键词:语法分析;FIRST集合;FOLLOW集合;分析表 一、设计内容及要求 (1)基于PL/0语言,通过编程判断该文法是否为LL(1)文法; (2)计算出文法的First()Follow() (3)构造相应文法的预测分析表 (4)对某个输入句子进行语法分析 二、实现原理 1.LL(1)文法 LL(1)文法是一类可以进行确定的自顶向下语法分析的文法。就是要求描述语言的文法是无左递归的和无回溯的。根据LL(1)文法的定义,对于同一非终结符A的任意两个产生式A:=a和A:=b,都要满足:SELECT(A:=a)∩SELECT(A:=b)=?。 (1)文法的左递归 当一个文法是左递归文法时,采用自顶向下分析法会使分析过程进入无穷循环之中。所以采用自顶向下语法分析需要消除文法的左递归性。文法的左递归是指若文法中对任一非终结符A有推导A?A…,则称该文法是左递归的。 左递归又可以分为直接左递归和间接左递归。 ●直接左递归 若文法中的某一产生式形如A→Aα,α∈V*,则称该文法是直接左递归的。 消除直接左递归的方法: 设有产生式是关于非终结符A的直接左递归:A→Aα|β(α,β∈V*,且β不以A 开头) 对A引入一个新的非终结符A′,把上式改写为: A→βA′ A′→αA′|ε ●间接左递归 若文法中存在某一非终结符A,使得A?A…至少需要两步推导,则称该文法是间接左递归的。 消除间接左递归的方法: 【方法一】采用代入法把间接左递归变成直接左递归。 【方法二】直接改写文法:设有文法G10[S]: S→Aα|β⑴ A→Sγ⑵ 因为S?Aα?Sγα,所以S是一个间接递归的非终结符。为了消除这种间接左递归,将⑵式代入⑴式,即可得到与原文法等价的文法(可以证明): S→Sγα|β⑶C语言语法分析器
编译原理课程设计LL文法分析器设计C语言实现