基于Appel-Tiger编译器前端的简易语法分析器

            基于Appel-Tiger编译器前端的简易语法分析器

说明: 

       本例修改自Appel的Tiger编译器前端。
       本例给出某文法的一个简单的语法分析器。它是在parser0的基础上添加语义动作而得到的。
       输入:用该文法所表示的语言写的源程序文件。
       输出:分析树的数据结构描述,可以显示在屏幕上,也可以写入指定的文件中。
       该语言的文法为:(与parser0文法相同)

program--> PROGRAM ID; vardec BEGIN stmts END. 
vardec-->   VAR declist 
declist-->  ID:INTEGER;
stmts--> ID := exp
exp--> INT
       该语法分析器的测试例(输入文件)为:testcases/test0.p
       该语法分析器的词法分析器由lex编写,本例并未给出lex规则源程序,只给出了flex编译后的c语言程序lex.yy.c。本词法分析器支持以(*开始,以*)结束的注释(不支持注释的嵌套)。
       parsetest.c为该语法分析器主控程序,包含main函数。
       util.c含有一般工具函数,util.h是其头文件。
       errormsg.c含有错误管理函数,errormsg.h是其头文件。
       parser.y是语法分析器的文法说明文件。 在该文法说明文件中,我们为产生式添加了语义动 作,语义动作为产生语法分析树。

       ast.h文件给出了语法分析器所应生成的语法分析树(抽象语法树)的各部分的数据结构;而ast.c则为这些数据结构提供了构造函数(注意:ast.c提供的构造函数并不完整,需要你进行完善)
       prast.c文件含有语法分析树各个数据结构的打印函数。prast.h是其头文件。
       testcases文件夹下的文件为语法分析器的测试例,test0.p为当前语法分析器可通过的测试例,
       test1.p为P178页上机题所示文法的一个测试例。你写的其他测试例也应该放在该文件夹下。
       makefile文件表示了本例的编译方法:
             在cygwin下,输入make,将会得到一些中间object文件以及可执行文件parser1.exe;
             输入 make clean,会将编译及运行中生成的文件删除(只留下原有文件);
             编译完成后,输入make test00,将会以testcases/test0.p为输入源程序运行生成的语法分析器parser0.exe,输出的分析树将显示在屏幕上。
            编译完成后,输入make test01,将会以testcases/test0.p为输入源程序运行生成的语法分析器parser0.exe,输出的分析树将写入指定文件test0.out中。

      用到的文件截图:


源代码:

      (1) ast.c

/* 本文件给出抽象语法树上各数据结构的构造函数,实验8需要修改该文件的一些函数 */

#include "ast.h"




/* make id node */
a_id A_Id(a_pos pos, string val){
  a_id ret = checked_malloc(sizeof(*ret));
  ret->pos = pos;
  ret->val = val;
  return ret;
}


/* make exp node from integer */
a_exp A_IntExp(a_pos pos, int ival){
  a_exp ret = checked_malloc(sizeof(*ret));
  ret->kind = A_intExp;
  ret->pos = pos;
  ret->exp.ival = ival;
  return ret;
}

/* make exp node from real */
a_exp A_RealExp(a_pos pos, double fval){
  a_exp ret = checked_malloc(sizeof(*ret));
  //请完善该函数
  ret->kind = A_realExp;
  ret->pos = pos;
  ret->exp.fval = fval;
  return ret;
}

/* make exp node from id node */
a_exp A_VarExp(a_pos pos, a_id var){
  a_exp ret = checked_malloc(sizeof(*ret));
  //请完善该函数
  ret->kind = A_varExp;
  ret->pos = pos;
  ret->exp.var = var;
  return ret;
}

 /* make binary operands exp node */
a_exp A_OpExp(a_pos pos, a_op op, a_exp left, a_exp right){
  a_exp ret = checked_malloc(sizeof(*ret));
  //请完善该函数
  ret->kind = A_opExp;
  ret->pos = pos;
  ret->exp.biopExp.op=op;
  ret->exp.biopExp.left=left;
  //ret->exp.biopExp.right=right;
  ret->exp.biopExp.right=right;
  
  return ret;
}

/* make boolean exp node */
a_bexp A_BExp(a_pos pos, a_bop bop, a_exp left, a_exp right){
  a_bexp ret = checked_malloc(sizeof(*ret));
  //请完善该函数
  ret->pos = pos;
  ret->bexp.bop = bop;
  ret->bexp.left = left;
  ret->bexp.right = right;
  return ret;
}

/* make assign statement */
a_stm A_Assign (a_pos pos, a_id var, a_exp exp){
  a_stm ret = checked_malloc(sizeof(*ret));
  ret->kind = A_assign;
  ret->pos = pos;
  ret->stm.assign.var = var;
  ret->stm.assign.exp = exp;
  return ret;
}

/* make if statement */
a_stm A_If(a_pos pos, a_bexp b, a_stm s1, a_stm s2){
  a_stm ret = checked_malloc(sizeof(*ret));
  //请完善该函数
  ret->kind = A_if;
  ret->pos = pos;
  ret->stm.iff.b=b;
  ret->stm.iff.s1=s1;
  ret->stm.iff.s2=s2;
  return ret;
}

/* make while statement */
a_stm A_While(a_pos pos, a_bexp b, a_stm s){
  a_stm ret = checked_malloc(sizeof(*ret));
  //请完善该函数
  ret->kind = A_while;
  ret->pos = pos;
  ret->stm.whilee.b=b;
  ret->stm.whilee.s=s;
  return ret;
}

/* make sequence statement */
a_stm A_Seq(a_pos pos, a_stm_list sl){
  a_stm ret = checked_malloc(sizeof(*ret));
  //请完善该函数
  ret->kind = A_seq;
  ret->pos = pos;
  ret->stm.seq=sl;
  return ret; 
}

/* make statement list */
a_stm_list A_StmList(a_stm s, a_stm_list sl){
  a_stm_list ret = checked_malloc(sizeof(*ret));
  ret->head = s;
  ret->tail = sl;
  return ret;
}

/* make var list */
a_var_list A_VarList(a_id v, a_var_list vl){
  a_var_list ret = checked_malloc(sizeof(*ret));
  ret->head = v;
  ret->tail = vl;
  return ret;
}

/* make variable declaration node */
a_dec A_VarDec(a_pos pos, a_var_list vl, ttype t){
  a_dec ret = checked_malloc(sizeof(*ret));
  ret->type = t;
  ret->pos = pos;
  ret->varlist = vl;
  return ret;
}

/* make variable declaration list */
a_dec_list A_DecList(a_dec vd, a_dec_list vdl){
  a_dec_list ret = checked_malloc(sizeof(*ret));
  ret->head = vd;
  ret->tail = vdl;
  return ret;
}

/* make program node */
a_prog A_Prog (a_pos pos, char * name, a_dec_list dl, a_stm_list sl){
  a_prog ret = checked_malloc(sizeof(*ret));
  ret->name = name;
  ret->pos =pos;
  ret->declist = dl;
  ret->stmlist = sl;
  return ret;
}
    (2) ast.h

/* 定义抽象语法树(分析树)的数据结构 */

#include "util.h"

typedef int a_pos; //a_pos为源文件某记号的位置类型,报错用。

typedef struct a_exp_ * a_exp;
typedef struct a_bexp_ * a_bexp;
typedef struct a_id_ * a_id;
typedef struct a_stm_ * a_stm;
typedef struct a_stm_list_ * a_stm_list;
typedef struct a_dec_ * a_dec;
typedef struct a_dec_list_ * a_dec_list;
typedef struct a_var_list_ * a_var_list;
typedef struct a_prog_ * a_prog;

/* 变量类型有整型T_int和实型T_real两种 */
typedef enum{T_int, T_real} ttype;

/* 二元算术运算有四种:+ - * / */
typedef enum {A_plusOp, A_minusOp, A_timesOp, A_divideOp} a_op;

/* 二元布尔运算六种:=, <>, <, <=, >, >= */
typedef enum {A_eqOp, A_neqOp, A_ltOp, A_leOp, A_gtOp, A_geOp} a_bop;


/* id的数据结构,pos为位置,val为id的名字 */
struct a_id_ {
  a_pos pos;
  string val;
};

/* 算术表达式数据结构。
 * kind为表达式的类型,分为变量、整型数、实型数和二元表达式
 */
struct a_exp_ {
  enum {A_varExp, A_intExp, A_realExp, A_opExp} kind;
  a_pos pos;
  union {
    struct {
      a_op op;
      a_exp left;
      a_exp right;
    }biopExp; //二元运算表达式:left op right
    a_id var; //变量表达式
    int ival; //整型数表达式
    double fval;//实型数表达式
  }exp;
};

/* 布尔表达式数据结构 */
struct a_bexp_{
	a_pos pos;
	struct {
    a_bop bop;
    a_exp left;
    a_exp right;
  } bexp;
};

/* 语句数据结构。
 * 类型分为赋值语句、if语句、while语句、顺序语句(语句序列) 
 */
struct a_stm_ {
  enum {A_assign, A_if, A_while, A_seq} kind;
  a_pos pos;
  union {
    struct a_assign_stm_ {
      a_id var;
      a_exp exp;
    } assign;//赋值语句:var = exp;
    struct a_if_stm_ {
      a_bexp b;
      a_stm s1;
      a_stm s2;
    } iff;// if语句:if b then s1 else s2;
    struct a_while_stm_ {
      a_bexp b;
      a_stm s;
    } whilee;// while语句:while b do s;
    a_stm_list seq;//顺序语句:是若干顺序的语句的一个列表。
  } stm;
};

/* 语句列表数据结构 */
struct a_stm_list_ {
  a_stm head;
  a_stm_list tail;
};

/* 变量列表数据结构 */
struct a_var_list_ {
  a_id head;
  a_var_list tail;
};

/* 变量声明数据结构 。
 * 变量类型为type,变量列表为varlist。
 * 例:声明var a, b, c : INTEGER;
 *     其中a,b,c组成varlist,type为T_int(表示INTEGER)。
 */
struct a_dec_ {
  ttype type;
  a_pos pos;
  a_var_list varlist;
};

/* 变量声明列表数据结构 */
struct a_dec_list_ {
  a_dec head;
  a_dec_list tail;
};

/* 程序数据结构。
 * name为程序名,declist为程序变量声明列表 */
struct a_prog_ {
  char * name;
  a_pos pos;
  a_dec_list declist;
  a_stm_list stmlist;
};

/* 下面的函数是各个语法结构的构造函数 */
a_id A_Id(a_pos pos, string val);
a_exp A_IntExp(a_pos pos, int ival);
a_exp A_RealExp(a_pos pos, double fval);
a_exp A_VarExp(a_pos pos, a_id var);
a_exp A_OpExp(a_pos pos, a_op op, a_exp left, a_exp right);
a_bexp A_BExp(a_pos pos, a_bop bop, a_exp left, a_exp right);
a_stm A_Assign (a_pos pos, a_id var, a_exp exp);
a_stm A_If(a_pos pos, a_bexp b, a_stm s1, a_stm s2);
a_stm A_While(a_pos pos, a_bexp b, a_stm s);
a_stm A_Seq(a_pos pos, a_stm_list sl);
a_stm_list A_StmList(a_stm s, a_stm_list sl);
a_var_list A_VarList(a_id v, a_var_list vl);
a_dec A_VarDec(a_pos pos, a_var_list vl, ttype t);
a_dec_list A_DecList(a_dec vd, a_dec_list vdl);
a_prog A_Prog (a_pos pos, char * name, a_dec_list dl, a_stm_list sl);

    (3)errormsg.c

/*
 * errormsg.c - functions used in all phases of the compiler to give
 *              error messages about the program.
 *
 */

/* 本文件定义各种错误管理操作 */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "util.h"
#include "errormsg.h"

extern void resetLexState();

bool anyErrors= FALSE;

static string fileName = "";

static int lineNum = 1;//行号,用于报错

int EM_tokPos=0;

extern FILE *yyin;
extern FILE *yyout;

extern int yydebug;//bison中用于查错的标记,yydebug非0时,输出错误信息。



typedef struct intList {int i; struct intList *rest;} *IntList;

static IntList intList(int i, IntList rest) 
{IntList l= checked_malloc(sizeof *l);
 l->i=i; l->rest=rest;
 return l;
}

static IntList linePos=NULL; //行内位置,用于报错。

/* 换行时,处理行号和行内位置的函数。 */
void EM_newline(void)
{lineNum++;
 linePos = intList(EM_tokPos, linePos);
}

/* 报错函数,message是错误信息格式串,pos是错误位置。 */
void EM_error(int pos, char *message,...)
{va_list ap;//可变参数列表指针
 IntList lines = linePos; 
 int num=lineNum;
 

  anyErrors=TRUE;
  while (lines && lines->i >= pos) 
       {lines=lines->rest; num--;}

  if (fileName) fprintf(stderr,"%s:",fileName);
  if (lines) fprintf(stderr,"%d.%d: ", num, pos-lines->i);
  va_start(ap,message);//ap指向message这个参数的地址
  //格式打印到文件stderr中,格式串为message,所需的参数由ap指针指向
  vfprintf(stderr, message, ap);
  va_end(ap);//ap指针归零
  fprintf(stderr,"\n");

}


/* 重置关于错误管理的一些设置。 */
void EM_reset(string fname, string output)
{
 anyErrors=FALSE; fileName=fname; lineNum=1;
 linePos=intList(0,NULL);
 yyin = fopen(fname,"r");
 if (output){
 	yyout = fopen(output, "w");
 }
 yyrestart(yyin);//用于重置缓冲区的内容
 /* 在flex中,函数 void yyrestart(FILE * newfile) 会将yyin的指针指向newfile的开始处,并且,
  * 原lex输入缓冲区中的内容全部抹掉。这可以用来重启yylex()。(因为当文件读取一半时,重新
  * 调用yylex仍会接着原文件的位置分析,即使重新制定yyin,缓冲区内的内容也还是原来的内容)
  * 该函数不会重置lex的状态为INITIAL。
  */
 resetLexState(); //重置lex状态为INTIAL。
 if (!yyin) {EM_error(0,"cannot open"); exit(1);}
}

/* 此函数用于设定语法分析查错 */
void EM_yydebug(){
	yydebug = 1;
}
    (4)errormsg.h

extern bool EM_anyErrors;

void EM_newline(void);

extern int EM_tokPos;

void EM_error(int, string,...);

void EM_reset(string filename, string output);

void EM_yydebug();
    (5)lex.yy.c

#line 3 "lex.yy.c"

#define  YY_INT_ALIGNED short int

/* A lexical scanner generated by flex */

#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 5
#define YY_FLEX_SUBMINOR_VERSION 35
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif

/* First, we deal with  platform-specific or compiler-specific issues. */

/* begin standard C headers. */
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>

/* end standard C headers. */

/* flex integer type definitions */

#ifndef FLEXINT_H
#define FLEXINT_H

/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */

#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L

/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
 * if you want the limit (max/min) macros for int types. 
 */
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
#endif

#include <inttypes.h>
typedef int8_t flex_int8_t;
typedef uint8_t flex_uint8_t;
typedef int16_t flex_int16_t;
typedef uint16_t flex_uint16_t;
typedef int32_t flex_int32_t;
typedef uint32_t flex_uint32_t;
#else
typedef signed char flex_int8_t;
typedef short int flex_int16_t;
typedef int flex_int32_t;
typedef unsigned char flex_uint8_t; 
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
#endif /* ! C99 */

/* Limits of integral types. */
#ifndef INT8_MIN
#define INT8_MIN               (-128)
#endif
#ifndef INT16_MIN
#define INT16_MIN              (-32767-1)
#endif
#ifndef INT32_MIN
#define INT32_MIN              (-2147483647-1)
#endif
#ifndef INT8_MAX
#define INT8_MAX               (127)
#endif
#ifndef INT16_MAX
#define INT16_MAX              (32767)
#endif
#ifndef INT32_MAX
#define INT32_MAX              (2147483647)
#endif
#ifndef UINT8_MAX
#define UINT8_MAX              (255U)
#endif
#ifndef UINT16_MAX
#define UINT16_MAX             (65535U)
#endif
#ifndef UINT32_MAX
#define UINT32_MAX             (4294967295U)
#endif

#endif /* ! FLEXINT_H */

#ifdef __cplusplus

/* The "const" storage-class-modifier is valid. */
#define YY_USE_CONST

#else	/* ! __cplusplus */

/* C99 requires __STDC__ to be defined as 1. */
#if defined (__STDC__)

#define YY_USE_CONST

#endif	/* defined (__STDC__) */
#endif	/* ! __cplusplus */

#ifdef YY_USE_CONST
#define yyconst const
#else
#define yyconst
#endif

/* Returned upon end-of-file. */
#define YY_NULL 0

/* Promotes a possibly negative, possibly signed char to an unsigned
 * integer for use as an array index.  If the signed char is negative,
 * we want to instead treat it as an 8-bit unsigned char, hence the
 * double cast.
 */
#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)

/* Enter a start condition.  This macro really ought to take a parameter,
 * but we do it the disgusting crufty way forced on us by the ()-less
 * definition of BEGIN.
 */
#define BEGIN (yy_start) = 1 + 2 *

/* Translate the current start state into a value that can be later handed
 * to BEGIN to return to the state.  The YYSTATE alias is for lex
 * compatibility.
 */
#define YY_START (((yy_start) - 1) / 2)
#define YYSTATE YY_START

/* Action number for EOF rule of a given start state. */
#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)

/* Special action meaning "start processing a new file". */
#define YY_NEW_FILE yyrestart(yyin  )

#define YY_END_OF_BUFFER_CHAR 0

/* Size of default input buffer. */
#ifndef YY_BUF_SIZE
#define YY_BUF_SIZE 16384
#endif

/* The state buf must be large enough to hold one stat
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值