📄 slparse.c
字号:
_SLparse_error ("Binary op stack overflow", ctok, 0); return; } op_stack [op_num] = type; level_stack [op_num] = level; op_num++; get_token (ctok); unary_expression (ctok); type = ctok->type; } while (op_num > 0) append_token_of_type(op_stack[--op_num]);}/* unary-expression: * postfix-expression * ++ postfix-expression * -- postfix-expression * case unary-expression * OP3 unary-expression * (OP3: + - ~ & not @) * * Note: This grammar permits: case case case WHATEVER */static void unary_expression (_SLang_Token_Type *ctok){ unsigned char save_unary_ops [16]; unsigned int num_unary_ops; unsigned char type; _SLang_Token_Type *last_token; num_unary_ops = 0; while (SLang_Error == 0) { type = ctok->type; switch (type) { case PLUSPLUS_TOKEN: case MINUSMINUS_TOKEN: get_token (ctok); postfix_expression (ctok); check_for_lvalue (type, NULL); goto out_of_switch; case ADD_TOKEN: get_token (ctok); /* skip it-- it's unary here */ break; case SUB_TOKEN: (void) get_token (ctok); if (IS_INTEGER_TOKEN (ctok->type)) { ctok->v.long_val = -ctok->v.long_val; break; } if (num_unary_ops == 16) goto stack_overflow_error; save_unary_ops [num_unary_ops++] = CHS_TOKEN; break; case DEREF_TOKEN: case BNOT_TOKEN: case NOT_TOKEN: case CASE_TOKEN: if (num_unary_ops == 16) goto stack_overflow_error; save_unary_ops [num_unary_ops++] = type; get_token (ctok); break; /* Try to avoid ->postfix_expression->primary_expression * subroutine calls. */ case STRING_TOKEN: append_token (ctok); get_token (ctok); goto out_of_switch; default: postfix_expression (ctok); goto out_of_switch; } } out_of_switch: if (num_unary_ops == 0) return; if ((DEREF_TOKEN == save_unary_ops[num_unary_ops - 1]) && (NULL != (last_token = get_last_token ())) && (IS_ASSIGN_TOKEN(last_token->type))) { /* FIXME: Priority=medium * This needs generalized so that things like @a.y = 1 will work properly. */ if ((num_unary_ops != 1) || (last_token->type != _SCALAR_ASSIGN_TOKEN)) { SLang_verror (SL_NOT_IMPLEMENTED, "Only derefence assignments to simple variables are possible"); return; } last_token->type += (_DEREF_ASSIGN_TOKEN - _SCALAR_ASSIGN_TOKEN); return; } while (num_unary_ops) { num_unary_ops--; append_token_of_type (save_unary_ops [num_unary_ops]); } return; stack_overflow_error: _SLparse_error ("Too many unary operators.", ctok, 0);}static int combine_namespace_tokens (_SLang_Token_Type *a, _SLang_Token_Type *b){ char *sa, *sb, *sc; unsigned int lena, lenb; unsigned long hash; /* This is somewhat of a hack. Combine the TWO identifier names * (NAMESPACE) and (name) into the form NAMESPACE->name. Then when the * byte compiler compiles the object it will not be found. It will then * check for this hack and make the appropriate namespace lookup. */ sa = a->v.s_val; sb = b->v.s_val; lena = strlen (sa); lenb = strlen (sb); sc = SLmalloc (lena + lenb + 3); if (sc == NULL) return -1; strcpy (sc, sa); strcpy (sc + lena, "->"); strcpy (sc + lena + 2, sb); sb = _SLstring_make_hashed_string (sc, lena + lenb + 2, &hash); SLfree (sc); if (sb == NULL) return -1; /* I can free this string because no other token should be referencing it. * (num_refs == 1). */ _SLfree_hashed_string (sa, lena, a->hash); a->v.s_val = sb; a->hash = hash; return 0;}static void append_identifier_token (_SLang_Token_Type *ctok){ _SLang_Token_Type *last_token; append_token (ctok); if (NAMESPACE_TOKEN != get_token (ctok)) return; if (IDENT_TOKEN != get_token (ctok)) { _SLparse_error ("Expecting name-space identifier", ctok, 0); return; } last_token = get_last_token (); if (-1 == combine_namespace_tokens (last_token, ctok)) return; (void) get_token (ctok);}static int get_identifier_expr_token (_SLang_Token_Type *ctok){ _SLang_Token_Type next_token; if (IDENT_TOKEN != get_identifier_token (ctok)) return -1; init_token (&next_token); if (NAMESPACE_TOKEN != get_token (&next_token)) { unget_token (&next_token); return IDENT_TOKEN; } if (IDENT_TOKEN != get_identifier_token (&next_token)) { free_token (&next_token); return -1; } if (-1 == combine_namespace_tokens (ctok, &next_token)) { free_token (&next_token); return -1; } free_token (&next_token); return IDENT_TOKEN;}/* postfix-expression: * primary-expression * postfix-expression [ expression ] * postfix-expression ( function-args-expression ) * postfix-expression . identifier * postfix-expression ^ unary-expression * postfix-expression ++ * postfix-expression -- * postfix-expression = simple-expression * postfix-expression += simple-expression * postfix-expression -= simple-expression * * primary-expression: * literal * identifier-expr * ( expression_opt ) * [ inline-array-expression ] * &identifier-expr * struct-definition * __tmp(identifier-expr) * * identifier-expr: * identifier * identifier->identifier */static void postfix_expression (_SLang_Token_Type *ctok){ unsigned int start_pos, end_pos; unsigned char type; if (Token_List == NULL) return; start_pos = Token_List->len; switch (ctok->type) { case IDENT_TOKEN: append_identifier_token (ctok); break; case CHAR_TOKEN: case SHORT_TOKEN: case INT_TOKEN: case LONG_TOKEN: case UCHAR_TOKEN: case USHORT_TOKEN: case UINT_TOKEN: case ULONG_TOKEN: case STRING_TOKEN: case BSTRING_TOKEN:#ifdef SLANG_HAS_FLOAT case DOUBLE_TOKEN: case FLOAT_TOKEN:#endif#ifdef SLANG_HAS_COMPLEX case COMPLEX_TOKEN:#endif append_token (ctok); get_token (ctok); break; case OPAREN_TOKEN: if (CPAREN_TOKEN != get_token (ctok)) { expression (ctok); if (ctok->type != CPAREN_TOKEN) _SLparse_error("Expecting )", ctok, 0); } get_token (ctok); break; case BAND_TOKEN: if (IDENT_TOKEN != get_identifier_expr_token (ctok)) break; ctok->type = _REF_TOKEN; append_token (ctok); get_token (ctok); break; case OBRACKET_TOKEN: get_token (ctok); inline_array_expression (ctok); break; case NO_OP_LITERAL: /* This token was introduced by try_multiple_assignment. There, * a new token_list was pushed and (expression) was evaluated. * NO_OP_LITERAL represents the result of expression. However, * we need to tweak the start_pos variable to point to the beginning * of the token list to complete the equivalence. */ start_pos = 0; get_token (ctok); break; case STRUCT_TOKEN: get_token (ctok); struct_declaration (ctok); break; case TMP_TOKEN: get_token (ctok); if (ctok->type == OPAREN_TOKEN) { if (IDENT_TOKEN == get_identifier_expr_token (ctok)) { ctok->type = TMP_TOKEN; append_token (ctok); get_token (ctok); if (ctok->type == CPAREN_TOKEN) { get_token (ctok); break; } } } _SLparse_error ("Expecting form __tmp(NAME)", ctok, 0); break; default: if (IS_INTERNAL_FUNC(ctok->type)) { append_token (ctok); get_token (ctok); } else _SLparse_error("Expecting a PRIMARY", ctok, 0); } while (SLang_Error == 0) { end_pos = Token_List->len; type = ctok->type; switch (type) { case OBRACKET_TOKEN: /* X[args] ==> [args] X ARRAY */ get_token (ctok); append_token_of_type (ARG_TOKEN); if (ctok->type != CBRACKET_TOKEN) array_index_expression (ctok); if (ctok->type != CBRACKET_TOKEN) { _SLparse_error ("Expecting ']'", ctok, 0); return; } get_token (ctok); /* append_token_of_type (EARG_TOKEN); -- ARRAY_TOKEN implicitely does this */ token_list_element_exchange (start_pos, end_pos); append_token_of_type (ARRAY_TOKEN); break; case OPAREN_TOKEN: /* f(args) ==> args f */ if (CPAREN_TOKEN != get_token (ctok)) { function_args_expression (ctok, 1); token_list_element_exchange (start_pos, end_pos); } else get_token (ctok); break; case DOT_TOKEN: /* S.a ==> "a" S DOT * This means that if S is X[b], then X[b].a ==> a b X ARRAY DOT * and f(a).X[b].c ==> "c" b "X" a f . ARRAY . * Also, f(a).X[b] = g(x); ==> x g b "X" a f . */ if (IDENT_TOKEN != get_identifier_token (ctok)) return; ctok->type = DOT_TOKEN; append_token (ctok); get_token (ctok); break; case PLUSPLUS_TOKEN: case MINUSMINUS_TOKEN: check_for_lvalue (type, NULL); get_token (ctok); break; case ASSIGN_TOKEN: case PLUSEQS_TOKEN: case MINUSEQS_TOKEN: case TIMESEQS_TOKEN: case DIVEQS_TOKEN: case BOREQS_TOKEN: case BANDEQS_TOKEN: check_for_lvalue (type, NULL); get_token (ctok); simple_expression (ctok); token_list_element_exchange (start_pos, end_pos); break; case POW_TOKEN: get_token (ctok); unary_expression (ctok); append_token_of_type (POW_TOKEN); break; default: return; } }}static void function_args_expression (_SLang_Token_Type *ctok, int handle_num_args){ unsigned char last_type, this_type; if (handle_num_args) append_token_of_type (ARG_TOKEN); last_type = COMMA_TOKEN; while (SLang_Error == 0) { this_type = ctok->type; switch (this_type) { case COMMA_TOKEN: if (last_type == COMMA_TOKEN) append_token_of_type (_NULL_TOKEN); get_token (ctok); break; case CPAREN_TOKEN: if (last_type == COMMA_TOKEN) append_token_of_type (_NULL_TOKEN); if (handle_num_args) append_token_of_type (EARG_TOKEN); get_token (ctok); return; default: simple_expression (ctok); if ((ctok->type != COMMA_TOKEN) && (ctok->type != CPAREN_TOKEN)) { _SLparse_error ("Expecting ')'", ctok, 0); break; } } last_type = this_type; }}static int check_for_lvalue (unsigned char eqs_type, _SLang_Token_Type *ctok){ unsigned char type; if ((ctok == NULL) && (NULL == (ctok = get_last_token ()))) return -1; type = ctok->type; eqs_type -= ASSIGN_TOKEN; if (type == IDENT_TOKEN) eqs_type += _SCALAR_ASSIGN_TOKEN; else if (type == ARRAY_TOKEN) eqs_type += _ARRAY_ASSIGN_TOKEN; else if (type == DOT_TOKEN) eqs_type += _STRUCT_ASSIGN_TOKEN; else { _SLparse_error ("Expecting LVALUE", ctok, 0); return -1; } ctok->type = eqs_type; return 0;}static void array_index_expression (_SLang_Token_Type *ctok){ unsigned int num_commas; num_commas = 0; while (1) { switch (ctok->type) { case COLON_TOKEN: if (num_commas) _SLparse_error ("Misplaced ':'", ctok, 0); return; case TIMES_TOKEN: append_token_of_type (_INLINE_WILDCARD_ARRAY_TOKEN); get_token (ctok); break; case COMMA_TOKEN: _SLparse_error ("Misplaced ','", ctok, 0); return; default: simple_expression (ctok); } if (ctok->type != COMMA_TOKEN) return; num_commas++; get_token (ctok); }}/* inline-array-expression: * array_index_expression * simple_expression : simple_expression * simple_expression : simple_expression : simple_expression */static void inline_array_expression (_SLang_Token_Type *ctok){ int num_colons = 0; append_token_of_type (ARG_TOKEN); if (ctok->type == COLON_TOKEN) /* [:...] */ append_token_of_type (_NULL_TOKEN); else if (ctok->type != CBRACKET_TOKEN) array_index_expression (ctok); if (ctok->type == COLON_TOKEN) { num_colons++; if ((COLON_TOKEN == get_token (ctok)) || (ctok->type == CBRACKET_TOKEN)) append_token_of_type (_NULL_TOKEN); else simple_expression (ctok); if (ctok->type == COLON_TOKEN) { num_colons++; get_token (ctok); simple_expression (ctok); } } if (ctok->type != CBRACKET_TOKEN) { _SLparse_error ("Expecting ']'", ctok, 0); return; } /* append_token_of_type (EARG_TOKEN); */ if (num_colons) append_token_of_type (_INLINE_IMPLICIT_ARRAY_TOKEN); else append_token_of_type (_INLINE_ARRAY_TOKEN); get_token (ctok);}static void do_multiple_assignment (_SLang_Token_Type *ctok){ _SLang_Token_Type *s; unsigned int i, k, len; unsigned char assign_type; assign_type = ctok->type; /* The LHS token list has already been pushed. Here we do the RHS * so push to another token list, process it, then come back to * LHS for assignment. */ if (NULL == push_token_list ()) return; get_token (ctok); expression (ctok); compile_token_list (); if (SLang_Error) return; /* Finally compile the LHS of the assignment expression * that has been saved. */ s = Token_List->stack; len = Token_List->len; if (len == 0) { compile_token_of_type (POP_TOKEN); return; } while (len > 0) { /* List is of form: * a , b, c d e, f , g , , , h , * The missing expressions will be replaced by a POP * ,,a */ /* Start from back looking for a COMMA */ k = len - 1; if (s[k].type == COMMA_TOKEN) { compile_token_of_type (POP_TOKEN); len = k; continue; } if (-1 == check_for_lvalue (assign_type, s + k)) return; i = 0; while (1) { if (s[k].type == COMMA_TOKEN) { i = k + 1; break; } if (k == 0) break; k--; } while (i < len) { compile_token (s + i); i++; } len = k; } if (s[0].type == COMMA_TOKEN) compile_token_of_type (POP_TOKEN);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -