diff options
Diffstat (limited to 'mdk-stage1/slang/slparse.c')
-rw-r--r-- | mdk-stage1/slang/slparse.c | 1970 |
1 files changed, 0 insertions, 1970 deletions
diff --git a/mdk-stage1/slang/slparse.c b/mdk-stage1/slang/slparse.c deleted file mode 100644 index bc709d1fb..000000000 --- a/mdk-stage1/slang/slparse.c +++ /dev/null @@ -1,1970 +0,0 @@ -/* Copyright (c) 1998, 1999, 2001 John E. Davis - * This file is part of the S-Lang library. - * - * You may distribute under the terms of either the GNU General Public - * License or the Perl Artistic License. - */ - -#include "slinclud.h" - -#include "slang.h" -#include "_slang.h" - -static SLang_Load_Type *LLT; -int _SLang_Compile_Line_Num_Info; - -static void free_token (_SLang_Token_Type *t) -{ - register unsigned int nrefs = t->num_refs; - - if (nrefs == 0) - return; - - if (nrefs == 1) - { - if (t->free_sval_flag) - { - if (t->type == BSTRING_TOKEN) - SLbstring_free (t->v.b_val); - else - _SLfree_hashed_string (t->v.s_val, strlen (t->v.s_val), t->hash); - t->v.s_val = NULL; - } - } - - t->num_refs = nrefs - 1; -} - -static void init_token (_SLang_Token_Type *t) -{ - memset ((char *) t, 0, sizeof (_SLang_Token_Type)); -#if _SLANG_HAS_DEBUG_CODE - t->line_number = -1; -#endif -} - -/* Allow room for one push back of a token. This is necessary for - * multiple assignment. - */ -static unsigned int Use_Next_Token; -static _SLang_Token_Type Next_Token; -#if _SLANG_HAS_DEBUG_CODE -static int Last_Line_Number = -1; -#endif - -static int unget_token (_SLang_Token_Type *ctok) -{ - if (SLang_Error) - return -1; - if (Use_Next_Token != 0) - { - _SLparse_error ("unget_token failed", ctok, 0); - return -1; - } - - Use_Next_Token++; - Next_Token = *ctok; - init_token (ctok); - return 0; -} - -static int get_token (_SLang_Token_Type *ctok) -{ - if (ctok->num_refs) - free_token (ctok); - - if (Use_Next_Token) - { - Use_Next_Token--; - *ctok = Next_Token; - return ctok->type; - } - - return _SLget_token (ctok); -} - -static int compile_token (_SLang_Token_Type *t) -{ -#if _SLANG_HAS_DEBUG_CODE - if (_SLang_Compile_Line_Num_Info - && (t->line_number != Last_Line_Number) - && (t->line_number != -1)) - { - _SLang_Token_Type tok; - tok.type = LINE_NUM_TOKEN; - tok.v.long_val = Last_Line_Number = t->line_number; - (*_SLcompile_ptr) (&tok); - } -#endif - (*_SLcompile_ptr) (t); - return 0; -} - -typedef struct -{ -#define USE_PARANOID_MAGIC 0 -#if USE_PARANOID_MAGIC - unsigned long magic; -#endif - _SLang_Token_Type *stack; - unsigned int len; - unsigned int size; -} -Token_List_Type; - -#define MAX_TOKEN_LISTS 16 -static Token_List_Type Token_List_Stack [MAX_TOKEN_LISTS]; -static unsigned int Token_List_Stack_Depth = 0; -static Token_List_Type *Token_List = NULL; - -static void init_token_list (Token_List_Type *t) -{ - t->size = 0; - t->len = 0; - t->stack = NULL; -#if USE_PARANOID_MAGIC - t->magic = 0xABCDEF12; -#endif -} - -static void free_token_list (Token_List_Type *t) -{ - _SLang_Token_Type *s; - - if (t == NULL) - return; -#if USE_PARANOID_MAGIC - if (t->magic != 0xABCDEF12) - { - SLang_doerror ("Magic error."); - return; - } -#endif - s = t->stack; - if (s != NULL) - { - _SLang_Token_Type *smax = s + t->len; - while (s != smax) - { - if (s->num_refs) free_token (s); - s++; - } - - SLfree ((char *) t->stack); - } - - memset ((char *) t, 0, sizeof (Token_List_Type)); -} - -static Token_List_Type *push_token_list (void) -{ - if (Token_List_Stack_Depth == MAX_TOKEN_LISTS) - { - _SLparse_error ("Token list stack size exceeded", NULL, 0); - return NULL; - } - - Token_List = Token_List_Stack + Token_List_Stack_Depth; - Token_List_Stack_Depth++; - init_token_list (Token_List); - return Token_List; -} - -static int pop_token_list (int do_free) -{ - if (Token_List_Stack_Depth == 0) - { - if (SLang_Error == 0) - _SLparse_error ("Token list stack underflow", NULL, 0); - return -1; - } - Token_List_Stack_Depth--; - - if (do_free) free_token_list (Token_List); - - if (Token_List_Stack_Depth != 0) - Token_List = Token_List_Stack + (Token_List_Stack_Depth - 1); - else - Token_List = NULL; - - return 0; -} - -static int check_token_list_space (Token_List_Type *t, unsigned int delta_size) -{ - _SLang_Token_Type *st; - unsigned int len; -#if USE_PARANOID_MAGIC - if (t->magic != 0xABCDEF12) - { - SLang_doerror ("Magic error."); - return -1; - } -#endif - len = t->len + delta_size; - if (len <= t->size) return 0; - - if (delta_size < 4) - { - delta_size = 4; - len = t->len + delta_size; - } - - st = (_SLang_Token_Type *) SLrealloc((char *) t->stack, - len * sizeof(_SLang_Token_Type)); - if (st == NULL) - { - _SLparse_error ("Malloc error", NULL, 0); - return -1; - } - - memset ((char *) (st + t->len), 0, delta_size); - - t->stack = st; - t->size = len; - return 0; -} - -static int append_token (_SLang_Token_Type *t) -{ - if (-1 == check_token_list_space (Token_List, 1)) - return -1; - - Token_List->stack [Token_List->len] = *t; - Token_List->len += 1; - t->num_refs = 0; /* stealing it */ - return 0; -} - -static int append_token_of_type (unsigned char t) -{ - _SLang_Token_Type *tok; - - if (-1 == check_token_list_space (Token_List, 1)) - return -1; - - /* The memset when the list was created ensures that the other fields - * are properly initialized. - */ - tok = Token_List->stack + Token_List->len; - init_token (tok); - tok->type = t; - Token_List->len += 1; - return 0; -} - -static _SLang_Token_Type *get_last_token (void) -{ - unsigned int len; - - if ((Token_List == NULL) - || (0 == (len = Token_List->len))) - return NULL; - - len--; - return Token_List->stack + len; -} - -/* This function does NOT free the list. */ -static int compile_token_list_with_fun (int dir, Token_List_Type *list, - int (*f)(_SLang_Token_Type *)) -{ - _SLang_Token_Type *t0, *t1; - - if (list == NULL) - return -1; - - if (f == NULL) - f = compile_token; - - t0 = list->stack; - t1 = t0 + list->len; - - if (dir < 0) - { - /* backwards */ - - while ((SLang_Error == 0) && (t1 > t0)) - { - t1--; - (*f) (t1); - } - return 0; - } - - /* forward */ - while ((SLang_Error == 0) && (t0 < t1)) - { - (*f) (t0); - t0++; - } - return 0; -} - -static int compile_token_list (void) -{ - if (Token_List == NULL) - return -1; - - compile_token_list_with_fun (1, Token_List, NULL); - pop_token_list (1); - return 0; -} - -/* Take all elements in the list from pos2 to the end and exchange them - * with the elements at pos1, e.g., - * ...ABCDEabc ==> ...abcABCDE - * where pos1 denotes A and pos2 denotes a. - */ -static int token_list_element_exchange (unsigned int pos1, unsigned int pos2) -{ - _SLang_Token_Type *s, *s1, *s2; - unsigned int len, nloops; - - if (Token_List == NULL) - return -1; - - s = Token_List->stack; - len = Token_List->len; - - if ((s == NULL) || (len == 0) - || (pos2 >= len)) - return -1; - - /* This may not be the most efficient algorithm but the number to swap - * is most-likely going to be small, e.g, 3 - * The algorithm is to rotate the list. The particular rotation - * direction was chosen to make insert_token fast. - * It works like: - * @ ABCabcde --> BCabcdeA --> CabcdeAB --> abcdefAB - * which is optimal for Abcdef sequence produced by function calls. - * - * Profiling indicates that nloops is almost always 1, whereas the inner - * loop can loop many times (e.g., 9 times). - */ - - s2 = s + (len - 1); - s1 = s + pos1; - nloops = pos2 - pos1; - - while (nloops) - { - _SLang_Token_Type save; - - s = s1; - save = *s; - - while (s < s2) - { - *s = *(s + 1); - s++; - } - *s = save; - - nloops--; - } - return 0; -} - -#if 0 -static int insert_token (_SLang_Token_Type *t, unsigned int pos) -{ - if (-1 == append_token (t)) - return -1; - - return token_list_element_exchange (pos, Token_List->len - 1); -} -#endif -static void compile_token_of_type (unsigned char t) -{ - _SLang_Token_Type tok; - -#if _SLANG_HAS_DEBUG_CODE - tok.line_number = -1; -#endif - tok.type = t; - compile_token(&tok); -} - -static void statement (_SLang_Token_Type *); -static void compound_statement (_SLang_Token_Type *); -static void expression_with_parenthesis (_SLang_Token_Type *); -static void handle_semicolon (_SLang_Token_Type *); -static void statement_list (_SLang_Token_Type *); -static void variable_list (_SLang_Token_Type *, unsigned char); -static void struct_declaration (_SLang_Token_Type *); -static void define_function_args (_SLang_Token_Type *); -static void typedef_definition (_SLang_Token_Type *); -static void function_args_expression (_SLang_Token_Type *, int); -static void expression (_SLang_Token_Type *); -static void expression_with_commas (_SLang_Token_Type *, int); -static void simple_expression (_SLang_Token_Type *); -static void unary_expression (_SLang_Token_Type *); -static void postfix_expression (_SLang_Token_Type *); -static int check_for_lvalue (unsigned char, _SLang_Token_Type *); -/* static void primary_expression (_SLang_Token_Type *); */ -static void block (_SLang_Token_Type *); -static void inline_array_expression (_SLang_Token_Type *); -static void array_index_expression (_SLang_Token_Type *); -static void do_multiple_assignment (_SLang_Token_Type *); -static void try_multiple_assignment (_SLang_Token_Type *); -#if 0 -static void not_implemented (char *what) -{ - char err [256]; - sprintf (err, "Expression not implemented: %s", what); - _SLparse_error (err, NULL, 0); -} -#endif -static void rpn_parse_line (_SLang_Token_Type *tok) -{ - do - { - /* multiple RPN tokens possible when the file looks like: - * . <end of line> - * . <end of line> - */ - if (tok->type != RPN_TOKEN) - compile_token (tok); - free_token (tok); - } - while (EOF_TOKEN != _SLget_rpn_token (tok)); -} - -static int get_identifier_token (_SLang_Token_Type *tok) -{ - if (IDENT_TOKEN == get_token (tok)) - return IDENT_TOKEN; - - _SLparse_error ("Expecting identifier", tok, 0); - return tok->type; -} - -static void define_function (_SLang_Token_Type *ctok, unsigned char type) -{ - _SLang_Token_Type fname; - - switch (type) - { - case STATIC_TOKEN: - type = DEFINE_STATIC_TOKEN; - break; - - case PUBLIC_TOKEN: - type = DEFINE_PUBLIC_TOKEN; - break; - - case PRIVATE_TOKEN: - type = DEFINE_PRIVATE_TOKEN; - } - - init_token (&fname); - if (IDENT_TOKEN != get_identifier_token (&fname)) - { - free_token (&fname); - return; - } - - compile_token_of_type(OPAREN_TOKEN); - get_token (ctok); - define_function_args (ctok); - compile_token_of_type(FARG_TOKEN); - - if (ctok->type == OBRACE_TOKEN) - compound_statement(ctok); - - else if (ctok->type != SEMICOLON_TOKEN) - { - _SLparse_error("Expecting {", ctok, 0); - free_token (&fname); - return; - } - - fname.type = type; - compile_token (&fname); - free_token (&fname); -} - -/* statement: - * compound-statement - * if ( expression ) statement - * if ( expression ) statement else statement - * !if ( expression ) statement - * loop ( expression ) statement - * _for ( expression ) statement - * foreach ( expression ) statement - * foreach (expression ) using (expression-list) statement - * while ( expression ) statement - * do statement while (expression) ; - * for ( expressionopt ; expressionopt ; expressionopt ) statement - * ERROR_BLOCK statement - * EXIT_BLOCK statement - * USER_BLOCK0 statement - * USER_BLOCK1 statement - * USER_BLOCK2 statement - * USER_BLOCK3 statement - * USER_BLOCK4 statement - * forever statement - * break ; - * continue ; - * return expressionopt ; - * variable variable-list ; - * struct struct-decl ; - * define identifier function-args ; - * define identifier function-args compound-statement - * switch ( expression ) statement - * rpn-line - * at-line - * push ( expression ) - * ( expression ) = expression ; - * expression ; - * expression : - */ - -/* Note: This function does not return with a new token. It is up to the - * calling routine to handle that. - */ -static void statement (_SLang_Token_Type *ctok) -{ - unsigned char type; - - if (SLang_Error) - return; - - LLT->parse_level += 1; - - switch (ctok->type) - { - case OBRACE_TOKEN: - compound_statement (ctok); - break; - - case IF_TOKEN: - case IFNOT_TOKEN: - type = ctok->type; - get_token (ctok); - expression_with_parenthesis (ctok); - block (ctok); - - if (ELSE_TOKEN != get_token (ctok)) - { - compile_token_of_type (type); - unget_token (ctok); - break; - } - get_token (ctok); - block (ctok); - if (type == IF_TOKEN) type = ELSE_TOKEN; else type = NOTELSE_TOKEN; - compile_token_of_type (type); - break; - - /* case IFNOT_TOKEN: */ - case LOOP_TOKEN: - case _FOR_TOKEN: - type = ctok->type; - get_token (ctok); - expression_with_parenthesis (ctok); - block (ctok); - compile_token_of_type (type); - break; - - case FOREACH_TOKEN: - get_token (ctok); - expression_with_parenthesis (ctok); - - if (NULL == push_token_list ()) - break; - - append_token_of_type (ARG_TOKEN); - if (ctok->type == USING_TOKEN) - { - if (OPAREN_TOKEN != get_token (ctok)) - { - _SLparse_error ("Expected 'using ('", ctok, 0); - break; - } - get_token (ctok); - function_args_expression (ctok, 0); - } - append_token_of_type (EARG_TOKEN); - - compile_token_list (); - - block (ctok); - compile_token_of_type (FOREACH_TOKEN); - break; - - case WHILE_TOKEN: - get_token (ctok); - compile_token_of_type (OBRACE_TOKEN); - expression_with_parenthesis (ctok); - compile_token_of_type (CBRACE_TOKEN); - block (ctok); - compile_token_of_type (WHILE_TOKEN); - break; - - case DO_TOKEN: - get_token (ctok); - block (ctok); - - if (WHILE_TOKEN != get_token (ctok)) - { - _SLparse_error("Expecting while", ctok, 0); - break; - } - - get_token (ctok); - - compile_token_of_type (OBRACE_TOKEN); - expression_with_parenthesis (ctok); - compile_token_of_type (CBRACE_TOKEN); - compile_token_of_type (DOWHILE_TOKEN); - handle_semicolon (ctok); - break; - - case FOR_TOKEN: - - /* Look for (exp_opt ; exp_opt ; exp_opt ) */ - - if (OPAREN_TOKEN != get_token (ctok)) - { - _SLparse_error("Expecting (.", ctok, 0); - break; - } - - if (NULL == push_token_list ()) - break; - - append_token_of_type (OBRACE_TOKEN); - if (SEMICOLON_TOKEN != get_token (ctok)) - { - expression (ctok); - if (ctok->type != SEMICOLON_TOKEN) - { - _SLparse_error("Expecting ;", ctok, 0); - break; - } - } - append_token_of_type (CBRACE_TOKEN); - - append_token_of_type (OBRACE_TOKEN); - if (SEMICOLON_TOKEN != get_token (ctok)) - { - expression (ctok); - if (ctok->type != SEMICOLON_TOKEN) - { - _SLparse_error("Expecting ;", ctok, 0); - break; - } - } - 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) - { - _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); -} - |