Tiny C语言编译程序之语法分析Parser
来源:互联网 发布:圣诞唱诗班歌曲知乎 编辑:程序博客网 时间:2024/05/22 07:02
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
阅读全文
0 0
- Tiny C语言编译程序之语法分析Parser
- Tiny C语言编译程序之词法分析Scanner
- Tiny语言编译器开发之语法分析
- Tiny语言编译器开发之语法分析(利…
- UCC-C语言语法分析
- PL/0语言编译程序整理实现:(5)、语法分析
- (编译原理)TINY扩充语言的语法分析
- C语言解释器-15 语法分析之辅助工具
- tiny扩充语法分析
- a Tiny Parser Generator
- 编译原理实验之语法分析(算符优先分析算法(C语言))
- 编译原理之 语法分析c代码
- Tiny语言编译器开发之词法分析
- Tiny语言编译器之符号表
- Tiny语言编译器之语义分析
- Tiny语言编译器之TM虚拟机开发
- Tiny语言编译器之TM虚拟机接口
- Tiny语言编译器之代码生成
- Spring 注入 Set
- 07.java数据溢出与数据转换
- 谷歌大牛说:为什么 Kotlin 比你们用的那些垃圾语言都好
- C++中间结果溢出
- Redis 各类型常用方法与 运用场景
- Tiny C语言编译程序之语法分析Parser
- 【Web】CSS3动画效果制作
- 初次接触Markdown
- 第6章 过滤器
- Java面试题-未被初始化的字符串打印出“null”的问题的分析
- LeetCode 485. Max Consecutive Ones
- ScrollView嵌套下ListView或ExpandableListView的高度自适应
- PHP分页+Elasticsearch查询
- 使用TextRank算法为文本生成关键字和摘要