实验四(二)实现一门语言的语法分析器

代码地址 Github

(二)实现一门语言的语法分析器

一、实验目的

通过本次实验,加深对语法分析的理解,学会编制语法分析器。

二、实验任务

用C或JAVA语言编写一门语言的语法分析器。

三、实验内容

(1)语言确定:C-语言,其定义在《编译原理及实践》附录A中。也可选择其它语言,不过要有该语言的详细定义(可仿照C-语言)。一旦选定,不能更改,因为要在以后继续实现编译器的其它部分。鼓励自己定义一门语言。

(2)完成C-语言的BNF文法到EBNF文法的转换。通过这一转换,消除左递归,提取左公因子,将文法改写为LL(1)文法,以适用于自顶向下的语法分析。规划需要将哪些非终结符写成递归下降函数。

(3)为每一个将要写成递归下降函数的非终结符,如:变量声明、函数声明、语句序列、语句、表达式等,定义其抽象语法子树的形式结构,然后定义C-语言的语法树的数据结构。

(4)仿照前面学习的语法分析器,编写选定语言的语法分析器。

(5)准备2~3个测试用例,测试并解释程序的运行结果。

四、语言确定 (c-Minus语言)

这里定义了一个编程语言称作C-M i n u s (或简称为C-),这是一种适合编译器设计方案的语言,它比T I N Y语言更复杂,包括函数和数组。本质上它是C的一个子集,但省去了一些重要的部分,因此得名。

1 关键字

else if int return void while

2 专用符号

+ - * / < <= > >= == != = ; , ( ) [ ] { } /* */

3 其它标记,通过正则表达式定义:

ID = letter letter*
NUM = digit digit*
letter = a|..|z|A|..|Z
digit = 0|..|9

五、具体实现 (c-Minus语言)

1 程序总定义: gloal.h

1.1 宏定义:

#define BUFLEN 256                                   //每一行读取的最大字符串长度
#define MAXLEN 256
#define MAXTOKENLEN 40                               //词法单元的最大长度
#define MAXCHILDREN 4

1.2 变量定义:

static int lineno;                                    //当前读取到第几行
static int linepos = 0;                               //读取的字符在 lineBuf 的位置
static int EOF_FLAG = false;                          //判断文件是否结束
static int bufsize = 0;                               //某行字符串的长度
static char lineBuf[BUFLEN];                          //暂存某一行源程序字符串
FILE * source;                                        //输入文件
char tokenString[MAXTOKENLEN+1];                      //暂存扫描到的词法单元字符串
string output;                                        //输出文件
TokenType token;                                      //当前词法单元

1.3 结构体定义:

enum TokenType                                        //词法单元类型
enum StateType  //状态类型
struct{ char* str;TokenType tok;} ReserverWords[6]    //关键字
struct{ string str;TokenType tk;} Ope[11] //操作符
enum NodeKind//节点类型
  //节点类型和字符串关系
struct{string str;NodeKind nk;}nodekind[18]
struct TreeNode //树节点
{
    struct TreeNode * child[4];
    struct TreeNode * sibling;
    int lineno;
    NodeKind nodekind;
    union{TokenType op;int val;const char * name;} attr;
};

1.4 BNF文法对应的函数声明:

TreeNode * declaration_list(void);
TreeNode * declaration(void);
TreeNode * params(void);
TreeNode * param_list(TreeNode * p);
TreeNode * param(TreeNode * p);
TreeNode * compound_stmt(void);
TreeNode * local_declaration(void);
TreeNode * statement_list(void);
TreeNode * statement(void);
TreeNode * expression_stmt(void);
TreeNode * selection_stmt(void);
TreeNode * iteration_stmt(void);
TreeNode * return_stmt(void);
TreeNode * expression(void);
TreeNode * var(void);
TreeNode * simple_expression(TreeNode * p);
TreeNode * additive_expression(TreeNode * p);
TreeNode * term(TreeNode * p);
TreeNode * factor(TreeNode * p);
TreeNode * call(TreeNode * p);
TreeNode * args(void);

2 词法分析部分:scan.h

2.1 词法分析的DFA:

这里写图片描述

2.2 函数说明:

void UnGetNextChar()                    //回退一个字符
int  GetNextChar()                      //获取下一字符
TokenType GetToken()                    //获取词法单元
TokenType ReservedLookUp(char * s)      //是否是关键字
string OpeLookUp(TokenType tk)
string Change(NodeKind nk)

3 语法分析部分:pase.h

3.1 设计思想:

pase用递归下降分析的方法实现,通过调用GetToken函数获取词法单元来实现语法分析。

3.2 c-的BNF文法:

这里写图片描述
这里写图片描述

3.3 函数说明:

void parse(void)                                 //语法分析求解函数
void match(TokenType expected)                   //匹配当前词法单元,获取下一词法单元
void PreOrder(TreeNode* t)                       //递归下降求解
char * copyString(char *s)                       //复制字符串
TreeNode * args(void)                            //arg_list | empty
TreeNode * call(TreeNode * k)                    //ID (args)
TreeNode * factor(TreeNode * k)                  //expression) | var | call | NUM
TreeNode * term(TreeNode * k)                    //term mulop factor | factor
TreeNode * additive_expression(TreeNode * k)     //additive_expression addop term | term
TreeNode * simple_expression(TreeNode * k)       //additive_expression relop additive_expression
                                                 // | additive_expression
TreeNode * var(void)                             //ID | ID [expression]
TreeNode * expression(void)                      //var = expression | simple-expression
TreeNode * expression_stmt(void)                 //expression ; | ;
TreeNode * return_stmt(void)                     //return ;| return expression
TreeNode * iteration_stmt(void)                  //while (expression) | statement
TreeNode * selection_stmt(void)                  //if(expression) tatement
                                                 //   | if(expression) tatement else statement
TreeNode * statement(void)                       //expression-stmt | compound-stmt | selection-stmt
                                                 // | iteration-stmt | return-stmt
TreeNode * statement_list(void)                  //statement-list statement | selection-stmt
TreeNode * local_declaration(void)               //local-declaration var-declaration | empty
TreeNode * param(TreeNode * k)                   //type-specifier ID | type-specifier Id [ ]
TreeNode * compound_stmt(void)                   //{local-declarations statment-list}
TreeNode * param_list(TreeNode * k)              //params-list,param | param
TreeNode * params(void)                          //params-list | void
TreeNode * declaration(void)                     //var-declaration|fun-declaration
TreeNode * declaration_list(void)                //declaration-list declaration | declaration
TreeNode * newNode(NodeKind kind)                // 新建节点

4 测试

4.1 测试一: test.c

/* A program to perform Euclid's
Algorithm to compute gcd. */
int gcd (int u, int v)
{
    if (v == 0)
        return u ;
    else
        return gcd(v,u-u/v*v);
    /* u-u/v*v == u mod v */
}
void main(void)
{
    int x;int y;
    x = input();
    y = input();
    output(gcd(x,y));
}

输出:

Syntax tree:
 Funck
   IntK
   IdK: gcd
   ParamsK
     ParamK
       IntK
       IdK: u
     ParamK
       IntK
       IdK: v
   CompK
     If
       Op: ==
         IdK: v
         ConstK: 0
       Return
         IdK: u
       Return
         CallK
           IdK: gcd
           ArgsK
             IdK: v
             Op: -
               IdK: u
               Op: *
                 Op: /
                   IdK: u
                   IdK: v
                 IdK: v
 Funck
   VoidK
   IdK: main
   ParamsK
     VoidK
   CompK
     Var_DeclK
       IntK
       IdK: x
     Var_DeclK
       IntK
       IdK: y
     Assign
       IdK: x
       CallK
         IdK: input
     Assign
       IdK: y
       CallK
         IdK: input
     CallK
       IdK: output
       ArgsK
         CallK
           IdK: gcd
           ArgsK
             IdK: x
             IdK: y

4.2 测试二 test1.c

/* A program to perform Euclid's
Algorithm to compute max. */
int max (int u, int v)
{
    if (u > v)
        return u ;
    else
        return v;
    /* u-u/v*v == u mod v */
}

void main(void)
{
    int x;int y;
    x = input();
    y = input();
    output(max(x,y));
}

测试结果:

Syntax tree:
 Funck
   IntK
   IdK: max
   ParamsK
     ParamK
       IntK
       IdK: u
     ParamK
       IntK
       IdK: v
   CompK
     If
       Op: >
         IdK: u
         IdK: v
       Return
         IdK: u
       Return
         IdK: v
 Funck
   VoidK
   IdK: main
   ParamsK
     VoidK
   CompK
     Var_DeclK
       IntK
       IdK: x
     Var_DeclK
       IntK
       IdK: y
     Assign
       IdK: x
       CallK
         IdK: input
     Assign
       IdK: y
       CallK
         IdK: input
     CallK
       IdK: output
       ArgsK
         CallK
           IdK: max
           ArgsK
             IdK: x
             IdK: y

4.3 测试三 test2.c

/* A program to perform Euclid's
Algorithm to compute add. */
int add (int a,int b)
{
    return a+b;
}
void main(void)
{
    int x;int y;
    x = input();
    y = input();
    output(add(x,y));
}

结果:

Syntax tree:
 Funck
   IntK
   IdK: add
   ParamsK
     ParamK
       IntK
       IdK: a
     ParamK
       IntK
       IdK: b
   CompK
     Return
       Op: +
         IdK: a
         IdK: b
 Funck
   VoidK
   IdK: main
   ParamsK
     VoidK
   CompK
     Var_DeclK
       IntK
       IdK: x
     Var_DeclK
       IntK
       IdK: y
     Assign
       IdK: x
       CallK
         IdK: input
     Assign
       IdK: y
       CallK
         IdK: input
     CallK
       IdK: output
       ArgsK
         CallK
           IdK: add
           ArgsK
             IdK: x
             IdK: y
相关推荐
附录c 编译程序实验 实验目的:用c语言对一个简单语言的子集编制一个一遍扫描的编译程序,以加深对编译原理的理解,掌握编译程序的实现方法和技术。 语法分析 C2.1 实验目的 编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析. C2.2 实验要求 利用C语言编制递归下降分析程序,并对简单语言进行语法分析. C2.2.1待分析的简单语言语法 实验目的 通过上机实习,加深对语法制导翻译原理的理解,掌握将语法分析所识别的语法成分变换为中间代码的语义翻译方法. 实验要求 采用递归下降语法制导翻译法,对算术表达式、赋值语句进行语义分析并生成四元式序列。 实验的输入和输出 输入是语法分析提供的正确的单词串,输出为三地址指令形式的四元式序列。 例如:对于语句串 begin a:=2+3*4;x:=(a+b)/c end# 输出的三地址指令如下: (1) t1=3*4 (2) t2=2+t1 (3) a=t2 (4) t3=a+b (5) t4=t3/c (6) x=t4 算法思想 1设置语义过程 (1) emit(char *result,char *arg1,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)主程序示意图如图c.10所示。 (2) 函数lrparser在原来语法分析的基础上插入相应的语义动作:将输入串翻译成四元式序列。在实验中我们只对表达式、赋值语句进行翻译。 语义分析程序的C语言程序框架 int lrparser() { int schain=0; kk=0; if(syn=1) { 读下一个单词符号; schain=yucu; /调用语句串分析函数进行分析/ if(syn=6) { 读下一个单词符号; if(syn=0 && (kk==0)) 输出(“success”); } else { if(kk!=1 ) 输出 ‘缺end’ 错误;kk=1;} else{输出’begin’错误;kk=1;} } return(schain); int yucu() { int schain=0; schain=statement();/调用语句分析函数进行分析/ while(syn=26) {读下一个单词符号; schain=statement(); /调用语句分析函数进行分析/ } return(schain); } int statement() { char tt[8],eplace[8]; int schain=0; {switch(syn) {case 10: strcpy(tt,token); scanner(); if(syn=18) {读下一个单词符号; strcpy(eplace,expression()); emit(tt,eplace,””,””); schain=0; } else {输出’缺少赋值号’的错误;kk=1; } return(schain); break; } } char *expression(void) {char *tp,*ep2,*eplace,*tt; tp=(char *)malloc(12);/分配空间/ ep2=(char *)malloc(12); eplace=(char *)malloc(12); tt =(char )malloc(12); strcpy(eplace,term ());/调用term分析产生表达式计算的第一项eplace/ while(syn=13 or 14) { 操作符 tt= ‘+’或者‘—’; 读下一个单词符号; strcpy(ep2,term());/调用term分析产生表达式计算的第项ep2/ strcpy(tp,newtemp());/调用newtemp产生临时变量tp存储计算结果/ emit(tp,eplace,tt,ep2);/生成四元式送入四元式表/ strcpy(eplace,tp); } return(eplace); } char *term(void)/仿照函数expression编写/ char *factor
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页