Tiny C语言编译程序之语法分析Parser

Tiny C语言编译程序之语法分析Parser

约定:

  • 用递归下降分析法,为每个语法符号编写子程序。进入每个子程序前已读入一个新Token。
  • 一个语法结构的内部表示形式为语法树,数据结构是globals.h中的treeNode。在做语法分析的同时建立语法结构的内部表示——语法树。

语法分析器parse.c

/****************************************************/
/* File: parse.c                                    */
/* The parser implementation for the TINY compiler  */
/****************************************************/

#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 * stmt_sequence(void);  /* 语句序列 */
static TreeNode * statement(void);      /* 语句 */
static TreeNode * if_stmt(void);        /* if语句 */ 
static TreeNode * repeat_stmt(void);    /* 循环语句 */ 
static TreeNode * assign_stmt(void);    /* 赋值语句 */
static TreeNode * read_stmt(void);      /* 输入语句 */
static TreeNode * write_stmt(void);     /* 输出语句 */
static TreeNode * exp(void);            /* 表达式 */
static TreeNode * simple_exp(void);     /* 简单表达式 */
static TreeNode * term(void);           /* 乘法项 */
static TreeNode * factor(void);         /* 因子 */

/* 显示出错信息*/
static void syntaxError(char * message)
{ fprintf(listing,"\n>>> ");
  fprintf(listing,"Syntax error at line %d: %s",lineno,message);
  Error = TRUE;
}

/* 保存向前看记号的静态变量token和检测输入的记号是否和预期相同 */
static void match(TokenType expected)
{ if (token == expected) token = getToken();/*它找到匹配时就调用getToken,否则就声明出错*/
  else {
    syntaxError("unexpected token -> ");
    printToken(token,tokenString);
    fprintf(listing,"      ");
  }
}

/* 用来匹配非终结符stmt_sequence */
TreeNode * stmt_sequence(void)
{ TreeNode * t = statement();
  TreeNode * p = t;
  while ((token!=ENDFILE) && (token!=END) &&
         (token!=ELSE) && (token!=UNTIL))/* 当输入的记号不标识语句序列结束的记号 */ 
  { TreeNode * q;
    match(SEMI);/* 跳过分号 */
    q = statement();
    if (q!=NULL) {
      if (t==NULL) t = p = q;
      else /* now p cannot be NULL either *//* 如果t不是NULL,那么p也一定不是NULL */
      { p->sibling = q;/* 把state链接起来 */
        p = q;
      }
    }
  }
  return t;
}

/* 用来匹配statement非终结符 */
TreeNode * statement(void)
{ TreeNode * t = NULL;
  switch (token) {/* 检测当前的token,根据输入决定如何识别 */
    case IF : t = if_stmt(); break;
    case REPEAT : t = repeat_stmt(); break;
    case ID : t = assign_stmt(); break;
    case READ : t = read_stmt(); break;
    case WRITE : t = write_stmt(); break;
    default : syntaxError("unexpected token -> ");
              printToken(token,tokenString);
              token = getToken();
              break;
  } /* end case */
  return t;
}

/* 用来匹配if_stmt非终结符 */
TreeNode * if_stmt(void)
{             
    TreeNode * t = newStmtNode(IfK);
    match(IF);
    if (t!=NULL) 
        t->child[0] = exp();
    match(THEN);
    if (t!=NULL) 
        t->child[1] = stmt_sequence(); 
    if (token==ELSE) {
        match(ELSE);
        if (t!=NULL) 
            t->child[2] = stmt_sequence();
    }
    match(END);
    return t;
}

/* 用来匹配repeat_stmt非终结符 */
TreeNode * repeat_stmt(void)
{   
    TreeNode * t = newStmtNode(RepeatK);
    match(REPEAT);
    if(t!=NULL){
        t->child[0] = stmt_sequence(); 
    }
    match(UNTIL);
    if(t!=NULL){
        t->child[1] = exp();
    }
    return t;
}

/* 用来匹配assign_stmt非终结符 */
TreeNode * assign_stmt(void)
{ 
    TreeNode * t = newStmtNode(AssignK);
    if((t!=NULL)&&(token==ID)){
        t->attr.name = copyString(tokenString);
    }
    match(ID);
    match(ASSIGN);
    if(t!=NULL){
        t->child[0] = exp();
    }
    return t;
}

/* 用来匹配read_stmt非终结符 */
TreeNode * read_stmt(void)
{
    TreeNode * t = newStmtNode(ReadK);
    match(READ);
    if((t!=NULL)&&(token==ID)){
        t->attr.name = copyString(tokenString);
    }
    match(ID);
    return t;
}

/* 用来匹配write_stmt非终结符 */
TreeNode * write_stmt(void)
{
    TreeNode * t = newStmtNode(WriteK);
    match(WRITE);
    if(t!=NULL){
        t->child[0] = exp();
    }
    return t;
}

/* 用来匹配exp非终结符 */
TreeNode * exp(void)
{ TreeNode * t = simple_exp();
  if ((token==LT)||(token==EQ)) {
    TreeNode * p = newExpNode(OpK);
    if (p!=NULL) {
      p->child[0] = t;
      p->attr.op = token;
      t = p;
    }
    match(token);
    if (t!=NULL)
      t->child[1] = simple_exp();
  }
  return t;
}

/* 用来匹配simple_stmt非终结符 */
TreeNode * simple_exp(void)
{
    TreeNode * t = term();
    while ((token==PLUS)||(token==MINUS)){ 
        TreeNode * p = newExpNode(OpK);
        if (p!=NULL) {
            p->child[0] = t;
            p->attr.op = token;
            t = p;
            match(token);
            t->child[1] = term();
        }
    }
    return t;
}

/* 用来匹配term非终结符 */
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;
            t = p;
            match(token);
            p->child[1] = factor();
        }
    }
    return t;
}

/* 用来匹配factor非终结符 */
TreeNode * factor(void)
{
    char msgerror[100];
    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 = newExpNode(IdK);
            if ((t!=NULL) && (token==ID)){
                t->attr.name = copyString(tokenString); 
            }
            match(ID);
            break;
        case LPAREN :
            match(LPAREN);
            t = exp();
            match(RPAREN);
            break;
        default:
            strcpy(msgerror,"unexpected token -> ");
            strcat(msgerror,tokenString);
            syntaxError(msgerror);
            //syntaxError("unexpected token -> ");
            //printToken(token,tokenString);
            token = getToken();
            break;
    }
    return t;
}

/****************************************/
/* the primary function of the parser   */
/****************************************/
/* Function parse returns the newly 
 * constructed syntax tree
 */
TreeNode * parse(void)
{ TreeNode * t;
  token = getToken();
  t = stmt_sequence();
  if (token!=ENDFILE)
    syntaxError("Code ends before file\n");
  return t;
}

分析后输出的语法树结构如下:

Syntax tree:
  Read: x
  If
    Op: <
      Const: 0
      Id: x
    Assign to: fact
      Const: 1
    Repeat
      Assign to: fact
        Op: *
          Id: fact
          Id: x
      Assign to: x
        Op: -
          Id: x
          Const: 1
      Op: =
        Id: x
        Const: 0
    Write
      Id: fact

你可能感兴趣的:(Tiny-C)