Tiny C语言编译程序之语法分析Parser
2017-05-22 22:09
801 查看
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
相关文章推荐
- 编译中的基于算符优先分析程序的语法制导翻译
- 关于Basic程序解释器及编译原理的简单化(1)---Basic器的语法分析及主要代码
- 吉首大学_编译原理实验题_基于预測方法的语法分析程序的设计【通过代码】
- 编译原理丨第十三周 ——1000. 输入输出LL(1)语法分析程序
- Tiny C语言编译程序之词法分析Scanner
- 编译原理:递归向下分析程序建立语法分析树的Java实现(二)
- 吉首大学_编译原理实验题_基于预测方法的语法分析程序的设计【通过代码】
- 编译原理-用Bison构造语法分析程序-二进制转换十进制
- 编译原理之算符优先分析语法程序
- 编译原理:递归向下分析程序建立语法分析树的Java实现(一)
- 编译原理 实验3 递归下降语法分析程序设计
- 关于Basic程序解释器及编译原理的简单化(1)---Basic器的语法分析及主要代码
- 编译原理语法分析对循环语句和条件判断语句编写词法分析编译程序,只能通过一遍扫描完成
- 编译原理-用Bison构造语法分析程序-小小计算器
- 编译原理——语法分析程序的设计
- 递归下降语法分析程序
- 【编译原理】简析文法分析,语法分析
- PL/0语言编译程序分析
- 编译源码查看日志,分析程序
- 用ADS编译ARM程序后生成镜像Image的信息分析