123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005 |
- /*
- * script parser for finsh shell.
- *
- * COPYRIGHT (C) 2006 - 2013, RT-Thread Development Team
- *
- * This file is part of RT-Thread (http://www.rt-thread.org)
- * Maintainer: bernard.xiong <bernard.xiong at gmail.com>
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Change Logs:
- * Date Author Notes
- * 2010-03-22 Bernard first version
- * 2013-10-09 Bernard fix the command line too long issue.
- */
- #include <finsh.h>
- #include "finsh_token.h"
- #include "finsh_node.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, 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;
- char id[FINSH_NAME_MAX + 1];
- struct finsh_node *node;
- struct finsh_node *end;
- struct finsh_node *assign;
- node = NULL;
- end = 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;
- }
- }
- 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;
- }
- }
- 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, char* id)
- {
- enum finsh_token_type token;
- match_token(token, &(self->token), finsh_token_type_identifier);
- strncpy(id, (char*)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);
- if (xor_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
- else 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;
- struct finsh_node* and_new;
- and = proc_and_expr(self);
- next_token(token, &(self->token));
- while ( token == finsh_token_type_xor )
- {
- and_new = proc_and_expr(self);
- if (and_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
- else and = make_sys_node(FINSH_NODE_SYS_XOR, and, and_new);
- next_token(token, &(self->token));
- }
- finsh_token_replay(&(self->token));
- return and;
- }
- /*
- expr_and -> expr_shift
- | expr_and '&' expr_shift
- */
- static struct finsh_node* proc_and_expr(struct finsh_parser* self)
- {
- enum finsh_token_type token;
- struct finsh_node* shift;
- struct finsh_node* shift_new;
- shift = proc_shift_expr(self);
- next_token(token, &(self->token));
- while ( token == finsh_token_type_and )
- {
- shift_new = proc_shift_expr(self);
- if (shift_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
- else shift = make_sys_node(FINSH_NODE_SYS_AND, shift, shift_new);
- next_token(token, &(self->token));
- }
- finsh_token_replay(&(self->token));
- return shift;
- }
- /*
- expr_shift -> expr_additive
- | expr_shift '<<' expr_additive
- | expr_shift '>>' expr_additive
- */
- static struct finsh_node* proc_shift_expr(struct finsh_parser* self)
- {
- enum finsh_token_type token;
- struct finsh_node* add;
- struct finsh_node* add_new;
- add = proc_additive_expr(self);
- next_token(token, &(self->token));
- while ( token == finsh_token_type_shl || token == finsh_token_type_shr)
- {
- add_new = proc_additive_expr(self);
- if (add_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
- else
- {
- switch (token)
- {
- case finsh_token_type_shl:
- add = make_sys_node(FINSH_NODE_SYS_SHL, add, add_new);
- break;
- case finsh_token_type_shr:
- add = make_sys_node(FINSH_NODE_SYS_SHR, add, add_new);
- break;
- default:
- finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
- break;
- }
- }
- next_token(token, &(self->token));
- }
- finsh_token_replay(&(self->token));
- return add;
- }
- /*
- expr_additive -> expr_multiplicative
- | expr_additive SUB expr_multiplicative
- | expr_additive ADD expr_multiplicative
- */
- static struct finsh_node* proc_additive_expr(struct finsh_parser* self)
- {
- enum finsh_token_type token;
- struct finsh_node* mul;
- struct finsh_node* mul_new;
- mul = proc_multiplicative_expr(self);
- next_token(token, &(self->token));
- while ( token == finsh_token_type_sub || token == finsh_token_type_add )
- {
- mul_new = proc_multiplicative_expr(self);
- if (mul_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
- else
- {
- switch (token)
- {
- case finsh_token_type_sub:
- mul = make_sys_node(FINSH_NODE_SYS_SUB, mul, mul_new);
- break;
- case finsh_token_type_add:
- mul = make_sys_node(FINSH_NODE_SYS_ADD, mul, mul_new);
- break;
- default:
- finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
- break;
- }
- }
- next_token(token, &(self->token));
- }
- finsh_token_replay(&(self->token));
- return mul;
- }
- /*
- expr_multiplicative -> expr_cast
- | expr_multiplicative '*' expr_cast
- | expr_multiplicative '/' expr_cast
- | expr_multiplicative '%' expr_cast
- */
- static struct finsh_node* proc_multiplicative_expr(struct finsh_parser* self)
- {
- enum finsh_token_type token;
- struct finsh_node* cast;
- struct finsh_node* cast_new;
- cast = proc_cast_expr(self);
- next_token(token, &(self->token));
- while (token == finsh_token_type_mul ||
- token == finsh_token_type_div ||
- token == finsh_token_type_mod )
- {
- cast_new = proc_cast_expr(self);
- if (cast_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
- else
- {
- switch (token)
- {
- case finsh_token_type_mul:
- cast = make_sys_node(FINSH_NODE_SYS_MUL, cast, cast_new);
- break;
- case finsh_token_type_div:
- cast = make_sys_node(FINSH_NODE_SYS_DIV, cast, cast_new);
- break;
- case finsh_token_type_mod:
- cast = make_sys_node(FINSH_NODE_SYS_MOD, cast, cast_new);
- break;
- default:
- finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
- break;
- }
- }
- next_token(token, &(self->token));
- }
- finsh_token_replay(&(self->token));
- return cast;
- }
- /*
- 20060313, add recast parse
- expr_cast -> expr_unary
- | '(' type ')' expr_cast
- */
- static struct finsh_node* proc_cast_expr(struct finsh_parser* self)
- {
- enum finsh_token_type token;
- enum finsh_type type;
- struct finsh_node* cast;
- next_token(token, &(self->token));
- if (token == finsh_token_type_left_paren)
- {
- type = proc_type(self);
- match_token(token, &(self->token), finsh_token_type_right_paren);
- cast = proc_cast_expr(self);
- if (cast != NULL)
- {
- cast->data_type = type;
- return cast;
- }
- }
- finsh_token_replay(&(self->token));
- return proc_unary_expr(self);
- }
- /*
- 20050921, add '*' and '&'
- expr_unary -> expr_postfix
- | ADD expr_cast
- | INC expr_cast
- | SUB expr_cast
- | DEC expr_cast
- | '~' expr_cast
- | '*' expr_cast
- | '&' expr_cast
- */
- static struct finsh_node* proc_unary_expr(struct finsh_parser* self)
- {
- enum finsh_token_type token;
- struct finsh_node *cast;
- next_token(token, &(self->token));
- switch (token)
- {
- case finsh_token_type_add: /* + */
- cast = proc_cast_expr(self);
- return cast;
- case finsh_token_type_inc: /* ++ */
- cast = proc_cast_expr(self);
- return make_sys_node(FINSH_NODE_SYS_PREINC, cast, NULL);
- case finsh_token_type_sub: /* - */
- cast = proc_cast_expr(self);
- return make_sys_node(FINSH_NODE_SYS_SUB, finsh_node_new_long(0), cast);
- case finsh_token_type_dec: /* -- */
- cast = proc_cast_expr(self);
- return make_sys_node(FINSH_NODE_SYS_PREDEC, cast, NULL);
- case finsh_token_type_bitwise: /* ~ */
- cast = proc_cast_expr(self);
- return make_sys_node(FINSH_NODE_SYS_BITWISE, cast, NULL);
- case finsh_token_type_mul: /* * */
- cast = proc_cast_expr(self);
- return make_sys_node(FINSH_NODE_SYS_GETVALUE, cast, NULL);
- case finsh_token_type_and: /* & */
- cast = proc_cast_expr(self);
- return make_sys_node(FINSH_NODE_SYS_GETADDR, cast, NULL);
- default:
- finsh_token_replay(&(self->token));
- return proc_postfix_expr(self);
- }
- }
- /*
- expr_postfix -> expr_primary
- | expr_postfix INC
- | expr_postfix DEC
- | expr_postfix '(' param_list ')'
- */
- static struct finsh_node* proc_postfix_expr(struct finsh_parser* self)
- {
- enum finsh_token_type token;
- struct finsh_node* postfix;
- postfix = proc_primary_expr(self);
- next_token(token, &(self->token));
- while ( token == finsh_token_type_inc ||
- token == finsh_token_type_dec ||
- token == finsh_token_type_left_paren )
- {
- switch (token)
- {
- case finsh_token_type_inc :/* '++' */
- postfix = make_sys_node(FINSH_NODE_SYS_INC, postfix, NULL);
- break;
- case finsh_token_type_dec :/* '--' */
- postfix = make_sys_node(FINSH_NODE_SYS_DEC, postfix, NULL);
- break;
- case finsh_token_type_left_paren :/* '(' */
- {
- struct finsh_node* param_list;
- param_list = NULL;
- next_token(token, &(self->token));
- if (token != finsh_token_type_right_paren)
- {
- finsh_token_replay(&(self->token));
- param_list = proc_param_list(self);
- match_token(token, &(self->token), finsh_token_type_right_paren);
- }
- postfix = make_sys_node(FINSH_NODE_SYS_FUNC, postfix, param_list);
- }
- break;
- default:
- break;
- }
- next_token(token, &(self->token));
- }
- finsh_token_replay(&(self->token));
- return postfix;
- }
- /*
- expr_primary -> literal
- | '(' expr ')'
- | identifier
- */
- static struct finsh_node* proc_primary_expr(struct finsh_parser* self)
- {
- enum finsh_token_type token;
- struct finsh_node* expr;
- next_token(token, &(self->token));
- switch ( token )
- {
- case finsh_token_type_identifier:
- {
- char id[FINSH_NAME_MAX + 1];
- finsh_token_replay(&(self->token));
- proc_identifier(self, id);
- return finsh_node_new_id(id);
- }
- case finsh_token_type_left_paren:
- expr = proc_expr(self);
- match_token(token, &(self->token), finsh_token_type_right_paren);
- return expr;
- case finsh_token_type_value_int:
- return finsh_node_new_int(self->token.value.int_value);
- case finsh_token_type_value_long:
- return finsh_node_new_long(self->token.value.long_value);
- case finsh_token_type_value_char:
- return finsh_node_new_char(self->token.value.char_value);
- case finsh_token_type_value_string:
- return finsh_node_new_string((char*)self->token.string);
- case finsh_token_type_value_null:
- return finsh_node_new_ptr(NULL);
- default:
- finsh_error_set(FINSH_ERROR_INVALID_TOKEN);
- break;
- }
- return NULL;
- }
- /*
- param_list -> empty
- | expr_assign
- | param_list ',' expr_assign
- */
- static struct finsh_node* proc_param_list(struct finsh_parser* self)
- {
- enum finsh_token_type token;
- struct finsh_node *node, *assign;
- assign = proc_assign_expr(self);
- if (assign == NULL) return NULL;
- node = assign;
- next_token(token, &(self->token));
- while (token == finsh_token_type_comma )
- {
- finsh_node_sibling(assign) = proc_assign_expr(self);
- if (finsh_node_sibling(assign) != NULL) assign = finsh_node_sibling(assign);
- else finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
- next_token(token, &(self->token));
- }
- finsh_token_replay(&(self->token));
- return node;
- }
- /*
- make a new node as following tree:
- new_node
- |
- node1__
- \
- node2
- */
- static struct finsh_node* make_sys_node(u_char type, struct finsh_node* node1, struct finsh_node* node2)
- {
- struct finsh_node* node;
- node = finsh_node_allocate(type);
- if ((node1 != NULL) && (node != NULL))
- {
- finsh_node_child(node) = node1;
- finsh_node_sibling(node1) = node2;
- }
- else finsh_error_set(FINSH_ERROR_NULL_NODE);
- return node;
- }
- /*
- start -> statement_expr | decl_variable
- */
- void finsh_parser_run(struct finsh_parser* self, const u_char* string)
- {
- enum finsh_token_type token;
- struct finsh_node *node;
- node = NULL;
- /* init parser */
- self->parser_string = (u_char*)string;
- /* init token */
- finsh_token_init(&(self->token), self->parser_string);
- /* get next token */
- next_token(token, &(self->token));
- while (token != finsh_token_type_eof && token != finsh_token_type_bad)
- {
- switch (token)
- {
- case finsh_token_type_identifier:
- /* process expr_statement */
- finsh_token_replay(&(self->token));
- if (self->root != NULL)
- {
- finsh_node_sibling(node) = proc_expr_statement(self);
- if (finsh_node_sibling(node) != NULL)
- node = finsh_node_sibling(node);
- }
- else
- {
- node = proc_expr_statement(self);
- self->root = node;
- }
- break;
- default:
- if (is_base_type(token) || token == finsh_token_type_unsigned)
- {
- /* variable decl */
- finsh_token_replay(&(self->token));
- if (self->root != NULL)
- {
- finsh_node_sibling(node) = proc_variable_decl(self);
- if (finsh_node_sibling(node) != NULL)
- node = finsh_node_sibling(node);
- }
- else
- {
- node = proc_variable_decl(self);
- self->root = node;
- }
- }
- else
- {
- /* process expr_statement */
- finsh_token_replay(&(self->token));
- if (self->root != NULL)
- {
- finsh_node_sibling(node) = proc_expr_statement(self);
- if (finsh_node_sibling(node) != NULL)
- node = finsh_node_sibling(node);
- else next_token(token, &(self->token));
- }
- else
- {
- node = proc_expr_statement(self);
- self->root = node;
- }
- }
- break;
- }
- /* no root found, break out */
- if (self->root == NULL) break;
- /* get next token */
- next_token(token, &(self->token));
- }
- }
- int finsh_parser_init(struct finsh_parser* self)
- {
- memset(self, 0, sizeof(struct finsh_parser));
- return 0;
- }
|