实验报告:递归下降分析法

实验目的

  1. 学习,掌握递归下降分析法和抽象语法树的基本原理。
  2. 学习,掌握递归下降分析程序的构造方法。

实验原理

  1. 递归下降分析法的基本思想:
    在不含有左递归的文法G中,为每个非终结符构造一个子程序,每个子程序的函数体按照非终结符的产生式分情况展开。遇到终结符则进行匹配,遇到非终结符则调用相应的非终结符的子程序。
    在这里插入图片描述

  2. 递归下降分析法的前提:
    改造文法:消除二义性、消除左递归、提取左因子,判断是否为LL(1)文法。

  3. 抽象语法树:
    给定文法:G=(Vn,Vt,P,S),对于G的任何句型都能构造与之关联的语法树(推导树)。树中的每一个节点都有一个标记,此标记是V=Vn∪Vt中的一个符号。语法树是句子结构的图形表示,它代表了句子的推导结果,有利于理解句子语法结构的层次。
    在这里插入图片描述


实验内容

  1. 学习所提供的表达式文法的递归下降处理:
    (1)理解rdlex.l、rdparser.c的内容;
    (2)在eclipse中建立工程并调试。
  2. 学习rdgram.txt所提供的文法,与词法分析所提供的文法作比较。
  3. 编写rdgram.text所提供文法的递归下降程序:
    (1)编写不生成语法树的递归下降程序【rdcheck.c】;
    (2)将rdcheck.c改造为生成语法树的递归下降程序【rdparser.c】;
    (3)改进词法分析程序、showAst函数、main函数等,使递归下降程序rdparser.c最终从命令行读取要分析的程序test.c,分析后调用showAst打印该程序的结构。
  4. 所有文件都以utf-8进行统一编码保存。

实验器材

visual studio 2017
Notepad++,flex 2.5.4.1


实验步骤

一、学习rdgram.txt所提供的文法

举例:

program
    : external_declaration
    | program external_declaration
    ;
decl_or_stmt
    : '{' statement_list '}'
    | '{' '}'
    | ',' declarator_list ';'
    | ';'
    ;

提取左因子,消除左递归后如下:

program → external_declaration program_1
program_1 → external_declaration program_1 | ε

decl_or_stmt → { statement_list_1 } | declarator_list_2 ;
statement_list_1 → statement_list | ε
declarator_list_2 → , declarator_list | ε

二、编写不生成语法树的递归下降程序【rdcheck.c】

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

enum yytokentype {
	IF = 245,
	ELSE = 246,
	WHILE = 247,
	RETURN = 248,
	PRINT = 249,
	SCAN = 250,
	CMP = 251,
	ASSIGN = 252,
	INT = 253,
	STR = 254,
	VOID = 255,
	STRING = 256,
	ID = 257,
	NUMBER = 258,
	EOL = 259
};

extern int yylex();
extern int yylval;
extern char* yytext;
extern FILE* yyin;

void advance();

int program();
int program_1();
int external_declaration();
int decl_or_stmt();
int declarator_list();
int declarator_list_1();
int intstr_list();
int intstr_list_1();
int initializer();
int declarator();
int parameter_list();
int parameter_list_1();
int parameter();
int type();
int statement();
int statement_list();
int statement_list_1();
int expression_statement();
int expr();
int cmp_expr();
int cmp_expr_1();
int add_expr();
int add_expr_1();
int mul_expr();
int mul_expr_1();
int primary_expr();
int expr_list();
int expr_list_1();
int id_list();
int id_list_1();

int tok;

int main(int argc, char **argv)
{
	printf("result:\n");
	yyin = fopen("test.c", "r");
	advance();
	int r = program();
	if (r == 1)
		printf("True!\n\n");
	else
		printf("Fault!\n\n");
	system("pause");
	return 0;
}

void advance() {
	tok = yylex();
	printf("tok: %s\n", yytext);
}

//program
//	: external_declaration
//	| program external_declaration
//	;
int program() {
	if (external_declaration())
		if (program_1())
			return 1;
	return 0;
}
int program_1() {
	if (external_declaration()) {
		if (program_1())
			return 1;
	}
	else
		return 1;
	return 0;
}

//external_declaration
//	: type declarator decl_or_stmt
//	;
int external_declaration() {
	if (type())
		if (declarator())
			if (decl_or_stmt())
				return 1;
	return 0;
}

//decl_or_stmt
//	: '{' statement_list '}'
//	| '{' '}'
//	| ',' declarator_list ';'
//	| ';'
//	;
int decl_or_stmt() {
	if (tok == '{') {
		advance();
		if (statement_list())
			;
		if (tok == '}') {
			advance();
			return 1;
		}
	}
	else if (tok == ',') {
		advance();
		if (declarator_list())
			if (tok == ';') {
				advance();
				return 1;
			}
	}
	else if (tok == ';') {
		advance();
		return 1;
	}
	return 0;
}

//declarator_list
//	: declarator
//	| declarator_list ',' declarator
//	;
int declarator_list() {
	if (declarator())
		if (declarator_list_1())
			return 1;
	return 0;
}
int declarator_list_1() {
	if (tok == ',') {
		advance();
		if (declarator())
			if (declarator_list_1())
				return 1;
	}
	else
		return 1;
	return 0;
}

//intstr_list
//	: initializer
//	| intstr_list ',' initializer
//	;
int intstr_list() {
	if (initializer())
		if (intstr_list_1())
			return 1;
	return 0;
}
int intstr_list_1() {
	if (tok == ',') {
		advance();
		if (initializer())
			if (intstr_list_1())
				return 1;
	}
	else
		return 1;
	return 0;
}

//initializer
//	: NUMBER
//	| STRING
//	;
int initializer() {
	if (tok == NUMBER) {
		advance();
		return 1;
	}
	else if (tok == STRING) {
		advance();
		return 1;
	}
	return 0;
}

//declarator
//	: ID
//	| ID '=' expr
//	| ID '(' parameter_list ')'
//	| ID '(' ')'
//	| ID '[' expr ']'
//	| ID '[' ']'
//	| ID '[' expr ']' '=' '{' intstr_list '}'
//	| ID '[' ']' '=' '{' intstr_list '}'
//	;
int declarator() {
	if (tok == ID) {
		advance();
		if (tok == '=') {
			advance();
			if (expr())
				return 1;
		}
		else if (tok == '(') {
			advance();
			if (parameter_list())
				;
			if (tok == ')') {
				advance();
				return 1;
			}
		}
		else if (tok == '[') {
			advance();
			if (expr())
				;
			if (tok == ']') {
				advance();
				if (tok == '=') {
					advance();
					if (tok == '{') {
						advance();
						if (intstr_list())
							if (tok == '}') {
								advance();
								return 1;
							}
					}
					return 0;
				}
				return 1;
			}
		}
		return 1;
	}
	return 0;
}

//parameter_list
//	: parameter
//	| parameter_list ',' parameter
//	;
int parameter_list() {
	if (parameter())
		if (parameter_list_1())
			return 1;
	return 0;
}
int parameter_list_1() {
	if (tok == ',') {
		advance();
		if (parameter())
			if (parameter_list_1())
				return 1;
	}
	else
		return 1;
	return 0;
}

//parameter
//	: type ID
//	;
int parameter() {
	if (type())
		if (tok == ID) {
			advance();
			return 1;
		}
	return 0;
}

//type
//	: INT
//	| STR
//	| VOID
//	;
int type() {
	if (tok == INT) {
		advance();
		return 1;
	}
	else if (tok == STR) {
		advance();
		return 1;
	}
	else if (tok == VOID) {
		advance();
		return 1;
	}
	return 0;
}

//statement
//	: type declarator_list ';'
//	| '{' statement_list '}'
//	| expr_statement	//⬅这个是不是有问题?先改成expression_statement
//	| IF '(' expr ')' statement
//	| IF '(' expr ')' statement ELSE statement
//	| WHILE '(' expr ')' statement
//	| RETURN ';'
//	| RETURN expr ';'
//	| PRINT ';'
//	| PRINT expr_list ';'
//	| SCAN id_list ';'
//	;
int statement() {
	if (type()) {
		if (declarator_list())
			if (tok == ';') {
				advance();
				return 1;
			}
	}
	else if (tok == '{') {
		advance();
		if (statement_list())
			if (tok == '}') {
				advance();
				return 1;
			}
	}
	else if (expression_statement())
		return 1;
	else if (tok == IF) {
		advance();
		if (tok == '(') {
			advance();
			if (expr())
				if (tok == ')') {
					advance();
					if (statement()) {
						if (tok == ELSE) {
							advance();
							if (statement())
								return 1;
						}
						else
							return 1;
					}
				}
		}
	}
	else if (tok == WHILE) {
		advance();
		if (tok == '(') {
			advance();
			if (expr())
				if (tok == ')') {
					advance();
					if (statement())
						return 1;
				}
		}
	}
	else if (tok == RETURN) {
		advance();
		if (expr())
			;
		if (tok == ';') {
			advance();
			return 1;
		}
	}
	else if (tok == PRINT) {
		advance();
		if (expr_list())
			;
		if (tok == ';') {
			advance();
			return 1;
		}
	}
	else if (tok == SCAN) {
		advance();
		if (id_list())
			if (tok == ';') {
				advance();
				return 1;
			}
	}
	return 0;
}

//statement_list
//	: statement
//	| statement_list statement
//	;
int statement_list() {
	if (statement())
		if (statement_list_1())
			return 1;
	return 0;
}
int statement_list_1() {
	if (statement()) {
		if (statement_list_1())
			return 1;
	}
	else
		return 1;
	return 0;
}

//expression_statement
//	: ';'
//	| expr ';'
//	;
int expression_statement() {
	if (tok == ';') {
		advance();
		return 1;
	}
	else if (expr())
		if (tok == ';') {
			advance();
			return 1;
		}
	return 0;
}

//expr
//	: cmp_expr
//	;
int expr() {
	if (cmp_expr())
		return 1;
	return 0;
}

//cmp_expr
//	: add_expr
//	| cmp_expr CMP add_expr
//	;
int cmp_expr() {
	if (add_expr())
		if (cmp_expr_1())
			return 1;
	return 0;
}
int cmp_expr_1() {
	if (tok == CMP) {
		advance();
		if (add_expr())
			if (cmp_expr_1())
				return 1;
	}
	else
		return 1;
	return 0;
}

//add_expr
//	: mul_expr
//	| add_expr '+' mul_expr
//	| add_expr '-' mul_expr
//	;
int add_expr() {
	if (mul_expr())
		if (add_expr_1())
			return 1;
	return 0;
}
int add_expr_1() {
	if (tok == '+' || tok == '-') {
		advance();
		if (mul_expr())
			if (add_expr_1())
				return 1;
	}
	else
		return 1;
	return 0;
}

//mul_expr
//	: primary_expr
//	| mul_expr '*' primary_expr
//	| mul_expr '/' primary_expr
//	| mul_expr '%' primary_expr
//	| '-' primary_expr
//	;
int mul_expr() {
	if (tok == '-')
		advance();
	if (primary_expr())
		if (mul_expr_1())
			return 1;
	return 0;
}
int mul_expr_1() {
	if (tok == '*' || tok == '/' || tok == '%') {
		advance();
		if (primary_expr())
			if (mul_expr_1())
				return 1;
	}
	else
		return 1;
	return 0;
}

//primary_expr
//	: ID '(' expr_list ')'
//	| ID '(' ')'
//	| '(' expr ')'
//	| ID
//	| NUMBER
//	| STRING
//	| ID ASSIGN expr
//	| ID '=' expr
//	| ID '[' expr ']'
//	| ID '[' expr ']' '=' expr
//	;
int primary_expr() {
	if (tok == ID) {
		advance();
		if (tok == '(') {
			advance();
			if (expr_list())
				;
			if (tok == ')') {
				advance();
				return 1;
			}
		}
		else if (tok == ASSIGN) {
			advance();
			if (expr())
				return 1;
		}
		else if (tok == '=') {
			advance();
			if (expr())
				return 1;
		}
		else if (tok == '[') {
			advance();
			if (expr())
				if (tok == ']') {
					advance();
					if (tok == '=') {
						advance();
						if (expr())
							return 1;
						else
							return 0;
					}
					return 1;
				}
		}
		else
			return 1;
	}
	else if (tok == '(') {
		advance();
		if (expr())
			if (tok == ')') {
				advance();
				return 1;
			}
	}
	else if (tok == NUMBER) {
		advance();
		return 1;
	}
	else if (tok == STRING) {
		advance();
		return 1;
	}
	return 0;
}

//expr_list
//	: expr
//	| expr_list ',' expr
//	;
int expr_list() {
	if (expr())
		if (expr_list_1())
			return 1;
	return 0;
}
int expr_list_1() {
	if (tok == ',') {
		advance();
		if (expr())
			if (expr_list_1())
				return 1;
	}
	else
		return 1;
	return 0;
}

//id_list
//	: ID
//	| id_list ',' ID
//	;
int id_list() {
	if (tok == ID) {
		advance();
		if (id_list_1())
			return 1;
	}
	return 0;
}
int id_list_1() {
	if (tok == ',') {
		advance();
		if (tok == ID) {
			advance();
			if (id_list_1())
				return 1;
		}
	}
	else
		return 1;
	return 0;
}

三、将rdcheck.c改造为生成语法树的递归下降程序【rdparser.c】

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

enum TokenType {
	IF = 245,
	ELSE = 246,
	WHILE = 247,
	RETURN = 248,
	PRINT = 249,
	SCAN = 250,
	CMP = 251,
	ASSIGN = 252,
	INT = 253,
	STR = 254,
	VOID = 255,
	STRING = 256,
	ID = 257,
	NUMBER = 258,
	EOL = 259
};

extern int yylex();
extern int yylval;
extern char* yytext;
extern FILE* yyin;

typedef struct _ast ast;
typedef struct _ast *past;
struct _ast {
	char *nodeType;		//类型
	char *content;		//内容
	past left;			//左分支
	past right;			//右分支
};

int tok;
void advance();

past program();
past external_declaration();
past decl_or_stmt();
past declarator_list();
past intstr_list();
past initializer();
past declarator();
past parameter_list();
past parameter();
past type();
past statement();
past statement_list();
past expression_statement();
past expr();
past cmp_expr();
past add_expr();
past mul_expr();
past primary_expr();
past expr_list();
past id_list();

past newAstNode(char *nodeType, char *content, past left, past right);
void showAst(past node, int nest);
void freeAst(past node);

int main(int argc, char **argv)
{
	printf("result:\n");
	yyin = fopen("test.c", "r");
	advance();
	past root = program();
	printf("");
	showAst(root, 0);
	freeAst(root);

	system("pause");
	return 0;
}

void advance() {
	tok = yylex();
	printf("tok: %s\n", yytext);
}

//构造新结点
past newAstNode(char *nodeType, char *content, past left, past right) {
	past node = (past)malloc(sizeof(ast));
	if (node == NULL) {
		printf("run out of memory.\n");
		exit(0);
	}
	node->nodeType = nodeType;
	node->content = content;
	node->left = left;
	node->right = right;
	return node;
}

//输出语法树
void showAst(past node, int nest) {
	if (node == NULL)
		return;

	int i = 0;
	for (i = 0; i < nest; i++)
		printf("  ");
	printf("%s: %s\n", node->nodeType, node->content);
	showAst(node->left, nest + 1);
	showAst(node->right, nest + 1);
}

//释放结点
void freeAst(past node) {
	if (node == NULL)
		return;
	freeAst(node->left);
	freeAst(node->right);
	free(node);
}

//program
//	: external_declaration
//	| program external_declaration
//	;
past program() {
	past root = NULL;
	if (root = external_declaration())
		root = newAstNode("program", "", root, program());
	return root;
}

//external_declaration
//	: type declarator decl_or_stmt
//	;
past external_declaration() {
	past root = NULL;
	if (root = type()) {
		root = newAstNode("external_declaration", "", root, newAstNode("typebody", "", NULL, NULL));
		if (root->right->left = declarator())
			if (root->right->right = decl_or_stmt())
				;
	}
	return root;
}

//decl_or_stmt
//	: '{' statement_list '}'
//	| '{' '}'
//	| ',' declarator_list ';'
//	| ';'
//	;
past decl_or_stmt() {
	past root = NULL;
	if (tok == '{') {
		advance();
		if (root = statement_list())
			root = newAstNode("decl_or_stmt", "", root, NULL);
		if (tok == '}')
			advance();
	}
	else if (tok == ',') {
		advance();
		if (root = declarator_list())
			if (tok == ';')
				advance();
	}
	else if (tok == ';')
		advance();
	return root;
}

//declarator_list
//	: declarator
//	| declarator_list ',' declarator
//	;
past declarator_list() {
	past root = NULL;
	if (root = declarator()) {
		root = newAstNode("declarator_list", "", root, NULL);
		if (tok == ',') {
			advance();
			root->right = declarator_list();
		}
	}
	return root;
}

//intstr_list
//	: initializer
//	| intstr_list ',' initializer
//	;
past intstr_list() {
	past root = NULL;
	if (root = initializer()) {
		root = newAstNode("intstr_list", "", root, NULL);
		if (tok == ',') {
			advance();
			root->right = intstr_list();
		}
	}
	return root;
}

//initializer
//	: NUMBER
//	| STRING
//	;
past initializer() {
	past root = NULL;
	if (tok == NUMBER) {
		root = newAstNode("number", strdup(yytext), NULL, NULL);
		advance();
	}
	else if (tok == STRING) {
		root = newAstNode("string", strdup(yytext), NULL, NULL);
		advance();
	}
	return root;
}

//declarator
//	: ID
//	| ID '=' expr
//	| ID '(' parameter_list ')'
//	| ID '(' ')'
//	| ID '[' expr ']'
//	| ID '[' ']'
//	| ID '[' expr ']' '=' '{' intstr_list '}'
//	| ID '[' ']' '=' '{' intstr_list '}'
//	;
past declarator() {
	past root = NULL;
	if (tok == ID) {
		root = newAstNode("declarator", strdup(yytext), NULL, NULL);
		advance();
		if (tok == '=') {
			advance();
			root->right = expr();
		}
		else if (tok == '(') {
			advance();
			root->left = parameter_list();
			if (tok == ')')
				advance();
		}
		else if (tok == '[') {
			advance();
			root->left = expr();
			if (tok == ']') {
				advance();
				if (tok == '=') {
					advance();
					if (tok == '{') {
						advance();
						if (root->right = intstr_list()) {
							root->right = newAstNode("InitListExpr", "", root->right, NULL);
							if (tok == '}')
								advance();
						}
					}
				}
			}
		}
	}
	return root;
}

//parameter_list
//	: parameter
//	| parameter_list ',' parameter
//	;
past parameter_list() {
	past root = NULL;
	if (root = parameter()) {
		root = newAstNode("parameter_list", "", root, NULL);
		if (tok == ',') {
			advance();
			root->right = parameter_list();
		}
	}
	return root;
}

//parameter
//	: type ID
//	;
past parameter() {
	past root = NULL;
	if (root = type())
		if (tok == ID) {
			root = newAstNode("parameter", "", root, newAstNode("ID", strdup(yytext), NULL, NULL));
			advance();
		}
	return root;
}

//type
//	: INT
//	| STR
//	| VOID
//	;
past type() {
	past root = NULL;
	if (tok == INT || tok == STR || tok == VOID) {
		root = newAstNode("type", strdup(yytext), NULL, NULL);
		advance();
	}
	return root;
}

//statement
//	: type declarator_list ';'
//	| '{' statement_list '}'
//	| expr_statement	//⬅这个是不是有问题?先改成expression_statement
//	| IF '(' expr ')' statement
//	| IF '(' expr ')' statement ELSE statement
//	| WHILE '(' expr ')' statement
//	| RETURN ';'
//	| RETURN expr ';'
//	| PRINT ';'
//	| PRINT expr_list ';'
//	| SCAN id_list ';'
//	;
past statement() {
	past root = NULL;
	if (root = type()) {
		root = newAstNode("declarator_statement", "", root, NULL);
		if (root->right = declarator_list())
			if (tok == ';')
				advance();
	}
	else if (tok == '{') {
		advance();
		if (root = statement_list()) {
			root = newAstNode("compound_statement", "", root, NULL);
			if (tok == '}')
				advance();
		}
	}
	else if (root = expression_statement())
		;
	else if (tok == IF) {
		root = newAstNode("if_statement", "", NULL, newAstNode("ifbody", "", NULL, NULL));
		advance();
		if (tok == '(') {
			advance();
			if (root->left = expr())
				if (tok == ')') {
					advance();
					if (root->right->left = statement())
						if (tok == ELSE) {
							advance();
							if (root->right->right = statement())
								;
						}
				}
		}
	}
	else if (tok == WHILE) {
		root = newAstNode("while_statement", "", NULL, NULL);
		advance();
		if (tok == '(') {
			advance();
			if (root->left = expr())
				if (tok == ')') {
					advance();
					if (root->right = statement())
						;
				}
		}
	}
	else if (tok == RETURN) {
		root = newAstNode("return_statement", "", NULL, NULL);
		advance();
		root->left = expr();
		if (tok == ';')
			advance();
	}
	else if (tok == PRINT) {
		root = newAstNode("print_statement", "", NULL, NULL);
		advance();
		root->left = expr_list();
		if (tok == ';')
			advance();
	}
	else if (tok == SCAN) {
		root = newAstNode("scan_statement", "", NULL, NULL);
		advance();
		if (root->left = id_list())
			if (tok == ';')
				advance();
	}
	return root;
}

//statement_list
//	: statement
//	| statement_list statement
//	;
past statement_list() {
	past right = statement();
	if (right == NULL)
		return NULL;
	else
		return newAstNode("statement_list", "", statement_list(), right);
}

//expression_statement
//	: ';'
//	| expr ';'
//	;
past expression_statement() {
	past root = NULL;
	if (tok == ';')
		advance();
	else if (root = expr()) {
		if (tok == ';')
			advance();
	}
	return root;
}

//expr
//	: cmp_expr
//	;
past expr() {
	return cmp_expr();
}

//cmp_expr
//	: add_expr
//	| cmp_expr CMP add_expr
//	;
past cmp_expr() {
	past root = NULL;
	root = add_expr();
	if (root)
		while (tok==CMP) {
			root = newAstNode("cmp_expr", strdup(yytext), root, NULL);
			advance();
			root->right = add_expr();
		}
	return root;
}

//add_expr
//	: mul_expr
//	| add_expr '+' mul_expr
//	| add_expr '-' mul_expr
//	;
past add_expr() {
	past root = NULL;
	root = mul_expr();
	if (root)
		while (tok == '+' || tok == '-') {
			root = newAstNode("add_expr", strdup(yytext), root, NULL);
			advance();
			root->right = mul_expr();
		}
	return root;
}

//mul_expr
//	: primary_expr
//	| mul_expr '*' primary_expr
//	| mul_expr '/' primary_expr
//	| mul_expr '%' primary_expr
//	| '-' primary_expr
//	;
past mul_expr() {
	past root = NULL;
	root = primary_expr();
	if (root) {
		while (tok == '*' || tok == '/' || tok == '%') {
			root = newAstNode("mul_expr", strdup(yytext), root, NULL);
			advance();
			root->right = primary_expr();
		}
	}
	else if (tok == '-') {
		root = newAstNode("mul_expr", strdup(yytext), NULL, NULL);
		advance();
		root->right = primary_expr();
	}
	return root;
}

//primary_expr
//	: ID '(' expr_list ')'
//	| ID '(' ')'
//	| '(' expr ')'
//	| ID
//	| NUMBER
//	| STRING
//	| ID ASSIGN expr
//	| ID '=' expr
//	| ID '[' expr ']'
//	| ID '[' expr ']' '=' expr
//	;
past primary_expr() {
	past root = NULL;
	if (tok == ID) {
		root = newAstNode("primary_expr", strdup(yytext), NULL, NULL);
		advance();
		if (tok == '(') {
			advance();
			root->left = expr_list();
			if (tok == ')')
				advance();
		}
		else if (tok == '[') {
			advance();
			if (root->left = expr())
				if (tok == ']') {
					advance();
					if (tok == '=') {
						root = newAstNode("Operator", strdup(yytext), root, NULL);
						advance();
						root->right = expr();
					}
				}
		}
		else if (tok == '=' || tok == ASSIGN) {
			root = newAstNode("primary_expr", strdup(yytext), root, NULL);
			advance();
			root->right = expr();
		}
	}
	else if (tok == '(') {
		advance();
		if (root = expr())
			if (tok == ')')
				advance();
	}
	else if (tok == NUMBER) {
		root = newAstNode("number", strdup(yytext), NULL, NULL);
		advance();
	}

	else if (tok == STRING) {
		root = newAstNode("string", strdup(yytext), NULL, NULL);
		advance();
	}
	return root;
}

//expr_list
//	: expr
//	| expr_list ',' expr
//	;
past expr_list() {
	past root = NULL;
	if (root = expr()) {
		root = newAstNode("expr_list", "", root, NULL);
		if (tok == ',') {
			advance();
			root->right = expr_list();
		}
	}
	return root;
}

//id_list
//	: ID
//	| id_list ',' ID
//	;
past id_list() {
	past root = NULL;
	if (tok == ID) {
		root = newAstNode("id_list", NULL, newAstNode("ID", strdup(yytext), NULL, NULL), NULL);
		advance();
		if (tok == ',') {
			advance();
			root->right = id_list();
		}
	}
	return root;
}

四、改进词法分析程序c14_lex.l、showAst函数、main函数等,使递归下降程序rdparser.c最终从命令行读取要分析的程序test.c,分析后调用showAst打印该程序的结构。

%{
enum yytokentype {
    IF = 245,
	ELSE = 246,
	WHILE = 247,
	RETURN = 248,
	PRINT = 249,
	SCAN = 250,
	CMP = 251,
	ASSIGN = 252,
    INT = 253,
	STR = 254,
	VOID = 255,
	STRING = 256,
    ID = 257,
	NUMBER = 258,
	EOL = 259
};

int yylval;

%}

NOTE [^\n]*
STRING [^"]*

%%

"//"{NOTE}				{ /* ignore note */ }
["][^"]*["]				{ yylval = atoi(yytext); return STRING; }

"int"					{ yylval = atoi(yytext); return INT; }
"str"					{ yylval = atoi(yytext); return STR; }
"void"					{ yylval = atoi(yytext); return VOID; }
"if"					{ yylval = atoi(yytext); return IF; }
"else"					{ yylval = atoi(yytext); return ELSE; }
"while"					{ yylval = atoi(yytext); return WHILE; }
"return"				{ yylval = atoi(yytext); return RETURN; }
"print"					{ yylval = atoi(yytext); return PRINT; }
"scan"					{ yylval = atoi(yytext); return SCAN; }
"assign"				{ yylval = atoi(yytext); return ASSIGN; }

"+"|"-"|"*"|"/"|"%"|"="	{ return yytext[0]; }
"("|")"|"["|"]"|"{"|"}"	{ return yytext[0]; }
","|";"					{ return yytext[0]; }

">"|"<"|"<="|">="|"=="	{ yylval = atoi(yytext); return CMP; }
[a-z][a-zA-Z0-9|_]*		{ yylval = atoi(yytext); return ID; }
[0-9]+ 					{ yylval = atoi(yytext); return NUMBER; }

[ \t] 					{ /* ignore whitespace */ }
. 						{ printf("Mystery character %c\n", *yytext); }

%%

int yyerror(char *s)
{
	fprintf(stderr, "error: %s\n", s);
	return 0;
}

int yywrap()
{
	return 1;
}

实验结果

一、不生成语法树的递归下降程序【rdcheck.c】
在这里插入图片描述

二、生成语法树的递归下降程序【rdparser.c】
在这里插入图片描述


编译技术实验:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值