qse/ase/stx/parser.c

1609 lines
41 KiB
C
Raw Normal View History

2005-05-12 15:51:20 +00:00
/*
2007-03-22 11:19:28 +00:00
* $Id: parser.c,v 1.81 2007-03-22 11:19:28 bacon Exp $
2005-05-12 15:51:20 +00:00
*/
2007-03-22 11:19:28 +00:00
#include <ase/stx/parser.h>
#include <ase/stx/object.h>
#include <ase/stx/class.h>
#include <ase/stx/method.h>
#include <ase/stx/symbol.h>
#include <ase/stx/bytecode.h>
#include <ase/stx/dict.h>
#include <ase/stx/misc.h>
2005-05-22 04:11:54 +00:00
2005-06-06 03:47:56 +00:00
static int __parse_method (
2007-03-22 11:19:28 +00:00
ase_stx_parser_t* parser,
ase_word_t method_class, void* input);
static int __finish_method (ase_stx_parser_t* parser);
static int __parse_message_pattern (ase_stx_parser_t* parser);
static int __parse_unary_pattern (ase_stx_parser_t* parser);
static int __parse_binary_pattern (ase_stx_parser_t* parser);
static int __parse_keyword_pattern (ase_stx_parser_t* parser);
static int __parse_temporaries (ase_stx_parser_t* parser);
static int __parse_primitive (ase_stx_parser_t* parser);
static int __parse_statements (ase_stx_parser_t* parser);
static int __parse_block_statements (ase_stx_parser_t* parser);
static int __parse_statement (ase_stx_parser_t* parser);
static int __parse_expression (ase_stx_parser_t* parser);
2005-06-06 03:47:56 +00:00
2005-06-19 16:16:33 +00:00
static int __parse_assignment (
2007-03-22 11:19:28 +00:00
ase_stx_parser_t* parser, const ase_char_t* target);
2005-06-23 04:55:44 +00:00
static int __parse_basic_expression (
2007-03-22 11:19:28 +00:00
ase_stx_parser_t* parser, const ase_char_t* ident);
2005-06-23 04:55:44 +00:00
static int __parse_primary (
2007-03-22 11:19:28 +00:00
ase_stx_parser_t* parser, const ase_char_t* ident, ase_bool_t* is_super);
2005-07-08 11:32:50 +00:00
static int __parse_primary_ident (
2007-03-22 11:19:28 +00:00
ase_stx_parser_t* parser, const ase_char_t* ident, ase_bool_t* is_super);
2005-07-08 11:32:50 +00:00
2007-03-22 11:19:28 +00:00
static int __parse_block_constructor (ase_stx_parser_t* parser);
2005-09-30 12:19:00 +00:00
static int __parse_message_continuation (
2007-03-22 11:19:28 +00:00
ase_stx_parser_t* parser, ase_bool_t is_super);
2005-09-30 12:19:00 +00:00
static int __parse_keyword_message (
2007-03-22 11:19:28 +00:00
ase_stx_parser_t* parser, ase_bool_t is_super);
2005-09-30 12:19:00 +00:00
static int __parse_binary_message (
2007-03-22 11:19:28 +00:00
ase_stx_parser_t* parser, ase_bool_t is_super);
2005-09-30 12:19:00 +00:00
static int __parse_unary_message (
2007-03-22 11:19:28 +00:00
ase_stx_parser_t* parser, ase_bool_t is_super);
static int __get_token (ase_stx_parser_t* parser);
static int __get_ident (ase_stx_parser_t* parser);
static int __get_numlit (ase_stx_parser_t* parser, ase_bool_t negated);
static int __get_charlit (ase_stx_parser_t* parser);
static int __get_strlit (ase_stx_parser_t* parser);
static int __get_binary (ase_stx_parser_t* parser);
static int __skip_spaces (ase_stx_parser_t* parser);
static int __skip_comment (ase_stx_parser_t* parser);
static int __get_char (ase_stx_parser_t* parser);
static int __unget_char (ase_stx_parser_t* parser, ase_cint_t c);
static int __open_input (ase_stx_parser_t* parser, void* input);
static int __close_input (ase_stx_parser_t* parser);
ase_stx_parser_t* ase_stx_parser_open (ase_stx_parser_t* parser, ase_stx_t* stx)
2005-05-22 04:11:54 +00:00
{
2007-03-22 11:19:28 +00:00
if (parser == ASE_NULL) {
parser = (ase_stx_parser_t*)
ase_malloc (ase_sizeof(ase_stx_parser_t));
if (parser == ASE_NULL) return ASE_NULL;
parser->__dynamic = ase_true;
2005-05-22 04:11:54 +00:00
}
2007-03-22 11:19:28 +00:00
else parser->__dynamic = ase_false;
2005-05-22 04:11:54 +00:00
2007-03-22 11:19:28 +00:00
if (ase_stx_name_open (&parser->method_name, 0) == ASE_NULL) {
if (parser->__dynamic) ase_free (parser);
return ASE_NULL;
2005-06-12 16:22:47 +00:00
}
2007-03-22 11:19:28 +00:00
if (ase_stx_token_open (&parser->token, 0) == ASE_NULL) {
ase_stx_name_close (&parser->method_name);
if (parser->__dynamic) ase_free (parser);
return ASE_NULL;
2005-05-30 15:27:31 +00:00
}
2007-03-22 11:19:28 +00:00
if (ase_arr_open (
2005-07-05 09:02:13 +00:00
&parser->bytecode, 256,
2007-03-22 11:19:28 +00:00
ase_sizeof(ase_byte_t), ASE_NULL) == ASE_NULL) {
ase_stx_name_close (&parser->method_name);
ase_stx_token_close (&parser->token);
if (parser->__dynamic) ase_free (parser);
return ASE_NULL;
2005-06-19 16:16:33 +00:00
}
2005-06-08 03:19:31 +00:00
parser->stx = stx;
2007-03-22 11:19:28 +00:00
parser->error_code = ASE_STX_PARSER_ERROR_NONE;
2005-06-12 14:40:35 +00:00
2005-06-12 16:46:45 +00:00
parser->temporary_count = 0;
2005-07-07 16:32:37 +00:00
parser->argument_count = 0;
2005-07-04 11:47:25 +00:00
parser->literal_count = 0;
2005-06-12 14:40:35 +00:00
2007-03-22 11:19:28 +00:00
parser->curc = ASE_T_EOF;
2005-06-05 05:27:02 +00:00
parser->ungotc_count = 0;
2005-06-04 16:27:30 +00:00
2007-03-22 11:19:28 +00:00
parser->input_owner = ASE_NULL;
parser->input_func = ASE_NULL;
2005-05-22 04:11:54 +00:00
return parser;
}
2007-03-22 11:19:28 +00:00
void ase_stx_parser_close (ase_stx_parser_t* parser)
2005-05-22 04:11:54 +00:00
{
2005-06-12 16:46:45 +00:00
while (parser->temporary_count > 0) {
2007-03-22 11:19:28 +00:00
ase_free (parser->temporaries[--parser->temporary_count]);
2005-06-12 16:46:45 +00:00
}
2005-07-07 16:32:37 +00:00
parser->argument_count = 0;
2005-06-12 15:46:02 +00:00
2007-03-22 11:19:28 +00:00
ase_arr_close (&parser->bytecode);
ase_stx_name_close (&parser->method_name);
ase_stx_token_close (&parser->token);
2005-06-19 16:16:33 +00:00
2007-03-22 11:19:28 +00:00
if (parser->__dynamic) ase_free (parser);
2005-05-22 04:11:54 +00:00
}
2005-05-12 15:51:20 +00:00
2005-06-05 05:27:02 +00:00
#define GET_CHAR(parser) \
do { if (__get_char(parser) == -1) return -1; } while (0)
#define UNGET_CHAR(parser,c) \
do { if (__unget_char(parser,c) == -1) return -1; } while (0)
2005-06-05 16:44:05 +00:00
#define GET_TOKEN(parser) \
do { if (__get_token(parser) == -1) return -1; } while (0)
2005-06-06 16:04:18 +00:00
#define ADD_TOKEN_CHAR(parser,c) \
do { \
2007-03-22 11:19:28 +00:00
if (ase_stx_token_addc (&(parser)->token, c) == -1) { \
(parser)->error_code = ASE_STX_PARSER_ERROR_MEMORY; \
2005-06-06 16:04:18 +00:00
return -1; \
} \
} while (0)
2005-06-05 16:44:05 +00:00
2007-03-22 11:19:28 +00:00
const ase_char_t* ase_stx_parser_error_string (ase_stx_parser_t* parser)
2005-06-12 12:33:31 +00:00
{
2007-03-22 11:19:28 +00:00
static const ase_char_t* msg[] =
2005-06-12 12:33:31 +00:00
{
2007-03-22 11:19:28 +00:00
ASE_T("no error"),
ASE_T("input fucntion not ready"),
ASE_T("input function error"),
ASE_T("out of memory"),
ASE_T("invalid character"),
ASE_T("incomplete character literal"),
ASE_T("incomplete string literal"),
ASE_T("incomplete literal"),
ASE_T("message selector"),
ASE_T("invalid argument name"),
ASE_T("too many arguments"),
ASE_T("invalid primitive type"),
ASE_T("primitive number expected"),
ASE_T("primitive number out of range"),
ASE_T("primitive not closed"),
ASE_T("temporary list not closed"),
ASE_T("too many temporaries"),
ASE_T("cannot redefine pseudo variable"),
ASE_T("invalid primary/expression-start"),
ASE_T("no period at end of statement"),
ASE_T("no closing parenthesis"),
ASE_T("block argument name missing"),
ASE_T("block argument list not closed"),
ASE_T("block not closed"),
ASE_T("undeclared name"),
ASE_T("too many literals")
2005-06-12 12:33:31 +00:00
};
if (parser->error_code >= 0 &&
2007-03-22 11:19:28 +00:00
parser->error_code < ase_countof(msg)) return msg[parser->error_code];
2005-06-12 12:33:31 +00:00
2007-03-22 11:19:28 +00:00
return ASE_T("unknown error");
2005-06-12 12:33:31 +00:00
}
2007-03-22 11:19:28 +00:00
static INLINE ase_bool_t __is_pseudo_variable (const ase_stx_token_t* token)
2005-06-19 16:16:33 +00:00
{
2007-03-22 11:19:28 +00:00
return token->type == ASE_STX_TOKEN_IDENT &&
(ase_strcmp(token->name.buffer, ASE_T("self")) == 0 ||
ase_strcmp(token->name.buffer, ASE_T("super")) == 0 ||
ase_strcmp(token->name.buffer, ASE_T("nil")) == 0 ||
ase_strcmp(token->name.buffer, ASE_T("true")) == 0 ||
ase_strcmp(token->name.buffer, ASE_T("false")) == 0);
2005-06-19 16:16:33 +00:00
}
2007-03-22 11:19:28 +00:00
static INLINE ase_bool_t __is_vbar_token (const ase_stx_token_t* token)
2005-06-23 07:20:44 +00:00
{
return
2007-03-22 11:19:28 +00:00
token->type == ASE_STX_TOKEN_BINARY &&
2005-06-23 07:20:44 +00:00
token->name.size == 1 &&
2007-03-22 11:19:28 +00:00
token->name.buffer[0] == ASE_T('|');
2005-06-23 07:20:44 +00:00
}
2007-03-22 11:19:28 +00:00
static INLINE ase_bool_t __is_primitive_opener (const ase_stx_token_t* token)
2005-07-04 10:02:00 +00:00
{
return
2007-03-22 11:19:28 +00:00
token->type == ASE_STX_TOKEN_BINARY &&
2005-07-04 10:02:00 +00:00
token->name.size == 1 &&
2007-03-22 11:19:28 +00:00
token->name.buffer[0] == ASE_T('<');
2005-07-04 10:02:00 +00:00
}
2007-03-22 11:19:28 +00:00
static INLINE ase_bool_t __is_primitive_closer (const ase_stx_token_t* token)
2005-07-04 10:02:00 +00:00
{
return
2007-03-22 11:19:28 +00:00
token->type == ASE_STX_TOKEN_BINARY &&
2005-07-04 10:02:00 +00:00
token->name.size == 1 &&
2007-03-22 11:19:28 +00:00
token->name.buffer[0] == ASE_T('>');
2005-07-04 10:02:00 +00:00
}
2007-03-22 11:19:28 +00:00
static INLINE ase_bool_t __is_binary_char (ase_cint_t c)
2005-06-23 07:20:44 +00:00
{
/*
* binaryCharacter ::=
* '!' | '%' | '&' | '*' | '+' | ',' |
* '/' | '<' | '=' | '>' | '?' | '@' |
* '\' | '~' | '|' | '-'
*/
return
2007-03-22 11:19:28 +00:00
c == ASE_T('!') || c == ASE_T('%') ||
c == ASE_T('&') || c == ASE_T('*') ||
c == ASE_T('+') || c == ASE_T(',') ||
c == ASE_T('/') || c == ASE_T('<') ||
c == ASE_T('=') || c == ASE_T('>') ||
c == ASE_T('?') || c == ASE_T('@') ||
c == ASE_T('\\') || c == ASE_T('|') ||
c == ASE_T('~') || c == ASE_T('-');
2005-06-23 07:20:44 +00:00
}
2007-03-22 11:19:28 +00:00
static INLINE ase_bool_t __is_closing_char (ase_cint_t c)
2005-06-23 07:20:44 +00:00
{
return
2007-03-22 11:19:28 +00:00
c == ASE_T('.') || c == ASE_T(']') ||
c == ASE_T(')') || c == ASE_T(';') ||
c == ASE_T('\"') || c == ASE_T('\'');
2005-06-23 07:20:44 +00:00
}
2005-07-10 09:21:46 +00:00
#define EMIT_CODE_TEST(parser,high,low) \
do { if (__emit_code_test(parser,high,low) == -1) return -1; } while (0)
#define EMIT_CODE(parser,code) \
do { if (__emit_code(parser,code) == -1) return -1; } while(0)
#define EMIT_PUSH_RECEIVER_VARIABLE(parser,pos) \
do { \
if (__emit_stack_positional ( \
parser, PUSH_RECEIVER_VARIABLE, pos) == -1) return -1; \
} while (0)
#define EMIT_PUSH_TEMPORARY_LOCATION(parser,pos) \
do { \
if (__emit_stack_positional ( \
parser, PUSH_TEMPORARY_LOCATION, pos) == -1) return -1; \
} while (0)
#define EMIT_PUSH_LITERAL_CONSTANT(parser,pos) \
do { \
if (__emit_stack_positional ( \
parser, PUSH_LITERAL_CONSTANT, pos) == -1) return -1; \
} while (0)
#define EMIT_PUSH_LITERAL_VARIABLE(parser,pos) \
do { \
if (__emit_stack_positional ( \
parser, PUSH_LITERAL_VARIABLE, pos) == -1) return -1; \
} while (0)
#define EMIT_STORE_RECEIVER_VARIABLE(parser,pos) \
do { \
if (__emit_stack_positional ( \
parser, STORE_RECEIVER_VARIABLE, pos) == -1) return -1; \
} while (0)
#define EMIT_STORE_TEMPORARY_LOCATION(parser,pos) \
do { \
if (__emit_stack_positional ( \
parser, STORE_TEMPORARY_LOCATION, pos) == -1) return -1; \
} while (0)
#define EMIT_POP_STACK_TOP(parser) EMIT_CODE(parser, POP_STACK_TOP)
#define EMIT_DUPLICATE_STACK_TOP(parser) EMIT_CODE(parser, DUPLICATE_STACK_TOP)
#define EMIT_PUSH_ACTIVE_CONTEXT(parser) EMIT_CODE(parser, PUSH_ACTIVE_CONTEXT)
#define EMIT_RETURN_FROM_MESSAGE(parser) EMIT_CODE(parser, RETURN_FROM_MESSAGE)
#define EMIT_RETURN_FROM_BLOCK(parser) EMIT_CODE(parser, RETURN_FROM_BLOCK)
2005-07-10 16:50:50 +00:00
#define EMIT_SEND_TO_SELF(parser,nargs,selector) \
2005-07-10 09:21:46 +00:00
do { \
2005-07-10 16:50:50 +00:00
if (__emit_send_to_self(parser,nargs,selector) == -1) return -1; \
2005-07-10 09:21:46 +00:00
} while (0)
2005-07-10 16:50:50 +00:00
#define EMIT_SEND_TO_SUPER(parser,nargs,selector) \
2005-07-10 09:21:46 +00:00
do { \
2005-07-10 16:50:50 +00:00
if (__emit_send_to_super(parser,nargs,selector) == -1) return -1; \
2005-07-10 09:21:46 +00:00
} while (0)
#define EMIT_DO_PRIMITIVE(parser,no) \
do { if (__emit_do_primitive(parser,no) == -1) return -1; } while(0)
2005-07-05 11:38:01 +00:00
static INLINE int __emit_code_test (
2007-03-22 11:19:28 +00:00
ase_stx_parser_t* parser, const ase_char_t* high, const ase_char_t* low)
2005-07-05 11:15:51 +00:00
{
2007-03-22 11:19:28 +00:00
ase_printf (ASE_T("CODE: %s %s\n"), high, low);
2005-07-05 11:15:51 +00:00
return 0;
}
2007-03-22 11:19:28 +00:00
static INLINE int __emit_code (ase_stx_parser_t* parser, ase_byte_t code)
2005-07-05 11:15:51 +00:00
{
2007-03-22 11:19:28 +00:00
if (ase_arr_adddatum(&parser->bytecode, &code) == ASE_NULL) {
parser->error_code = ASE_STX_PARSER_ERROR_MEMORY;
2005-07-07 07:45:05 +00:00
return -1;
}
return 0;
2005-07-05 11:15:51 +00:00
}
2005-07-10 09:21:46 +00:00
static INLINE int __emit_stack_positional (
2007-03-22 11:19:28 +00:00
ase_stx_parser_t* parser, int opcode, int pos)
2005-07-10 03:16:40 +00:00
{
2007-03-22 11:19:28 +00:00
ase_assert (pos >= 0x0 && pos <= 0xFF);
2005-07-10 03:16:40 +00:00
2005-07-10 09:21:46 +00:00
if (pos <= 0x0F) {
EMIT_CODE (parser, (opcode & 0xF0) | (pos & 0x0F));
2005-07-10 03:16:40 +00:00
}
else {
2005-07-10 09:21:46 +00:00
EMIT_CODE (parser, (opcode >> 4) & 0x6F);
EMIT_CODE (parser, pos & 0xFF);
2005-07-10 03:16:40 +00:00
}
return 0;
}
2005-07-10 09:21:46 +00:00
static INLINE int __emit_send_to_self (
2007-03-22 11:19:28 +00:00
ase_stx_parser_t* parser, int nargs, int selector)
2005-07-10 03:16:40 +00:00
{
2007-03-22 11:19:28 +00:00
ase_assert (nargs >= 0x00 && nargs <= 0xFF);
ase_assert (selector >= 0x00 && selector <= 0xFF);
2005-07-10 16:50:50 +00:00
if (nargs <= 0x08 && selector <= 0x1F) {
EMIT_CODE (parser, SEND_TO_SELF);
EMIT_CODE (parser, (nargs << 5) | selector);
}
else {
EMIT_CODE (parser, SEND_TO_SELF_EXTENDED);
EMIT_CODE (parser, nargs);
EMIT_CODE (parser, selector);
}
2005-07-11 13:41:59 +00:00
return 0;
2005-07-10 09:21:46 +00:00
}
2005-07-08 11:32:50 +00:00
2005-07-10 09:21:46 +00:00
static INLINE int __emit_send_to_super (
2007-03-22 11:19:28 +00:00
ase_stx_parser_t* parser, int nargs, int selector)
2005-07-10 09:21:46 +00:00
{
2007-03-22 11:19:28 +00:00
ase_assert (nargs >= 0x00 && nargs <= 0xFF);
ase_assert (selector >= 0x00 && selector <= 0xFF);
2005-07-10 16:50:50 +00:00
if (nargs <= 0x08 && selector <= 0x1F) {
EMIT_CODE (parser, SEND_TO_SUPER);
EMIT_CODE (parser, (nargs << 5) | selector);
}
else {
EMIT_CODE (parser, SEND_TO_SUPER_EXTENDED);
EMIT_CODE (parser, nargs);
EMIT_CODE (parser, selector);
}
2005-07-11 13:41:59 +00:00
return 0;
2005-07-08 11:32:50 +00:00
}
2007-03-22 11:19:28 +00:00
static INLINE int __emit_do_primitive (ase_stx_parser_t* parser, int no)
2005-07-10 09:21:46 +00:00
{
2007-03-22 11:19:28 +00:00
ase_assert (no >= 0x0 && no <= 0xFFF);
2005-07-10 09:21:46 +00:00
2005-09-11 15:15:35 +00:00
EMIT_CODE (parser, DO_PRIMITIVE | ((no >> 8) & 0x0F));
2005-07-10 09:21:46 +00:00
EMIT_CODE (parser, no & 0xFF);
return 0;
}
2005-07-07 07:45:05 +00:00
2007-03-22 11:19:28 +00:00
static int __add_literal (ase_stx_parser_t* parser, ase_word_t literal)
2005-07-11 13:41:59 +00:00
{
2007-03-22 11:19:28 +00:00
ase_word_t i;
2005-07-12 16:16:42 +00:00
for (i = 0; i < parser->literal_count; i++) {
/*
* it would remove redundancy of symbols and small integers.
* more complex redundacy check may be done somewhere else
* like in __add_string_literal.
*/
if (parser->literals[i] == literal) return i;
}
2007-03-22 11:19:28 +00:00
if (parser->literal_count >= ase_countof(parser->literals)) {
parser->error_code = ASE_STX_PARSER_ERROR_TOO_MANY_LITERALS;
2005-07-11 13:41:59 +00:00
return -1;
}
2005-07-12 16:16:42 +00:00
2005-07-11 13:41:59 +00:00
parser->literals[parser->literal_count++] = literal;
return parser->literal_count - 1;
}
2007-03-22 11:19:28 +00:00
static int __add_character_literal (ase_stx_parser_t* parser, ase_char_t ch)
2005-07-12 16:16:42 +00:00
{
2007-03-22 11:19:28 +00:00
ase_word_t i, c, literal;
ase_stx_t* stx = parser->stx;
2005-07-12 16:16:42 +00:00
for (i = 0; i < parser->literal_count; i++) {
2007-03-22 11:19:28 +00:00
c = ASE_STX_IS_SMALLINT(parser->literals[i])?
stx->class_smallinteger: ASE_STX_CLASS (stx, parser->literals[i]);
2005-07-12 16:16:42 +00:00
if (c != stx->class_character) continue;
2007-03-22 11:19:28 +00:00
if (ch == ASE_STX_CHAR_AT(stx,parser->literals[i],0)) return i;
2005-07-12 16:16:42 +00:00
}
2007-03-22 11:19:28 +00:00
literal = ase_stx_instantiate (
stx, stx->class_character, &ch, ASE_NULL, 0);
2005-07-12 16:16:42 +00:00
return __add_literal (parser, literal);
}
static int __add_string_literal (
2007-03-22 11:19:28 +00:00
ase_stx_parser_t* parser, const ase_char_t* str, ase_word_t size)
2005-07-12 16:16:42 +00:00
{
2007-03-22 11:19:28 +00:00
ase_word_t i, c, literal;
ase_stx_t* stx = parser->stx;
2005-07-12 16:16:42 +00:00
for (i = 0; i < parser->literal_count; i++) {
2007-03-22 11:19:28 +00:00
c = ASE_STX_IS_SMALLINT(parser->literals[i])?
stx->class_smallinteger: ASE_STX_CLASS (stx, parser->literals[i]);
2005-07-12 16:16:42 +00:00
if (c != stx->class_string) continue;
2007-03-22 11:19:28 +00:00
if (ase_strxncmp (str, size,
ASE_STX_DATA(stx,parser->literals[i]),
ASE_STX_SIZE(stx,parser->literals[i])) == 0) return i;
2005-07-12 16:16:42 +00:00
}
2007-03-22 11:19:28 +00:00
literal = ase_stx_instantiate (
stx, stx->class_string, ASE_NULL, str, size);
2005-07-12 16:16:42 +00:00
return __add_literal (parser, literal);
}
2005-09-11 17:01:56 +00:00
static int __add_symbol_literal (
2007-03-22 11:19:28 +00:00
ase_stx_parser_t* parser, const ase_char_t* str, ase_word_t size)
2005-09-11 17:01:56 +00:00
{
2007-03-22 11:19:28 +00:00
ase_stx_t* stx = parser->stx;
return __add_literal (parser, ase_stx_new_symbolx(stx, str, size));
2005-09-11 17:01:56 +00:00
}
2007-03-22 11:19:28 +00:00
int ase_stx_parser_parse_method (
ase_stx_parser_t* parser, ase_word_t method_class, void* input)
2005-06-05 05:27:02 +00:00
{
2005-06-06 03:47:56 +00:00
int n;
2007-03-22 11:19:28 +00:00
if (parser->input_func == ASE_NULL) {
parser->error_code = ASE_STX_PARSER_ERROR_INPUT_FUNC;
2005-06-05 05:27:02 +00:00
return -1;
}
2005-06-12 16:46:45 +00:00
parser->method_class = method_class;
if (__open_input(parser, input) == -1) return -1;
2005-06-06 03:47:56 +00:00
n = __parse_method (parser, method_class, input);
if (__close_input(parser) == -1) return -1;
return n;
}
static int __parse_method (
2007-03-22 11:19:28 +00:00
ase_stx_parser_t* parser, ase_word_t method_class, void* input)
2005-06-06 03:47:56 +00:00
{
2005-06-08 03:16:34 +00:00
/*
* <method definition> ::=
2005-07-04 10:02:00 +00:00
* <message pattern> [<temporaries>] [<primitive>] [<statements>]
2005-06-08 03:16:34 +00:00
*/
2005-06-05 05:27:02 +00:00
GET_CHAR (parser);
2005-06-05 16:44:05 +00:00
GET_TOKEN (parser);
2005-06-05 05:27:02 +00:00
2007-03-22 11:19:28 +00:00
ase_stx_name_clear (&parser->method_name);
ase_arr_clear (&parser->bytecode);
2005-06-12 16:46:45 +00:00
while (parser->temporary_count > 0) {
2007-03-22 11:19:28 +00:00
ase_free (parser->temporaries[--parser->temporary_count]);
2005-06-12 16:46:45 +00:00
}
2005-07-07 16:32:37 +00:00
parser->argument_count = 0;
2005-07-04 11:47:25 +00:00
parser->literal_count = 0;
2005-06-12 16:46:45 +00:00
2005-06-23 07:20:44 +00:00
if (__parse_message_pattern(parser) == -1) return -1;
if (__parse_temporaries(parser) == -1) return -1;
2005-07-04 10:02:00 +00:00
if (__parse_primitive(parser) == -1) return -1;
2005-06-23 07:20:44 +00:00
if (__parse_statements(parser) == -1) return -1;
2005-07-04 11:32:41 +00:00
if (__finish_method (parser) == -1) return -1;
return 0;
}
2007-03-22 11:19:28 +00:00
static int __finish_method (ase_stx_parser_t* parser)
2005-07-04 11:32:41 +00:00
{
2007-03-22 11:19:28 +00:00
ase_stx_t* stx = parser->stx;
ase_stx_class_t* class_obj;
ase_stx_method_t* method_obj;
ase_word_t method, selector;
2005-07-05 09:02:13 +00:00
2007-03-22 11:19:28 +00:00
ase_assert (parser->bytecode.size != 0);
2005-07-04 11:32:41 +00:00
2007-03-22 11:19:28 +00:00
class_obj = (ase_stx_class_t*)
ASE_STX_OBJECT(stx, parser->method_class);
2005-07-04 11:32:41 +00:00
2005-07-05 06:26:33 +00:00
if (class_obj->methods == stx->nil) {
2005-07-04 11:32:41 +00:00
/* TODO: reconfigure method dictionary size */
2007-03-22 11:19:28 +00:00
class_obj->methods = ase_stx_instantiate (
2005-07-19 12:08:04 +00:00
stx, stx->class_system_dictionary,
2007-03-22 11:19:28 +00:00
ASE_NULL, ASE_NULL, 64);
2005-07-04 11:32:41 +00:00
}
2007-03-22 11:19:28 +00:00
ase_assert (class_obj->methods != stx->nil);
2005-07-04 11:32:41 +00:00
2007-03-22 11:19:28 +00:00
selector = ase_stx_new_symbolx (
2005-07-05 09:02:13 +00:00
stx, parser->method_name.buffer, parser->method_name.size);
2005-07-04 11:32:41 +00:00
2007-03-22 11:19:28 +00:00
method = ase_stx_instantiate(stx, stx->class_method,
ASE_NULL, parser->literals, parser->literal_count);
method_obj = (ase_stx_method_t*)ASE_STX_OBJECT(stx, method);
2005-07-04 11:32:41 +00:00
2005-07-05 09:02:13 +00:00
/* TODO: text saving must be optional */
2007-03-22 11:19:28 +00:00
/*method_obj->text = ase_stx_instantiate (
stx, stx->class_string, ASE_NULL,
parser->text, ase_strlen(parser->text));
2005-07-05 09:02:13 +00:00
*/
method_obj->selector = selector;
2007-03-22 11:19:28 +00:00
method_obj->bytecodes = ase_stx_instantiate (
stx, stx->class_bytearray, ASE_NULL,
2006-01-30 16:44:03 +00:00
parser->bytecode.buf, parser->bytecode.size);
2005-09-11 15:15:35 +00:00
/* TODO: better way to store argument count & temporary count */
method_obj->tmpcount =
2007-03-22 11:19:28 +00:00
ASE_STX_TO_SMALLINT(parser->temporary_count - parser->argument_count);
method_obj->argcount = ASE_STX_TO_SMALLINT(parser->argument_count);
2005-07-05 09:52:00 +00:00
2007-03-22 11:19:28 +00:00
ase_stx_dict_put (stx, class_obj->methods, selector, method);
2005-06-06 03:54:32 +00:00
return 0;
}
2007-03-22 11:19:28 +00:00
static int __parse_message_pattern (ase_stx_parser_t* parser)
2005-06-06 03:54:32 +00:00
{
2005-06-08 03:16:34 +00:00
/*
* <message pattern> ::=
* <unary pattern> | <binary pattern> | <keyword pattern>
* <unary pattern> ::= unarySelector
* <binary pattern> ::= binarySelector <method argument>
* <keyword pattern> ::= (keyword <method argument>)+
*/
2005-06-12 15:46:02 +00:00
int n;
2005-06-08 03:16:34 +00:00
2007-03-22 11:19:28 +00:00
if (parser->token.type == ASE_STX_TOKEN_IDENT) {
2005-06-12 15:46:02 +00:00
n = __parse_unary_pattern (parser);
2005-06-07 16:09:58 +00:00
}
2007-03-22 11:19:28 +00:00
else if (parser->token.type == ASE_STX_TOKEN_BINARY) {
2005-06-12 15:46:02 +00:00
n = __parse_binary_pattern (parser);
}
2007-03-22 11:19:28 +00:00
else if (parser->token.type == ASE_STX_TOKEN_KEYWORD) {
2005-06-12 15:46:02 +00:00
n = __parse_keyword_pattern (parser);
}
else {
2007-03-22 11:19:28 +00:00
parser->error_code = ASE_STX_PARSER_ERROR_MESSAGE_SELECTOR;
2005-06-12 15:46:02 +00:00
n = -1;
}
2005-07-07 16:32:37 +00:00
parser->temporary_count = parser->argument_count;
2005-06-12 15:46:02 +00:00
return n;
}
2007-03-22 11:19:28 +00:00
static int __parse_unary_pattern (ase_stx_parser_t* parser)
2005-06-12 15:46:02 +00:00
{
/* TODO: check if the method name exists */
2005-06-12 16:46:45 +00:00
2007-03-22 11:19:28 +00:00
if (ase_stx_name_adds(
2005-06-12 16:22:47 +00:00
&parser->method_name, parser->token.name.buffer) == -1) {
2007-03-22 11:19:28 +00:00
parser->error_code = ASE_STX_PARSER_ERROR_MEMORY;
2005-06-12 16:07:23 +00:00
return -1;
}
2005-06-12 15:46:02 +00:00
GET_TOKEN (parser);
return 0;
}
2007-03-22 11:19:28 +00:00
static int __parse_binary_pattern (ase_stx_parser_t* parser)
2005-06-12 15:46:02 +00:00
{
/* TODO: check if the method name exists */
2005-06-12 16:46:45 +00:00
2007-03-22 11:19:28 +00:00
if (ase_stx_name_adds(
2005-06-12 16:22:47 +00:00
&parser->method_name, parser->token.name.buffer) == -1) {
2007-03-22 11:19:28 +00:00
parser->error_code = ASE_STX_PARSER_ERROR_MEMORY;
2005-06-12 16:07:23 +00:00
return -1;
}
2005-06-12 15:46:02 +00:00
GET_TOKEN (parser);
2007-03-22 11:19:28 +00:00
if (parser->token.type != ASE_STX_TOKEN_IDENT) {
parser->error_code = ASE_STX_PARSER_ERROR_ARGUMENT_NAME;
2005-06-12 15:46:02 +00:00
return -1;
}
2007-03-22 11:19:28 +00:00
if (parser->argument_count >= ase_countof(parser->temporaries)) {
parser->error_code = ASE_STX_PARSER_ERROR_TOO_MANY_ARGUMENTS;
2005-06-12 15:46:02 +00:00
return -1;
}
2005-06-12 16:46:45 +00:00
/* TODO: check for duplicate entries...in instvars */
2005-07-07 16:32:37 +00:00
parser->temporaries[parser->argument_count] =
2007-03-22 11:19:28 +00:00
ase_stx_token_yield (&parser->token, 0);
if (parser->temporaries[parser->argument_count] == ASE_NULL) {
parser->error_code = ASE_STX_PARSER_ERROR_MEMORY;
2005-06-12 15:46:02 +00:00
return -1;
}
parser->argument_count++;
GET_TOKEN (parser);
return 0;
}
2007-03-22 11:19:28 +00:00
static int __parse_keyword_pattern (ase_stx_parser_t* parser)
2005-06-12 15:46:02 +00:00
{
do {
2007-03-22 11:19:28 +00:00
if (ase_stx_name_adds(
2005-06-12 16:22:47 +00:00
&parser->method_name, parser->token.name.buffer) == -1) {
2007-03-22 11:19:28 +00:00
parser->error_code = ASE_STX_PARSER_ERROR_MEMORY;
2005-06-12 16:07:23 +00:00
return -1;
}
2005-06-12 12:33:31 +00:00
GET_TOKEN (parser);
2007-03-22 11:19:28 +00:00
if (parser->token.type != ASE_STX_TOKEN_IDENT) {
parser->error_code = ASE_STX_PARSER_ERROR_ARGUMENT_NAME;
2005-06-12 12:33:31 +00:00
return -1;
}
2005-06-19 16:16:33 +00:00
if (__is_pseudo_variable(&parser->token)) {
2007-03-22 11:19:28 +00:00
parser->error_code = ASE_STX_PARSER_ERROR_PSEUDO_VARIABLE;
2005-06-19 16:16:33 +00:00
return -1;
}
2007-03-22 11:19:28 +00:00
if (parser->argument_count >= ase_countof(parser->temporaries)) {
parser->error_code = ASE_STX_PARSER_ERROR_TOO_MANY_ARGUMENTS;
2005-06-12 15:46:02 +00:00
return -1;
}
2005-07-07 16:32:37 +00:00
parser->temporaries[parser->argument_count] =
2007-03-22 11:19:28 +00:00
ase_stx_token_yield (&parser->token, 0);
if (parser->temporaries[parser->argument_count] == ASE_NULL) {
parser->error_code = ASE_STX_PARSER_ERROR_MEMORY;
2005-06-12 15:46:02 +00:00
return -1;
}
2005-07-07 16:32:37 +00:00
/* TODO: check for duplicate entries...in instvars/arguments */
2005-06-12 15:46:02 +00:00
parser->argument_count++;
2005-06-12 12:33:31 +00:00
GET_TOKEN (parser);
2007-03-22 11:19:28 +00:00
} while (parser->token.type == ASE_STX_TOKEN_KEYWORD);
2005-06-12 15:46:02 +00:00
/* TODO: check if the method name exists */
/* if it exists, collapse arguments */
2007-03-22 11:19:28 +00:00
ase_printf (ASE_T("METHOD NAME ==> [%s]\n"), parser->method_name.buffer);
2005-06-11 18:01:25 +00:00
2005-06-05 05:27:02 +00:00
return 0;
}
2007-03-22 11:19:28 +00:00
static int __parse_temporaries (ase_stx_parser_t* parser)
2005-06-08 03:16:34 +00:00
{
2005-06-12 16:46:45 +00:00
/*
* <temporaries> ::= '|' <temporary variable list> '|'
* <temporary variable list> ::= identifier*
*/
2005-06-11 18:01:25 +00:00
if (!__is_vbar_token(&parser->token)) return 0;
GET_TOKEN (parser);
2007-03-22 11:19:28 +00:00
while (parser->token.type == ASE_STX_TOKEN_IDENT) {
if (parser->temporary_count >= ase_countof(parser->temporaries)) {
parser->error_code = ASE_STX_PARSER_ERROR_TOO_MANY_TEMPORARIES;
2005-06-12 16:46:45 +00:00
return -1;
}
2005-06-19 16:16:33 +00:00
if (__is_pseudo_variable(&parser->token)) {
2007-03-22 11:19:28 +00:00
parser->error_code = ASE_STX_PARSER_ERROR_PSEUDO_VARIABLE;
2005-06-19 16:16:33 +00:00
return -1;
}
2005-07-07 16:32:37 +00:00
parser->temporaries[parser->temporary_count] =
2007-03-22 11:19:28 +00:00
ase_stx_token_yield (&parser->token, 0);
if (parser->temporaries[parser->temporary_count] == ASE_NULL) {
parser->error_code = ASE_STX_PARSER_ERROR_MEMORY;
2005-06-12 16:46:45 +00:00
return -1;
}
2005-07-07 16:32:37 +00:00
/* TODO: check for duplicate entries...in instvars/arguments/temporaries */
2005-06-12 16:46:45 +00:00
parser->temporary_count++;
2005-06-11 18:01:25 +00:00
GET_TOKEN (parser);
}
if (!__is_vbar_token(&parser->token)) {
2007-03-22 11:19:28 +00:00
parser->error_code = ASE_STX_PARSER_ERROR_TEMPORARIES_NOT_CLOSED;
2005-06-11 18:01:25 +00:00
return -1;
}
GET_TOKEN (parser);
return 0;
2005-06-08 03:16:34 +00:00
}
2007-03-22 11:19:28 +00:00
static int __parse_primitive (ase_stx_parser_t* parser)
2005-07-04 10:02:00 +00:00
{
/*
* <primitive> ::= '<' 'primitive:' number '>'
*/
2005-07-07 07:45:05 +00:00
int prim_no;
2005-07-04 10:02:00 +00:00
if (!__is_primitive_opener(&parser->token)) return 0;
GET_TOKEN (parser);
2007-03-22 11:19:28 +00:00
if (parser->token.type != ASE_STX_TOKEN_KEYWORD ||
ase_strcmp (parser->token.name.buffer, ASE_T("primitive:")) != 0) {
parser->error_code = ASE_STX_PARSER_ERROR_PRIMITIVE_KEYWORD;
2005-07-04 10:02:00 +00:00
return -1;
}
GET_TOKEN (parser); /* TODO: only integer */
2007-03-22 11:19:28 +00:00
if (parser->token.type != ASE_STX_TOKEN_NUMLIT) {
parser->error_code = ASE_STX_PARSER_ERROR_PRIMITIVE_NUMBER;
2005-07-04 10:02:00 +00:00
return -1;
}
2005-07-07 07:45:05 +00:00
/*TODO: more checks the validity of the primitive number */
2007-03-22 11:19:28 +00:00
if (!ase_stristype(parser->token.name.buffer, ase_isdigit)) {
parser->error_code = ASE_STX_PARSER_ERROR_PRIMITIVE_NUMBER;
2005-07-07 07:45:05 +00:00
return -1;
}
2007-03-22 11:19:28 +00:00
ASE_STRTOI (prim_no, parser->token.name.buffer, ASE_NULL, 10);
2005-07-10 09:21:46 +00:00
if (prim_no < 0 || prim_no > 0xFF) {
2007-03-22 11:19:28 +00:00
parser->error_code = ASE_STX_PARSER_ERROR_PRIMITIVE_NUMBER_RANGE;
2005-07-07 07:45:05 +00:00
return -1;
}
2005-07-05 11:15:51 +00:00
2005-07-10 09:21:46 +00:00
EMIT_DO_PRIMITIVE (parser, prim_no);
2005-07-05 11:15:51 +00:00
2005-07-04 10:02:00 +00:00
GET_TOKEN (parser);
if (!__is_primitive_closer(&parser->token)) {
2007-03-22 11:19:28 +00:00
parser->error_code = ASE_STX_PARSER_ERROR_PRIMITIVE_NOT_CLOSED;
2005-07-04 10:02:00 +00:00
return -1;
}
GET_TOKEN (parser);
return 0;
}
2007-03-22 11:19:28 +00:00
static int __parse_statements (ase_stx_parser_t* parser)
2005-06-11 18:01:25 +00:00
{
/*
2005-06-23 04:55:44 +00:00
* <statements> ::= (ORIGINAL->maybe wrong)
2005-06-11 18:01:25 +00:00
* (<return statement> ['.'] ) |
* (<expression> ['.' [<statements>]])
2005-06-23 04:55:44 +00:00
* <statements> ::= (REVISED->correct?)
* <statement> ['. [<statements>]]
2005-06-11 18:01:25 +00:00
*/
2007-03-22 11:19:28 +00:00
while (parser->token.type != ASE_STX_TOKEN_END) {
2005-06-23 04:55:44 +00:00
if (__parse_statement (parser) == -1) return -1;
2005-06-15 16:07:14 +00:00
2007-03-22 11:19:28 +00:00
if (parser->token.type == ASE_STX_TOKEN_PERIOD) {
2005-06-15 16:07:14 +00:00
GET_TOKEN (parser);
2005-06-23 04:55:44 +00:00
continue;
2005-06-15 16:07:14 +00:00
}
2005-06-23 04:55:44 +00:00
2007-03-22 11:19:28 +00:00
if (parser->token.type != ASE_STX_TOKEN_END) {
parser->error_code = ASE_STX_PARSER_ERROR_NO_PERIOD;
2005-06-15 16:07:14 +00:00
return -1;
}
2005-06-12 12:33:31 +00:00
}
2005-06-15 16:07:14 +00:00
2005-10-01 05:33:06 +00:00
EMIT_CODE (parser, RETURN_RECEIVER);
2005-06-12 12:33:31 +00:00
return 0;
}
2007-03-22 11:19:28 +00:00
static int __parse_block_statements (ase_stx_parser_t* parser)
2005-06-29 10:56:42 +00:00
{
2007-03-22 11:19:28 +00:00
while (parser->token.type != ASE_STX_TOKEN_RBRACKET &&
parser->token.type != ASE_STX_TOKEN_END) {
2005-06-29 10:56:42 +00:00
if (__parse_statement(parser) == -1) return -1;
2007-03-22 11:19:28 +00:00
if (parser->token.type != ASE_STX_TOKEN_PERIOD) break;
2005-06-29 10:56:42 +00:00
GET_TOKEN (parser);
}
return 0;
}
2007-03-22 11:19:28 +00:00
static int __parse_statement (ase_stx_parser_t* parser)
2005-06-12 12:33:31 +00:00
{
2005-06-23 04:55:44 +00:00
/*
* <statement> ::= <return statement> | <expression>
* <return statement> ::= returnOperator <expression>
* returnOperator ::= '^'
*/
2007-03-22 11:19:28 +00:00
if (parser->token.type == ASE_STX_TOKEN_RETURN) {
2005-06-12 12:33:31 +00:00
GET_TOKEN (parser);
2005-06-23 04:55:44 +00:00
if (__parse_expression(parser) == -1) return -1;
2005-07-10 09:21:46 +00:00
EMIT_RETURN_FROM_MESSAGE (parser);
2005-06-11 18:01:25 +00:00
}
else {
2005-06-23 04:55:44 +00:00
if (__parse_expression(parser) == -1) return -1;
2005-06-12 12:33:31 +00:00
}
2005-06-11 18:01:25 +00:00
return 0;
}
2007-03-22 11:19:28 +00:00
static int __parse_expression (ase_stx_parser_t* parser)
2005-06-08 03:16:34 +00:00
{
2005-06-12 12:33:31 +00:00
/*
* <expression> ::= <assignment> | <basic expression>
2005-06-23 04:55:44 +00:00
* <assignment> ::= <assignment target> assignmentOperator <expression>
2005-06-12 12:33:31 +00:00
* <basic expression> ::= <primary> [<messages> <cascaded messages>]
2005-06-23 04:55:44 +00:00
* <assignment target> ::= identifier
2005-06-12 12:33:31 +00:00
* assignmentOperator ::= ':='
*/
2007-03-22 11:19:28 +00:00
ase_stx_t* stx = parser->stx;
2005-06-12 12:33:31 +00:00
2007-03-22 11:19:28 +00:00
if (parser->token.type == ASE_STX_TOKEN_IDENT) {
ase_char_t* ident = ase_stx_token_yield (&parser->token, 0);
if (ident == ASE_NULL) {
parser->error_code = ASE_STX_PARSER_ERROR_MEMORY;
2005-06-19 16:16:33 +00:00
return -1;
}
2005-06-16 16:42:02 +00:00
2005-06-12 12:33:31 +00:00
GET_TOKEN (parser);
2007-03-22 11:19:28 +00:00
if (parser->token.type == ASE_STX_TOKEN_ASSIGN) {
2005-06-15 16:07:14 +00:00
GET_TOKEN (parser);
2005-06-19 16:16:33 +00:00
if (__parse_assignment(parser, ident) == -1) {
2007-03-22 11:19:28 +00:00
ase_free (ident);
2005-06-19 16:16:33 +00:00
return -1;
}
2005-06-15 16:07:14 +00:00
}
else {
2005-06-23 04:55:44 +00:00
if (__parse_basic_expression(parser, ident) == -1) {
2007-03-22 11:19:28 +00:00
ase_free (ident);
2005-06-22 15:02:41 +00:00
return -1;
2005-06-19 16:16:33 +00:00
}
2005-06-15 16:07:14 +00:00
}
2005-06-19 16:16:33 +00:00
2007-03-22 11:19:28 +00:00
ase_free (ident);
2005-06-12 12:33:31 +00:00
}
2005-06-22 15:02:41 +00:00
else {
2007-03-22 11:19:28 +00:00
if (__parse_basic_expression(parser, ASE_NULL) == -1) return -1;
2005-06-22 15:02:41 +00:00
}
return 0;
}
2005-07-04 10:02:00 +00:00
static int __parse_basic_expression (
2007-03-22 11:19:28 +00:00
ase_stx_parser_t* parser, const ase_char_t* ident)
2005-06-22 15:02:41 +00:00
{
/*
2005-06-23 04:55:44 +00:00
* <basic expression> ::= <primary> [<messages> <cascaded messages>]
2005-06-22 15:02:41 +00:00
*/
2007-03-22 11:19:28 +00:00
ase_bool_t is_super;
2005-06-22 15:02:41 +00:00
2005-09-30 12:19:00 +00:00
if (__parse_primary(parser, ident, &is_super) == -1) return -1;
2007-03-22 11:19:28 +00:00
if (parser->token.type != ASE_STX_TOKEN_END &&
parser->token.type != ASE_STX_TOKEN_PERIOD) {
2005-09-30 12:19:00 +00:00
if (__parse_message_continuation(parser, is_super) == -1) return -1;
2005-06-12 12:33:31 +00:00
}
2005-06-23 04:55:44 +00:00
return 0;
2005-06-08 03:16:34 +00:00
}
2005-06-22 15:02:41 +00:00
2005-06-19 16:16:33 +00:00
static int __parse_assignment (
2007-03-22 11:19:28 +00:00
ase_stx_parser_t* parser, const ase_char_t* target)
2005-06-19 16:16:33 +00:00
{
/*
* <assignment> ::= <assignment target> assignmentOperator <expression>
*/
2007-03-22 11:19:28 +00:00
ase_word_t i;
ase_stx_t* stx = parser->stx;
2005-06-19 16:16:33 +00:00
2005-07-07 16:32:37 +00:00
for (i = parser->argument_count; i < parser->temporary_count; i++) {
2007-03-22 11:19:28 +00:00
if (ase_strcmp (target, parser->temporaries[i]) == 0) {
2005-06-19 16:16:33 +00:00
if (__parse_expression(parser) == -1) return -1;
2005-07-10 09:21:46 +00:00
EMIT_STORE_TEMPORARY_LOCATION (parser, i);
2005-06-19 16:16:33 +00:00
return 0;
}
}
2007-03-22 11:19:28 +00:00
if (ase_stx_get_instance_variable_index (
2005-07-05 06:26:33 +00:00
stx, parser->method_class, target, &i) == 0) {
2005-06-29 16:01:32 +00:00
if (__parse_expression(parser) == -1) return -1;
2005-07-10 09:21:46 +00:00
EMIT_STORE_RECEIVER_VARIABLE (parser, i);
2005-06-29 16:01:32 +00:00
return 0;
2005-06-29 12:02:39 +00:00
}
2005-06-19 16:16:33 +00:00
2007-03-22 11:19:28 +00:00
if (ase_stx_lookup_class_variable (
2005-07-05 06:26:33 +00:00
stx, parser->method_class, target) != stx->nil) {
2005-07-03 16:37:01 +00:00
if (__parse_expression(parser) == -1) return -1;
2005-07-08 11:32:50 +00:00
/* TODO */
2007-03-22 11:19:28 +00:00
EMIT_CODE_TEST (parser, ASE_T("ASSIGN_CLASSVAR #"), target);
2005-07-10 09:21:46 +00:00
//EMIT_STORE_CLASS_VARIABLE (parser, target);
2005-07-03 16:37:01 +00:00
return 0;
}
2005-06-19 16:16:33 +00:00
2005-07-04 10:02:00 +00:00
/* TODO: IMPLEMENT POOL DICTIONARIES */
/* TODO: IMPLEMENT GLOBLAS, but i don't like this idea */
2005-06-19 16:16:33 +00:00
2007-03-22 11:19:28 +00:00
parser->error_code = ASE_STX_PARSER_ERROR_UNDECLARED_NAME;
2005-06-19 16:16:33 +00:00
return -1;
}
2005-09-30 12:19:00 +00:00
static int __parse_primary (
2007-03-22 11:19:28 +00:00
ase_stx_parser_t* parser, const ase_char_t* ident, ase_bool_t* is_super)
2005-06-23 04:55:44 +00:00
{
/*
* <primary> ::=
* identifier | <literal> |
* <block constructor> | ( '('<expression>')' )
*/
2007-03-22 11:19:28 +00:00
ase_stx_t* stx = parser->stx;
2005-07-11 13:41:59 +00:00
2007-03-22 11:19:28 +00:00
if (ident == ASE_NULL) {
2005-07-11 13:41:59 +00:00
int pos;
2007-03-22 11:19:28 +00:00
ase_word_t literal;
2005-07-11 13:41:59 +00:00
2007-03-22 11:19:28 +00:00
*is_super = ase_false;
2005-09-30 16:49:39 +00:00
2007-03-22 11:19:28 +00:00
if (parser->token.type == ASE_STX_TOKEN_IDENT) {
2005-09-30 12:19:00 +00:00
if (__parse_primary_ident(parser,
parser->token.name.buffer, is_super) == -1) return -1;
2005-06-23 04:55:44 +00:00
GET_TOKEN (parser);
}
2007-03-22 11:19:28 +00:00
else if (parser->token.type == ASE_STX_TOKEN_CHARLIT) {
2005-07-12 16:16:42 +00:00
pos = __add_character_literal(
parser, parser->token.name.buffer[0]);
2005-07-11 13:41:59 +00:00
if (pos == -1) return -1;
EMIT_PUSH_LITERAL_CONSTANT (parser, pos);
2005-06-23 04:55:44 +00:00
GET_TOKEN (parser);
}
2007-03-22 11:19:28 +00:00
else if (parser->token.type == ASE_STX_TOKEN_STRLIT) {
2005-07-12 16:16:42 +00:00
pos = __add_string_literal (parser,
2005-07-11 13:41:59 +00:00
parser->token.name.buffer, parser->token.name.size);
if (pos == -1) return -1;
EMIT_PUSH_LITERAL_CONSTANT (parser, pos);
2005-06-23 04:55:44 +00:00
GET_TOKEN (parser);
}
2007-03-22 11:19:28 +00:00
else if (parser->token.type == ASE_STX_TOKEN_NUMLIT) {
2005-07-12 16:16:42 +00:00
/* TODO: other types of numbers, negative numbers, etc */
2007-03-22 11:19:28 +00:00
ase_word_t tmp;
ASE_STRTOI (tmp, parser->token.name.buffer, ASE_NULL, 10);
literal = ASE_STX_TO_SMALLINT(tmp);
2005-07-12 16:16:42 +00:00
pos = __add_literal(parser, literal);
if (pos == -1) return -1;
EMIT_PUSH_LITERAL_CONSTANT (parser, pos);
2005-06-23 04:55:44 +00:00
GET_TOKEN (parser);
}
2007-03-22 11:19:28 +00:00
else if (parser->token.type == ASE_STX_TOKEN_SYMLIT) {
2005-09-11 17:01:56 +00:00
pos = __add_symbol_literal (parser,
parser->token.name.buffer, parser->token.name.size);
if (pos == -1) return -1;
EMIT_PUSH_LITERAL_CONSTANT (parser, pos);
2005-06-23 04:55:44 +00:00
GET_TOKEN (parser);
}
2007-03-22 11:19:28 +00:00
else if (parser->token.type == ASE_STX_TOKEN_LBRACKET) {
2005-06-23 04:55:44 +00:00
GET_TOKEN (parser);
2005-06-29 10:56:42 +00:00
if (__parse_block_constructor(parser) == -1) return -1;
2005-06-23 04:55:44 +00:00
}
2007-03-22 11:19:28 +00:00
else if (parser->token.type == ASE_STX_TOKEN_APAREN) {
2005-06-23 04:55:44 +00:00
/* TODO: array literal */
}
2007-03-22 11:19:28 +00:00
else if (parser->token.type == ASE_STX_TOKEN_LPAREN) {
2005-06-23 04:55:44 +00:00
GET_TOKEN (parser);
2005-06-29 10:56:42 +00:00
if (__parse_expression(parser) == -1) return -1;
2007-03-22 11:19:28 +00:00
if (parser->token.type != ASE_STX_TOKEN_RPAREN) {
parser->error_code = ASE_STX_PARSER_ERROR_NO_RPAREN;
2005-06-23 04:55:44 +00:00
return -1;
}
GET_TOKEN (parser);
}
else {
2007-03-22 11:19:28 +00:00
parser->error_code = ASE_STX_PARSER_ERROR_PRIMARY;
2005-06-23 04:55:44 +00:00
return -1;
}
}
else {
2005-08-11 16:16:04 +00:00
/*if (__parse_primary_ident(parser, parser->token.name.buffer) == -1) return -1;*/
2005-09-30 12:19:00 +00:00
if (__parse_primary_ident(parser, ident, is_super) == -1) return -1;
2005-06-23 04:55:44 +00:00
}
return 0;
}
2005-09-30 12:19:00 +00:00
static int __parse_primary_ident (
2007-03-22 11:19:28 +00:00
ase_stx_parser_t* parser, const ase_char_t* ident, ase_bool_t* is_super)
2005-07-08 11:32:50 +00:00
{
2007-03-22 11:19:28 +00:00
ase_word_t i;
ase_stx_t* stx = parser->stx;
2005-07-08 11:32:50 +00:00
2007-03-22 11:19:28 +00:00
*is_super = ase_false;
2005-09-30 12:19:00 +00:00
2007-03-22 11:19:28 +00:00
if (ase_strcmp(ident, ASE_T("self")) == 0) {
2005-09-30 12:19:00 +00:00
EMIT_CODE (parser, PUSH_RECEIVER);
return 0;
2005-08-11 11:18:30 +00:00
}
2007-03-22 11:19:28 +00:00
else if (ase_strcmp(ident, ASE_T("super")) == 0) {
*is_super = ase_true;
2005-09-30 12:19:00 +00:00
EMIT_CODE (parser, PUSH_RECEIVER);
return 0;
2005-08-11 11:18:30 +00:00
}
2007-03-22 11:19:28 +00:00
else if (ase_strcmp(ident, ASE_T("nil")) == 0) {
2005-08-11 16:16:04 +00:00
EMIT_CODE (parser, PUSH_NIL);
return 0;
2005-08-11 11:18:30 +00:00
}
2007-03-22 11:19:28 +00:00
else if (ase_strcmp(ident, ASE_T("true")) == 0) {
2005-08-11 16:16:04 +00:00
EMIT_CODE (parser, PUSH_TRUE);
return 0;
2005-08-11 11:18:30 +00:00
}
2007-03-22 11:19:28 +00:00
else if (ase_strcmp(ident, ASE_T("false")) == 0) {
2005-08-11 16:16:04 +00:00
EMIT_CODE (parser, PUSH_FALSE);
return 0;
2005-08-11 11:18:30 +00:00
}
2005-07-08 11:32:50 +00:00
/* Refer to __parse_assignment for identifier lookup */
for (i = 0; i < parser->temporary_count; i++) {
2007-03-22 11:19:28 +00:00
if (ase_strcmp(ident, parser->temporaries[i]) == 0) {
2005-07-10 09:21:46 +00:00
EMIT_PUSH_TEMPORARY_LOCATION (parser, i);
2005-07-08 11:32:50 +00:00
return 0;
}
}
2007-03-22 11:19:28 +00:00
if (ase_stx_get_instance_variable_index (
2005-07-10 09:21:46 +00:00
stx, parser->method_class, ident, &i) == 0) {
EMIT_PUSH_RECEIVER_VARIABLE (parser, i);
2005-07-08 11:32:50 +00:00
return 0;
}
2005-07-10 09:21:46 +00:00
/* TODO: what is the best way to look up a class variable? */
/* 1. Use the class containing it and using its position */
/* 2. Use a primitive method after pushing the name as a symbol */
/* 3. Implement a vm instruction to do it */
/*
2007-03-22 11:19:28 +00:00
if (ase_stx_lookup_class_variable (
2005-07-10 09:21:46 +00:00
stx, parser->method_class, ident) != stx->nil) {
//EMIT_LOOKUP_CLASS_VARIABLE (parser, ident);
2005-07-08 11:32:50 +00:00
return 0;
}
2005-07-10 09:21:46 +00:00
*/
2005-07-08 11:32:50 +00:00
/* TODO: IMPLEMENT POOL DICTIONARIES */
/* TODO: IMPLEMENT GLOBLAS, but i don't like this idea */
2007-03-22 11:19:28 +00:00
parser->error_code = ASE_STX_PARSER_ERROR_UNDECLARED_NAME;
2005-07-08 11:32:50 +00:00
return -1;
}
2007-03-22 11:19:28 +00:00
static int __parse_block_constructor (ase_stx_parser_t* parser)
2005-06-23 04:55:44 +00:00
{
/*
* <block constructor> ::= '[' <block body> ']'
* <block body> ::= [<block argument>* '|']
* [<temporaries>] [<statements>]
* <block argument> ::= ':' identifier
*/
2007-03-22 11:19:28 +00:00
if (parser->token.type == ASE_STX_TOKEN_COLON) {
2005-06-23 07:20:44 +00:00
do {
2005-06-29 10:56:42 +00:00
GET_TOKEN (parser);
2007-03-22 11:19:28 +00:00
if (parser->token.type != ASE_STX_TOKEN_IDENT) {
parser->error_code = ASE_STX_PARSER_ERROR_BLOCK_ARGUMENT_NAME;
2005-06-23 07:20:44 +00:00
return -1;
}
/* TODO : store block arguments */
GET_TOKEN (parser);
2007-03-22 11:19:28 +00:00
} while (parser->token.type == ASE_STX_TOKEN_COLON);
2005-06-23 07:20:44 +00:00
if (!__is_vbar_token(&parser->token)) {
2007-03-22 11:19:28 +00:00
parser->error_code = ASE_STX_PARSER_ERROR_BLOCK_ARGUMENT_LIST;
2005-06-23 07:20:44 +00:00
return -1;
}
GET_TOKEN (parser);
}
/* TODO: create a block closure */
2005-06-29 10:56:42 +00:00
if (__parse_temporaries(parser) == -1) return -1;
if (__parse_block_statements(parser) == -1) return -1;
2005-06-23 07:20:44 +00:00
2007-03-22 11:19:28 +00:00
if (parser->token.type != ASE_STX_TOKEN_RBRACKET) {
parser->error_code = ASE_STX_PARSER_ERROR_BLOCK_NOT_CLOSED;
2005-06-23 07:20:44 +00:00
return -1;
}
GET_TOKEN (parser);
/* TODO: do special treatment for block closures */
2005-06-23 04:55:44 +00:00
return 0;
}
2005-09-30 12:19:00 +00:00
static int __parse_message_continuation (
2007-03-22 11:19:28 +00:00
ase_stx_parser_t* parser, ase_bool_t is_super)
2005-06-19 16:16:33 +00:00
{
2005-06-22 15:02:41 +00:00
/*
* <messages> ::=
* (<unary message>+ <binary message>* [<keyword message>] ) |
* (<binary message>+ [<keyword message>] ) |
* <keyword message>
* <cascaded messages> ::= (';' <messages>)*
*/
2005-09-30 12:19:00 +00:00
if (__parse_keyword_message(parser, is_super) == -1) return -1;
2005-06-19 16:16:33 +00:00
2007-03-22 11:19:28 +00:00
while (parser->token.type == ASE_STX_TOKEN_SEMICOLON) {
EMIT_CODE_TEST (parser, ASE_T("DoSpecial(DUP_RECEIVER(CASCADE))"), ASE_T(""));
2005-06-19 16:16:33 +00:00
GET_TOKEN (parser);
2007-03-22 11:19:28 +00:00
if (__parse_keyword_message(parser, ase_false) == -1) return -1;
EMIT_CODE_TEST (parser, ASE_T("DoSpecial(POP_TOP)"), ASE_T(""));
2005-06-19 16:16:33 +00:00
}
return 0;
}
2007-03-22 11:19:28 +00:00
static int __parse_keyword_message (ase_stx_parser_t* parser, ase_bool_t is_super)
2005-06-15 16:07:14 +00:00
{
2005-06-23 04:55:44 +00:00
/*
* <keyword message> ::= (keyword <keyword argument> )+
* <keyword argument> ::= <primary> <unary message>* <binary message>*
*/
2007-03-22 11:19:28 +00:00
ase_stx_name_t name;
ase_word_t pos;
ase_bool_t is_super2;
2005-09-30 12:19:00 +00:00
int nargs = 0, n;
2005-06-23 04:55:44 +00:00
2005-09-30 12:19:00 +00:00
if (__parse_binary_message (parser, is_super) == -1) return -1;
2007-03-22 11:19:28 +00:00
if (parser->token.type != ASE_STX_TOKEN_KEYWORD) return 0;
2005-06-23 04:55:44 +00:00
2007-03-22 11:19:28 +00:00
if (ase_stx_name_open(&name, 0) == ASE_NULL) {
parser->error_code = ASE_STX_PARSER_ERROR_MEMORY;
2005-06-23 04:55:44 +00:00
return -1;
}
2005-07-10 16:50:50 +00:00
do {
2007-03-22 11:19:28 +00:00
if (ase_stx_name_adds(&name, parser->token.name.buffer) == -1) {
parser->error_code = ASE_STX_PARSER_ERROR_MEMORY;
ase_stx_name_close (&name);
2005-06-23 04:55:44 +00:00
return -1;
}
GET_TOKEN (parser);
2007-03-22 11:19:28 +00:00
if (__parse_primary(parser, ASE_NULL, &is_super2) == -1) {
ase_stx_name_close (&name);
2005-06-23 04:55:44 +00:00
return -1;
}
2005-09-30 12:19:00 +00:00
if (__parse_binary_message(parser, is_super2) == -1) {
2007-03-22 11:19:28 +00:00
ase_stx_name_close (&name);
2005-06-23 04:55:44 +00:00
return -1;
}
2005-07-10 16:50:50 +00:00
nargs++;
2005-09-13 07:07:24 +00:00
/* TODO: check if it has too many arguments.. */
2007-03-22 11:19:28 +00:00
} while (parser->token.type == ASE_STX_TOKEN_KEYWORD);
2005-07-10 16:50:50 +00:00
2005-09-13 07:07:24 +00:00
pos = __add_symbol_literal (parser, name.buffer, name.size);
if (pos == -1) {
2007-03-22 11:19:28 +00:00
ase_stx_name_close (&name);
2005-09-13 07:07:24 +00:00
return -1;
}
2005-09-30 12:19:00 +00:00
n = (is_super)?
__emit_send_to_super(parser,nargs,pos):
__emit_send_to_self(parser,nargs,pos);
if (n == -1) {
2007-03-22 11:19:28 +00:00
ase_stx_name_close (&name);
2005-09-13 07:07:24 +00:00
return -1;
}
2005-07-10 16:50:50 +00:00
2007-03-22 11:19:28 +00:00
ase_stx_name_close (&name);
2005-06-22 15:02:41 +00:00
return 0;
2005-06-15 16:07:14 +00:00
}
2007-03-22 11:19:28 +00:00
static int __parse_binary_message (ase_stx_parser_t* parser, ase_bool_t is_super)
2005-06-15 16:07:14 +00:00
{
2005-06-22 15:02:41 +00:00
/*
* <binary message> ::= binarySelector <binary argument>
* <binary argument> ::= <primary> <unary message>*
*/
2007-03-22 11:19:28 +00:00
ase_word_t pos;
ase_bool_t is_super2;
2005-09-30 12:19:00 +00:00
int n;
2005-06-22 15:02:41 +00:00
2005-09-30 12:19:00 +00:00
if (__parse_unary_message (parser, is_super) == -1) return -1;
2005-06-22 15:02:41 +00:00
2007-03-22 11:19:28 +00:00
while (parser->token.type == ASE_STX_TOKEN_BINARY) {
ase_char_t* op = ase_stx_token_yield (&parser->token, 0);
if (op == ASE_NULL) {
parser->error_code = ASE_STX_PARSER_ERROR_MEMORY;
2005-06-23 04:55:44 +00:00
return -1;
}
2005-06-22 15:02:41 +00:00
GET_TOKEN (parser);
2007-03-22 11:19:28 +00:00
if (__parse_primary(parser, ASE_NULL, &is_super2) == -1) {
ase_free (op);
2005-06-23 04:55:44 +00:00
return -1;
}
2005-09-30 12:19:00 +00:00
if (__parse_unary_message(parser, is_super2) == -1) {
2007-03-22 11:19:28 +00:00
ase_free (op);
2005-06-23 04:55:44 +00:00
return -1;
}
2007-03-22 11:19:28 +00:00
pos = __add_symbol_literal (parser, op, ase_strlen(op));
2005-09-13 07:07:24 +00:00
if (pos == -1) {
2007-03-22 11:19:28 +00:00
ase_free (op);
2005-09-13 07:07:24 +00:00
return -1;
}
2005-09-30 12:19:00 +00:00
n = (is_super)?
__emit_send_to_super(parser,2,pos):
__emit_send_to_self(parser,2,pos);
if (n == -1) {
2007-03-22 11:19:28 +00:00
ase_free (op);
2005-09-13 07:07:24 +00:00
return -1;
}
2005-07-10 16:50:50 +00:00
2007-03-22 11:19:28 +00:00
ase_free (op);
2005-06-22 15:02:41 +00:00
}
return 0;
2005-06-15 16:07:14 +00:00
}
2007-03-22 11:19:28 +00:00
static int __parse_unary_message (ase_stx_parser_t* parser, ase_bool_t is_super)
2005-06-19 16:16:33 +00:00
{
2005-06-22 15:02:41 +00:00
/* <unary message> ::= unarySelector */
2005-06-19 16:16:33 +00:00
2007-03-22 11:19:28 +00:00
ase_word_t pos;
2005-09-30 12:19:00 +00:00
int n;
2005-09-11 17:01:56 +00:00
2007-03-22 11:19:28 +00:00
while (parser->token.type == ASE_STX_TOKEN_IDENT) {
2005-09-11 17:01:56 +00:00
pos = __add_symbol_literal (parser,
parser->token.name.buffer, parser->token.name.size);
if (pos == -1) return -1;
2005-09-30 12:19:00 +00:00
n = (is_super)?
__emit_send_to_super(parser,0,pos):
__emit_send_to_self(parser,0,pos);
if (n == -1) return -1;
2005-06-22 15:02:41 +00:00
GET_TOKEN (parser);
2005-06-19 16:16:33 +00:00
}
return 0;
}
2007-03-22 11:19:28 +00:00
static int __get_token (ase_stx_parser_t* parser)
2005-06-05 05:27:02 +00:00
{
2007-03-22 11:19:28 +00:00
ase_cint_t c;
2005-06-05 05:27:02 +00:00
do {
if (__skip_spaces(parser) == -1) return -1;
2007-03-22 11:19:28 +00:00
if (parser->curc == ASE_T('"')) {
2005-06-05 05:27:02 +00:00
GET_CHAR (parser);
if (__skip_comment(parser) == -1) return -1;
}
else break;
} while (1);
c = parser->curc;
2007-03-22 11:19:28 +00:00
ase_stx_token_clear (&parser->token);
2005-06-05 05:27:02 +00:00
2007-03-22 11:19:28 +00:00
if (c == ASE_T_EOF) {
parser->token.type = ASE_STX_TOKEN_END;
2005-06-06 16:04:18 +00:00
}
2007-03-22 11:19:28 +00:00
else if (ase_isalpha(c)) {
2005-06-05 16:44:05 +00:00
if (__get_ident(parser) == -1) return -1;
2005-06-05 05:27:02 +00:00
}
2007-03-22 11:19:28 +00:00
else if (ase_isdigit(c)) {
if (__get_numlit(parser, ase_false) == -1) return -1;
2005-06-07 16:09:58 +00:00
}
2007-03-22 11:19:28 +00:00
else if (c == ASE_T('$')) {
2005-06-06 16:47:10 +00:00
GET_CHAR (parser);
2005-06-05 16:44:05 +00:00
if (__get_charlit(parser) == -1) return -1;
}
2007-03-22 11:19:28 +00:00
else if (c == ASE_T('\'')) {
2005-06-06 16:47:10 +00:00
GET_CHAR (parser);
2005-06-05 16:44:05 +00:00
if (__get_strlit(parser) == -1) return -1;
2005-06-05 05:27:02 +00:00
}
2007-03-22 11:19:28 +00:00
else if (c == ASE_T(':')) {
parser->token.type = ASE_STX_TOKEN_COLON;
2005-06-07 16:09:58 +00:00
ADD_TOKEN_CHAR(parser, c);
GET_CHAR (parser);
c = parser->curc;
2007-03-22 11:19:28 +00:00
if (c == ASE_T('=')) {
parser->token.type = ASE_STX_TOKEN_ASSIGN;
2005-06-07 16:09:58 +00:00
ADD_TOKEN_CHAR(parser, c);
GET_CHAR (parser);
}
}
2007-03-22 11:19:28 +00:00
else if (c == ASE_T('^')) {
parser->token.type = ASE_STX_TOKEN_RETURN;
2005-06-06 16:04:18 +00:00
ADD_TOKEN_CHAR(parser, c);
GET_CHAR (parser);
}
2007-03-22 11:19:28 +00:00
else if (c == ASE_T('[')) {
parser->token.type = ASE_STX_TOKEN_LBRACKET;
2005-06-07 16:09:58 +00:00
ADD_TOKEN_CHAR(parser, c);
GET_CHAR (parser);
}
2007-03-22 11:19:28 +00:00
else if (c == ASE_T(']')) {
parser->token.type = ASE_STX_TOKEN_RBRACKET;
2005-06-07 16:09:58 +00:00
ADD_TOKEN_CHAR(parser, c);
GET_CHAR (parser);
}
2007-03-22 11:19:28 +00:00
else if (c == ASE_T('(')) {
parser->token.type = ASE_STX_TOKEN_LPAREN;
2005-06-12 12:33:31 +00:00
ADD_TOKEN_CHAR(parser, c);
GET_CHAR (parser);
}
2007-03-22 11:19:28 +00:00
else if (c == ASE_T(')')) {
parser->token.type = ASE_STX_TOKEN_RPAREN;
2005-06-12 12:33:31 +00:00
ADD_TOKEN_CHAR(parser, c);
GET_CHAR (parser);
}
2007-03-22 11:19:28 +00:00
else if (c == ASE_T('#')) {
2005-06-23 04:55:44 +00:00
/*ADD_TOKEN_CHAR(parser, c);*/
GET_CHAR (parser);
c = parser->curc;
2007-03-22 11:19:28 +00:00
if (c == ASE_T_EOF) {
parser->error_code = ASE_STX_PARSER_ERROR_LITERAL;
2005-06-23 04:55:44 +00:00
return -1;
}
2007-03-22 11:19:28 +00:00
else if (c == ASE_T('(')) {
2005-06-23 04:55:44 +00:00
ADD_TOKEN_CHAR(parser, c);
2007-03-22 11:19:28 +00:00
parser->token.type = ASE_STX_TOKEN_APAREN;
2005-06-23 04:55:44 +00:00
GET_CHAR (parser);
}
2007-03-22 11:19:28 +00:00
else if (c == ASE_T('\'')) {
2005-06-23 04:55:44 +00:00
GET_CHAR (parser);
if (__get_strlit(parser) == -1) return -1;
2007-03-22 11:19:28 +00:00
parser->token.type = ASE_STX_TOKEN_SYMLIT;
2005-06-23 04:55:44 +00:00
}
2007-03-22 11:19:28 +00:00
else if (!__is_closing_char(c) && !ase_isspace(c)) {
2005-06-23 04:55:44 +00:00
do {
ADD_TOKEN_CHAR(parser, c);
GET_CHAR (parser);
c = parser->curc;
2007-03-22 11:19:28 +00:00
} while (!__is_closing_char(c) && !ase_isspace(c));
2005-06-23 04:55:44 +00:00
2007-03-22 11:19:28 +00:00
parser->token.type = ASE_STX_TOKEN_SYMLIT;
2005-06-23 04:55:44 +00:00
}
else {
2007-03-22 11:19:28 +00:00
parser->error_code = ASE_STX_PARSER_ERROR_LITERAL;
2005-06-23 04:55:44 +00:00
return -1;
}
}
2007-03-22 11:19:28 +00:00
else if (c == ASE_T('.')) {
parser->token.type = ASE_STX_TOKEN_PERIOD;
2005-06-07 16:09:58 +00:00
ADD_TOKEN_CHAR(parser, c);
GET_CHAR (parser);
}
2007-03-22 11:19:28 +00:00
else if (c == ASE_T(';')) {
parser->token.type = ASE_STX_TOKEN_SEMICOLON;
2005-06-19 16:16:33 +00:00
ADD_TOKEN_CHAR(parser, c);
GET_CHAR (parser);
}
2005-06-08 15:49:35 +00:00
else if (__is_binary_char(c)) {
if (__get_binary(parser) == -1) return -1;
}
2005-06-05 05:27:02 +00:00
else {
2007-03-22 11:19:28 +00:00
parser->error_code = ASE_STX_PARSER_ERROR_CHAR;
2005-06-05 05:27:02 +00:00
return -1;
}
2007-03-22 11:19:28 +00:00
//ase_printf (ASE_T("TOKEN: %s\n"), parser->token.name.buffer);
2005-06-05 05:27:02 +00:00
return 0;
}
2007-03-22 11:19:28 +00:00
static int __get_ident (ase_stx_parser_t* parser)
2005-06-05 16:44:05 +00:00
{
/*
* identifier ::= letter (letter | digit)*
* keyword ::= identifier ':'
*/
2007-03-22 11:19:28 +00:00
ase_cint_t c = parser->curc;
parser->token.type = ASE_STX_TOKEN_IDENT;
2005-06-05 16:44:05 +00:00
do {
2005-06-06 16:04:18 +00:00
ADD_TOKEN_CHAR(parser, c);
2005-06-05 16:44:05 +00:00
GET_CHAR (parser);
c = parser->curc;
2007-03-22 11:19:28 +00:00
} while (ase_isalnum(c));
2005-06-05 16:44:05 +00:00
2007-03-22 11:19:28 +00:00
if (c == ASE_T(':')) {
2005-06-23 04:55:44 +00:00
ADD_TOKEN_CHAR (parser, c);
2007-03-22 11:19:28 +00:00
parser->token.type = ASE_STX_TOKEN_KEYWORD;
2005-06-05 16:44:05 +00:00
GET_CHAR (parser);
}
return 0;
}
2007-03-22 11:19:28 +00:00
static int __get_numlit (ase_stx_parser_t* parser, ase_bool_t negated)
2005-06-07 16:09:58 +00:00
{
/*
* <number literal> ::= ['-'] <number>
* <number> ::= integer | float | scaledDecimal
* integer ::= decimalInteger | radixInteger
* decimalInteger ::= digits
* digits ::= digit+
* radixInteger ::= radixSpecifier 'r' radixDigits
* radixSpecifier := digits
* radixDigits ::= (digit | uppercaseAlphabetic)+
* float ::= mantissa [exponentLetter exponent]
* mantissa ::= digits'.' digits
* exponent ::= ['-']decimalInteger
* exponentLetter ::= 'e' | 'd' | 'q'
* scaledDecimal ::= scaledMantissa 's' [fractionalDigits]
* scaledMantissa ::= decimalInteger | mantissa
* fractionalDigits ::= decimalInteger
*/
2007-03-22 11:19:28 +00:00
ase_cint_t c = parser->curc;
parser->token.type = ASE_STX_TOKEN_NUMLIT;
2005-06-07 16:09:58 +00:00
do {
ADD_TOKEN_CHAR(parser, c);
GET_CHAR (parser);
c = parser->curc;
2007-03-22 11:19:28 +00:00
} while (ase_isalnum(c));
2005-06-07 16:09:58 +00:00
/* TODO; more */
return 0;
}
2007-03-22 11:19:28 +00:00
static int __get_charlit (ase_stx_parser_t* parser)
2005-06-05 16:44:05 +00:00
{
/*
* character_literal ::= '$' character
* character ::= "Any character in the implementation-defined character set"
*/
2007-03-22 11:19:28 +00:00
ase_cint_t c = parser->curc; /* even a new-line or white space would be taken */
if (c == ASE_T_EOF) {
parser->error_code = ASE_STX_PARSER_ERROR_CHARLIT;
2005-06-05 16:44:05 +00:00
return -1;
}
2007-03-22 11:19:28 +00:00
parser->token.type = ASE_STX_TOKEN_CHARLIT;
2005-06-06 16:04:18 +00:00
ADD_TOKEN_CHAR(parser, c);
2005-06-05 16:44:05 +00:00
GET_CHAR (parser);
return 0;
}
2007-03-22 11:19:28 +00:00
static int __get_strlit (ase_stx_parser_t* parser)
2005-06-05 16:44:05 +00:00
{
/*
* string_literal ::= stringDelimiter stringBody stringDelimiter
* stringBody ::= (nonStringDelimiter | (stringDelimiter stringDelimiter)*)
* stringDelimiter ::= ''' "a single quote"
*/
/* TODO: C-like string */
2007-03-22 11:19:28 +00:00
ase_cint_t c = parser->curc;
parser->token.type = ASE_STX_TOKEN_STRLIT;
2005-06-05 16:44:05 +00:00
do {
do {
2005-06-06 16:04:18 +00:00
ADD_TOKEN_CHAR (parser, c);
2005-06-05 16:44:05 +00:00
GET_CHAR (parser);
c = parser->curc;
2007-03-22 11:19:28 +00:00
if (c == ASE_T_EOF) {
parser->error_code = ASE_STX_PARSER_ERROR_STRLIT;
2005-06-05 16:44:05 +00:00
return -1;
}
2007-03-22 11:19:28 +00:00
} while (c != ASE_T('\''));
2005-06-05 16:44:05 +00:00
GET_CHAR (parser);
c = parser->curc;
2007-03-22 11:19:28 +00:00
} while (c == ASE_T('\''));
2005-06-05 16:44:05 +00:00
return 0;
}
2007-03-22 11:19:28 +00:00
static int __get_binary (ase_stx_parser_t* parser)
2005-06-08 15:49:35 +00:00
{
/*
* binarySelector ::= binaryCharacter+
*/
2007-03-22 11:19:28 +00:00
ase_cint_t c = parser->curc;
2005-06-08 15:49:35 +00:00
ADD_TOKEN_CHAR (parser, c);
2007-03-22 11:19:28 +00:00
if (c == ASE_T('-')) {
2005-06-08 15:49:35 +00:00
GET_CHAR (parser);
c = parser->curc;
2007-03-22 11:19:28 +00:00
if (ase_isdigit(c)) return __get_numlit(parser,ase_true);
2005-06-08 15:49:35 +00:00
}
else {
GET_CHAR (parser);
c = parser->curc;
}
2005-06-11 18:01:25 +00:00
/* up to 2 characters only */
2005-06-08 15:49:35 +00:00
if (__is_binary_char(c)) {
ADD_TOKEN_CHAR (parser, c);
GET_CHAR (parser);
2005-06-11 18:01:25 +00:00
c = parser->curc;
}
/* or up to any occurrences */
/*
while (__is_binary_char(c)) {
ADD_TOKEN_CHAR (parser, c);
GET_CHAR (parser);
c = parser->curc;
2005-06-08 15:49:35 +00:00
}
2005-06-11 18:01:25 +00:00
*/
2005-06-08 15:49:35 +00:00
2007-03-22 11:19:28 +00:00
parser->token.type = ASE_STX_TOKEN_BINARY;
2005-06-08 15:49:35 +00:00
return 0;
}
2007-03-22 11:19:28 +00:00
static int __skip_spaces (ase_stx_parser_t* parser)
2005-05-30 15:27:31 +00:00
{
2007-03-22 11:19:28 +00:00
while (ase_isspace(parser->curc)) GET_CHAR (parser);
2005-06-05 05:27:02 +00:00
return 0;
}
2005-06-04 16:27:30 +00:00
2007-03-22 11:19:28 +00:00
static int __skip_comment (ase_stx_parser_t* parser)
2005-06-05 05:27:02 +00:00
{
2007-03-22 11:19:28 +00:00
while (parser->curc != ASE_T('"')) GET_CHAR (parser);
2005-06-05 05:27:02 +00:00
GET_CHAR (parser);
return 0;
}
2005-05-30 15:27:31 +00:00
2007-03-22 11:19:28 +00:00
static int __get_char (ase_stx_parser_t* parser)
2005-06-05 05:27:02 +00:00
{
2007-03-22 11:19:28 +00:00
ase_cint_t c;
2005-06-05 16:44:05 +00:00
if (parser->ungotc_count > 0) {
parser->curc = parser->ungotc[parser->ungotc_count--];
}
else {
2005-06-06 03:47:56 +00:00
if (parser->input_func (
2007-03-22 11:19:28 +00:00
ASE_STX_PARSER_INPUT_CONSUME,
2005-06-06 03:47:56 +00:00
parser->input_owner, (void*)&c) == -1) {
2007-03-22 11:19:28 +00:00
parser->error_code = ASE_STX_PARSER_ERROR_INPUT;
2005-06-05 16:44:05 +00:00
return -1;
}
parser->curc = c;
2005-06-05 05:27:02 +00:00
}
2005-05-30 15:27:31 +00:00
return 0;
}
2005-06-04 07:01:57 +00:00
2007-03-22 11:19:28 +00:00
static int __unget_char (ase_stx_parser_t* parser, ase_cint_t c)
2005-06-05 05:27:02 +00:00
{
2007-03-22 11:19:28 +00:00
if (parser->ungotc_count >= ase_countof(parser->ungotc)) return -1;
2005-06-05 05:27:02 +00:00
parser->ungotc[parser->ungotc_count++] = c;
return 0;
}
2007-03-22 11:19:28 +00:00
static int __open_input (ase_stx_parser_t* parser, void* input)
2005-06-05 05:27:02 +00:00
{
2005-06-06 03:47:56 +00:00
if (parser->input_func(
2007-03-22 11:19:28 +00:00
ASE_STX_PARSER_INPUT_OPEN,
2005-06-06 03:47:56 +00:00
(void*)&parser->input_owner, input) == -1) {
2007-03-22 11:19:28 +00:00
parser->error_code = ASE_STX_PARSER_ERROR_INPUT;
2005-06-06 03:47:56 +00:00
return -1;
}
2005-06-05 05:27:02 +00:00
2007-03-22 11:19:28 +00:00
parser->error_code = ASE_STX_PARSER_ERROR_NONE;
parser->curc = ASE_T_EOF;
2005-06-05 05:27:02 +00:00
parser->ungotc_count = 0;
return 0;
}
2007-03-22 11:19:28 +00:00
static int __close_input (ase_stx_parser_t* parser)
2005-06-06 03:47:56 +00:00
{
if (parser->input_func(
2007-03-22 11:19:28 +00:00
ASE_STX_PARSER_INPUT_CLOSE,
parser->input_owner, ASE_NULL) == -1) {
parser->error_code = ASE_STX_PARSER_ERROR_INPUT;
2005-06-06 03:47:56 +00:00
return -1;
}
return 0;
}
2005-07-08 11:32:50 +00:00