static void _syx_parser_parse_temporaries (SyxParser *self) { SyxToken token = syx_lexer_get_last_token (self->lexer); SyxParserScope scope; scope.start = self->_temporary_names_top; scope.end = self->_temporary_names_top; if (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, "|")) { syx_token_free (token); token = syx_lexer_next_token (self->lexer); while (token.type == SYX_TOKEN_NAME_CONST) { self->_temporary_names[self->_temporary_names_top++] = token.value.string; scope.end++; token = syx_lexer_next_token (self->lexer); } if (! (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, "|"))) syx_signal (SYX_ERROR_INTERP, syx_string_new ("Temporary list not terminated by bar")); syx_token_free (token); syx_lexer_next_token (self->lexer); } self->_temporary_scopes.stack[(syx_int32) self->_temporary_scopes.top++] = scope; }
static SyxOop _syx_parser_parse_literal_array (SyxParser *self) { SyxOop elements[256]; syx_varsize top = 0; SyxToken token; token = syx_lexer_next_token (self->lexer); while (! (token.type == SYX_TOKEN_END || (token.type == SYX_TOKEN_CLOSING && token.value.character == ')'))) { switch (token.type) { case SYX_TOKEN_ARRAY_BEGIN: elements[top++] = _syx_parser_parse_literal_array (self); break; case SYX_TOKEN_INT_CONST: elements[top++] = syx_small_integer_new (token.value.integer); break; case SYX_TOKEN_BINARY: if (!strcmp (token.value.string, "(")) { elements[top++] = _syx_parser_parse_literal_array (self); syx_token_free (token); break; } case SYX_TOKEN_NAME_CONST: case SYX_TOKEN_NAME_COLON: case SYX_TOKEN_SYM_CONST: elements[top++] = syx_symbol_new (token.value.string); syx_token_free (token); break; case SYX_TOKEN_STR_CONST: elements[top++] = syx_string_new (token.value.string); syx_token_free (token); break; case SYX_TOKEN_CHAR_CONST: elements[top++] = syx_character_new (token.value.character); break; default: syx_signal (SYX_ERROR_INTERP, syx_string_new ("Illegal text in literal array\n")); break; } token = syx_lexer_next_token (self->lexer); } return syx_array_new_ref (top, elements); }
static void _syx_parser_parse_primitive (SyxParser *self) { SyxToken token = syx_lexer_get_last_token (self->lexer); syx_int32 prim_index; SYX_METHOD_PRIMITIVE(self->method) = syx_small_integer_new (-1); if (! (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, "<"))) return; syx_token_free (token); token = syx_lexer_next_token (self->lexer); if (token.type != SYX_TOKEN_NAME_COLON) syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected name colon")); if (!strcmp (token.value.string, "primitive:")) { syx_token_free (token); token = syx_lexer_next_token (self->lexer); if (token.type != SYX_TOKEN_STR_CONST) syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected a string containing the primitive to be called")); prim_index = syx_primitive_get_index (token.value.string); if (prim_index < 0) syx_signal (SYX_ERROR_INTERP, syx_string_new ("Unknown primitive named", token.value.string)); syx_token_free (token); token = syx_lexer_next_token (self->lexer); if (! (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, ">"))) syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected >")); syx_token_free (token); SYX_METHOD_PRIMITIVE (self->method) = syx_small_integer_new (prim_index); syx_lexer_next_token (self->lexer); } else if (!strcmp (token.value.string, "cCall:")) { syx_token_free (token); token = syx_lexer_next_token (self->lexer); if (token.type != SYX_TOKEN_STR_CONST) syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected a string containing the primitive to be called")); syx_bytecode_gen_literal (self->bytecode, syx_symbol_new (token.value.string)); syx_token_free (token); token = syx_lexer_next_token (self->lexer); if (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, ">")) { syx_token_free (token); syx_bytecode_gen_literal (self->bytecode, syx_nil); SYX_METHOD_PRIMITIVE (self->method) = syx_small_integer_new (-2); syx_lexer_next_token (self->lexer); return; } if (! (token.type == SYX_TOKEN_NAME_COLON && !strcmp (token.value.string, "plugin:"))) syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected plugin:")); syx_token_free (token); token = syx_lexer_next_token (self->lexer); if (token.type != SYX_TOKEN_STR_CONST) syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected a string containing the plugin name")); syx_bytecode_gen_literal (self->bytecode, syx_symbol_new (token.value.string)); syx_token_free (token); token = syx_lexer_next_token (self->lexer); if (! (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, ">"))) syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected >")); syx_token_free (token); syx_lexer_next_token (self->lexer); SYX_METHOD_PRIMITIVE(self->method) = syx_small_integer_new (-2); } else syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected primitive or cCall")); return; }
static syx_bool _syx_parser_parse_term (SyxParser *self) { SyxToken token = syx_lexer_get_last_token (self->lexer); syx_bool super_term = FALSE; switch (token.type) { case SYX_TOKEN_NAME_CONST: super_term = _syx_parser_parse_name_term (self, token.value.string); syx_token_free (token); break; case SYX_TOKEN_STR_CONST: syx_bytecode_push_literal (self->bytecode, syx_string_new (token.value.string)); syx_token_free (token); break; case SYX_TOKEN_INT_CONST: syx_bytecode_push_literal (self->bytecode, syx_small_integer_new (token.value.integer)); syx_token_free (token); break; #ifdef HAVE_LIBGMP case SYX_TOKEN_LARGE_INT_CONST: syx_bytecode_push_literal (self->bytecode, syx_large_integer_new_mpz (token.value.large_integer)); syx_token_free (token); break; #endif case SYX_TOKEN_FLOAT_CONST: syx_bytecode_push_literal (self->bytecode, syx_float_new (token.value.floating)); syx_token_free (token); break; case SYX_TOKEN_SYM_CONST: syx_bytecode_push_literal (self->bytecode, syx_symbol_new (token.value.string)); syx_token_free (token); break; case SYX_TOKEN_CHAR_CONST: syx_bytecode_push_literal (self->bytecode, syx_character_new (token.value.character)); syx_token_free (token); break; case SYX_TOKEN_ARRAY_BEGIN: syx_bytecode_push_literal (self->bytecode, _syx_parser_parse_literal_array (self)); syx_token_free (token); break; case SYX_TOKEN_BINARY: if (!strcmp (token.value.string, "(")) { syx_token_free (token); token = syx_lexer_next_token (self->lexer); _syx_parser_parse_expression (self); token = syx_lexer_get_last_token (self->lexer); if (! (token.type == SYX_TOKEN_CLOSING && token.value.character == ')')) syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected ) after sub expression")); break; } else if (!strcmp (token.value.string, "[")) { _syx_parser_parse_block (self); break; } else if (!strcmp (token.value.string, "{")) { _syx_parser_parse_array (self); break; } else if (!strcmp (token.value.string, "-")) { syx_token_free (token); token = syx_lexer_next_token (self->lexer); if (token.type == SYX_TOKEN_INT_CONST) syx_bytecode_push_literal (self->bytecode, syx_small_integer_new (-token.value.integer)); #ifdef HAVE_LIBGMP else if (token.type == SYX_TOKEN_LARGE_INT_CONST) { mpz_neg (*token.value.large_integer, *token.value.large_integer); syx_bytecode_push_literal (self->bytecode, syx_large_integer_new_mpz (token.value.large_integer)); } #endif /* HAVE_LIBGMP */ else if (token.type == SYX_TOKEN_FLOAT_CONST) syx_bytecode_push_literal (self->bytecode, syx_float_new (-token.value.floating)); else syx_signal(SYX_ERROR_INTERP, syx_string_new ("Negation not followed by number")); syx_token_free (token); break; } /* We continue here because of weird binary token used as expression start */ default: switch (token.type) { case SYX_TOKEN_END: syx_signal (SYX_ERROR_INTERP, syx_string_new ("Unexpected end of input")); break; case SYX_TOKEN_STRING_ENTRY: syx_signal (SYX_ERROR_INTERP, syx_string_new ("Invalid expression start: %s", token.value.string)); syx_token_free (token); break; case SYX_TOKEN_CLOSING: syx_signal (SYX_ERROR_INTERP, syx_string_new ("Unexpected closing: %c", token.value.character)); break; default: syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected expression")); break; } } syx_lexer_next_token (self->lexer); return super_term; }