📄 finsh_parser.c
字号:
#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 + -