⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 finsh_parser.c

📁 中国人自己的c语言
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <finsh/finsh.h>

#include "finsh_token.h"
#include "finsh_node.h"
#include "finsh_type.h"
#include "finsh_error.h"
#include "finsh_parser.h"
#include "finsh_var.h"

/*
 * the structure of abstract syntax tree:
 * root____________
 * |               \
 * child__        sibling__
 * |      \       |        \
 * child sibling  child   sibling
 *                          ...
 */
static enum finsh_type proc_type(struct finsh_parser* self);
static int proc_identifier(struct finsh_parser* self, u_char* id);
static struct finsh_node* proc_variable_decl(struct finsh_parser* self);
static struct finsh_node* proc_expr(struct finsh_parser* self);
static struct finsh_node* proc_assign_expr(struct finsh_parser* self);
static struct finsh_node* proc_inclusive_or_expr(struct finsh_parser* self);
static struct finsh_node* proc_exclusive_or_expr(struct finsh_parser* self);
static struct finsh_node* proc_and_expr(struct finsh_parser* self);
static struct finsh_node* proc_shift_expr(struct finsh_parser* self);
static struct finsh_node* proc_additive_expr(struct finsh_parser* self);
static struct finsh_node* proc_multiplicative_expr(struct finsh_parser* self);
static struct finsh_node* proc_cast_expr(struct finsh_parser* self);
static struct finsh_node* proc_unary_expr(struct finsh_parser* self);
static struct finsh_node* proc_postfix_expr(struct finsh_parser* self);
static struct finsh_node* proc_primary_expr(struct finsh_parser* self);
static struct finsh_node* proc_param_list(struct finsh_parser* self);
static struct finsh_node* proc_expr_statement(struct finsh_parser* self);
static struct finsh_node* make_sys_node(u_char type, struct finsh_node* node1,
	struct finsh_node* node2);

/* check token */
#define check_token(token, lex, type) if ( (token) != (type) ) \
	{ \
		finsh_error_set(FINSH_ERROR_INVALID_TOKEN); \
		finsh_token_replay(lex); \
	}

/* is the token a data type? */
#define is_base_type(token)	((token) == finsh_token_type_void \
    || (token) == finsh_token_type_char \
	|| (token) == finsh_token_type_short \
	|| (token) == finsh_token_type_int \
	|| (token) == finsh_token_type_long)

/* get the next token */
#define next_token(token, lex)	(token) = finsh_token_token(lex)

/* match a specified token */
#define match_token(token, lex, type)	next_token(token, lex); \
	check_token(token, lex, type)

/**
process for function and variable declaration.
decl_variable -> type declaration_list ';'
declarator_list -> declarator_list ',' declarator
	| declarator
declarator -> identifier
	| identifier ASSIGN expr_assign
*/
static struct finsh_node* proc_variable_decl(struct finsh_parser* self)
{
	enum finsh_token_type token;
	enum finsh_type type;
	u_char id[FINSH_NAME_MAX + 1];

	struct finsh_node *node;
	struct finsh_node *end;
	struct finsh_node *assign;

    node = NULL;

	/* get type */
	type = proc_type(self);

	/*process id.*/
	if (proc_identifier(self, id) == 0)
	{
		/* if add variable failed */
		if (finsh_var_insert(id, type) < 0)
		{
			finsh_error_set(FINSH_ERROR_VARIABLE_EXIST);
		}
	}

	next_token(token, &(self->token));
	switch ( token )
	{
	case finsh_token_type_comma:/*',', it's a variable_list declaration.*/
		if (proc_identifier(self, id) == 0)
		{
			/* if add variable failed */
			if (finsh_var_insert(id, type) < 0)
			{
				finsh_error_set(FINSH_ERROR_VARIABLE_EXIST);
			}
		}

		next_token(token, &(self->token));
		if ( token == finsh_token_type_assign )
		{
			/* get the right side of assign expression */
			assign = proc_assign_expr(self);

			if (assign != NULL)
			{
				struct finsh_node* idnode;

				idnode = finsh_node_new_id(id);
				end = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign);
				node = end;

				next_token(token, &(self->token));
			}
		}

		while ( token == finsh_token_type_comma )
		{
			if (proc_identifier(self, id) == 0)
			{
				/* if add variable failed */
				if (finsh_var_insert(id, type) < 0)
				{
					finsh_error_set(FINSH_ERROR_VARIABLE_EXIST);
				}
			}

			next_token(token, &(self->token));
			if ( token == finsh_token_type_assign )
			{
				/* get the right side of assign expression */
				assign = proc_assign_expr(self);

				if (assign != NULL)
				{
					struct finsh_node* idnode;

					idnode = finsh_node_new_id(id);

					/* make assign expression node */
					if (node != NULL)
					{
						finsh_node_sibling(end) = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign);
						end = finsh_node_sibling(end);
					}
					else
					{
						end = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign);
						node = end;
					}

					next_token(token, &(self->token));
				}
			}
		}

		check_token(token, &(self->token), finsh_token_type_semicolon);
		return node;

	case finsh_token_type_assign:/*'=', it's a variable with assign declaration.*/
	{
		struct finsh_node *idnode;

		assign = proc_assign_expr(self);
		if (assign != NULL)
		{
			idnode = finsh_node_new_id(id);

			/* make assign expression node */
			end = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign);
			node = end;

			next_token(token, &(self->token));
		}

		while ( token == finsh_token_type_comma )
		{
			if (proc_identifier(self, id) == 0)
			{
				/* if add variable failed */
				if (finsh_var_insert(id, type) < 0)
				{
					finsh_error_set(FINSH_ERROR_VARIABLE_EXIST);
				}
			}

			next_token(token, &(self->token));
			if (token == finsh_token_type_assign)
			{
				/* get the right side of assign expression */
				assign = proc_assign_expr(self);

				if (assign != NULL)
				{
					idnode = finsh_node_new_id(id);

					/* make assign expression node */
					if (node != NULL)
					{
						finsh_node_sibling(end) = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign);
						end = finsh_node_sibling(end);
					}
					else
					{
						end = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign);
						node = end;
					}

					next_token(token, &(self->token));
				}
			}
		}

		check_token(token, &(self->token), finsh_token_type_semicolon);
		return node;
	}

	case finsh_token_type_semicolon:/*';', it's a variable declaration.*/
		return node;

	default:
		finsh_error_set(FINSH_ERROR_EXPECT_TYPE);

		return NULL;
	}
}

/**
type -> type_prefix type_basic | type_basic
type_prefix -> UNSIGNED
type_basic -> VOID
	| CHAR
	| SHORT
	| INT
	| STRING
*/
static enum finsh_type proc_type(struct finsh_parser* self)
{
	enum finsh_type type;
	enum finsh_token_type token;

	/* set init type */
	type = finsh_type_unknown;

	next_token(token, &(self->token));
	if ( is_base_type(token) ) /* base_type */
	{
		switch (token)
		{
		case finsh_token_type_void:
			type = finsh_type_void;
			break;

		case finsh_token_type_char:
			type = finsh_type_char;
			break;

		case finsh_token_type_short:
			type = finsh_type_short;
			break;

		case finsh_token_type_int:
			type = finsh_type_int;
			break;

		case finsh_token_type_long:
			type = finsh_type_long;
			break;

		default:
			goto __return;
			break;
		}
	}
	else if ( token == finsh_token_type_unsigned ) /* unsigned base_type */
	{
		next_token(token, &(self->token));
		if ( is_base_type(token) )
		{
			switch (token)
			{
			case finsh_token_type_char:
				type = finsh_type_uchar;
				break;

			case finsh_token_type_short:
				type = finsh_type_ushort;
				break;

			case finsh_token_type_int:
				type = finsh_type_uint;
				break;

			case finsh_token_type_long:
				type = finsh_type_ulong;
				break;

			default:
				goto __return;
				break;
			}
		}
		else
		{
			finsh_token_replay(&(self->token));
			finsh_error_set(FINSH_ERROR_EXPECT_TYPE);
		}
	}
	else
	{
		goto __return;
	}

	/* parse for pointer */
	next_token(token, &(self->token));
	if (token == finsh_token_type_mul)
	{
		switch (type)
		{
		case finsh_type_void:
			type = finsh_type_voidp;
			break;

		case finsh_type_char:
		case finsh_type_uchar:
			type = finsh_type_charp;
			break;

		case finsh_type_short:
		case finsh_type_ushort:
			type = finsh_type_shortp;
			break;

		case finsh_type_int:
		case finsh_type_uint:
			type = finsh_type_intp;
			break;

		case finsh_type_long:
		case finsh_type_ulong:
			type = finsh_type_longp;
			break;

		default:
			type = finsh_type_voidp;
			break;
		}
	}
	else finsh_token_replay(&(self->token));

	return type;

__return:
	finsh_token_replay(&(self->token));
	finsh_error_set(FINSH_ERROR_UNKNOWN_TYPE);

	return type;
}

/**
identifier -> IDENTIFIER
*/
static int proc_identifier(struct finsh_parser* self, u_char* id)
{
	enum finsh_token_type token;

	match_token(token, &(self->token), finsh_token_type_identifier);

	strncpy(id, self->token.string, FINSH_NAME_MAX);

	return 0;
}

/**
statement_expr -> ';'
	| expr ';'
*/
static struct finsh_node* proc_expr_statement(struct finsh_parser* self)
{
	enum finsh_token_type token;
	struct finsh_node* expr;

	expr = NULL;
	next_token(token, &(self->token));
	if ( token != finsh_token_type_semicolon )
	{
		finsh_token_replay(&(self->token));
		expr = proc_expr(self);

		match_token(token, &(self->token), finsh_token_type_semicolon);
	}

	return expr;
}

/**
expr -> expr_assign
*/
static struct finsh_node* proc_expr(struct finsh_parser* self)
{
	return proc_assign_expr(self);
}

/**
expr_assign -> expr_inclusive_or
	| expr_unary ASSIGN expr_assign
*/
static struct finsh_node* proc_assign_expr(struct finsh_parser* self)
{
	enum finsh_token_type token;
	struct finsh_node* or;
	struct finsh_node* assign;

	or = proc_inclusive_or_expr(self);

	next_token(token, &(self->token));

	if (token == finsh_token_type_assign)
	{
		assign = proc_assign_expr(self);

		return make_sys_node(FINSH_NODE_SYS_ASSIGN, or, assign);
	}
	else finsh_token_replay(&(self->token));

	return or;
}

/**
expr_inclusive_or -> expr_exclusive_or
	| expr_inclusive_or '|' expr_exclusive_or
*/
static struct finsh_node* proc_inclusive_or_expr(struct finsh_parser* self)
{
	enum finsh_token_type token;
	struct finsh_node* xor;
	struct finsh_node* xor_new;

	xor = proc_exclusive_or_expr(self);

	next_token(token, &(self->token));
	while ( token == finsh_token_type_or )
	{
		xor_new = proc_exclusive_or_expr(self);
		xor = make_sys_node(FINSH_NODE_SYS_OR, xor, xor_new);

		next_token(token, &(self->token));
	}

	finsh_token_replay(&(self->token));
	return xor;
}

/**
expr_exclusive_or -> expr_and
	| expr_exclusive '^' expr_and
*/
static struct finsh_node* proc_exclusive_or_expr(struct finsh_parser* self)
{
	enum finsh_token_type token;
	struct finsh_node* and;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -