📄 slparse.c
字号:
} } append_token_of_type (CBRACE_TOKEN); append_token_of_type (OBRACE_TOKEN); if (CPAREN_TOKEN != get_token (ctok)) { expression (ctok); if (ctok->type != CPAREN_TOKEN) { _SLparse_error("Expecting ).", ctok, 0); break; } } append_token_of_type (CBRACE_TOKEN); compile_token_list (); get_token (ctok); block (ctok); compile_token_of_type (FOR_TOKEN); break; case ERRBLK_TOKEN: case EXITBLK_TOKEN: case USRBLK0_TOKEN: case USRBLK1_TOKEN: case USRBLK2_TOKEN: case USRBLK3_TOKEN: case USRBLK4_TOKEN: case FOREVER_TOKEN: type = ctok->type; get_token (ctok); block (ctok); compile_token_of_type (type); break; case BREAK_TOKEN: case CONT_TOKEN: compile_token_of_type (ctok->type); get_token (ctok); handle_semicolon (ctok); break; case RETURN_TOKEN: if (SEMICOLON_TOKEN != get_token (ctok)) { if (NULL == push_token_list ()) break; expression (ctok); if (ctok->type != SEMICOLON_TOKEN) { _SLparse_error ("Expecting ;", ctok, 0); break; } compile_token_list (); } compile_token_of_type (RETURN_TOKEN); handle_semicolon (ctok); break; case STATIC_TOKEN: case PRIVATE_TOKEN: case PUBLIC_TOKEN: type = ctok->type; get_token (ctok); if (ctok->type == VARIABLE_TOKEN) { get_token (ctok); variable_list (ctok, type); handle_semicolon (ctok); break; } if (ctok->type == DEFINE_TOKEN) { define_function (ctok, type); break; } _SLparse_error ("Expecting 'variable' or 'define'", ctok, 0); break; case VARIABLE_TOKEN: get_token (ctok); variable_list (ctok, OBRACKET_TOKEN); handle_semicolon (ctok); break; case TYPEDEF_TOKEN: get_token (ctok); if (NULL == push_token_list ()) break; typedef_definition (ctok); compile_token_list (); handle_semicolon (ctok); break; case DEFINE_TOKEN: define_function (ctok, DEFINE_TOKEN); break; case SWITCH_TOKEN: get_token (ctok); expression_with_parenthesis (ctok); while ((SLang_Error == 0) && (OBRACE_TOKEN == ctok->type)) { compile_token_of_type (OBRACE_TOKEN); compound_statement (ctok); compile_token_of_type (CBRACE_TOKEN); get_token (ctok); } compile_token_of_type (SWITCH_TOKEN); unget_token (ctok); break; case EOF_TOKEN: break;#if 0 case PUSH_TOKEN: get_token (ctok); expression_list_with_parenthesis (ctok); handle_semicolon (ctok); break;#endif case SEMICOLON_TOKEN: handle_semicolon (ctok); break; case RPN_TOKEN: if (POUND_TOKEN == get_token (ctok)) _SLcompile_byte_compiled (); else if (ctok->type != EOF_TOKEN) rpn_parse_line (ctok); break; case OPAREN_TOKEN: /* multiple assignment */ try_multiple_assignment (ctok); if (ctok->type == COLON_TOKEN) compile_token_of_type (COLON_TOKEN); else handle_semicolon (ctok); break; default: if (NULL == push_token_list ()) break; expression (ctok); compile_token_list (); if (ctok->type == COLON_TOKEN) compile_token_of_type (COLON_TOKEN); else handle_semicolon (ctok); break; } LLT->parse_level -= 1;}static void block (_SLang_Token_Type *ctok){ compile_token_of_type (OBRACE_TOKEN); statement (ctok); compile_token_of_type (CBRACE_TOKEN);}/* * statement-list: * statement * statement-list statement */static void statement_list (_SLang_Token_Type *ctok){ while ((SLang_Error == 0) && (ctok->type != CBRACE_TOKEN) && (ctok->type != EOF_TOKEN)) { statement(ctok); get_token (ctok); }}/* compound-statement: * { statement-list } */static void compound_statement (_SLang_Token_Type *ctok){ /* ctok->type is OBRACE_TOKEN here */ get_token (ctok); statement_list(ctok); if (CBRACE_TOKEN != ctok->type) { _SLparse_error ("Expecting '}'", ctok, 0); return; }}/* This function is only called from statement. */static void expression_with_parenthesis (_SLang_Token_Type *ctok){ if (ctok->type != OPAREN_TOKEN) { _SLparse_error("Expecting (", ctok, 0); return; } if (NULL == push_token_list ()) return; get_token (ctok); expression (ctok); if (ctok->type != CPAREN_TOKEN) _SLparse_error("Expecting )", ctok, 0); compile_token_list (); get_token (ctok);}static void handle_semicolon (_SLang_Token_Type *ctok){ if ((ctok->type == SEMICOLON_TOKEN) || (ctok->type == EOF_TOKEN)) return; _SLparse_error ("Expecting ;", ctok, 0);}void _SLparse_start (SLang_Load_Type *llt){ _SLang_Token_Type ctok; SLang_Load_Type *save_llt; unsigned int save_use_next_token; _SLang_Token_Type save_next_token; Token_List_Type *save_list;#if _SLANG_HAS_DEBUG_CODE int save_last_line_number = Last_Line_Number; Last_Line_Number = -1;#endif save_use_next_token = Use_Next_Token; save_next_token = Next_Token; save_list = Token_List; save_llt = LLT; LLT = llt; init_token (&Next_Token); Use_Next_Token = 0; init_token (&ctok); get_token (&ctok); llt->parse_level = 0; statement_list (&ctok); if ((SLang_Error == 0) && (ctok.type != EOF_TOKEN)) _SLparse_error ("Parse ended prematurely", &ctok, 0); if (SLang_Error) { if (SLang_Error < 0) /* severe error */ save_list = NULL; while (Token_List != save_list) { if (-1 == pop_token_list (1)) break; /* ??? when would this happen? */ } } free_token (&ctok); LLT = save_llt; if (Use_Next_Token) free_token (&Next_Token); Use_Next_Token = save_use_next_token; Next_Token = save_next_token;#if _SLANG_HAS_DEBUG_CODE Last_Line_Number = save_last_line_number;#endif}/* variable-list: * variable-decl * variable-decl variable-list * * variable-decl: * identifier * identifier = simple-expression */static void variable_list (_SLang_Token_Type *name_token, unsigned char variable_type){ int declaring; _SLang_Token_Type tok; if (name_token->type != IDENT_TOKEN) { _SLparse_error ("Expecting a variable name", name_token, 0); return; } declaring = 0; do { if (declaring == 0) { declaring = 1; compile_token_of_type (variable_type); } compile_token (name_token); init_token (&tok); if (ASSIGN_TOKEN == get_token (&tok)) { compile_token_of_type (CBRACKET_TOKEN); declaring = 0; get_token (&tok); push_token_list (); simple_expression (&tok); compile_token_list (); name_token->type = _SCALAR_ASSIGN_TOKEN; compile_token (name_token); } free_token (name_token); *name_token = tok; } while ((name_token->type == COMMA_TOKEN) && (IDENT_TOKEN == get_token (name_token))); if (declaring) compile_token_of_type (CBRACKET_TOKEN);}/* struct-declaration: * struct { struct-field-list }; * * struct-field-list: * struct-field-name , struct-field-list * struct-field-name * * Generates code: "field-name-1" ... "field-name-N" N STRUCT_TOKEN */static void struct_declaration (_SLang_Token_Type *ctok){ int n; _SLang_Token_Type num_tok; if (ctok->type != OBRACE_TOKEN) { _SLparse_error ("Expecting {", ctok, 0); return; } n = 0; while (IDENT_TOKEN == get_token (ctok)) { n++; ctok->type = STRING_TOKEN; append_token (ctok); if (COMMA_TOKEN != get_token (ctok)) break; } if (ctok->type != CBRACE_TOKEN) { _SLparse_error ("Expecting }", ctok, 0); return; } if (n == 0) { _SLparse_error ("struct requires at least 1 field", ctok, 0); return; } init_token (&num_tok); num_tok.type = INT_TOKEN; num_tok.v.long_val = n; append_token (&num_tok); append_token_of_type (STRUCT_TOKEN); get_token (ctok);}/* struct-declaration: * typedef struct { struct-field-list } Type_Name; * * struct-field-list: * struct-field-name , struct-field-list * struct-field-name * * Generates code: "field-name-1" ... "field-name-N" N STRUCT_TOKEN typedef */static void typedef_definition (_SLang_Token_Type *t){ if (t->type != STRUCT_TOKEN) { _SLparse_error ("Expecting `struct'", t, 0); return; } get_token (t); struct_declaration (t); if (t->type != IDENT_TOKEN) { _SLparse_error ("Expecting identifier", t, 0); return; } t->type = STRING_TOKEN; append_token (t); append_token_of_type (TYPEDEF_TOKEN); get_token (t);}/* function-args: * ( args-dec-opt ) * * args-decl-opt: * identifier * args-decl , identifier */static void define_function_args (_SLang_Token_Type *ctok){ if (CPAREN_TOKEN == get_token (ctok)) { get_token (ctok); return; } compile_token_of_type(OBRACKET_TOKEN); while ((SLang_Error == 0) && (ctok->type == IDENT_TOKEN)) { compile_token (ctok); if (COMMA_TOKEN != get_token (ctok)) break; get_token (ctok); } if (CPAREN_TOKEN != ctok->type) { _SLparse_error("Expecting )", ctok, 0); return; } compile_token_of_type(CBRACKET_TOKEN); get_token (ctok);}void try_multiple_assignment (_SLang_Token_Type *ctok){ /* This is called with ctok->type == OPAREN_TOKEN. We have no idea * what follows this. There are various possibilities such as: * @ () = x; * @ ( expression ) = x; * @ ( expression ) ; * @ ( expression ) OP expression; * @ ( expression ) [expression] = expression; * and only the first two constitute a multiple assignment. The last * two forms create the difficulty. * * Here is the plan. First parse (expression) and then check next token. * If it is an equal operator, then it will be parsed as a multiple * assignment. In fact, that is the easy part. * * The hard part stems from the fact that by parsing (expression), we * have effectly truncated the parse if (expression) is part of a binary * or unary expression. Somehow, the parsing must be resumed. The trick * here is to use a dummy literal that generates no code: NO_OP_LITERAL * Using it, we just call 'expression' and proceed. */ if (NULL == push_token_list ()) return; get_token (ctok); if (ctok->type != CPAREN_TOKEN) { expression_with_commas (ctok, 1); if (ctok->type != CPAREN_TOKEN) { _SLparse_error ("Expecting )", ctok, 0); return; } } switch (get_token (ctok)) { case ASSIGN_TOKEN: case PLUSEQS_TOKEN: case MINUSEQS_TOKEN: case TIMESEQS_TOKEN: case DIVEQS_TOKEN: case BOREQS_TOKEN: case BANDEQS_TOKEN: do_multiple_assignment (ctok); pop_token_list (1); break; default: unget_token (ctok); ctok->type = NO_OP_LITERAL; expression (ctok); compile_token_list (); break; }}/* Note: expression never gets compiled directly. Rather, it gets * appended to the token list and then compiled by a calling * routine. *//* expression: * simple_expression * simple-expression , expression * <none> */static void expression_with_commas (_SLang_Token_Type *ctok, int save_comma){ while (SLang_Error == 0) { if (ctok->type != COMMA_TOKEN) { if (ctok->type == CPAREN_TOKEN) return; simple_expression (ctok); if (ctok->type != COMMA_TOKEN) break; } if (save_comma) append_token (ctok); get_token (ctok); }}static void expression (_SLang_Token_Type *ctok){ expression_with_commas (ctok, 0);}/* priority levels of binary operations */static unsigned char Binop_Level[] ={/* ADD_TOKEN */ 2,/* SUB_TOKEN */ 2,/* MUL_TOKEN */ 1,/* DIV_TOKEN */ 1,/* LT_TOKEN */ 4,/* LE_TOKEN */ 4,/* GT_TOKEN */ 4,/* GE_TOKEN */ 4,/* EQ_TOKEN */ 5,/* NE_TOKEN */ 5,/* AND_TOKEN */ 9,/* OR_TOKEN */ 10,/* MOD_TOKEN */ 1,/* BAND_TOKEN */ 6,/* SHL_TOKEN */ 3,/* SHR_TOKEN */ 3,/* BXOR_TOKEN */ 7,/* BOR_TOKEN */ 8,/* POUND_TOKEN */ 1 /* Matrix Multiplication */};/* % Note: simple-expression groups operators OP1 at same level. The * % actual implementation will not do this. * simple-expression: * unary-expression * binary-expression BINARY-OP unary-expression * andelse xxelse-expression-list * orelse xxelse-expression-list * * xxelse-expression-list: * { expression } * xxelse-expression-list { expression } * binary-expression: * unary-expression * unary-expression BINARY-OP binary-expression */static void simple_expression (_SLang_Token_Type *ctok){ unsigned char type; unsigned char op_stack [64]; unsigned char level_stack [64]; unsigned char level; unsigned int op_num; switch (ctok->type) { case ANDELSE_TOKEN: case ORELSE_TOKEN: type = ctok->type; if (OBRACE_TOKEN != get_token (ctok)) { _SLparse_error ("Expecting '{'", ctok, 0); return; } while (ctok->type == OBRACE_TOKEN) { append_token (ctok); get_token (ctok); expression (ctok); if (CBRACE_TOKEN != ctok->type) { _SLparse_error("Expecting }", ctok, 0); return; } append_token (ctok); get_token (ctok); } append_token_of_type (type); return; /* avoid unary-expression if possible */ case STRING_TOKEN: append_token (ctok); get_token (ctok); break; default: unary_expression (ctok); break; } if (SEMICOLON_TOKEN == (type = ctok->type)) return; op_num = 0; while ((SLang_Error == 0) && (IS_BINARY_OP(type))) { level = Binop_Level[type - FIRST_BINARY_OP]; while ((op_num > 0) && (level_stack [op_num - 1] <= level)) append_token_of_type (op_stack [--op_num]); if (op_num >= sizeof (op_stack) - 1) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -