2016-06-14 06:09:13 -07:00
|
|
|
#include <assert.h>
|
2019-05-26 09:09:34 -07:00
|
|
|
#include <limits.h>
|
2016-06-14 06:09:13 -07:00
|
|
|
|
2014-09-23 12:48:16 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
#include "eo_parser.h"
|
2017-10-30 22:20:09 -07:00
|
|
|
#include "eolian_priv.h"
|
2014-06-18 03:25:07 -07:00
|
|
|
|
2014-06-20 07:07:25 -07:00
|
|
|
#define CASE_LOCK(ls, var, msg) \
|
|
|
|
if (has_##var) \
|
2014-07-01 10:25:17 -07:00
|
|
|
eo_lexer_syntax_error(ls, "double " msg); \
|
2014-06-20 07:07:25 -07:00
|
|
|
has_##var = EINA_TRUE;
|
|
|
|
|
2018-03-08 08:30:30 -08:00
|
|
|
#define FILL_BASE(exp, ls, l, c, tp) \
|
2018-03-16 08:16:16 -07:00
|
|
|
(exp).unit = ls->unit; \
|
2015-02-18 07:41:50 -08:00
|
|
|
(exp).file = eina_stringshare_ref(ls->filename); \
|
|
|
|
(exp).line = l; \
|
2018-03-08 08:30:30 -08:00
|
|
|
(exp).column = c; \
|
|
|
|
(exp).type = EOLIAN_OBJECT_##tp
|
2015-02-18 07:41:50 -08:00
|
|
|
|
2015-06-03 07:35:13 -07:00
|
|
|
#define FILL_DOC(ls, def, docf) \
|
|
|
|
if (ls->t.token == TOK_DOC) \
|
|
|
|
{ \
|
|
|
|
def->docf = ls->t.value.doc; \
|
|
|
|
ls->t.value.doc = NULL; \
|
|
|
|
eo_lexer_get(ls); \
|
|
|
|
}
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
static void
|
|
|
|
error_expected(Eo_Lexer *ls, int token)
|
|
|
|
{
|
2018-11-06 08:07:28 -08:00
|
|
|
char buf[256 + 128];
|
2014-06-18 03:25:07 -07:00
|
|
|
char tbuf[256];
|
|
|
|
eo_lexer_token_to_str(token, tbuf);
|
|
|
|
snprintf(buf, sizeof(buf), "'%s' expected", tbuf);
|
|
|
|
eo_lexer_syntax_error(ls, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
test_next(Eo_Lexer *ls, int token)
|
|
|
|
{
|
|
|
|
if (ls->t.token == token)
|
|
|
|
{
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
check(Eo_Lexer *ls, int token)
|
|
|
|
{
|
|
|
|
if (ls->t.token != token)
|
2014-07-01 10:25:17 -07:00
|
|
|
error_expected(ls, token);
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
check_kw(Eo_Lexer *ls, int kw)
|
|
|
|
{
|
|
|
|
if (ls->t.kw != kw)
|
2014-07-01 10:25:17 -07:00
|
|
|
error_expected(ls, TOK_VALUE + kw);
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
check_next(Eo_Lexer *ls, int token)
|
|
|
|
{
|
|
|
|
check(ls, token);
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
check_kw_next(Eo_Lexer *ls, int kw)
|
|
|
|
{
|
|
|
|
check_kw(ls, kw);
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-07-02 16:00:02 -07:00
|
|
|
check_match(Eo_Lexer *ls, int what, int who, int where, int col)
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
|
|
|
if (!test_next(ls, what))
|
|
|
|
{
|
|
|
|
if (where == ls->line_number)
|
2014-07-01 10:25:17 -07:00
|
|
|
error_expected(ls, what);
|
2014-06-18 03:25:07 -07:00
|
|
|
else
|
|
|
|
{
|
2018-11-07 01:44:42 -08:00
|
|
|
char buf[256 + 256 + 128];
|
2014-06-18 03:25:07 -07:00
|
|
|
char tbuf[256];
|
|
|
|
char vbuf[256];
|
|
|
|
eo_lexer_token_to_str(what, tbuf);
|
|
|
|
eo_lexer_token_to_str(who , vbuf);
|
|
|
|
snprintf(buf, sizeof(buf),
|
2014-07-22 07:01:09 -07:00
|
|
|
"'%s' expected (to close '%s' at line %d, column %d)",
|
2014-07-02 16:00:02 -07:00
|
|
|
tbuf, vbuf, where, col);
|
2014-06-18 03:25:07 -07:00
|
|
|
eo_lexer_syntax_error(ls, buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-16 06:31:37 -07:00
|
|
|
static Eina_Stringshare *
|
|
|
|
make_c_name(const char *fulln)
|
|
|
|
{
|
|
|
|
char *mbuf = strdup(fulln);
|
|
|
|
for (char *p = mbuf; (p = strchr(p, '.')); ++p)
|
|
|
|
*p = '_';
|
|
|
|
Eina_Stringshare *ret = eina_stringshare_add(mbuf);
|
|
|
|
free(mbuf);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-08-01 05:59:46 -07:00
|
|
|
static Eina_Bool
|
2015-02-11 06:58:53 -08:00
|
|
|
compare_class_file(const char *fn1, const char *fn2)
|
2014-08-01 05:59:46 -07:00
|
|
|
{
|
2015-02-11 06:58:53 -08:00
|
|
|
return !strcmp(fn1, fn2);
|
2014-08-01 05:59:46 -07:00
|
|
|
}
|
|
|
|
|
2018-03-08 14:59:40 -08:00
|
|
|
|
|
|
|
static Eolian_Object *
|
|
|
|
_eolian_decl_get(Eo_Lexer *ls, const char *name)
|
|
|
|
{
|
2018-03-22 09:05:26 -07:00
|
|
|
Eolian_Object *obj = eina_hash_find(ls->state->main.unit.objects, name);
|
2018-03-22 07:34:32 -07:00
|
|
|
if (!obj)
|
2018-03-22 09:05:26 -07:00
|
|
|
obj = eina_hash_find(ls->state->staging.unit.objects, name);
|
2018-03-08 14:59:40 -08:00
|
|
|
if (obj && ((obj->type == EOLIAN_OBJECT_CLASS) ||
|
|
|
|
(obj->type == EOLIAN_OBJECT_TYPEDECL) ||
|
|
|
|
(obj->type == EOLIAN_OBJECT_VARIABLE)))
|
|
|
|
return obj;
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
_eolian_decl_name_get(Eolian_Object *obj)
|
|
|
|
{
|
|
|
|
switch (obj->type)
|
|
|
|
{
|
|
|
|
case EOLIAN_OBJECT_CLASS:
|
|
|
|
return "class";
|
|
|
|
case EOLIAN_OBJECT_TYPEDECL:
|
|
|
|
switch (((Eolian_Typedecl *)obj)->type)
|
|
|
|
{
|
|
|
|
case EOLIAN_TYPEDECL_ALIAS:
|
|
|
|
return "type alias";
|
|
|
|
case EOLIAN_TYPEDECL_STRUCT:
|
|
|
|
case EOLIAN_TYPEDECL_STRUCT_OPAQUE:
|
|
|
|
return "struct";
|
|
|
|
case EOLIAN_TYPEDECL_ENUM:
|
|
|
|
return "enum";
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2018-11-06 08:02:48 -08:00
|
|
|
goto end;
|
2018-03-08 14:59:40 -08:00
|
|
|
case EOLIAN_OBJECT_VARIABLE:
|
|
|
|
return "variable";
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2018-11-06 08:02:48 -08:00
|
|
|
end:
|
2018-03-08 14:59:40 -08:00
|
|
|
return "unknown";
|
|
|
|
}
|
2015-05-15 07:10:58 -07:00
|
|
|
|
2014-07-22 07:01:09 -07:00
|
|
|
static void
|
2018-03-08 14:59:40 -08:00
|
|
|
redef_error(Eo_Lexer *ls, Eolian_Object *obj, Eolian_Object *nobj)
|
2014-07-22 07:01:09 -07:00
|
|
|
{
|
2018-11-07 01:44:42 -08:00
|
|
|
char buf[256 + 128], fbuf[256] = { '\0' };
|
2015-05-15 07:10:58 -07:00
|
|
|
if (ls->filename != obj->file)
|
|
|
|
snprintf(fbuf, sizeof(fbuf), "%s:%d:%d", obj->file, obj->line, obj->column);
|
|
|
|
else
|
|
|
|
snprintf(fbuf, sizeof(fbuf), "%d:%d", obj->line, obj->column);
|
|
|
|
|
2018-03-08 14:59:40 -08:00
|
|
|
if (nobj->type != obj->type)
|
2015-05-15 07:10:58 -07:00
|
|
|
snprintf(buf, sizeof(buf), "%s '%s' redefined as %s (originally at %s)",
|
2018-03-08 14:59:40 -08:00
|
|
|
_eolian_decl_name_get(obj), obj->name,
|
|
|
|
_eolian_decl_name_get(nobj), fbuf);
|
2015-05-15 07:10:58 -07:00
|
|
|
else
|
|
|
|
snprintf(buf, sizeof(buf), "%s '%s' redefined (originally at %s)",
|
2018-03-08 14:59:40 -08:00
|
|
|
_eolian_decl_name_get(obj), obj->name, fbuf);
|
2015-05-15 07:10:58 -07:00
|
|
|
|
2014-07-22 07:01:09 -07:00
|
|
|
eo_lexer_syntax_error(ls, buf);
|
|
|
|
}
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
static Eina_Strbuf *
|
|
|
|
parse_name(Eo_Lexer *ls, Eina_Strbuf *buf)
|
|
|
|
{
|
|
|
|
check(ls, TOK_VALUE);
|
2016-06-30 06:04:03 -07:00
|
|
|
if (eo_lexer_is_type_keyword(ls->t.kw))
|
2014-07-21 07:11:19 -07:00
|
|
|
eo_lexer_syntax_error(ls, "invalid name");
|
2014-06-18 03:25:07 -07:00
|
|
|
eina_strbuf_reset(buf);
|
|
|
|
for (;;)
|
|
|
|
{
|
2014-07-17 09:16:31 -07:00
|
|
|
eina_strbuf_append(buf, ls->t.value.s);
|
2014-06-18 03:25:07 -07:00
|
|
|
eo_lexer_get(ls);
|
2014-06-20 02:45:55 -07:00
|
|
|
if (ls->t.token != '.') break;
|
2014-06-18 03:25:07 -07:00
|
|
|
eo_lexer_get(ls);
|
2014-06-20 02:45:55 -07:00
|
|
|
eina_strbuf_append(buf, ".");
|
2014-06-18 03:25:07 -07:00
|
|
|
check(ls, TOK_VALUE);
|
2016-06-30 06:04:03 -07:00
|
|
|
if (eo_lexer_is_type_keyword(ls->t.kw))
|
2014-07-21 07:11:19 -07:00
|
|
|
eo_lexer_syntax_error(ls, "invalid name");
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2019-05-30 07:20:09 -07:00
|
|
|
static Eina_Stringshare *
|
|
|
|
parse_c_name(Eo_Lexer *ls)
|
|
|
|
{
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
int pline = ls->line_number, pcol = ls->column;
|
|
|
|
check_next(ls, '(');
|
|
|
|
check(ls, TOK_VALUE);
|
|
|
|
if (eo_lexer_is_type_keyword(ls->t.kw))
|
|
|
|
eo_lexer_syntax_error(ls, "invalid name");
|
|
|
|
Eina_Stringshare *cname = eina_stringshare_add(ls->t.value.s);
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
if (ls->t.token != ')')
|
|
|
|
{
|
|
|
|
eina_stringshare_del(cname);
|
|
|
|
check_match(ls, ')', '(', pline, pcol);
|
2019-08-05 06:41:28 -07:00
|
|
|
return NULL; /* unreachable */
|
2019-05-30 07:20:09 -07:00
|
|
|
}
|
|
|
|
return cname;
|
|
|
|
}
|
|
|
|
|
2014-07-17 09:16:31 -07:00
|
|
|
static Eolian_Binary_Operator
|
|
|
|
get_binop_id(int tok)
|
|
|
|
{
|
|
|
|
switch (tok)
|
|
|
|
{
|
2014-07-18 02:47:07 -07:00
|
|
|
case '+': return EOLIAN_BINOP_ADD;
|
|
|
|
case '-': return EOLIAN_BINOP_SUB;
|
|
|
|
case '*': return EOLIAN_BINOP_MUL;
|
|
|
|
case '/': return EOLIAN_BINOP_DIV;
|
|
|
|
case '%': return EOLIAN_BINOP_MOD;
|
2014-07-17 09:16:31 -07:00
|
|
|
|
2014-07-18 02:47:07 -07:00
|
|
|
case TOK_EQ: return EOLIAN_BINOP_EQ;
|
|
|
|
case TOK_NQ: return EOLIAN_BINOP_NQ;
|
2014-07-18 03:48:40 -07:00
|
|
|
case '>' : return EOLIAN_BINOP_GT;
|
|
|
|
case '<' : return EOLIAN_BINOP_LT;
|
2014-07-18 02:47:07 -07:00
|
|
|
case TOK_GE: return EOLIAN_BINOP_GE;
|
|
|
|
case TOK_LE: return EOLIAN_BINOP_LE;
|
2014-07-17 09:16:31 -07:00
|
|
|
|
2014-07-18 02:47:07 -07:00
|
|
|
case TOK_AND: return EOLIAN_BINOP_AND;
|
|
|
|
case TOK_OR : return EOLIAN_BINOP_OR;
|
2014-07-17 09:16:31 -07:00
|
|
|
|
2014-07-18 02:47:07 -07:00
|
|
|
case '&': return EOLIAN_BINOP_BAND;
|
|
|
|
case '|': return EOLIAN_BINOP_BOR;
|
|
|
|
case '^': return EOLIAN_BINOP_BXOR;
|
2014-07-17 09:16:31 -07:00
|
|
|
|
2014-07-18 02:47:07 -07:00
|
|
|
case TOK_LSH: return EOLIAN_BINOP_LSH;
|
|
|
|
case TOK_RSH: return EOLIAN_BINOP_RSH;
|
2014-07-17 09:16:31 -07:00
|
|
|
|
2017-01-13 06:15:10 -08:00
|
|
|
default: return EOLIAN_BINOP_INVALID;
|
2014-07-17 09:16:31 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eolian_Unary_Operator
|
|
|
|
get_unop_id(int tok)
|
|
|
|
{
|
|
|
|
switch (tok)
|
|
|
|
{
|
2014-07-18 02:47:07 -07:00
|
|
|
case '-': return EOLIAN_UNOP_UNM;
|
|
|
|
case '+': return EOLIAN_UNOP_UNP;
|
|
|
|
case '!': return EOLIAN_UNOP_NOT;
|
|
|
|
case '~': return EOLIAN_UNOP_BNOT;
|
2014-07-17 09:16:31 -07:00
|
|
|
|
2017-01-13 06:15:10 -08:00
|
|
|
default: return EOLIAN_UNOP_INVALID;
|
2014-07-17 09:16:31 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static const int binprec[] = {
|
2017-01-13 06:15:10 -08:00
|
|
|
-1, /* invalid */
|
|
|
|
|
2014-07-17 09:16:31 -07:00
|
|
|
8, /* + */
|
|
|
|
8, /* - */
|
|
|
|
9, /* * */
|
|
|
|
9, /* / */
|
|
|
|
9, /* % */
|
|
|
|
|
|
|
|
3, /* == */
|
|
|
|
3, /* != */
|
|
|
|
3, /* > */
|
|
|
|
3, /* < */
|
|
|
|
3, /* >= */
|
|
|
|
3, /* <= */
|
|
|
|
|
|
|
|
2, /* && */
|
|
|
|
1, /* || */
|
|
|
|
|
|
|
|
6, /* & */
|
|
|
|
4, /* | */
|
|
|
|
5, /* ^ */
|
|
|
|
7, /* << */
|
|
|
|
7 /* >> */
|
|
|
|
};
|
|
|
|
|
|
|
|
#define UNARY_PRECEDENCE 10
|
|
|
|
|
|
|
|
static Eolian_Expression *parse_expr_bin(Eo_Lexer *ls, int min_prec);
|
|
|
|
static Eolian_Expression *parse_expr(Eo_Lexer *ls);
|
|
|
|
|
|
|
|
static Eolian_Expression *
|
|
|
|
parse_expr_simple(Eo_Lexer *ls)
|
|
|
|
{
|
|
|
|
Eolian_Expression *expr;
|
|
|
|
Eolian_Unary_Operator unop = get_unop_id(ls->t.token);
|
2017-01-13 06:15:10 -08:00
|
|
|
if (unop != EOLIAN_UNOP_INVALID)
|
2014-07-17 09:16:31 -07:00
|
|
|
{
|
2014-08-06 08:30:42 -07:00
|
|
|
int line = ls->line_number, col = ls->column;
|
2015-01-29 03:12:04 -08:00
|
|
|
eo_lexer_get(ls);
|
2014-07-17 09:16:31 -07:00
|
|
|
Eolian_Expression *exp = parse_expr_bin(ls, UNARY_PRECEDENCE);
|
2018-03-15 08:08:59 -07:00
|
|
|
expr = eo_lexer_expr_new(ls);
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(expr->base, ls, line, col, EXPRESSION);
|
2014-08-22 00:20:53 -07:00
|
|
|
expr->unop = unop;
|
2014-07-17 09:16:31 -07:00
|
|
|
expr->type = EOLIAN_EXPR_UNARY;
|
|
|
|
expr->expr = exp;
|
2018-03-15 08:08:59 -07:00
|
|
|
eo_lexer_expr_release_ref(ls, exp);
|
2014-07-17 09:16:31 -07:00
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
switch (ls->t.token)
|
|
|
|
{
|
|
|
|
case TOK_NUMBER:
|
|
|
|
{
|
2014-08-06 08:30:42 -07:00
|
|
|
int line = ls->line_number, col = ls->column;
|
2018-03-15 08:08:59 -07:00
|
|
|
expr = eo_lexer_expr_new(ls);
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(expr->base, ls, line, col, EXPRESSION);
|
2014-07-17 09:16:31 -07:00
|
|
|
expr->type = ls->t.kw + 1; /* map Numbers from lexer to expr type */
|
2015-06-02 10:12:09 -07:00
|
|
|
memcpy(&expr->value, &ls->t.value, sizeof(expr->value));
|
2014-07-17 09:16:31 -07:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case TOK_STRING:
|
|
|
|
{
|
2014-08-06 08:30:42 -07:00
|
|
|
int line = ls->line_number, col = ls->column;
|
2018-03-15 08:08:59 -07:00
|
|
|
expr = eo_lexer_expr_new(ls);
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(expr->base, ls, line, col, EXPRESSION);
|
2014-07-17 09:16:31 -07:00
|
|
|
expr->type = EOLIAN_EXPR_STRING;
|
|
|
|
expr->value.s = eina_stringshare_ref(ls->t.value.s);
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
|
|
|
}
|
2014-08-07 07:15:07 -07:00
|
|
|
case TOK_CHAR:
|
|
|
|
{
|
|
|
|
int line = ls->line_number, col = ls->column;
|
2018-03-15 08:08:59 -07:00
|
|
|
expr = eo_lexer_expr_new(ls);
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(expr->base, ls, line, col, EXPRESSION);
|
2014-08-07 07:15:07 -07:00
|
|
|
expr->type = EOLIAN_EXPR_CHAR;
|
|
|
|
expr->value.c = ls->t.value.c;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
|
|
|
}
|
2014-07-17 09:16:31 -07:00
|
|
|
case TOK_VALUE:
|
|
|
|
{
|
2014-08-06 08:30:42 -07:00
|
|
|
int line = ls->line_number, col = ls->column;
|
2014-07-17 09:16:31 -07:00
|
|
|
switch (ls->t.kw)
|
|
|
|
{
|
|
|
|
case KW_true:
|
|
|
|
case KW_false:
|
|
|
|
{
|
2018-03-15 08:08:59 -07:00
|
|
|
expr = eo_lexer_expr_new(ls);
|
2014-07-17 09:16:31 -07:00
|
|
|
expr->type = EOLIAN_EXPR_BOOL;
|
|
|
|
expr->value.b = (ls->t.kw == KW_true);
|
2014-08-07 07:15:07 -07:00
|
|
|
eo_lexer_get(ls);
|
2014-07-17 09:16:31 -07:00
|
|
|
break;
|
2014-08-07 07:15:07 -07:00
|
|
|
}
|
|
|
|
case KW_null:
|
|
|
|
{
|
2018-03-15 08:08:59 -07:00
|
|
|
expr = eo_lexer_expr_new(ls);
|
2014-08-07 07:15:07 -07:00
|
|
|
expr->type = EOLIAN_EXPR_NULL;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
|
|
|
}
|
2014-07-17 09:16:31 -07:00
|
|
|
default:
|
|
|
|
{
|
2018-03-15 06:12:18 -07:00
|
|
|
Eina_Strbuf *buf = eina_strbuf_new();
|
|
|
|
eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_strbuf_free), buf);
|
2018-03-15 08:08:59 -07:00
|
|
|
expr = eo_lexer_expr_new(ls);
|
2015-05-12 08:15:29 -07:00
|
|
|
expr->type = EOLIAN_EXPR_NAME;
|
2014-08-12 05:11:13 -07:00
|
|
|
parse_name(ls, buf);
|
|
|
|
expr->value.s = eina_stringshare_add(eina_strbuf_string_get
|
|
|
|
(buf));
|
2018-03-15 06:12:18 -07:00
|
|
|
eo_lexer_dtor_pop(ls);
|
2014-07-17 09:16:31 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(expr->base, ls, line, col, EXPRESSION);
|
2014-08-07 07:15:07 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case '(':
|
|
|
|
{
|
|
|
|
int line = ls->line_number, col = ls->column;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
expr = parse_expr(ls);
|
|
|
|
check_match(ls, ')', '(', line, col);
|
2014-08-26 19:32:17 -07:00
|
|
|
break;
|
2014-07-17 09:16:31 -07:00
|
|
|
}
|
2014-08-07 07:15:07 -07:00
|
|
|
default:
|
|
|
|
expr = NULL; /* shut up compiler */
|
|
|
|
eo_lexer_syntax_error(ls, "unexpected symbol");
|
|
|
|
break;
|
2014-07-17 09:16:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eolian_Expression *
|
|
|
|
parse_expr_bin(Eo_Lexer *ls, int min_prec)
|
|
|
|
{
|
2014-08-06 08:30:42 -07:00
|
|
|
int line = ls->line_number, col = ls->column;
|
2014-07-17 09:16:31 -07:00
|
|
|
Eolian_Expression *lhs = parse_expr_simple(ls);
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
Eolian_Expression *rhs, *bin;
|
|
|
|
Eolian_Binary_Operator op = get_binop_id(ls->t.token);
|
2017-01-13 06:15:10 -08:00
|
|
|
int prec = binprec[op];
|
|
|
|
if ((op == EOLIAN_BINOP_INVALID) || (prec < 0) || (prec < min_prec))
|
2014-07-17 09:16:31 -07:00
|
|
|
break;
|
2014-08-12 08:29:02 -07:00
|
|
|
eo_lexer_get(ls);
|
2014-07-17 09:16:31 -07:00
|
|
|
rhs = parse_expr_bin(ls, prec + 1);
|
2018-03-15 08:08:59 -07:00
|
|
|
bin = eo_lexer_expr_new(ls);
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(bin->base, ls, line, col, EXPRESSION);
|
2014-07-17 09:16:31 -07:00
|
|
|
bin->binop = op;
|
|
|
|
bin->type = EOLIAN_EXPR_BINARY;
|
|
|
|
bin->lhs = lhs;
|
2018-03-15 08:08:59 -07:00
|
|
|
eo_lexer_expr_release_ref(ls, lhs);
|
2014-07-17 09:16:31 -07:00
|
|
|
bin->rhs = rhs;
|
2018-03-15 08:08:59 -07:00
|
|
|
eo_lexer_expr_release_ref(ls, rhs);
|
2014-07-17 09:16:31 -07:00
|
|
|
lhs = bin;
|
|
|
|
}
|
|
|
|
return lhs;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eolian_Expression *
|
|
|
|
parse_expr(Eo_Lexer *ls)
|
|
|
|
{
|
|
|
|
return parse_expr_bin(ls, 1);
|
|
|
|
}
|
|
|
|
|
2019-02-16 17:11:02 -08:00
|
|
|
static Eolian_Type *parse_type_void(Eo_Lexer *ls, Eina_Bool allow_ptr);
|
2014-06-30 15:07:32 -07:00
|
|
|
|
2014-07-10 06:44:17 -07:00
|
|
|
static Eolian_Type *
|
2019-02-16 17:11:02 -08:00
|
|
|
parse_type(Eo_Lexer *ls, Eina_Bool allow_ptr)
|
2014-06-30 15:07:32 -07:00
|
|
|
{
|
2014-07-22 07:27:11 -07:00
|
|
|
Eolian_Type *ret;
|
|
|
|
eo_lexer_context_push(ls);
|
2019-02-16 17:11:02 -08:00
|
|
|
ret = parse_type_void(ls, allow_ptr);
|
2014-06-30 15:07:32 -07:00
|
|
|
if (ret->type == EOLIAN_TYPE_VOID)
|
|
|
|
{
|
2014-07-22 07:27:11 -07:00
|
|
|
eo_lexer_context_restore(ls);
|
2014-06-30 15:07:32 -07:00
|
|
|
eo_lexer_syntax_error(ls, "non-void type expected");
|
|
|
|
}
|
2014-07-22 07:27:11 -07:00
|
|
|
eo_lexer_context_pop(ls);
|
2014-06-30 15:07:32 -07:00
|
|
|
return ret;
|
|
|
|
}
|
2014-06-30 13:52:57 -07:00
|
|
|
|
2014-07-10 06:44:17 -07:00
|
|
|
static void
|
2014-08-22 08:56:41 -07:00
|
|
|
_struct_field_free(Eolian_Struct_Type_Field *def)
|
2014-07-10 06:44:17 -07:00
|
|
|
{
|
2018-03-08 10:30:40 -08:00
|
|
|
eina_stringshare_del(def->base.file);
|
|
|
|
eina_stringshare_del(def->base.name);
|
2014-07-10 06:44:17 -07:00
|
|
|
database_type_del(def->type);
|
2015-06-03 07:35:13 -07:00
|
|
|
database_doc_del(def->doc);
|
2014-07-22 02:22:21 -07:00
|
|
|
free(def);
|
2014-07-10 06:44:17 -07:00
|
|
|
}
|
|
|
|
|
2016-03-01 07:37:57 -08:00
|
|
|
static Eolian_Typedecl *
|
2014-07-22 06:48:08 -07:00
|
|
|
parse_struct(Eo_Lexer *ls, const char *name, Eina_Bool is_extern,
|
2019-05-30 07:20:09 -07:00
|
|
|
Eina_Bool is_beta, int line, int column, const char *freefunc,
|
|
|
|
const char *cname)
|
2014-07-08 07:02:36 -07:00
|
|
|
{
|
2014-07-22 06:48:08 -07:00
|
|
|
int bline = ls->line_number, bcolumn = ls->column;
|
2018-03-15 07:50:53 -07:00
|
|
|
Eolian_Typedecl *def = eo_lexer_typedecl_new(ls);
|
2014-07-15 07:33:22 -07:00
|
|
|
def->is_extern = is_extern;
|
2019-03-08 05:17:01 -08:00
|
|
|
def->base.is_beta = is_beta;
|
2018-03-11 07:55:10 -07:00
|
|
|
def->base.name = name;
|
2019-02-28 11:25:51 -08:00
|
|
|
def->type = EOLIAN_TYPEDECL_STRUCT;
|
2014-07-10 06:44:17 -07:00
|
|
|
def->fields = eina_hash_string_small_new(EINA_FREE_CB(_struct_field_free));
|
2018-03-15 08:34:08 -07:00
|
|
|
if (freefunc)
|
2019-07-03 06:03:59 -07:00
|
|
|
{
|
|
|
|
def->freefunc = eina_stringshare_ref(freefunc);
|
|
|
|
def->ownable = EINA_TRUE;
|
|
|
|
}
|
2019-05-30 07:20:09 -07:00
|
|
|
if (cname)
|
2018-03-15 08:34:08 -07:00
|
|
|
{
|
2019-05-30 07:20:09 -07:00
|
|
|
def->base.c_name = cname;
|
2018-03-15 08:34:08 -07:00
|
|
|
eo_lexer_dtor_pop(ls);
|
|
|
|
}
|
2019-05-30 07:20:09 -07:00
|
|
|
else
|
|
|
|
def->base.c_name = make_c_name(name);
|
|
|
|
/* we can't know the order, pop when both are filled */
|
|
|
|
if (freefunc && cname)
|
|
|
|
{
|
|
|
|
eo_lexer_dtor_pop(ls);
|
|
|
|
eo_lexer_dtor_pop(ls);
|
|
|
|
}
|
|
|
|
else if (freefunc || cname)
|
|
|
|
eo_lexer_dtor_pop(ls);
|
2014-07-08 07:44:42 -07:00
|
|
|
check_next(ls, '{');
|
2015-06-03 07:35:13 -07:00
|
|
|
FILL_DOC(ls, def, doc);
|
2014-07-08 07:44:42 -07:00
|
|
|
while (ls->t.token != '}')
|
|
|
|
{
|
2014-07-08 08:42:33 -07:00
|
|
|
const char *fname;
|
2014-08-22 08:56:41 -07:00
|
|
|
Eolian_Struct_Type_Field *fdef;
|
2014-07-10 06:44:17 -07:00
|
|
|
Eolian_Type *tp;
|
2014-08-04 07:01:16 -07:00
|
|
|
int fline = ls->line_number, fcol = ls->column;
|
2014-07-08 07:44:42 -07:00
|
|
|
check(ls, TOK_VALUE);
|
2014-07-17 09:16:31 -07:00
|
|
|
if (eina_hash_find(def->fields, ls->t.value.s))
|
2014-07-08 08:17:44 -07:00
|
|
|
eo_lexer_syntax_error(ls, "double field definition");
|
2014-08-22 08:56:41 -07:00
|
|
|
fdef = calloc(1, sizeof(Eolian_Struct_Type_Field));
|
2014-07-17 09:16:31 -07:00
|
|
|
fname = eina_stringshare_ref(ls->t.value.s);
|
2014-08-15 03:07:06 -07:00
|
|
|
eina_hash_add(def->fields, fname, fdef);
|
2014-08-22 08:56:41 -07:00
|
|
|
def->field_list = eina_list_append(def->field_list, fdef);
|
2017-12-04 05:44:29 -08:00
|
|
|
eolian_object_ref(&fdef->base);
|
2014-07-08 07:44:42 -07:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
check_next(ls, ':');
|
2019-02-16 17:11:02 -08:00
|
|
|
tp = parse_type(ls, EINA_TRUE);
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(fdef->base, ls, fline, fcol, STRUCT_FIELD);
|
2018-03-15 07:31:08 -07:00
|
|
|
fdef->type = eo_lexer_type_release(ls, tp);
|
2018-03-08 10:30:40 -08:00
|
|
|
fdef->base.name = eina_stringshare_ref(fname);
|
2019-08-30 07:08:31 -07:00
|
|
|
Eina_Bool has_owned = EINA_FALSE, has_by_ref = EINA_FALSE;
|
|
|
|
for (;;) switch (ls->t.kw)
|
|
|
|
{
|
|
|
|
case KW_at_by_ref:
|
|
|
|
CASE_LOCK(ls, by_ref, "by_ref qualifier");
|
|
|
|
fdef->by_ref = EINA_TRUE;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
|
|
|
case KW_at_owned:
|
|
|
|
case KW_at_move:
|
|
|
|
CASE_LOCK(ls, owned, "owned qualifier");
|
|
|
|
fdef->type->owned = fdef->move = EINA_TRUE;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
goto qual_end;
|
|
|
|
}
|
|
|
|
qual_end:
|
2014-07-08 07:44:42 -07:00
|
|
|
check_next(ls, ';');
|
2015-06-03 07:35:13 -07:00
|
|
|
FILL_DOC(ls, fdef, doc);
|
2014-07-08 07:44:42 -07:00
|
|
|
}
|
2014-07-22 06:48:08 -07:00
|
|
|
check_match(ls, '}', '{', bline, bcolumn);
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(def->base, ls, line, column, TYPEDECL);
|
2019-02-28 11:25:51 -08:00
|
|
|
database_struct_add(ls->unit, eo_lexer_typedecl_release(ls, def));
|
2014-07-08 07:44:42 -07:00
|
|
|
return def;
|
2014-07-08 07:02:36 -07:00
|
|
|
}
|
|
|
|
|
2014-08-11 06:56:50 -07:00
|
|
|
static void
|
2014-08-22 08:56:41 -07:00
|
|
|
_enum_field_free(Eolian_Enum_Type_Field *def)
|
2014-08-11 06:56:50 -07:00
|
|
|
{
|
2018-03-08 10:30:40 -08:00
|
|
|
eina_stringshare_del(def->base.file);
|
|
|
|
eina_stringshare_del(def->base.name);
|
2014-08-11 06:56:50 -07:00
|
|
|
database_expr_del(def->value);
|
2015-06-03 07:35:13 -07:00
|
|
|
database_doc_del(def->doc);
|
2014-08-11 06:56:50 -07:00
|
|
|
free(def);
|
|
|
|
}
|
|
|
|
|
2016-03-01 07:37:57 -08:00
|
|
|
static Eolian_Typedecl *
|
2014-08-11 06:56:50 -07:00
|
|
|
parse_enum(Eo_Lexer *ls, const char *name, Eina_Bool is_extern,
|
2019-05-30 07:20:09 -07:00
|
|
|
Eina_Bool is_beta, int line, int column, const char *cname)
|
2014-08-11 06:56:50 -07:00
|
|
|
{
|
|
|
|
int bline = ls->line_number, bcolumn = ls->column;
|
2018-03-15 07:50:53 -07:00
|
|
|
Eolian_Typedecl *def = eo_lexer_typedecl_new(ls);
|
2014-08-11 06:56:50 -07:00
|
|
|
def->is_extern = is_extern;
|
2019-03-08 05:17:01 -08:00
|
|
|
def->base.is_beta = is_beta;
|
2018-03-11 07:55:10 -07:00
|
|
|
def->base.name = name;
|
2019-05-30 07:20:09 -07:00
|
|
|
if (cname)
|
|
|
|
{
|
|
|
|
def->base.c_name = cname;
|
|
|
|
eo_lexer_dtor_pop(ls);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
def->base.c_name = make_c_name(name);
|
2016-03-01 07:37:57 -08:00
|
|
|
def->type = EOLIAN_TYPEDECL_ENUM;
|
2014-08-11 06:56:50 -07:00
|
|
|
def->fields = eina_hash_string_small_new(EINA_FREE_CB(_enum_field_free));
|
|
|
|
check_next(ls, '{');
|
2015-06-03 07:35:13 -07:00
|
|
|
FILL_DOC(ls, def, doc);
|
2014-08-11 06:56:50 -07:00
|
|
|
if (ls->t.token == TOK_VALUE && ls->t.kw == KW_legacy)
|
|
|
|
{
|
|
|
|
if (eo_lexer_lookahead(ls) == ':')
|
|
|
|
{
|
|
|
|
/* consume keyword */
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
/* consume colon */
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
check(ls, TOK_VALUE);
|
|
|
|
def->legacy = eina_stringshare_ref(ls->t.value.s);
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
check_next(ls, ';');
|
|
|
|
}
|
|
|
|
}
|
2015-05-13 10:10:02 -07:00
|
|
|
Eolian_Enum_Type_Field *prev_fl = NULL;
|
|
|
|
int fl_nadd = 0;
|
2014-08-11 06:56:50 -07:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
const char *fname;
|
2014-08-22 08:56:41 -07:00
|
|
|
Eolian_Enum_Type_Field *fdef;
|
2014-08-11 06:56:50 -07:00
|
|
|
int fline = ls->line_number, fcol = ls->column;
|
|
|
|
check(ls, TOK_VALUE);
|
|
|
|
if (eina_hash_find(def->fields, ls->t.value.s))
|
|
|
|
eo_lexer_syntax_error(ls, "double field definition");
|
2014-08-22 08:56:41 -07:00
|
|
|
fdef = calloc(1, sizeof(Eolian_Enum_Type_Field));
|
2014-08-11 06:56:50 -07:00
|
|
|
fname = eina_stringshare_ref(ls->t.value.s);
|
2014-08-15 03:07:06 -07:00
|
|
|
eina_hash_add(def->fields, fname, fdef);
|
2014-08-22 08:56:41 -07:00
|
|
|
def->field_list = eina_list_append(def->field_list, fdef);
|
2017-12-04 05:44:29 -08:00
|
|
|
eolian_object_ref(&fdef->base);
|
2014-08-11 06:56:50 -07:00
|
|
|
eo_lexer_get(ls);
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(fdef->base, ls, fline, fcol, ENUM_FIELD);
|
2015-05-12 09:04:54 -07:00
|
|
|
fdef->base_enum = def;
|
2018-03-08 10:30:40 -08:00
|
|
|
fdef->base.name = eina_stringshare_ref(fname);
|
2014-08-11 06:56:50 -07:00
|
|
|
if (ls->t.token != '=')
|
|
|
|
{
|
2015-05-13 10:10:02 -07:00
|
|
|
if (!prev_fl)
|
2014-08-11 06:56:50 -07:00
|
|
|
{
|
2018-03-15 08:08:59 -07:00
|
|
|
Eolian_Expression *eexp = eo_lexer_expr_new(ls);
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(eexp->base, ls, -1, -1, EXPRESSION);
|
2015-05-13 10:10:02 -07:00
|
|
|
eexp->type = EOLIAN_EXPR_INT;
|
|
|
|
eexp->value.i = 0;
|
|
|
|
fdef->value = eexp;
|
2015-05-13 09:56:18 -07:00
|
|
|
fdef->is_public_value = EINA_TRUE;
|
2018-03-15 08:08:59 -07:00
|
|
|
eo_lexer_expr_release_ref(ls, eexp);
|
2015-05-13 10:10:02 -07:00
|
|
|
prev_fl = fdef;
|
|
|
|
fl_nadd = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-03-15 08:08:59 -07:00
|
|
|
Eolian_Expression *rhs = eo_lexer_expr_new(ls),
|
|
|
|
*bin = eo_lexer_expr_new(ls);
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(rhs->base, ls, -1, -1, EXPRESSION);
|
|
|
|
FILL_BASE(bin->base, ls, -1, -1, EXPRESSION);
|
2015-05-13 10:10:02 -07:00
|
|
|
|
|
|
|
rhs->type = EOLIAN_EXPR_INT;
|
|
|
|
rhs->value.i = ++fl_nadd;
|
|
|
|
|
|
|
|
bin->type = EOLIAN_EXPR_BINARY;
|
|
|
|
bin->binop = EOLIAN_BINOP_ADD;
|
|
|
|
bin->lhs = prev_fl->value;
|
|
|
|
bin->rhs = rhs;
|
|
|
|
bin->weak_lhs = EINA_TRUE;
|
2018-03-15 08:08:59 -07:00
|
|
|
eo_lexer_expr_release_ref(ls, rhs);
|
2015-05-13 10:10:02 -07:00
|
|
|
|
|
|
|
fdef->value = bin;
|
2018-03-15 08:08:59 -07:00
|
|
|
eo_lexer_expr_release_ref(ls, bin);
|
2014-08-11 06:56:50 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ls->expr_mode = EINA_TRUE;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
fdef->value = parse_expr(ls);
|
2015-05-13 09:56:18 -07:00
|
|
|
fdef->is_public_value = EINA_TRUE;
|
2014-08-11 06:56:50 -07:00
|
|
|
ls->expr_mode = EINA_FALSE;
|
2015-05-13 10:10:02 -07:00
|
|
|
prev_fl = fdef;
|
|
|
|
fl_nadd = 0;
|
2018-03-15 08:08:59 -07:00
|
|
|
eo_lexer_expr_release_ref(ls, fdef->value);
|
2014-08-11 06:56:50 -07:00
|
|
|
}
|
|
|
|
Eina_Bool want_next = (ls->t.token == ',');
|
|
|
|
if (want_next)
|
|
|
|
eo_lexer_get(ls);
|
2015-06-03 07:35:13 -07:00
|
|
|
FILL_DOC(ls, fdef, doc);
|
2015-07-03 07:19:12 -07:00
|
|
|
if (!want_next || ls->t.token == '}')
|
2014-08-11 06:56:50 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
check_match(ls, '}', '{', bline, bcolumn);
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(def->base, ls, line, column, TYPEDECL);
|
2018-03-15 07:50:53 -07:00
|
|
|
database_enum_add(ls->unit, eo_lexer_typedecl_release(ls, def));
|
2014-08-11 06:56:50 -07:00
|
|
|
return def;
|
|
|
|
}
|
|
|
|
|
2019-06-21 06:05:50 -07:00
|
|
|
/* error(Error1, Error2, Error3, ...) */
|
|
|
|
static Eolian_Type *
|
|
|
|
parse_type_error(Eo_Lexer *ls)
|
|
|
|
{
|
|
|
|
Eolian_Type *def = eo_lexer_type_new(ls);
|
|
|
|
Eina_Strbuf *buf = eina_strbuf_new();
|
|
|
|
eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_strbuf_free), buf);
|
|
|
|
for (Eolian_Type *cdef = def;; cdef = cdef->next_type)
|
|
|
|
{
|
|
|
|
FILL_BASE(cdef->base, ls, ls->line_number, ls->column, TYPE);
|
|
|
|
parse_name(ls, buf);
|
|
|
|
cdef->type = EOLIAN_TYPE_ERROR;
|
|
|
|
cdef->base.name = eina_stringshare_add(eina_strbuf_string_get(buf));
|
|
|
|
eina_strbuf_reset(buf);
|
|
|
|
if (ls->t.token != ',')
|
|
|
|
break;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
cdef->next_type = eo_lexer_type_release(ls, eo_lexer_type_new(ls));
|
|
|
|
}
|
|
|
|
eo_lexer_dtor_pop(ls);
|
|
|
|
return def;
|
|
|
|
}
|
|
|
|
|
2014-08-11 06:56:50 -07:00
|
|
|
static Eolian_Type *
|
2019-02-16 17:11:02 -08:00
|
|
|
parse_type_void(Eo_Lexer *ls, Eina_Bool allow_ptr)
|
2014-06-26 03:51:08 -07:00
|
|
|
{
|
2014-07-10 06:44:17 -07:00
|
|
|
Eolian_Type *def;
|
2014-07-21 07:11:19 -07:00
|
|
|
Eina_Strbuf *buf;
|
2014-08-04 07:01:16 -07:00
|
|
|
int line = ls->line_number, col = ls->column;
|
2014-06-26 03:51:08 -07:00
|
|
|
switch (ls->t.kw)
|
|
|
|
{
|
2014-07-01 10:25:17 -07:00
|
|
|
case KW_const:
|
|
|
|
{
|
2014-08-21 01:25:19 -07:00
|
|
|
int pline, pcol;
|
2014-07-01 10:25:17 -07:00
|
|
|
eo_lexer_get(ls);
|
2014-08-21 01:25:19 -07:00
|
|
|
pline = ls->line_number;
|
|
|
|
pcol = ls->column;
|
2014-07-01 10:25:17 -07:00
|
|
|
check_next(ls, '(');
|
2019-02-16 17:11:02 -08:00
|
|
|
def = parse_type_void(ls, allow_ptr);
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(def->base, ls, line, col, TYPE);
|
2014-07-01 10:25:17 -07:00
|
|
|
def->is_const = EINA_TRUE;
|
2014-08-21 01:25:19 -07:00
|
|
|
check_match(ls, ')', '(', pline, pcol);
|
2016-11-10 07:20:19 -08:00
|
|
|
return def;
|
2014-07-01 10:25:17 -07:00
|
|
|
}
|
2016-11-02 05:06:38 -07:00
|
|
|
case KW_ptr:
|
2016-06-08 07:49:09 -07:00
|
|
|
{
|
2019-02-16 17:11:02 -08:00
|
|
|
if (!allow_ptr)
|
|
|
|
break;
|
2016-06-08 07:49:09 -07:00
|
|
|
int pline, pcol;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
pline = ls->line_number;
|
|
|
|
pcol = ls->column;
|
|
|
|
check_next(ls, '(');
|
2019-02-16 17:11:02 -08:00
|
|
|
def = parse_type_void(ls, EINA_FALSE);
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(def->base, ls, line, col, TYPE);
|
2016-11-03 06:21:57 -07:00
|
|
|
def->is_ptr = EINA_TRUE;
|
2016-06-08 07:49:09 -07:00
|
|
|
check_match(ls, ')', '(', pline, pcol);
|
2016-11-10 07:20:19 -08:00
|
|
|
return def;
|
2016-06-08 07:49:09 -07:00
|
|
|
}
|
2019-06-21 06:05:50 -07:00
|
|
|
case KW_error:
|
|
|
|
{
|
|
|
|
int pline, pcolumn;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
pline = ls->line_number;
|
|
|
|
pcolumn = ls->column;
|
|
|
|
check_next(ls, '(');
|
|
|
|
def = parse_type_error(ls);
|
|
|
|
check_match(ls, ')', '(', pline, pcolumn);
|
|
|
|
return def;
|
|
|
|
}
|
2014-07-01 10:25:17 -07:00
|
|
|
default:
|
|
|
|
break;
|
2014-06-26 03:51:08 -07:00
|
|
|
}
|
2018-03-15 07:31:08 -07:00
|
|
|
def = eo_lexer_type_new(ls);
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(def->base, ls, line, col, TYPE);
|
2014-07-15 09:06:18 -07:00
|
|
|
if (ls->t.kw == KW_void)
|
2014-07-21 07:11:19 -07:00
|
|
|
{
|
|
|
|
def->type = EOLIAN_TYPE_VOID;
|
2017-09-22 11:47:39 -07:00
|
|
|
def->btype = EOLIAN_TYPE_BUILTIN_VOID;
|
2014-07-21 07:11:19 -07:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
}
|
2015-11-19 06:04:37 -08:00
|
|
|
else if (ls->t.kw == KW___undefined_type)
|
|
|
|
{
|
|
|
|
def->type = EOLIAN_TYPE_UNDEFINED;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
}
|
2014-06-30 15:07:32 -07:00
|
|
|
else
|
|
|
|
{
|
2014-09-08 06:52:49 -07:00
|
|
|
int tpid = ls->t.kw;
|
2014-07-15 09:06:18 -07:00
|
|
|
def->type = EOLIAN_TYPE_REGULAR;
|
2014-06-30 15:07:32 -07:00
|
|
|
check(ls, TOK_VALUE);
|
2016-06-30 06:04:03 -07:00
|
|
|
if (eo_lexer_is_type_keyword(ls->t.kw))
|
2014-07-21 07:11:19 -07:00
|
|
|
{
|
2017-09-22 11:38:17 -07:00
|
|
|
def->btype = ls->t.kw - KW_byte + 1;
|
2018-03-11 07:55:10 -07:00
|
|
|
def->base.name = eina_stringshare_ref(ls->t.value.s);
|
2019-05-16 06:31:37 -07:00
|
|
|
def->base.c_name = eina_stringshare_ref(def->base.name);
|
2014-07-21 07:11:19 -07:00
|
|
|
eo_lexer_get(ls);
|
2019-02-28 11:25:51 -08:00
|
|
|
if ((tpid >= KW_accessor && tpid <= KW_list) ||
|
2019-02-21 06:24:35 -08:00
|
|
|
(tpid >= KW_slice && tpid <= KW_rw_slice))
|
2014-09-08 06:52:49 -07:00
|
|
|
{
|
2015-05-14 03:27:00 -07:00
|
|
|
int bline = ls->line_number, bcol = ls->column;
|
|
|
|
check_next(ls, '<');
|
2018-05-03 08:10:31 -07:00
|
|
|
if (tpid == KW_future)
|
2019-02-16 17:11:02 -08:00
|
|
|
def->base_type = eo_lexer_type_release(ls, parse_type_void(ls, EINA_TRUE));
|
2018-05-03 08:10:31 -07:00
|
|
|
else
|
2019-02-16 17:11:02 -08:00
|
|
|
def->base_type = eo_lexer_type_release(ls, parse_type(ls, EINA_TRUE));
|
2019-06-26 04:54:12 -07:00
|
|
|
/* view-only types are not allowed to own the contents */
|
|
|
|
if (tpid == KW_array || tpid == KW_hash || tpid == KW_list || tpid == KW_future)
|
2019-08-30 07:08:31 -07:00
|
|
|
if ((def->base_type->owned = (ls->t.kw == KW_at_owned || ls->t.kw == KW_at_move)))
|
2019-06-26 04:54:12 -07:00
|
|
|
eo_lexer_get(ls);
|
2015-05-14 03:27:00 -07:00
|
|
|
if (tpid == KW_hash)
|
2014-09-08 06:52:49 -07:00
|
|
|
{
|
2015-05-14 03:27:00 -07:00
|
|
|
check_next(ls, ',');
|
2018-03-15 07:31:08 -07:00
|
|
|
def->base_type->next_type =
|
2019-02-16 17:11:02 -08:00
|
|
|
eo_lexer_type_release(ls, parse_type(ls, EINA_TRUE));
|
2019-08-30 07:08:31 -07:00
|
|
|
if ((def->base_type->next_type->owned = (ls->t.kw == KW_at_owned || ls->t.kw == KW_at_move)))
|
2017-09-15 07:24:46 -07:00
|
|
|
eo_lexer_get(ls);
|
2014-09-08 06:52:49 -07:00
|
|
|
}
|
2015-05-14 03:27:00 -07:00
|
|
|
check_match(ls, '>', '<', bline, bcol);
|
2014-09-08 06:52:49 -07:00
|
|
|
}
|
2014-07-21 07:11:19 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-07-30 07:35:57 -07:00
|
|
|
const char *bnm, *nm;
|
|
|
|
char *fnm;
|
2018-03-15 06:12:18 -07:00
|
|
|
buf = eina_strbuf_new();
|
|
|
|
eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_strbuf_free), buf);
|
2015-05-22 07:03:38 -07:00
|
|
|
eo_lexer_context_push(ls);
|
2014-07-21 07:11:19 -07:00
|
|
|
parse_name(ls, buf);
|
2014-07-30 03:57:11 -07:00
|
|
|
nm = eina_strbuf_string_get(buf);
|
2014-08-08 07:19:52 -07:00
|
|
|
bnm = eina_stringshare_ref(ls->filename);
|
2014-07-30 07:35:57 -07:00
|
|
|
fnm = database_class_to_filename(nm);
|
2014-08-01 05:59:46 -07:00
|
|
|
if (!compare_class_file(bnm, fnm))
|
2014-07-30 03:57:11 -07:00
|
|
|
{
|
2014-07-30 07:35:57 -07:00
|
|
|
eina_stringshare_del(bnm);
|
2018-04-18 06:23:07 -07:00
|
|
|
if (eina_hash_find(ls->state->filenames_eo, fnm))
|
2014-07-30 03:57:11 -07:00
|
|
|
{
|
2018-04-18 06:23:07 -07:00
|
|
|
database_defer(ls->state, fnm, EINA_TRUE);
|
2014-07-30 07:35:57 -07:00
|
|
|
def->type = EOLIAN_TYPE_CLASS;
|
2014-07-30 03:57:11 -07:00
|
|
|
}
|
2017-12-22 03:53:51 -08:00
|
|
|
free(fnm);
|
2014-07-30 03:57:11 -07:00
|
|
|
}
|
2014-07-30 07:35:57 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
eina_stringshare_del(bnm);
|
|
|
|
free(fnm);
|
|
|
|
def->type = EOLIAN_TYPE_CLASS;
|
|
|
|
}
|
2018-03-11 07:55:10 -07:00
|
|
|
def->base.name = eina_stringshare_add(nm);
|
2015-05-22 07:03:38 -07:00
|
|
|
eo_lexer_context_pop(ls);
|
2018-03-15 06:12:18 -07:00
|
|
|
eo_lexer_dtor_pop(ls);
|
2014-07-21 07:11:19 -07:00
|
|
|
}
|
2014-06-30 15:07:32 -07:00
|
|
|
}
|
2014-06-27 06:47:40 -07:00
|
|
|
return def;
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
|
|
|
|
2016-03-01 07:37:57 -08:00
|
|
|
static Eolian_Typedecl *
|
2014-06-18 03:25:07 -07:00
|
|
|
parse_typedef(Eo_Lexer *ls)
|
|
|
|
{
|
2018-03-15 07:50:53 -07:00
|
|
|
Eolian_Typedecl *def = eo_lexer_typedecl_new(ls);
|
2014-07-21 08:53:25 -07:00
|
|
|
Eina_Strbuf *buf;
|
2014-06-18 03:25:07 -07:00
|
|
|
eo_lexer_get(ls);
|
2019-05-30 07:20:09 -07:00
|
|
|
Eina_Stringshare *cname = NULL;
|
|
|
|
Eina_Bool has_extern = EINA_FALSE, has_beta = EINA_FALSE, has_c_name = EINA_FALSE;
|
2019-03-08 05:17:01 -08:00
|
|
|
for (;;) switch (ls->t.kw)
|
2018-03-15 08:34:08 -07:00
|
|
|
{
|
2019-03-08 05:17:01 -08:00
|
|
|
case KW_at_extern:
|
|
|
|
CASE_LOCK(ls, extern, "extern qualifier");
|
2019-02-16 17:20:35 -08:00
|
|
|
def->is_extern = EINA_TRUE;
|
|
|
|
eo_lexer_get(ls);
|
2019-03-08 05:17:01 -08:00
|
|
|
break;
|
|
|
|
case KW_at_beta:
|
|
|
|
CASE_LOCK(ls, beta, "beta qualifier");
|
|
|
|
def->base.is_beta = EINA_TRUE;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
2019-05-30 07:20:09 -07:00
|
|
|
case KW_at_c_name:
|
|
|
|
CASE_LOCK(ls, c_name, "@c_name specifier");
|
|
|
|
cname = parse_c_name(ls);
|
|
|
|
eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_stringshare_del), (void *)cname);
|
|
|
|
break;
|
2019-03-08 05:17:01 -08:00
|
|
|
default:
|
|
|
|
goto tags_done;
|
2018-03-15 08:34:08 -07:00
|
|
|
}
|
2019-03-08 05:17:01 -08:00
|
|
|
tags_done:
|
2016-03-01 07:37:57 -08:00
|
|
|
def->type = EOLIAN_TYPEDECL_ALIAS;
|
2018-03-15 06:12:18 -07:00
|
|
|
buf = eina_strbuf_new();
|
|
|
|
eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_strbuf_free), buf);
|
2014-07-22 07:27:11 -07:00
|
|
|
eo_lexer_context_push(ls);
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(def->base, ls, ls->line_number, ls->column, TYPEDECL);
|
2014-07-21 08:53:25 -07:00
|
|
|
parse_name(ls, buf);
|
2018-03-11 07:55:10 -07:00
|
|
|
def->base.name = eina_stringshare_add(eina_strbuf_string_get(buf));
|
2019-05-30 07:20:09 -07:00
|
|
|
if (cname)
|
|
|
|
{
|
|
|
|
def->base.c_name = cname;
|
|
|
|
eo_lexer_dtor_pop(ls);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
def->base.c_name = make_c_name(def->base.name);
|
2018-03-08 14:59:40 -08:00
|
|
|
Eolian_Object *decl = _eolian_decl_get(ls, def->base.name);
|
2015-05-15 07:10:58 -07:00
|
|
|
if (decl)
|
2014-07-21 08:53:25 -07:00
|
|
|
{
|
2014-07-22 07:27:11 -07:00
|
|
|
eo_lexer_context_restore(ls);
|
2018-03-08 14:59:40 -08:00
|
|
|
redef_error(ls, decl, &def->base);
|
2014-07-21 08:53:25 -07:00
|
|
|
}
|
2014-07-22 07:27:11 -07:00
|
|
|
eo_lexer_context_pop(ls);
|
2014-08-08 07:57:39 -07:00
|
|
|
check_next(ls, ':');
|
2019-02-16 17:11:02 -08:00
|
|
|
def->base_type = eo_lexer_type_release(ls, parse_type(ls, EINA_FALSE));
|
2014-06-18 03:25:07 -07:00
|
|
|
check_next(ls, ';');
|
2015-06-03 07:35:13 -07:00
|
|
|
FILL_DOC(ls, def, doc);
|
2018-03-15 06:12:18 -07:00
|
|
|
eo_lexer_dtor_pop(ls);
|
2014-07-21 08:53:25 -07:00
|
|
|
return def;
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
|
|
|
|
2014-08-08 07:57:39 -07:00
|
|
|
static Eolian_Variable *
|
|
|
|
parse_variable(Eo_Lexer *ls, Eina_Bool global)
|
|
|
|
{
|
2018-03-15 07:42:40 -07:00
|
|
|
Eolian_Variable *def = eo_lexer_variable_new(ls);
|
2014-08-08 07:57:39 -07:00
|
|
|
Eina_Strbuf *buf;
|
|
|
|
eo_lexer_get(ls);
|
2019-05-30 07:20:09 -07:00
|
|
|
Eina_Stringshare *cname = NULL;
|
|
|
|
Eina_Bool has_extern = EINA_FALSE, has_beta = EINA_FALSE, has_c_name = EINA_FALSE;
|
2019-03-08 05:17:01 -08:00
|
|
|
for (;;) switch (ls->t.kw)
|
2014-08-08 07:57:39 -07:00
|
|
|
{
|
2019-03-08 05:17:01 -08:00
|
|
|
case KW_at_extern:
|
|
|
|
CASE_LOCK(ls, extern, "extern qualifier");
|
2016-10-19 06:24:26 -07:00
|
|
|
def->is_extern = EINA_TRUE;
|
2014-08-08 07:57:39 -07:00
|
|
|
eo_lexer_get(ls);
|
2019-03-08 05:17:01 -08:00
|
|
|
break;
|
|
|
|
case KW_at_beta:
|
|
|
|
CASE_LOCK(ls, beta, "beta qualifier");
|
|
|
|
def->base.is_beta = EINA_TRUE;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
2019-05-30 07:20:09 -07:00
|
|
|
case KW_at_c_name:
|
|
|
|
CASE_LOCK(ls, c_name, "@c_name specifier");
|
|
|
|
cname = parse_c_name(ls);
|
|
|
|
eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_stringshare_del), (void *)cname);
|
|
|
|
break;
|
2019-03-08 05:17:01 -08:00
|
|
|
default:
|
|
|
|
goto tags_done;
|
2014-08-08 07:57:39 -07:00
|
|
|
}
|
2019-03-08 05:17:01 -08:00
|
|
|
tags_done:
|
2014-08-08 07:57:39 -07:00
|
|
|
def->type = global ? EOLIAN_VAR_GLOBAL : EOLIAN_VAR_CONSTANT;
|
2018-03-15 06:12:18 -07:00
|
|
|
buf = eina_strbuf_new();
|
|
|
|
eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_strbuf_free), buf);
|
2014-08-08 07:57:39 -07:00
|
|
|
eo_lexer_context_push(ls);
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(def->base, ls, ls->line_number, ls->column, VARIABLE);
|
2014-08-08 07:57:39 -07:00
|
|
|
parse_name(ls, buf);
|
2018-03-11 07:55:10 -07:00
|
|
|
def->base.name = eina_stringshare_add(eina_strbuf_string_get(buf));
|
2019-05-30 07:20:09 -07:00
|
|
|
if (cname)
|
|
|
|
{
|
|
|
|
def->base.c_name = cname;
|
|
|
|
eo_lexer_dtor_pop(ls);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
def->base.c_name = make_c_name(def->base.name);
|
2018-03-08 14:59:40 -08:00
|
|
|
Eolian_Object *decl = _eolian_decl_get(ls, def->base.name);
|
2015-05-15 07:10:58 -07:00
|
|
|
if (decl)
|
|
|
|
{
|
|
|
|
eo_lexer_context_restore(ls);
|
2018-03-08 14:59:40 -08:00
|
|
|
redef_error(ls, decl, &def->base);
|
2015-05-15 07:10:58 -07:00
|
|
|
}
|
|
|
|
eo_lexer_context_pop(ls);
|
2014-08-08 07:57:39 -07:00
|
|
|
check_next(ls, ':');
|
2019-02-16 17:11:02 -08:00
|
|
|
def->base_type = eo_lexer_type_release(ls, parse_type(ls, EINA_TRUE));
|
2016-10-19 06:24:26 -07:00
|
|
|
/* constants are required to have a value */
|
|
|
|
if (!global)
|
|
|
|
check(ls, '=');
|
|
|
|
/* globals can optionally have a value */
|
|
|
|
if (ls->t.token == '=')
|
2014-08-08 07:57:39 -07:00
|
|
|
{
|
|
|
|
ls->expr_mode = EINA_TRUE;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
def->value = parse_expr(ls);
|
|
|
|
ls->expr_mode = EINA_FALSE;
|
2018-03-15 08:08:59 -07:00
|
|
|
eo_lexer_expr_release_ref(ls, def->value);
|
2014-08-08 07:57:39 -07:00
|
|
|
}
|
|
|
|
check_next(ls, ';');
|
2015-06-03 07:35:13 -07:00
|
|
|
FILL_DOC(ls, def, doc);
|
2018-03-15 06:12:18 -07:00
|
|
|
eo_lexer_dtor_pop(ls);
|
2014-08-08 07:57:39 -07:00
|
|
|
return def;
|
|
|
|
}
|
|
|
|
|
2019-06-21 06:05:50 -07:00
|
|
|
static Eolian_Error *
|
|
|
|
parse_error(Eo_Lexer *ls)
|
|
|
|
{
|
|
|
|
Eolian_Error *def = eo_lexer_error_new(ls);
|
|
|
|
Eina_Strbuf *buf;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
Eina_Stringshare *cname = NULL;
|
|
|
|
Eina_Bool has_extern = EINA_FALSE, has_beta = EINA_FALSE, has_c_name = EINA_FALSE;
|
|
|
|
for (;;) switch (ls->t.kw)
|
|
|
|
{
|
|
|
|
case KW_at_extern:
|
|
|
|
CASE_LOCK(ls, extern, "extern qualifier");
|
|
|
|
def->is_extern = EINA_TRUE;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
|
|
|
case KW_at_beta:
|
|
|
|
CASE_LOCK(ls, beta, "beta qualifier");
|
|
|
|
def->base.is_beta = EINA_TRUE;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
|
|
|
case KW_at_c_name:
|
|
|
|
CASE_LOCK(ls, c_name, "@c_name specifier");
|
|
|
|
cname = parse_c_name(ls);
|
|
|
|
eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_stringshare_del), (void *)cname);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
goto tags_done;
|
|
|
|
}
|
|
|
|
tags_done:
|
|
|
|
buf = eina_strbuf_new();
|
|
|
|
eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_strbuf_free), buf);
|
|
|
|
eo_lexer_context_push(ls);
|
|
|
|
FILL_BASE(def->base, ls, ls->line_number, ls->column, ERROR);
|
|
|
|
parse_name(ls, buf);
|
|
|
|
def->base.name = eina_stringshare_add(eina_strbuf_string_get(buf));
|
|
|
|
if (cname)
|
|
|
|
{
|
|
|
|
def->base.c_name = cname;
|
|
|
|
eo_lexer_dtor_pop(ls);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
def->base.c_name = make_c_name(def->base.name);
|
|
|
|
Eolian_Object *decl = _eolian_decl_get(ls, def->base.name);
|
|
|
|
if (decl)
|
|
|
|
{
|
|
|
|
eo_lexer_context_restore(ls);
|
|
|
|
redef_error(ls, decl, &def->base);
|
|
|
|
}
|
|
|
|
eo_lexer_context_pop(ls);
|
|
|
|
check(ls, '=');
|
|
|
|
/* we need to parse a string so switch to exprmode */
|
|
|
|
ls->expr_mode = EINA_TRUE;
|
|
|
|
/* consume = to get string */
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
/* verify and switch back to plain syntax mode */
|
|
|
|
check(ls, TOK_STRING);
|
|
|
|
ls->expr_mode = EINA_FALSE;
|
|
|
|
def->msg = eina_stringshare_ref(ls->t.value.s);
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
check_next(ls, ';');
|
|
|
|
FILL_DOC(ls, def, doc);
|
|
|
|
eo_lexer_dtor_pop(ls);
|
|
|
|
return def;
|
|
|
|
}
|
|
|
|
|
2014-09-10 08:17:47 -07:00
|
|
|
typedef struct _Eo_Ret_Def
|
|
|
|
{
|
|
|
|
Eolian_Type *type;
|
2015-06-03 07:35:13 -07:00
|
|
|
Eolian_Documentation *doc;
|
2014-09-10 08:17:47 -07:00
|
|
|
Eolian_Expression *default_ret_val;
|
2019-05-26 08:41:22 -07:00
|
|
|
Eina_Bool no_unused: 1;
|
2017-09-15 06:51:25 -07:00
|
|
|
Eina_Bool owned: 1;
|
2019-08-30 07:08:31 -07:00
|
|
|
Eina_Bool by_ref: 1;
|
2014-09-10 08:17:47 -07:00
|
|
|
} Eo_Ret_Def;
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
static void
|
2017-09-15 06:54:48 -07:00
|
|
|
parse_return(Eo_Lexer *ls, Eo_Ret_Def *ret, Eina_Bool allow_void,
|
|
|
|
Eina_Bool allow_def, Eina_Bool is_funcptr)
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
|
|
|
eo_lexer_get(ls);
|
2014-08-07 08:58:45 -07:00
|
|
|
check_next(ls, ':');
|
2014-06-30 15:13:04 -07:00
|
|
|
if (allow_void)
|
2019-02-16 17:11:02 -08:00
|
|
|
ret->type = parse_type_void(ls, EINA_TRUE);
|
2014-06-30 15:13:04 -07:00
|
|
|
else
|
2019-02-16 17:11:02 -08:00
|
|
|
ret->type = parse_type(ls, EINA_TRUE);
|
2015-06-03 07:35:13 -07:00
|
|
|
ret->doc = NULL;
|
2014-09-10 08:17:47 -07:00
|
|
|
ret->default_ret_val = NULL;
|
2019-05-26 08:41:22 -07:00
|
|
|
ret->no_unused = EINA_FALSE;
|
2017-09-15 06:51:25 -07:00
|
|
|
ret->owned = EINA_FALSE;
|
2019-08-30 07:08:31 -07:00
|
|
|
ret->by_ref = EINA_FALSE;
|
2017-08-28 08:22:09 -07:00
|
|
|
if (allow_def && (ls->t.token == '('))
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
2014-07-02 16:00:02 -07:00
|
|
|
int line = ls->line_number, col = ls->column;
|
2014-08-08 03:32:07 -07:00
|
|
|
ls->expr_mode = EINA_TRUE;
|
2014-06-18 03:25:07 -07:00
|
|
|
eo_lexer_get(ls);
|
2014-08-07 07:15:07 -07:00
|
|
|
ret->default_ret_val = parse_expr(ls);
|
2014-08-08 03:32:07 -07:00
|
|
|
ls->expr_mode = EINA_FALSE;
|
2014-07-02 16:00:02 -07:00
|
|
|
check_match(ls, ')', '(', line, col);
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
2019-08-30 07:08:31 -07:00
|
|
|
Eina_Bool has_no_unused = EINA_FALSE, has_owned = EINA_FALSE,
|
|
|
|
has_by_ref = EINA_FALSE;
|
2017-09-15 06:54:48 -07:00
|
|
|
if (!is_funcptr) for (;;) switch (ls->t.kw)
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
2019-05-26 08:41:22 -07:00
|
|
|
case KW_at_no_unused:
|
|
|
|
CASE_LOCK(ls, no_unused, "no_unused qualifier");
|
|
|
|
ret->no_unused = EINA_TRUE;
|
2014-06-18 03:25:07 -07:00
|
|
|
eo_lexer_get(ls);
|
2016-06-07 06:59:36 -07:00
|
|
|
break;
|
2017-09-15 06:51:25 -07:00
|
|
|
case KW_at_owned:
|
2019-08-30 07:08:31 -07:00
|
|
|
case KW_at_move:
|
2017-09-15 06:51:25 -07:00
|
|
|
CASE_LOCK(ls, owned, "owned qualifier");
|
|
|
|
ret->owned = EINA_TRUE;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
2019-08-30 07:08:31 -07:00
|
|
|
case KW_at_by_ref:
|
|
|
|
CASE_LOCK(ls, by_ref, "by_ref qualifier");
|
|
|
|
ret->by_ref = EINA_TRUE;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
2016-06-07 06:59:36 -07:00
|
|
|
default:
|
|
|
|
goto end;
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
2016-06-07 06:59:36 -07:00
|
|
|
end:
|
2014-06-18 03:25:07 -07:00
|
|
|
check_next(ls, ';');
|
2015-06-03 07:35:13 -07:00
|
|
|
FILL_DOC(ls, ret, doc);
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-09-12 05:35:48 -07:00
|
|
|
parse_param(Eo_Lexer *ls, Eina_List **params, Eina_Bool allow_inout,
|
|
|
|
Eina_Bool is_vals)
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
2019-05-26 08:25:15 -07:00
|
|
|
Eina_Bool has_optional = EINA_FALSE,
|
2019-08-30 07:08:31 -07:00
|
|
|
has_owned = EINA_FALSE,
|
|
|
|
has_by_ref = EINA_FALSE;
|
2014-09-10 06:24:41 -07:00
|
|
|
Eolian_Function_Parameter *par = calloc(1, sizeof(Eolian_Function_Parameter));
|
2017-01-13 06:15:10 -08:00
|
|
|
par->param_dir = EOLIAN_IN_PARAM;
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(par->base, ls, ls->line_number, ls->column, FUNCTION_PARAMETER);
|
2014-09-12 05:35:48 -07:00
|
|
|
*params = eina_list_append(*params, par);
|
2017-12-04 05:44:29 -08:00
|
|
|
eolian_object_ref(&par->base);
|
2019-08-29 04:46:35 -07:00
|
|
|
if (allow_inout && (ls->t.kw == KW_at_in))
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
2016-06-06 07:22:56 -07:00
|
|
|
par->param_dir = EOLIAN_IN_PARAM;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
}
|
|
|
|
else if (allow_inout && ls->t.kw == KW_at_out)
|
|
|
|
{
|
|
|
|
par->param_dir = EOLIAN_OUT_PARAM;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
}
|
|
|
|
else if (allow_inout && ls->t.kw == KW_at_inout)
|
|
|
|
{
|
|
|
|
par->param_dir = EOLIAN_INOUT_PARAM;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
}
|
|
|
|
else par->param_dir = EOLIAN_IN_PARAM;
|
2015-05-18 08:13:08 -07:00
|
|
|
check(ls, TOK_VALUE);
|
2018-03-08 10:30:40 -08:00
|
|
|
par->base.name = eina_stringshare_ref(ls->t.value.s);
|
2015-05-18 08:13:08 -07:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
check_next(ls, ':');
|
2014-09-10 06:24:41 -07:00
|
|
|
if (par->param_dir == EOLIAN_OUT_PARAM || par->param_dir == EOLIAN_INOUT_PARAM)
|
2019-02-16 17:11:02 -08:00
|
|
|
par->type = eo_lexer_type_release(ls, parse_type_void(ls, EINA_TRUE));
|
2014-06-30 15:21:36 -07:00
|
|
|
else
|
2019-02-16 17:11:02 -08:00
|
|
|
par->type = eo_lexer_type_release(ls, parse_type(ls, EINA_TRUE));
|
2014-09-10 06:24:41 -07:00
|
|
|
if ((is_vals || (par->param_dir == EOLIAN_OUT_PARAM)) && (ls->t.token == '('))
|
2014-09-02 02:47:38 -07:00
|
|
|
{
|
|
|
|
int line = ls->line_number, col = ls->column;
|
|
|
|
ls->expr_mode = EINA_TRUE;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
par->value = parse_expr(ls);
|
|
|
|
ls->expr_mode = EINA_FALSE;
|
2018-03-15 08:08:59 -07:00
|
|
|
eo_lexer_expr_release_ref(ls, par->value);
|
2014-09-02 02:47:38 -07:00
|
|
|
check_match(ls, ')', '(', line, col);
|
|
|
|
}
|
2015-02-12 03:14:45 -08:00
|
|
|
for (;;) switch (ls->t.kw)
|
|
|
|
{
|
|
|
|
case KW_at_optional:
|
|
|
|
CASE_LOCK(ls, optional, "optional qualifier");
|
2015-02-12 03:32:34 -08:00
|
|
|
par->optional = EINA_TRUE;
|
2015-02-12 03:14:45 -08:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
2017-09-15 06:51:25 -07:00
|
|
|
case KW_at_owned:
|
|
|
|
CASE_LOCK(ls, owned, "owned qualifier");
|
2019-08-30 07:08:31 -07:00
|
|
|
par->type->owned = par->move = EINA_TRUE;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
|
|
|
case KW_at_by_ref:
|
|
|
|
CASE_LOCK(ls, by_ref, "by_ref qualifier");
|
|
|
|
par->by_ref = EINA_TRUE;
|
2017-09-15 06:51:25 -07:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
2015-02-12 03:14:45 -08:00
|
|
|
default:
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
end:
|
2014-06-18 03:25:07 -07:00
|
|
|
check_next(ls, ';');
|
2015-06-03 07:35:13 -07:00
|
|
|
FILL_DOC(ls, par, doc);
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
|
|
|
|
2015-05-20 09:42:00 -07:00
|
|
|
static void
|
|
|
|
parse_params(Eo_Lexer *ls, Eina_List **params, Eina_Bool allow_inout,
|
|
|
|
Eina_Bool is_vals)
|
|
|
|
{
|
|
|
|
int line, col;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
line = ls->line_number, col = ls->column;
|
|
|
|
check_next(ls, '{');
|
|
|
|
while (ls->t.token != '}')
|
|
|
|
parse_param(ls, params, allow_inout, is_vals);
|
|
|
|
check_match(ls, '}', '{', line, col);
|
|
|
|
}
|
|
|
|
|
2019-01-17 08:13:55 -08:00
|
|
|
static void
|
|
|
|
check_abstract_pure_virtual(Eo_Lexer *ls)
|
|
|
|
{
|
|
|
|
if ((ls->klass->type != EOLIAN_CLASS_ABSTRACT) && (ls->klass->type != EOLIAN_CLASS_MIXIN))
|
|
|
|
eo_lexer_syntax_error(ls, "@pure_virtual only allowed in abstract classes or mixins");
|
|
|
|
}
|
|
|
|
|
2014-09-10 07:53:20 -07:00
|
|
|
static void
|
2014-09-10 08:58:29 -07:00
|
|
|
parse_accessor(Eo_Lexer *ls, Eolian_Function *prop)
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
2014-07-02 16:00:02 -07:00
|
|
|
int line, col;
|
2019-03-08 07:54:10 -08:00
|
|
|
Eina_Bool has_return = EINA_FALSE, has_keys = EINA_FALSE,
|
2016-06-09 08:54:43 -07:00
|
|
|
has_values = EINA_FALSE, has_protected = EINA_FALSE,
|
2017-01-13 06:40:29 -08:00
|
|
|
has_virtp = EINA_FALSE;
|
2014-09-10 07:53:20 -07:00
|
|
|
Eina_Bool is_get = (ls->t.kw == KW_get);
|
|
|
|
if (is_get)
|
|
|
|
{
|
2014-09-10 08:58:29 -07:00
|
|
|
if (prop->base.file)
|
|
|
|
eina_stringshare_del(prop->base.file);
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(prop->base, ls, ls->line_number, ls->column, FUNCTION);
|
2014-09-10 08:17:47 -07:00
|
|
|
if (prop->type == EOLIAN_PROP_SET)
|
|
|
|
prop->type = EOLIAN_PROPERTY;
|
|
|
|
else
|
|
|
|
prop->type = EOLIAN_PROP_GET;
|
2014-09-10 07:53:20 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(prop->set_base, ls, ls->line_number, ls->column, FUNCTION);
|
2014-09-10 08:17:47 -07:00
|
|
|
if (prop->type == EOLIAN_PROP_GET)
|
|
|
|
prop->type = EOLIAN_PROPERTY;
|
|
|
|
else
|
|
|
|
prop->type = EOLIAN_PROP_SET;
|
2014-09-10 07:53:20 -07:00
|
|
|
}
|
2014-06-18 03:25:07 -07:00
|
|
|
eo_lexer_get(ls);
|
2016-06-09 08:54:43 -07:00
|
|
|
for (;;) switch (ls->t.kw)
|
2016-05-12 07:41:56 -07:00
|
|
|
{
|
2017-01-13 06:44:09 -08:00
|
|
|
case KW_at_pure_virtual:
|
2019-01-17 08:13:55 -08:00
|
|
|
check_abstract_pure_virtual(ls);
|
2017-01-13 06:44:09 -08:00
|
|
|
CASE_LOCK(ls, virtp, "pure_virtual qualifier");
|
2017-01-16 06:51:11 -08:00
|
|
|
if (is_get) prop->impl->get_pure_virtual = EINA_TRUE;
|
|
|
|
else prop->impl->set_pure_virtual = EINA_TRUE;
|
2016-05-12 07:41:56 -07:00
|
|
|
eo_lexer_get(ls);
|
2016-06-09 08:54:43 -07:00
|
|
|
break;
|
|
|
|
case KW_at_protected:
|
|
|
|
CASE_LOCK(ls, protected, "protected qualifier");
|
|
|
|
if (is_get) prop->get_scope = EOLIAN_SCOPE_PROTECTED;
|
|
|
|
else prop->set_scope = EOLIAN_SCOPE_PROTECTED;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
goto parse_accessor;
|
2016-05-12 07:41:56 -07:00
|
|
|
}
|
2016-06-09 08:54:43 -07:00
|
|
|
parse_accessor:
|
2014-06-18 03:25:07 -07:00
|
|
|
line = ls->line_number;
|
2014-07-02 16:00:02 -07:00
|
|
|
col = ls->column;
|
2014-06-18 03:25:07 -07:00
|
|
|
check_next(ls, '{');
|
2017-01-19 05:46:40 -08:00
|
|
|
if ((ls->t.token == TOK_DOC) && !prop->impl->common_doc)
|
2016-05-19 08:57:12 -07:00
|
|
|
{
|
|
|
|
if (getenv("EOLIAN_PROPERTY_DOC_WARN"))
|
|
|
|
{
|
2018-03-20 09:05:22 -07:00
|
|
|
Eolian_Object tmp;
|
|
|
|
memset(&tmp, 0, sizeof(Eolian_Object));
|
|
|
|
tmp.file = prop->base.file;
|
|
|
|
tmp.line = line;
|
|
|
|
tmp.column = col;
|
|
|
|
tmp.unit = ls->unit;
|
|
|
|
eolian_state_log_obj(ls->state, &tmp,
|
|
|
|
"%s doc without property doc for '%s.%s'",
|
|
|
|
is_get ? "getter" : "setter",
|
|
|
|
ls->klass->base.name, prop->base.name);
|
2016-05-19 08:57:12 -07:00
|
|
|
}
|
|
|
|
}
|
2015-06-03 07:35:13 -07:00
|
|
|
if (is_get)
|
|
|
|
{
|
2017-01-19 05:46:40 -08:00
|
|
|
FILL_DOC(ls, prop->impl, get_doc);
|
2015-06-03 07:35:13 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-01-19 05:46:40 -08:00
|
|
|
FILL_DOC(ls, prop->impl, set_doc);
|
2015-06-03 07:35:13 -07:00
|
|
|
}
|
2014-07-01 10:25:17 -07:00
|
|
|
for (;;) switch (ls->t.kw)
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
2014-07-01 10:25:17 -07:00
|
|
|
case KW_return:
|
|
|
|
CASE_LOCK(ls, return, "return")
|
2014-09-10 08:17:47 -07:00
|
|
|
Eo_Ret_Def ret;
|
2017-09-15 06:54:48 -07:00
|
|
|
parse_return(ls, &ret, is_get, EINA_TRUE, EINA_FALSE);
|
2018-03-15 08:08:59 -07:00
|
|
|
if (ret.default_ret_val)
|
|
|
|
eo_lexer_expr_release_ref(ls, ret.default_ret_val);
|
2014-09-10 07:53:20 -07:00
|
|
|
if (is_get)
|
2014-09-10 08:17:47 -07:00
|
|
|
{
|
2018-03-15 07:31:08 -07:00
|
|
|
prop->get_ret_type = eo_lexer_type_release(ls, ret.type);
|
2015-06-03 07:35:13 -07:00
|
|
|
prop->get_return_doc = ret.doc;
|
2014-09-10 08:17:47 -07:00
|
|
|
prop->get_ret_val = ret.default_ret_val;
|
2019-05-26 08:41:22 -07:00
|
|
|
prop->get_return_no_unused = ret.no_unused;
|
2019-08-30 07:08:31 -07:00
|
|
|
prop->get_return_by_ref = ret.by_ref;
|
|
|
|
prop->get_return_move = prop->get_ret_type->owned = ret.owned;
|
2014-09-10 08:17:47 -07:00
|
|
|
}
|
2014-09-10 07:53:20 -07:00
|
|
|
else
|
2014-09-10 08:17:47 -07:00
|
|
|
{
|
2018-03-15 07:31:08 -07:00
|
|
|
prop->set_ret_type = eo_lexer_type_release(ls, ret.type);
|
2015-06-03 07:35:13 -07:00
|
|
|
prop->set_return_doc = ret.doc;
|
2014-09-10 08:17:47 -07:00
|
|
|
prop->set_ret_val = ret.default_ret_val;
|
2019-05-26 08:41:22 -07:00
|
|
|
prop->set_return_no_unused = ret.no_unused;
|
2019-08-30 07:08:31 -07:00
|
|
|
prop->set_return_by_ref = ret.by_ref;
|
|
|
|
prop->set_return_move = prop->set_ret_type->owned = ret.owned;
|
2014-09-10 08:17:47 -07:00
|
|
|
}
|
2014-07-01 10:25:17 -07:00
|
|
|
break;
|
2015-05-20 09:42:00 -07:00
|
|
|
case KW_keys:
|
|
|
|
{
|
|
|
|
Eina_List **stor;
|
|
|
|
CASE_LOCK(ls, keys, "keys definition")
|
|
|
|
stor = is_get ? &prop->prop_keys_get : &prop->prop_keys_set;
|
|
|
|
parse_params(ls, stor, EINA_FALSE, EINA_FALSE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case KW_values:
|
|
|
|
{
|
|
|
|
Eina_List **stor;
|
|
|
|
CASE_LOCK(ls, values, "values definition")
|
|
|
|
stor = is_get ? &prop->prop_values_get : &prop->prop_values_set;
|
|
|
|
parse_params(ls, stor, EINA_FALSE, EINA_TRUE);
|
|
|
|
break;
|
|
|
|
}
|
2014-07-01 10:25:17 -07:00
|
|
|
default:
|
2014-09-10 07:06:12 -07:00
|
|
|
goto end;
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
|
|
|
end:
|
2014-07-02 16:00:02 -07:00
|
|
|
check_match(ls, '}', '{', line, col);
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
|
|
|
|
2014-09-10 08:58:29 -07:00
|
|
|
static void
|
2017-01-13 06:40:29 -08:00
|
|
|
_func_pure_virtual_set(Eo_Lexer *ls, Eolian_Function *foo_id, Eina_Bool virt)
|
2014-09-10 08:58:29 -07:00
|
|
|
{
|
2018-03-15 04:30:06 -07:00
|
|
|
if (ls->klass->type != EOLIAN_CLASS_INTERFACE && !virt)
|
2014-09-10 08:58:29 -07:00
|
|
|
return;
|
|
|
|
|
2014-09-11 02:29:48 -07:00
|
|
|
if (foo_id->type == EOLIAN_PROP_GET || foo_id->type == EOLIAN_METHOD)
|
2017-01-16 06:51:11 -08:00
|
|
|
foo_id->impl->get_pure_virtual = EINA_TRUE;
|
2014-09-10 08:58:29 -07:00
|
|
|
else if (foo_id->type == EOLIAN_PROP_SET)
|
2017-01-16 06:51:11 -08:00
|
|
|
foo_id->impl->set_pure_virtual = EINA_TRUE;
|
2014-09-11 02:29:48 -07:00
|
|
|
else if (foo_id->type == EOLIAN_PROPERTY)
|
2017-01-16 06:51:11 -08:00
|
|
|
foo_id->impl->get_pure_virtual = foo_id->impl->set_pure_virtual = EINA_TRUE;
|
2014-09-10 08:58:29 -07:00
|
|
|
}
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
static void
|
|
|
|
parse_property(Eo_Lexer *ls)
|
|
|
|
{
|
2014-07-02 16:00:02 -07:00
|
|
|
int line, col;
|
2014-09-10 08:58:29 -07:00
|
|
|
Eolian_Function *prop = NULL;
|
2017-01-16 06:51:11 -08:00
|
|
|
Eolian_Implement *impl = NULL;
|
2014-07-24 04:05:12 -07:00
|
|
|
Eina_Bool has_get = EINA_FALSE, has_set = EINA_FALSE,
|
|
|
|
has_keys = EINA_FALSE, has_values = EINA_FALSE,
|
2014-12-03 06:59:24 -08:00
|
|
|
has_protected = EINA_FALSE, has_class = EINA_FALSE,
|
2017-08-30 10:31:23 -07:00
|
|
|
has_beta = EINA_FALSE, has_virtp = EINA_FALSE;
|
2014-09-10 08:58:29 -07:00
|
|
|
prop = calloc(1, sizeof(Eolian_Function));
|
2018-03-15 04:30:06 -07:00
|
|
|
prop->klass = ls->klass;
|
2014-09-16 07:10:22 -07:00
|
|
|
prop->type = EOLIAN_UNRESOLVED;
|
2017-01-13 06:15:10 -08:00
|
|
|
prop->get_scope = prop->set_scope = EOLIAN_SCOPE_PUBLIC;
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(prop->base, ls, ls->line_number, ls->column, FUNCTION);
|
2017-01-16 06:51:11 -08:00
|
|
|
impl = calloc(1, sizeof(Eolian_Implement));
|
2018-11-04 07:08:48 -08:00
|
|
|
impl->klass = impl->implklass = ls->klass;
|
2017-01-16 06:51:11 -08:00
|
|
|
impl->foo_id = prop;
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(impl->base, ls, ls->line_number, ls->column, IMPLEMENT);
|
2017-01-16 06:51:11 -08:00
|
|
|
prop->impl = impl;
|
2018-03-15 04:30:06 -07:00
|
|
|
ls->klass->properties = eina_list_append(ls->klass->properties, prop);
|
|
|
|
ls->klass->implements = eina_list_append(ls->klass->implements, impl);
|
2017-12-04 05:44:29 -08:00
|
|
|
eolian_object_ref(&prop->base);
|
|
|
|
eolian_object_ref(&impl->base);
|
2014-07-22 08:35:54 -07:00
|
|
|
check(ls, TOK_VALUE);
|
2016-08-23 05:43:46 -07:00
|
|
|
if (ls->t.kw == KW_get || ls->t.kw == KW_set)
|
|
|
|
{
|
|
|
|
eo_lexer_syntax_error(ls, "reserved keyword as property name");
|
|
|
|
return;
|
|
|
|
}
|
2018-03-08 10:30:40 -08:00
|
|
|
prop->base.name = eina_stringshare_ref(ls->t.value.s);
|
2018-03-15 04:30:06 -07:00
|
|
|
impl->base.name = eina_stringshare_printf("%s.%s", ls->klass->base.name, prop->base.name);
|
2014-07-22 08:35:54 -07:00
|
|
|
eo_lexer_get(ls);
|
2014-07-24 04:05:12 -07:00
|
|
|
for (;;) switch (ls->t.kw)
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
2014-07-24 04:05:12 -07:00
|
|
|
case KW_at_protected:
|
|
|
|
CASE_LOCK(ls, protected, "protected qualifier")
|
2016-06-09 08:54:43 -07:00
|
|
|
prop->get_scope = prop->set_scope = EOLIAN_SCOPE_PROTECTED;
|
2014-06-18 03:25:07 -07:00
|
|
|
eo_lexer_get(ls);
|
2014-07-24 04:05:12 -07:00
|
|
|
break;
|
2019-08-16 07:27:00 -07:00
|
|
|
case KW_at_static:
|
2014-07-24 04:05:12 -07:00
|
|
|
CASE_LOCK(ls, class, "class qualifier");
|
2019-08-16 07:27:00 -07:00
|
|
|
prop->is_static = EINA_TRUE;
|
2014-07-24 06:01:33 -07:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
2015-05-08 06:00:07 -07:00
|
|
|
case KW_at_beta:
|
|
|
|
CASE_LOCK(ls, beta, "beta qualifier");
|
2019-03-08 05:17:01 -08:00
|
|
|
prop->base.is_beta = EINA_TRUE;
|
2015-05-08 06:00:07 -07:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
2017-01-13 06:44:09 -08:00
|
|
|
case KW_at_pure_virtual:
|
2019-01-17 08:13:55 -08:00
|
|
|
check_abstract_pure_virtual(ls);
|
2017-01-13 06:44:09 -08:00
|
|
|
CASE_LOCK(ls, virtp, "pure_virtual qualifier");
|
2016-05-12 07:41:56 -07:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
2014-07-24 04:05:12 -07:00
|
|
|
default:
|
|
|
|
goto body;
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
2014-07-24 04:05:12 -07:00
|
|
|
body:
|
2014-06-18 03:25:07 -07:00
|
|
|
line = ls->line_number;
|
2014-07-02 16:00:02 -07:00
|
|
|
col = ls->column;
|
2014-06-18 03:25:07 -07:00
|
|
|
check_next(ls, '{');
|
2017-01-19 05:46:40 -08:00
|
|
|
FILL_DOC(ls, prop->impl, common_doc);
|
2014-07-01 10:25:17 -07:00
|
|
|
for (;;) switch (ls->t.kw)
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
2014-07-01 10:25:17 -07:00
|
|
|
case KW_get:
|
|
|
|
CASE_LOCK(ls, get, "get definition")
|
2017-01-16 06:51:11 -08:00
|
|
|
impl->is_prop_get = EINA_TRUE;
|
2014-09-10 07:53:20 -07:00
|
|
|
parse_accessor(ls, prop);
|
2014-07-01 10:25:17 -07:00
|
|
|
break;
|
|
|
|
case KW_set:
|
|
|
|
CASE_LOCK(ls, set, "set definition")
|
2017-01-16 06:51:11 -08:00
|
|
|
impl->is_prop_set = EINA_TRUE;
|
2014-09-10 07:53:20 -07:00
|
|
|
parse_accessor(ls, prop);
|
2014-07-01 10:25:17 -07:00
|
|
|
break;
|
|
|
|
case KW_keys:
|
|
|
|
CASE_LOCK(ls, keys, "keys definition")
|
2015-05-20 09:42:00 -07:00
|
|
|
parse_params(ls, &prop->prop_keys, EINA_FALSE, EINA_FALSE);
|
2014-07-01 10:25:17 -07:00
|
|
|
break;
|
|
|
|
case KW_values:
|
|
|
|
CASE_LOCK(ls, values, "values definition")
|
2015-05-20 09:42:00 -07:00
|
|
|
parse_params(ls, &prop->prop_values, EINA_FALSE, EINA_TRUE);
|
2014-07-01 10:25:17 -07:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
goto end;
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
|
|
|
end:
|
2014-07-02 16:00:02 -07:00
|
|
|
check_match(ls, '}', '{', line, col);
|
2014-09-10 08:46:34 -07:00
|
|
|
if (!has_get && !has_set)
|
2017-01-16 06:51:11 -08:00
|
|
|
{
|
|
|
|
prop->type = EOLIAN_PROPERTY;
|
|
|
|
impl->is_prop_get = impl->is_prop_set = EINA_TRUE;
|
|
|
|
}
|
2017-01-13 06:40:29 -08:00
|
|
|
_func_pure_virtual_set(ls, prop, has_virtp);
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
|
|
|
|
2017-04-07 09:54:55 -07:00
|
|
|
static Eolian_Typedecl*
|
|
|
|
parse_function_pointer(Eo_Lexer *ls)
|
|
|
|
{
|
2017-08-30 07:02:30 -07:00
|
|
|
int bline, bcol;
|
|
|
|
int line = ls->line_number, col = ls->column;
|
|
|
|
|
2018-03-15 07:50:53 -07:00
|
|
|
Eolian_Typedecl *def = eo_lexer_typedecl_new(ls);
|
2018-03-15 06:12:18 -07:00
|
|
|
Eina_Strbuf *buf = eina_strbuf_new();
|
|
|
|
eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_strbuf_free), buf);
|
2017-04-07 09:54:55 -07:00
|
|
|
Eolian_Function *meth = NULL;
|
|
|
|
|
2019-05-30 07:20:09 -07:00
|
|
|
Eina_Stringshare *cname = NULL;
|
2017-08-30 04:53:22 -07:00
|
|
|
Eina_Bool has_params = EINA_FALSE,
|
2019-05-30 07:20:09 -07:00
|
|
|
has_return = EINA_FALSE,
|
|
|
|
has_c_name = EINA_FALSE;
|
2017-04-07 09:54:55 -07:00
|
|
|
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
|
|
|
|
def->type = EOLIAN_TYPEDECL_FUNCTION_POINTER;
|
2019-03-08 05:17:01 -08:00
|
|
|
Eina_Bool has_extern = EINA_FALSE, has_beta = EINA_FALSE;
|
|
|
|
for (;;) switch (ls->t.kw)
|
|
|
|
{
|
|
|
|
case KW_at_extern:
|
|
|
|
CASE_LOCK(ls, extern, "extern qualifier");
|
|
|
|
def->is_extern = EINA_TRUE;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
|
|
|
case KW_at_beta:
|
|
|
|
CASE_LOCK(ls, beta, "beta qualifier");
|
|
|
|
def->base.is_beta = EINA_TRUE;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
2019-05-30 07:20:09 -07:00
|
|
|
case KW_at_c_name:
|
|
|
|
CASE_LOCK(ls, c_name, "@c_name specifier");
|
|
|
|
cname = parse_c_name(ls);
|
|
|
|
eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_stringshare_del), (void *)cname);
|
|
|
|
break;
|
2019-03-08 05:17:01 -08:00
|
|
|
default:
|
|
|
|
goto tags_done;
|
|
|
|
}
|
|
|
|
tags_done:
|
2017-08-30 07:02:30 -07:00
|
|
|
parse_name(ls, buf);
|
2018-03-11 07:55:10 -07:00
|
|
|
def->base.name = eina_stringshare_add(eina_strbuf_string_get(buf));
|
2019-05-30 07:20:09 -07:00
|
|
|
if (cname)
|
|
|
|
{
|
|
|
|
def->base.c_name = cname;
|
|
|
|
eo_lexer_dtor_pop(ls);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
def->base.c_name = make_c_name(def->base.name);
|
2018-03-15 06:12:18 -07:00
|
|
|
eo_lexer_dtor_pop(ls);
|
2017-04-07 09:54:55 -07:00
|
|
|
|
|
|
|
meth = calloc(1, sizeof(Eolian_Function));
|
|
|
|
meth->klass = NULL;
|
|
|
|
meth->type = EOLIAN_FUNCTION_POINTER;
|
|
|
|
meth->get_scope = meth->set_scope = EOLIAN_SCOPE_PUBLIC;
|
2018-03-12 05:55:01 -07:00
|
|
|
meth->base.name = eina_stringshare_add(eolian_object_short_name_get(&def->base));
|
2017-04-07 09:54:55 -07:00
|
|
|
|
|
|
|
def->function_pointer = meth;
|
2017-12-04 05:44:29 -08:00
|
|
|
eolian_object_ref(&meth->base);
|
2017-04-07 09:54:55 -07:00
|
|
|
|
2019-03-08 05:17:01 -08:00
|
|
|
meth->base.is_beta = (ls->t.kw == KW_at_beta);
|
|
|
|
if (meth->base.is_beta)
|
2017-08-30 10:31:23 -07:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
|
2017-08-30 07:02:30 -07:00
|
|
|
bline = ls->line_number;
|
|
|
|
bcol = ls->column;
|
2017-04-07 09:54:55 -07:00
|
|
|
check_next(ls, '{');
|
2017-08-28 08:27:47 -07:00
|
|
|
FILL_DOC(ls, def, doc);
|
2017-04-07 09:54:55 -07:00
|
|
|
for (;;) switch (ls->t.kw)
|
|
|
|
{
|
|
|
|
case KW_return:
|
|
|
|
CASE_LOCK(ls, return, "return");
|
|
|
|
Eo_Ret_Def ret;
|
2017-09-15 06:54:48 -07:00
|
|
|
parse_return(ls, &ret, EINA_FALSE, EINA_FALSE, EINA_TRUE);
|
2018-03-15 07:31:08 -07:00
|
|
|
meth->get_ret_type = eo_lexer_type_release(ls, ret.type);
|
2017-04-07 09:54:55 -07:00
|
|
|
meth->get_return_doc = ret.doc;
|
|
|
|
meth->get_ret_val = NULL;
|
2019-05-26 08:41:22 -07:00
|
|
|
meth->get_return_no_unused = EINA_FALSE;
|
2017-04-07 09:54:55 -07:00
|
|
|
break;
|
|
|
|
case KW_params:
|
|
|
|
CASE_LOCK(ls, params, "params definition");
|
|
|
|
parse_params(ls, &meth->params, EINA_TRUE, EINA_FALSE);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
end:
|
2017-08-30 07:02:30 -07:00
|
|
|
check_match(ls, '}', '{', bline, bcol);
|
2017-04-07 09:54:55 -07:00
|
|
|
check_next(ls, ';');
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(def->base, ls, line, col, TYPEDECL);
|
|
|
|
FILL_BASE(meth->base, ls, line, col, FUNCTION);
|
2017-04-07 09:54:55 -07:00
|
|
|
return def;
|
|
|
|
}
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
static void
|
2014-12-03 06:59:24 -08:00
|
|
|
parse_method(Eo_Lexer *ls)
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
2014-07-02 16:00:02 -07:00
|
|
|
int line, col;
|
2014-09-11 02:29:48 -07:00
|
|
|
Eolian_Function *meth = NULL;
|
2017-01-16 06:51:11 -08:00
|
|
|
Eolian_Implement *impl = NULL;
|
2014-06-18 03:25:07 -07:00
|
|
|
Eina_Bool has_const = EINA_FALSE, has_params = EINA_FALSE,
|
2019-03-08 07:54:10 -08:00
|
|
|
has_return = EINA_FALSE, has_protected = EINA_FALSE,
|
|
|
|
has_class = EINA_FALSE, has_beta = EINA_FALSE,
|
2017-08-30 10:31:23 -07:00
|
|
|
has_virtp = EINA_FALSE;
|
2014-09-11 02:29:48 -07:00
|
|
|
meth = calloc(1, sizeof(Eolian_Function));
|
2018-03-15 04:30:06 -07:00
|
|
|
meth->klass = ls->klass;
|
2014-09-11 02:29:48 -07:00
|
|
|
meth->type = EOLIAN_METHOD;
|
2017-01-13 06:15:10 -08:00
|
|
|
meth->get_scope = meth->set_scope = EOLIAN_SCOPE_PUBLIC;
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(meth->base, ls, ls->line_number, ls->column, FUNCTION);
|
2017-01-16 06:51:11 -08:00
|
|
|
impl = calloc(1, sizeof(Eolian_Implement));
|
2018-11-04 07:08:48 -08:00
|
|
|
impl->klass = impl->implklass = ls->klass;
|
2017-01-16 06:51:11 -08:00
|
|
|
impl->foo_id = meth;
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(impl->base, ls, ls->line_number, ls->column, IMPLEMENT);
|
2017-01-16 06:51:11 -08:00
|
|
|
meth->impl = impl;
|
2018-03-15 04:30:06 -07:00
|
|
|
ls->klass->methods = eina_list_append(ls->klass->methods, meth);
|
|
|
|
ls->klass->implements = eina_list_append(ls->klass->implements, impl);
|
2017-12-04 05:44:29 -08:00
|
|
|
eolian_object_ref(&meth->base);
|
|
|
|
eolian_object_ref(&impl->base);
|
2014-12-03 06:59:24 -08:00
|
|
|
check(ls, TOK_VALUE);
|
2016-08-23 05:43:46 -07:00
|
|
|
if (ls->t.kw == KW_get || ls->t.kw == KW_set)
|
|
|
|
{
|
|
|
|
eo_lexer_syntax_error(ls, "reserved keyword as method name");
|
|
|
|
return;
|
|
|
|
}
|
2018-03-08 10:30:40 -08:00
|
|
|
meth->base.name = eina_stringshare_ref(ls->t.value.s);
|
2018-03-15 04:30:06 -07:00
|
|
|
impl->base.name = eina_stringshare_printf("%s.%s", ls->klass->base.name, meth->base.name);
|
2014-12-03 06:59:24 -08:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
for (;;) switch (ls->t.kw)
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
2014-12-03 06:59:24 -08:00
|
|
|
case KW_at_protected:
|
|
|
|
CASE_LOCK(ls, protected, "protected qualifier")
|
2016-06-09 08:54:43 -07:00
|
|
|
meth->get_scope = meth->set_scope = EOLIAN_SCOPE_PROTECTED;
|
2014-06-18 03:25:07 -07:00
|
|
|
eo_lexer_get(ls);
|
2014-12-03 06:59:24 -08:00
|
|
|
break;
|
|
|
|
case KW_at_const:
|
|
|
|
CASE_LOCK(ls, const, "const qualifier")
|
|
|
|
meth->obj_is_const = EINA_TRUE;
|
2014-07-22 08:35:54 -07:00
|
|
|
eo_lexer_get(ls);
|
2014-12-03 06:59:24 -08:00
|
|
|
break;
|
2019-08-16 07:27:00 -07:00
|
|
|
case KW_at_static:
|
2014-12-03 06:59:24 -08:00
|
|
|
CASE_LOCK(ls, class, "class qualifier");
|
2019-08-16 07:27:00 -07:00
|
|
|
meth->is_static = EINA_TRUE;
|
2014-12-03 06:59:24 -08:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
2015-05-08 06:00:07 -07:00
|
|
|
case KW_at_beta:
|
|
|
|
CASE_LOCK(ls, beta, "beta qualifier");
|
2019-03-08 05:17:01 -08:00
|
|
|
meth->base.is_beta = EINA_TRUE;
|
2015-05-08 06:00:07 -07:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
2017-01-13 06:44:09 -08:00
|
|
|
case KW_at_pure_virtual:
|
2019-01-17 08:13:55 -08:00
|
|
|
check_abstract_pure_virtual(ls);
|
2017-01-13 06:44:09 -08:00
|
|
|
CASE_LOCK(ls, virtp, "pure_virtual qualifier");
|
2016-05-12 07:41:56 -07:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
2014-12-03 06:59:24 -08:00
|
|
|
default:
|
|
|
|
goto body;
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
2014-07-22 09:13:24 -07:00
|
|
|
body:
|
2014-06-18 03:25:07 -07:00
|
|
|
line = ls->line_number;
|
2014-07-02 16:00:02 -07:00
|
|
|
col = ls->column;
|
2014-06-18 03:25:07 -07:00
|
|
|
check_next(ls, '{');
|
2017-01-19 05:46:40 -08:00
|
|
|
FILL_DOC(ls, meth->impl, common_doc);
|
2014-07-01 10:25:17 -07:00
|
|
|
for (;;) switch (ls->t.kw)
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
2014-07-01 10:25:17 -07:00
|
|
|
case KW_return:
|
|
|
|
CASE_LOCK(ls, return, "return")
|
2014-09-10 08:17:47 -07:00
|
|
|
Eo_Ret_Def ret;
|
2017-09-15 06:54:48 -07:00
|
|
|
parse_return(ls, &ret, EINA_FALSE, EINA_TRUE, EINA_FALSE);
|
2018-03-15 08:08:59 -07:00
|
|
|
if (ret.default_ret_val)
|
|
|
|
eo_lexer_expr_release_ref(ls, ret.default_ret_val);
|
2018-03-15 07:31:08 -07:00
|
|
|
meth->get_ret_type = eo_lexer_type_release(ls, ret.type);
|
2015-06-03 07:35:13 -07:00
|
|
|
meth->get_return_doc = ret.doc;
|
2014-09-11 02:29:48 -07:00
|
|
|
meth->get_ret_val = ret.default_ret_val;
|
2019-05-26 08:41:22 -07:00
|
|
|
meth->get_return_no_unused = ret.no_unused;
|
2019-08-30 07:08:31 -07:00
|
|
|
meth->get_return_by_ref = ret.by_ref;
|
|
|
|
meth->get_return_move = meth->get_ret_type->owned = ret.owned;
|
2014-07-01 10:25:17 -07:00
|
|
|
break;
|
|
|
|
case KW_params:
|
|
|
|
CASE_LOCK(ls, params, "params definition")
|
2014-09-12 05:35:48 -07:00
|
|
|
parse_params(ls, &meth->params, EINA_TRUE, EINA_FALSE);
|
2014-07-01 10:25:17 -07:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
goto end;
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
|
|
|
end:
|
2014-07-02 16:00:02 -07:00
|
|
|
check_match(ls, '}', '{', line, col);
|
2017-01-13 06:40:29 -08:00
|
|
|
_func_pure_virtual_set(ls, meth, has_virtp);
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
|
|
|
|
2017-10-24 08:32:58 -07:00
|
|
|
static void
|
|
|
|
parse_part(Eo_Lexer *ls)
|
|
|
|
{
|
2017-10-31 04:10:59 -07:00
|
|
|
Eolian_Part *part = calloc(1, sizeof(Eolian_Part));
|
2018-03-27 04:48:58 -07:00
|
|
|
FILL_BASE(part->base, ls, ls->line_number, ls->column, PART);
|
2018-03-15 04:30:06 -07:00
|
|
|
ls->klass->parts = eina_list_append(ls->klass->parts, part);
|
2017-12-04 05:44:29 -08:00
|
|
|
eolian_object_ref(&part->base);
|
2017-10-31 04:10:59 -07:00
|
|
|
check(ls, TOK_VALUE);
|
2018-03-08 10:30:40 -08:00
|
|
|
part->base.name = eina_stringshare_ref(ls->t.value.s);
|
2017-10-31 04:10:59 -07:00
|
|
|
eo_lexer_get(ls);
|
2019-05-05 08:06:21 -07:00
|
|
|
if (ls->t.kw == KW_at_beta)
|
|
|
|
{
|
|
|
|
part->base.is_beta = EINA_TRUE;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
}
|
2017-10-24 08:32:58 -07:00
|
|
|
check_next(ls, ':');
|
2018-03-15 06:12:18 -07:00
|
|
|
Eina_Strbuf *buf = eina_strbuf_new();
|
|
|
|
eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_strbuf_free), buf);
|
2017-10-31 04:10:59 -07:00
|
|
|
eo_lexer_context_push(ls);
|
2017-10-24 08:32:58 -07:00
|
|
|
parse_name(ls, buf);
|
2017-10-31 04:10:59 -07:00
|
|
|
const char *nm = eina_strbuf_string_get(buf);
|
|
|
|
char *fnm = database_class_to_filename(nm);
|
2018-04-18 06:23:07 -07:00
|
|
|
if (!eina_hash_find(ls->state->filenames_eo, fnm))
|
2017-10-31 04:10:59 -07:00
|
|
|
{
|
|
|
|
free(fnm);
|
2018-01-31 09:06:17 -08:00
|
|
|
char ebuf[PATH_MAX];
|
|
|
|
eo_lexer_context_restore(ls);
|
|
|
|
snprintf(ebuf, sizeof(ebuf), "unknown class '%s'", nm);
|
|
|
|
eo_lexer_syntax_error(ls, ebuf);
|
|
|
|
return;
|
2017-10-31 04:10:59 -07:00
|
|
|
}
|
2018-04-18 06:23:07 -07:00
|
|
|
database_defer(ls->state, fnm, EINA_TRUE);
|
2018-01-31 09:06:17 -08:00
|
|
|
free(fnm);
|
|
|
|
part->klass_name = eina_stringshare_add(nm);
|
2018-03-15 06:12:18 -07:00
|
|
|
eo_lexer_dtor_pop(ls);
|
2017-10-31 04:10:59 -07:00
|
|
|
check_next(ls, ';');
|
|
|
|
FILL_DOC(ls, part, doc);
|
2017-10-24 08:32:58 -07:00
|
|
|
}
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
static void
|
2014-06-20 04:24:10 -07:00
|
|
|
parse_implement(Eo_Lexer *ls, Eina_Bool iface)
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
|
|
|
Eina_Strbuf *buf = NULL;
|
2014-07-10 07:23:06 -07:00
|
|
|
Eolian_Implement *impl = NULL;
|
2014-09-11 03:18:48 -07:00
|
|
|
int iline = ls->line_number, icol = ls->column;
|
2014-06-20 04:24:10 -07:00
|
|
|
if (iface)
|
2014-07-01 10:25:17 -07:00
|
|
|
check_kw(ls, KW_class);
|
2014-06-18 03:25:07 -07:00
|
|
|
if (ls->t.kw == KW_class)
|
|
|
|
{
|
|
|
|
eo_lexer_get(ls);
|
2014-06-20 02:45:55 -07:00
|
|
|
check_next(ls, '.');
|
2014-06-18 03:25:07 -07:00
|
|
|
if (ls->t.kw == KW_destructor)
|
|
|
|
{
|
2018-03-15 04:30:06 -07:00
|
|
|
ls->klass->class_dtor_enable = EINA_TRUE;
|
2014-06-18 03:25:07 -07:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
check_kw_next(ls, KW_constructor);
|
2018-03-15 04:30:06 -07:00
|
|
|
ls->klass->class_ctor_enable = EINA_TRUE;
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
|
|
|
check_next(ls, ';');
|
|
|
|
return;
|
|
|
|
}
|
2017-01-11 10:25:54 -08:00
|
|
|
Eina_Bool glob_auto = EINA_FALSE, glob_empty = EINA_FALSE;
|
2014-08-29 06:33:56 -07:00
|
|
|
switch (ls->t.kw)
|
|
|
|
{
|
|
|
|
case KW_at_auto:
|
2017-01-11 10:25:54 -08:00
|
|
|
glob_auto = EINA_TRUE;
|
2014-08-29 06:33:56 -07:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
|
|
|
case KW_at_empty:
|
2017-01-11 10:25:54 -08:00
|
|
|
glob_empty = EINA_TRUE;
|
2014-08-29 06:33:56 -07:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (ls->t.token == '.')
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
2017-01-11 10:25:54 -08:00
|
|
|
eo_lexer_get(ls);
|
2016-12-27 10:37:15 -08:00
|
|
|
if (ls->t.token != TOK_VALUE)
|
2014-07-01 10:25:17 -07:00
|
|
|
eo_lexer_syntax_error(ls, "name expected");
|
2017-01-16 06:51:11 -08:00
|
|
|
Eina_Stringshare *iname = eina_stringshare_printf("%s.%s",
|
2018-03-15 04:30:06 -07:00
|
|
|
ls->klass->base.name,
|
2017-01-16 06:51:11 -08:00
|
|
|
ls->t.value.s);
|
|
|
|
Eina_List *l;
|
|
|
|
Eolian_Implement *fimp;
|
2018-03-15 04:30:06 -07:00
|
|
|
EINA_LIST_FOREACH(ls->klass->implements, l, fimp)
|
2018-03-08 10:30:40 -08:00
|
|
|
if (iname == fimp->base.name)
|
2017-01-16 06:51:11 -08:00
|
|
|
{
|
|
|
|
impl = fimp;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
eina_stringshare_del(iname);
|
|
|
|
if (!impl)
|
2017-02-10 07:56:35 -08:00
|
|
|
{
|
|
|
|
eo_lexer_syntax_error(ls, "implement of non-existent function");
|
|
|
|
return;
|
|
|
|
}
|
2014-06-18 03:25:07 -07:00
|
|
|
eo_lexer_get(ls);
|
2016-12-27 10:33:12 -08:00
|
|
|
goto propbeg;
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
2017-01-16 06:51:11 -08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
impl = calloc(1, sizeof(Eolian_Implement));
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(impl->base, ls, iline, icol, IMPLEMENT);
|
2018-03-15 04:30:06 -07:00
|
|
|
ls->klass->implements = eina_list_append(ls->klass->implements, impl);
|
2017-12-04 05:44:29 -08:00
|
|
|
eolian_object_ref(&impl->base);
|
2017-01-16 06:51:11 -08:00
|
|
|
}
|
2016-12-27 10:37:15 -08:00
|
|
|
if (ls->t.token != TOK_VALUE)
|
2014-07-01 10:25:17 -07:00
|
|
|
eo_lexer_syntax_error(ls, "class name expected");
|
2018-03-15 06:12:18 -07:00
|
|
|
buf = eina_strbuf_new();
|
|
|
|
eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_strbuf_free), buf);
|
2014-07-17 09:16:31 -07:00
|
|
|
eina_strbuf_append(buf, ls->t.value.s);
|
2014-06-18 03:25:07 -07:00
|
|
|
eo_lexer_get(ls);
|
2014-06-20 02:45:55 -07:00
|
|
|
check_next(ls, '.');
|
2016-12-27 10:37:15 -08:00
|
|
|
if (ls->t.token != TOK_VALUE)
|
2014-07-01 10:25:17 -07:00
|
|
|
eo_lexer_syntax_error(ls, "name or constructor/destructor expected");
|
2014-06-18 03:25:07 -07:00
|
|
|
for (;;)
|
|
|
|
{
|
2016-12-27 10:37:15 -08:00
|
|
|
if ((ls->t.kw == KW_constructor) || (ls->t.kw == KW_destructor))
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
2014-08-29 07:06:48 -07:00
|
|
|
eina_strbuf_append_char(buf, '.');
|
|
|
|
eina_strbuf_append(buf, eo_lexer_keyword_str_get(ls->t.kw));
|
|
|
|
eo_lexer_get(ls);
|
2017-01-18 06:33:44 -08:00
|
|
|
check(ls, ';');
|
|
|
|
goto propbeg;
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
2014-08-29 07:06:48 -07:00
|
|
|
eina_strbuf_append_char(buf, '.');
|
2014-06-18 03:25:07 -07:00
|
|
|
check(ls, TOK_VALUE);
|
2014-07-17 09:16:31 -07:00
|
|
|
eina_strbuf_append(buf, ls->t.value.s);
|
2014-06-18 03:25:07 -07:00
|
|
|
eo_lexer_get(ls);
|
2014-06-20 02:45:55 -07:00
|
|
|
if (ls->t.token != '.') break;
|
2014-06-18 03:25:07 -07:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
}
|
2016-12-27 10:33:12 -08:00
|
|
|
propbeg:
|
2016-12-23 08:24:00 -08:00
|
|
|
if (ls->t.token == '{')
|
|
|
|
{
|
|
|
|
Eina_Bool has_get = EINA_FALSE, has_set = EINA_FALSE;
|
|
|
|
eo_lexer_get(ls);
|
2017-01-18 06:33:44 -08:00
|
|
|
FILL_DOC(ls, impl, common_doc);
|
2016-12-23 08:24:00 -08:00
|
|
|
for (;;) switch (ls->t.kw)
|
|
|
|
{
|
|
|
|
case KW_get:
|
|
|
|
CASE_LOCK(ls, get, "get specifier");
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
impl->is_prop_get = EINA_TRUE;
|
2017-01-11 10:25:54 -08:00
|
|
|
impl->get_auto = glob_auto;
|
|
|
|
impl->get_empty = glob_empty;
|
|
|
|
if (ls->t.kw == KW_at_auto)
|
|
|
|
{
|
|
|
|
impl->get_auto = EINA_TRUE;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
}
|
|
|
|
else if (ls->t.kw == KW_at_empty)
|
|
|
|
{
|
|
|
|
impl->get_empty = EINA_TRUE;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
}
|
2016-12-27 07:05:22 -08:00
|
|
|
check_next(ls, ';');
|
2017-01-18 06:33:44 -08:00
|
|
|
FILL_DOC(ls, impl, get_doc);
|
2016-12-23 08:24:00 -08:00
|
|
|
break;
|
|
|
|
case KW_set:
|
|
|
|
CASE_LOCK(ls, set, "set specifier");
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
impl->is_prop_set = EINA_TRUE;
|
2017-01-11 10:25:54 -08:00
|
|
|
impl->set_auto = glob_auto;
|
|
|
|
impl->set_empty = glob_empty;
|
|
|
|
if (ls->t.kw == KW_at_auto)
|
|
|
|
{
|
|
|
|
impl->set_auto = EINA_TRUE;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
}
|
|
|
|
else if (ls->t.kw == KW_at_empty)
|
|
|
|
{
|
|
|
|
impl->set_empty = EINA_TRUE;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
}
|
2016-12-27 07:05:22 -08:00
|
|
|
check_next(ls, ';');
|
2017-01-18 06:33:44 -08:00
|
|
|
FILL_DOC(ls, impl, set_doc);
|
2016-12-23 08:24:00 -08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
goto propend;
|
|
|
|
}
|
|
|
|
propend:
|
2017-01-02 05:02:44 -08:00
|
|
|
if (!has_get && !has_set)
|
|
|
|
eo_lexer_syntax_error(ls, "property implements need at least get or set specified");
|
2016-12-23 08:24:00 -08:00
|
|
|
check_next(ls, '}');
|
|
|
|
}
|
|
|
|
else
|
2017-01-18 06:33:44 -08:00
|
|
|
{
|
2017-04-19 04:24:38 -07:00
|
|
|
if (glob_auto)
|
|
|
|
impl->get_auto = impl->set_auto = EINA_TRUE;
|
|
|
|
if (glob_empty)
|
|
|
|
impl->get_empty = impl->set_empty = EINA_TRUE;
|
2017-01-18 06:33:44 -08:00
|
|
|
check_next(ls, ';');
|
|
|
|
FILL_DOC(ls, impl, common_doc);
|
|
|
|
}
|
2016-12-27 10:33:12 -08:00
|
|
|
if (buf)
|
|
|
|
{
|
2018-03-08 10:30:40 -08:00
|
|
|
impl->base.name = eina_stringshare_add(eina_strbuf_string_get(buf));
|
2018-03-15 06:12:18 -07:00
|
|
|
eo_lexer_dtor_pop(ls);
|
2016-12-27 10:33:12 -08:00
|
|
|
}
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
|
|
|
|
2014-09-01 07:35:50 -07:00
|
|
|
static void
|
|
|
|
parse_constructor(Eo_Lexer *ls)
|
|
|
|
{
|
|
|
|
Eina_Strbuf *buf = NULL;
|
|
|
|
Eolian_Constructor *ctor = NULL;
|
2014-09-03 01:27:09 -07:00
|
|
|
ctor = calloc(1, sizeof(Eolian_Constructor));
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(ctor->base, ls, ls->line_number, ls->column, CONSTRUCTOR);
|
2018-03-15 04:30:06 -07:00
|
|
|
ls->klass->constructors = eina_list_append(ls->klass->constructors, ctor);
|
2017-12-04 05:44:29 -08:00
|
|
|
eolian_object_ref(&ctor->base);
|
2014-09-01 07:35:50 -07:00
|
|
|
if (ls->t.token == '.')
|
|
|
|
{
|
|
|
|
check_next(ls, '.');
|
|
|
|
if (ls->t.token != TOK_VALUE)
|
|
|
|
eo_lexer_syntax_error(ls, "name expected");
|
2018-03-08 10:30:40 -08:00
|
|
|
ctor->base.name = eina_stringshare_printf("%s.%s",
|
2018-03-15 04:30:06 -07:00
|
|
|
ls->klass->base.name,
|
2014-09-11 03:18:48 -07:00
|
|
|
ls->t.value.s);
|
2014-09-01 07:35:50 -07:00
|
|
|
eo_lexer_get(ls);
|
2018-10-30 18:47:58 -07:00
|
|
|
while (ls->t.kw == KW_at_optional || ls->t.kw == KW_at_ctor_param)
|
2014-11-20 07:21:44 -08:00
|
|
|
{
|
2018-10-30 18:47:58 -07:00
|
|
|
if (ls->t.kw == KW_at_optional)
|
|
|
|
{
|
|
|
|
ctor->is_optional = EINA_TRUE;
|
|
|
|
}
|
|
|
|
if (ls->t.kw == KW_at_ctor_param)
|
|
|
|
{
|
|
|
|
ctor->is_ctor_param = EINA_TRUE;
|
|
|
|
}
|
2014-11-20 07:21:44 -08:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
}
|
2014-09-01 07:35:50 -07:00
|
|
|
check_next(ls, ';');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
check(ls, TOK_VALUE);
|
2018-03-15 06:12:18 -07:00
|
|
|
buf = eina_strbuf_new();
|
|
|
|
eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_strbuf_free), buf);
|
2014-09-01 07:35:50 -07:00
|
|
|
eina_strbuf_append(buf, ls->t.value.s);
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
check_next(ls, '.');
|
|
|
|
check(ls, TOK_VALUE);
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
eina_strbuf_append_char(buf, '.');
|
|
|
|
check(ls, TOK_VALUE);
|
|
|
|
eina_strbuf_append(buf, ls->t.value.s);
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
if (ls->t.token != '.') break;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
}
|
2018-10-30 18:47:58 -07:00
|
|
|
while (ls->t.kw == KW_at_optional || ls->t.kw == KW_at_ctor_param)
|
2014-11-20 07:21:44 -08:00
|
|
|
{
|
2018-10-30 18:47:58 -07:00
|
|
|
if (ls->t.kw == KW_at_optional)
|
|
|
|
{
|
|
|
|
ctor->is_optional = EINA_TRUE;
|
|
|
|
}
|
|
|
|
if (ls->t.kw == KW_at_ctor_param)
|
|
|
|
{
|
|
|
|
ctor->is_ctor_param = EINA_TRUE;
|
|
|
|
}
|
2014-11-20 07:21:44 -08:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
}
|
2014-09-01 07:35:50 -07:00
|
|
|
check_next(ls, ';');
|
2018-03-08 10:30:40 -08:00
|
|
|
ctor->base.name = eina_stringshare_add(eina_strbuf_string_get(buf));
|
2018-03-15 06:12:18 -07:00
|
|
|
eo_lexer_dtor_pop(ls);
|
2014-09-01 07:35:50 -07:00
|
|
|
}
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
static void
|
|
|
|
parse_event(Eo_Lexer *ls)
|
|
|
|
{
|
2014-07-10 07:31:01 -07:00
|
|
|
Eolian_Event *ev = calloc(1, sizeof(Eolian_Event));
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(ev->base, ls, ls->line_number, ls->column, EVENT);
|
2017-01-13 06:15:10 -08:00
|
|
|
ev->scope = EOLIAN_SCOPE_PUBLIC;
|
2018-03-15 06:12:18 -07:00
|
|
|
Eina_Strbuf *buf = eina_strbuf_new();
|
|
|
|
eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_strbuf_free), buf);
|
2018-03-15 04:30:06 -07:00
|
|
|
ls->klass->events = eina_list_append(ls->klass->events, ev);
|
2017-12-04 05:44:29 -08:00
|
|
|
eolian_object_ref(&ev->base);
|
2014-06-18 03:25:07 -07:00
|
|
|
check(ls, TOK_VALUE);
|
2014-07-17 09:16:31 -07:00
|
|
|
eina_strbuf_append(buf, ls->t.value.s);
|
2014-06-18 03:25:07 -07:00
|
|
|
eo_lexer_get(ls);
|
2014-07-16 06:43:40 -07:00
|
|
|
while (ls->t.token == ',')
|
|
|
|
{
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
check(ls, TOK_VALUE);
|
|
|
|
eina_strbuf_append_char(buf, ',');
|
2014-07-17 09:16:31 -07:00
|
|
|
eina_strbuf_append(buf, ls->t.value.s);
|
2014-07-16 06:43:40 -07:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
}
|
2018-03-08 10:30:40 -08:00
|
|
|
ev->base.name = eina_stringshare_add(eina_strbuf_string_get(buf));
|
2018-03-15 06:12:18 -07:00
|
|
|
eo_lexer_dtor_pop(ls);
|
2016-02-02 09:55:01 -08:00
|
|
|
Eina_Bool has_scope = EINA_FALSE, has_beta = EINA_FALSE,
|
2019-03-21 08:17:06 -07:00
|
|
|
has_hot = EINA_FALSE, has_restart = EINA_FALSE;
|
2016-02-02 09:55:01 -08:00
|
|
|
for (;;) switch (ls->t.kw)
|
2014-08-13 03:53:33 -07:00
|
|
|
{
|
2016-02-02 09:55:01 -08:00
|
|
|
case KW_at_private:
|
|
|
|
case KW_at_protected:
|
|
|
|
CASE_LOCK(ls, scope, "scope qualifier")
|
|
|
|
ev->scope = (ls->t.kw == KW_at_private)
|
|
|
|
? EOLIAN_SCOPE_PRIVATE
|
|
|
|
: EOLIAN_SCOPE_PROTECTED;
|
2014-08-13 03:53:33 -07:00
|
|
|
eo_lexer_get(ls);
|
2016-02-02 09:55:01 -08:00
|
|
|
break;
|
|
|
|
case KW_at_beta:
|
|
|
|
CASE_LOCK(ls, beta, "beta qualifier")
|
2019-03-08 05:17:01 -08:00
|
|
|
ev->base.is_beta = EINA_TRUE;
|
2015-05-08 06:22:32 -07:00
|
|
|
eo_lexer_get(ls);
|
2016-02-02 09:55:01 -08:00
|
|
|
break;
|
|
|
|
case KW_at_hot:
|
|
|
|
CASE_LOCK(ls, hot, "hot qualifier");
|
|
|
|
ev->is_hot = EINA_TRUE;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
2016-04-20 15:53:16 -07:00
|
|
|
case KW_at_restart:
|
|
|
|
CASE_LOCK(ls, restart, "restart qualifier");
|
|
|
|
ev->is_restart = EINA_TRUE;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
2016-02-02 09:55:01 -08:00
|
|
|
default:
|
|
|
|
goto end;
|
2015-05-08 06:22:32 -07:00
|
|
|
}
|
2016-02-02 09:55:01 -08:00
|
|
|
end:
|
2018-05-18 16:49:06 -07:00
|
|
|
check_next(ls, ':');
|
2019-02-16 17:11:02 -08:00
|
|
|
ev->type = eo_lexer_type_release(ls, parse_type_void(ls, EINA_TRUE));
|
2014-06-18 03:25:07 -07:00
|
|
|
check(ls, ';');
|
2014-07-16 06:43:40 -07:00
|
|
|
eo_lexer_get(ls);
|
2015-06-03 07:35:13 -07:00
|
|
|
FILL_DOC(ls, ev, doc);
|
2018-03-15 04:30:06 -07:00
|
|
|
ev->klass = ls->klass;
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
parse_methods(Eo_Lexer *ls)
|
|
|
|
{
|
2014-11-21 05:59:42 -08:00
|
|
|
int line, col;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
line = ls->line_number, col = ls->column;
|
|
|
|
check_next(ls, '{');
|
|
|
|
while (ls->t.token != '}')
|
2015-05-07 06:57:46 -07:00
|
|
|
{
|
|
|
|
if (ls->t.kw == KW_at_property)
|
|
|
|
{
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
parse_property(ls);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
parse_method(ls);
|
|
|
|
}
|
2014-07-02 16:00:02 -07:00
|
|
|
check_match(ls, '}', '{', line, col);
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
|
|
|
|
2017-10-24 08:32:58 -07:00
|
|
|
static void
|
|
|
|
parse_parts(Eo_Lexer *ls)
|
|
|
|
{
|
|
|
|
int line, col;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
line = ls->line_number, col = ls->column;
|
|
|
|
check_next(ls, '{');
|
|
|
|
while (ls->t.token != '}')
|
|
|
|
parse_part(ls);
|
|
|
|
check_match(ls, '}', '{', line, col);
|
|
|
|
}
|
|
|
|
|
2019-01-18 08:24:12 -08:00
|
|
|
static void
|
|
|
|
parse_composite(Eo_Lexer *ls)
|
|
|
|
{
|
|
|
|
int line, col;
|
2019-01-23 06:57:48 -08:00
|
|
|
if (ls->klass->type == EOLIAN_CLASS_INTERFACE)
|
|
|
|
eo_lexer_syntax_error(ls, "composite section not allowed in interfaces");
|
2019-01-18 08:24:12 -08:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
line = ls->line_number, col = ls->column;
|
|
|
|
check_next(ls, '{');
|
|
|
|
while (ls->t.token != '}')
|
|
|
|
{
|
|
|
|
Eina_Strbuf *buf = eina_strbuf_new();
|
|
|
|
eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_strbuf_free), buf);
|
|
|
|
eo_lexer_context_push(ls);
|
|
|
|
parse_name(ls, buf);
|
|
|
|
const char *nm = eina_strbuf_string_get(buf);
|
|
|
|
char *fnm = database_class_to_filename(nm);
|
|
|
|
if (!eina_hash_find(ls->state->filenames_eo, fnm))
|
|
|
|
{
|
|
|
|
free(fnm);
|
|
|
|
char ebuf[PATH_MAX];
|
|
|
|
eo_lexer_context_restore(ls);
|
|
|
|
snprintf(ebuf, sizeof(ebuf), "unknown interface '%s'", nm);
|
|
|
|
eo_lexer_syntax_error(ls, ebuf);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* do not introduce a dependency */
|
|
|
|
database_defer(ls->state, fnm, EINA_FALSE);
|
|
|
|
free(fnm);
|
|
|
|
ls->klass->composite = eina_list_append(ls->klass->composite,
|
|
|
|
eina_stringshare_add(nm));
|
|
|
|
eo_lexer_dtor_pop(ls);
|
|
|
|
check_next(ls, ';');
|
|
|
|
}
|
|
|
|
check_match(ls, '}', '{', line, col);
|
|
|
|
}
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
static void
|
2014-06-20 04:24:10 -07:00
|
|
|
parse_implements(Eo_Lexer *ls, Eina_Bool iface)
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
2014-11-21 05:59:42 -08:00
|
|
|
int line, col;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
line = ls->line_number, col = ls->column;
|
|
|
|
check_next(ls, '{');
|
|
|
|
while (ls->t.token != '}')
|
|
|
|
parse_implement(ls, iface);
|
2014-07-02 16:00:02 -07:00
|
|
|
check_match(ls, '}', '{', line, col);
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
|
|
|
|
2014-09-01 07:35:50 -07:00
|
|
|
static void
|
|
|
|
parse_constructors(Eo_Lexer *ls)
|
|
|
|
{
|
2014-11-21 05:59:42 -08:00
|
|
|
int line, col;
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
line = ls->line_number, col = ls->column;
|
|
|
|
check_next(ls, '{');
|
|
|
|
while (ls->t.token != '}')
|
|
|
|
parse_constructor(ls);
|
2014-09-01 07:35:50 -07:00
|
|
|
check_match(ls, '}', '{', line, col);
|
|
|
|
}
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
static void
|
|
|
|
parse_events(Eo_Lexer *ls)
|
|
|
|
{
|
2014-07-02 16:00:02 -07:00
|
|
|
int line, col;
|
2014-06-18 03:25:07 -07:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
line = ls->line_number;
|
2014-07-02 16:00:02 -07:00
|
|
|
col = ls->column;
|
2014-06-18 03:25:07 -07:00
|
|
|
check(ls, '{');
|
2014-07-16 06:43:40 -07:00
|
|
|
eo_lexer_get(ls);
|
2014-06-18 03:25:07 -07:00
|
|
|
while (ls->t.token != '}')
|
2014-09-12 05:25:26 -07:00
|
|
|
parse_event(ls);
|
2014-07-02 16:00:02 -07:00
|
|
|
check_match(ls, '}', '{', line, col);
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
|
|
|
|
2016-03-07 07:01:13 -08:00
|
|
|
static void
|
|
|
|
_validate_pfx(Eo_Lexer *ls)
|
|
|
|
{
|
|
|
|
char ebuf[PATH_MAX];
|
|
|
|
check(ls, TOK_VALUE);
|
|
|
|
const char *str = ls->t.value.s;
|
|
|
|
if ((*str != '_') && ((*str < 'a') || (*str > 'z')))
|
|
|
|
goto error;
|
|
|
|
for (++str; *str; ++str)
|
|
|
|
{
|
|
|
|
if (*str == '_')
|
|
|
|
continue;
|
|
|
|
if ((*str >= 'a') && (*str <= 'z'))
|
|
|
|
continue;
|
|
|
|
if ((*str >= '0') && (*str <= '9'))
|
|
|
|
continue;
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
error:
|
|
|
|
snprintf(ebuf, sizeof(ebuf), "invalid prefix '%s'", ls->t.value.s);
|
|
|
|
eo_lexer_syntax_error(ls, ebuf);
|
|
|
|
}
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
static void
|
2014-08-27 07:38:28 -07:00
|
|
|
parse_class_body(Eo_Lexer *ls, Eolian_Class_Type type)
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
2019-05-09 07:16:42 -07:00
|
|
|
Eina_Bool has_c_prefix = EINA_FALSE,
|
2016-05-17 09:14:47 -07:00
|
|
|
has_event_prefix = EINA_FALSE,
|
2014-06-18 03:25:07 -07:00
|
|
|
has_data = EINA_FALSE,
|
|
|
|
has_methods = EINA_FALSE,
|
2017-10-24 08:32:58 -07:00
|
|
|
has_parts = EINA_FALSE,
|
2019-01-18 08:24:12 -08:00
|
|
|
has_composite = EINA_FALSE,
|
2014-06-18 03:25:07 -07:00
|
|
|
has_implements = EINA_FALSE,
|
2014-09-01 07:35:50 -07:00
|
|
|
has_constructors = EINA_FALSE,
|
2014-06-18 03:25:07 -07:00
|
|
|
has_events = EINA_FALSE;
|
2018-03-15 04:30:06 -07:00
|
|
|
FILL_DOC(ls, ls->klass, doc);
|
2014-07-18 09:29:25 -07:00
|
|
|
if (type == EOLIAN_CLASS_INTERFACE)
|
|
|
|
{
|
2018-03-15 04:30:06 -07:00
|
|
|
ls->klass->data_type = eina_stringshare_add("null");
|
2014-07-18 09:29:25 -07:00
|
|
|
}
|
2014-07-01 10:25:17 -07:00
|
|
|
for (;;) switch (ls->t.kw)
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
2019-05-09 07:16:42 -07:00
|
|
|
case KW_c_prefix:
|
|
|
|
CASE_LOCK(ls, c_prefix, "c prefix definition")
|
2014-07-01 10:25:17 -07:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
check_next(ls, ':');
|
2016-03-07 07:01:13 -08:00
|
|
|
_validate_pfx(ls);
|
2019-05-09 07:16:42 -07:00
|
|
|
ls->klass->c_prefix = eina_stringshare_ref(ls->t.value.s);
|
2014-07-01 10:25:17 -07:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
check_next(ls, ';');
|
|
|
|
break;
|
2016-05-17 09:14:47 -07:00
|
|
|
case KW_event_prefix:
|
|
|
|
CASE_LOCK(ls, event_prefix, "event prefix definition")
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
check_next(ls, ':');
|
|
|
|
_validate_pfx(ls);
|
2018-03-15 04:30:06 -07:00
|
|
|
ls->klass->ev_prefix = eina_stringshare_ref(ls->t.value.s);
|
2016-05-17 09:14:47 -07:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
check_next(ls, ';');
|
|
|
|
break;
|
2014-07-01 10:25:17 -07:00
|
|
|
case KW_data:
|
2014-07-18 09:29:25 -07:00
|
|
|
if (type == EOLIAN_CLASS_INTERFACE) return;
|
2014-07-01 10:25:17 -07:00
|
|
|
CASE_LOCK(ls, data, "data definition")
|
|
|
|
eo_lexer_get(ls);
|
2014-07-16 07:33:11 -07:00
|
|
|
check_next(ls, ':');
|
|
|
|
check(ls, TOK_VALUE);
|
2018-03-15 04:30:06 -07:00
|
|
|
ls->klass->data_type = eina_stringshare_ref(ls->t.value.s);
|
2014-07-01 10:25:17 -07:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
check_next(ls, ';');
|
|
|
|
break;
|
|
|
|
case KW_methods:
|
|
|
|
CASE_LOCK(ls, methods, "methods definition")
|
|
|
|
parse_methods(ls);
|
|
|
|
break;
|
2017-10-24 08:32:58 -07:00
|
|
|
case KW_parts:
|
|
|
|
CASE_LOCK(ls, parts, "parts definition")
|
|
|
|
parse_parts(ls);
|
|
|
|
break;
|
2019-01-18 08:24:12 -08:00
|
|
|
case KW_composite:
|
|
|
|
CASE_LOCK(ls, composite, "composite definition")
|
|
|
|
parse_composite(ls);
|
|
|
|
break;
|
2014-07-01 10:25:17 -07:00
|
|
|
case KW_implements:
|
|
|
|
CASE_LOCK(ls, implements, "implements definition")
|
|
|
|
parse_implements(ls, type == EOLIAN_CLASS_INTERFACE);
|
|
|
|
break;
|
2014-09-01 07:35:50 -07:00
|
|
|
case KW_constructors:
|
|
|
|
if (type == EOLIAN_CLASS_INTERFACE || type == EOLIAN_CLASS_MIXIN)
|
|
|
|
return;
|
|
|
|
CASE_LOCK(ls, constructors, "constructors definition")
|
|
|
|
parse_constructors(ls);
|
|
|
|
break;
|
2014-07-01 10:25:17 -07:00
|
|
|
case KW_events:
|
|
|
|
CASE_LOCK(ls, events, "events definition")
|
|
|
|
parse_events(ls);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-20 07:15:53 -07:00
|
|
|
static void
|
2018-11-22 07:21:52 -08:00
|
|
|
_inherit_dep(Eo_Lexer *ls, Eina_Strbuf *buf, Eina_Bool parent)
|
2015-05-20 07:15:53 -07:00
|
|
|
{
|
2018-11-22 07:21:52 -08:00
|
|
|
char ebuf[PATH_MAX];
|
2018-04-18 06:23:07 -07:00
|
|
|
const char *iname;
|
2015-05-20 07:15:53 -07:00
|
|
|
char *fnm;
|
|
|
|
eina_strbuf_reset(buf);
|
|
|
|
eo_lexer_context_push(ls);
|
|
|
|
parse_name(ls, buf);
|
|
|
|
iname = eina_strbuf_string_get(buf);
|
|
|
|
fnm = database_class_to_filename(iname);
|
|
|
|
if (compare_class_file(fnm, ls->filename))
|
|
|
|
{
|
|
|
|
free(fnm);
|
|
|
|
eo_lexer_context_restore(ls);
|
|
|
|
snprintf(ebuf, sizeof(ebuf), "class '%s' cannot inherit from itself",
|
|
|
|
iname);
|
|
|
|
eo_lexer_syntax_error(ls, ebuf);
|
2015-05-22 03:26:28 -07:00
|
|
|
return; /* unreachable (longjmp above), make static analysis shut up */
|
2015-05-20 07:15:53 -07:00
|
|
|
}
|
2018-04-18 06:23:07 -07:00
|
|
|
if (!eina_hash_find(ls->state->filenames_eo, fnm))
|
2015-05-20 07:15:53 -07:00
|
|
|
{
|
2018-01-30 08:03:37 -08:00
|
|
|
free(fnm);
|
2015-05-20 07:15:53 -07:00
|
|
|
eo_lexer_context_restore(ls);
|
|
|
|
snprintf(ebuf, sizeof(ebuf), "unknown inherit '%s'", iname);
|
|
|
|
eo_lexer_syntax_error(ls, ebuf);
|
2018-01-30 08:03:37 -08:00
|
|
|
return;
|
2015-05-20 07:15:53 -07:00
|
|
|
}
|
2018-01-30 08:03:37 -08:00
|
|
|
|
|
|
|
Eina_Stringshare *inames = eina_stringshare_add(iname), *oiname = NULL;
|
|
|
|
/* never allow duplicate inherits */
|
2018-11-22 07:21:52 -08:00
|
|
|
if (!parent)
|
2016-08-16 17:41:26 -07:00
|
|
|
{
|
2018-11-22 07:21:52 -08:00
|
|
|
Eina_List *l;
|
|
|
|
if (inames == ls->klass->parent_name)
|
|
|
|
goto inherit_dup;
|
|
|
|
EINA_LIST_FOREACH(ls->klass->extends, l, oiname)
|
2018-01-30 08:03:37 -08:00
|
|
|
{
|
2018-11-22 07:21:52 -08:00
|
|
|
if (inames == oiname)
|
|
|
|
goto inherit_dup;
|
2018-01-30 08:03:37 -08:00
|
|
|
}
|
2016-08-16 17:41:26 -07:00
|
|
|
}
|
2018-04-18 06:23:07 -07:00
|
|
|
database_defer(ls->state, fnm, EINA_TRUE);
|
2018-11-22 07:21:52 -08:00
|
|
|
if (parent)
|
|
|
|
ls->klass->parent_name = inames;
|
|
|
|
else
|
|
|
|
ls->klass->extends = eina_list_append(ls->klass->extends, inames);
|
2018-01-30 08:03:37 -08:00
|
|
|
free(fnm);
|
2015-05-20 07:15:53 -07:00
|
|
|
eo_lexer_context_pop(ls);
|
2018-11-22 07:21:52 -08:00
|
|
|
return;
|
|
|
|
|
|
|
|
inherit_dup:
|
|
|
|
free(fnm);
|
|
|
|
eina_stringshare_del(inames);
|
|
|
|
eo_lexer_context_restore(ls);
|
|
|
|
snprintf(ebuf, sizeof(ebuf), "duplicate inherit '%s'", iname);
|
|
|
|
eo_lexer_syntax_error(ls, ebuf);
|
2015-05-20 07:15:53 -07:00
|
|
|
}
|
|
|
|
|
2019-01-10 03:10:47 -08:00
|
|
|
static void
|
|
|
|
_requires_add(Eo_Lexer *ls, Eina_Strbuf *buf)
|
|
|
|
{
|
|
|
|
const char *required;
|
|
|
|
char *fnm;
|
|
|
|
|
|
|
|
eo_lexer_context_push(ls);
|
|
|
|
parse_name(ls, buf);
|
|
|
|
required = eina_strbuf_string_get(buf);
|
|
|
|
fnm = database_class_to_filename(required);
|
|
|
|
|
|
|
|
ls->klass->requires = eina_list_append(ls->klass->requires, eina_stringshare_add(required));
|
|
|
|
database_defer(ls->state, fnm, EINA_TRUE);
|
|
|
|
eo_lexer_context_pop(ls);
|
|
|
|
|
|
|
|
free(fnm);
|
|
|
|
}
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
static void
|
2014-08-27 07:38:28 -07:00
|
|
|
parse_class(Eo_Lexer *ls, Eolian_Class_Type type)
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
2014-07-30 03:57:11 -07:00
|
|
|
const char *bnm;
|
|
|
|
char *fnm;
|
|
|
|
Eina_Bool same;
|
2014-07-02 16:00:02 -07:00
|
|
|
int line, col;
|
2018-03-15 06:12:18 -07:00
|
|
|
Eina_Strbuf *buf = eina_strbuf_new();
|
|
|
|
eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_strbuf_free), buf);
|
2018-03-15 07:42:40 -07:00
|
|
|
ls->klass = (Eolian_Class *)eo_lexer_node_new(ls, sizeof(Eolian_Class));
|
2018-03-15 04:30:06 -07:00
|
|
|
FILL_BASE(ls->klass->base, ls, ls->line_number, ls->column, CLASS);
|
2014-06-18 03:25:07 -07:00
|
|
|
eo_lexer_get(ls);
|
2018-03-15 04:30:06 -07:00
|
|
|
ls->klass->type = type;
|
2014-07-30 07:51:08 -07:00
|
|
|
eo_lexer_context_push(ls);
|
2019-05-30 07:20:09 -07:00
|
|
|
Eina_Stringshare *cname = NULL;
|
|
|
|
Eina_Bool has_beta = EINA_FALSE, has_c_name = EINA_FALSE;
|
|
|
|
for (;;) switch (ls->t.kw)
|
2019-02-13 09:12:59 -08:00
|
|
|
{
|
2019-05-30 07:20:09 -07:00
|
|
|
case KW_at_beta:
|
|
|
|
CASE_LOCK(ls, beta, "beta qualifier");
|
2019-03-08 05:17:01 -08:00
|
|
|
ls->klass->base.is_beta = EINA_TRUE;
|
2019-02-13 09:12:59 -08:00
|
|
|
eo_lexer_get(ls);
|
2019-05-30 07:20:09 -07:00
|
|
|
break;
|
|
|
|
case KW_at_c_name:
|
|
|
|
CASE_LOCK(ls, c_name, "@c_name specifier");
|
|
|
|
cname = parse_c_name(ls);
|
|
|
|
eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_stringshare_del), (void *)cname);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
goto tags_done;
|
2019-02-13 09:12:59 -08:00
|
|
|
}
|
2019-05-30 07:20:09 -07:00
|
|
|
tags_done:
|
2014-06-18 03:25:07 -07:00
|
|
|
parse_name(ls, buf);
|
2014-08-08 07:19:52 -07:00
|
|
|
bnm = eina_stringshare_ref(ls->filename);
|
2014-07-30 03:57:11 -07:00
|
|
|
fnm = database_class_to_filename(eina_strbuf_string_get(buf));
|
2014-08-01 05:59:46 -07:00
|
|
|
same = compare_class_file(bnm, fnm);
|
2014-07-30 03:57:11 -07:00
|
|
|
eina_stringshare_del(bnm);
|
|
|
|
free(fnm);
|
|
|
|
if (!same)
|
2014-07-30 07:51:08 -07:00
|
|
|
{
|
|
|
|
eo_lexer_context_restore(ls);
|
|
|
|
eo_lexer_syntax_error(ls, "class and file names differ");
|
|
|
|
}
|
2018-03-15 04:30:06 -07:00
|
|
|
ls->klass->base.name = eina_stringshare_add(eina_strbuf_string_get(buf));
|
2019-05-30 07:20:09 -07:00
|
|
|
if (cname)
|
|
|
|
{
|
|
|
|
ls->klass->base.c_name = cname;
|
|
|
|
eo_lexer_dtor_pop(ls);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ls->klass->base.c_name = make_c_name(ls->klass->base.name);
|
2018-03-15 04:30:06 -07:00
|
|
|
Eolian_Object *decl = _eolian_decl_get(ls, ls->klass->base.name);
|
2015-05-15 07:10:58 -07:00
|
|
|
if (decl)
|
|
|
|
{
|
|
|
|
eo_lexer_context_restore(ls);
|
2018-03-15 04:30:06 -07:00
|
|
|
redef_error(ls, decl, &ls->klass->base);
|
2015-05-15 07:10:58 -07:00
|
|
|
}
|
|
|
|
eo_lexer_context_pop(ls);
|
2018-03-15 06:12:18 -07:00
|
|
|
eo_lexer_dtor_pop(ls);
|
2018-11-22 08:17:29 -08:00
|
|
|
|
|
|
|
Eina_Bool is_reg = (type == EOLIAN_CLASS_REGULAR) || (type == EOLIAN_CLASS_ABSTRACT);
|
2014-06-19 08:30:18 -07:00
|
|
|
if (ls->t.token != '{')
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
2014-06-19 08:30:18 -07:00
|
|
|
line = ls->line_number;
|
2014-07-02 16:00:02 -07:00
|
|
|
col = ls->column;
|
2018-11-22 08:17:29 -08:00
|
|
|
Eina_Strbuf *ibuf = eina_strbuf_new();
|
|
|
|
eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_strbuf_free), ibuf);
|
|
|
|
/* new inherits syntax, keep alongside old for now */
|
2019-01-10 03:10:47 -08:00
|
|
|
if (ls->t.kw == KW_requires)
|
|
|
|
{
|
|
|
|
if (type != EOLIAN_CLASS_MIXIN)
|
|
|
|
{
|
|
|
|
eo_lexer_syntax_error(ls, "\"requires\" keyword is only needed for mixin classes");
|
|
|
|
}
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
do
|
|
|
|
_requires_add(ls, ibuf);
|
|
|
|
while (test_next(ls, ','));
|
|
|
|
}
|
|
|
|
|
2018-11-22 08:17:29 -08:00
|
|
|
if (ls->t.kw == KW_extends || (is_reg && (ls->t.kw == KW_implements)))
|
|
|
|
{
|
|
|
|
Eina_Bool ext = (ls->t.kw == KW_extends);
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
if (is_reg && ext)
|
|
|
|
{
|
|
|
|
/* regular class can have a parent, but just one */
|
|
|
|
_inherit_dep(ls, ibuf, EINA_TRUE);
|
|
|
|
/* if not followed by implements, we're done */
|
|
|
|
if (ls->t.kw != KW_implements)
|
|
|
|
{
|
|
|
|
eo_lexer_dtor_pop(ls);
|
|
|
|
goto inherit_done;
|
|
|
|
}
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
}
|
|
|
|
do
|
|
|
|
_inherit_dep(ls, ibuf, EINA_FALSE);
|
|
|
|
while (test_next(ls, ','));
|
|
|
|
}
|
|
|
|
eo_lexer_dtor_pop(ls);
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
2018-11-22 08:17:29 -08:00
|
|
|
inherit_done:
|
2014-06-18 03:25:07 -07:00
|
|
|
line = ls->line_number;
|
2014-07-02 16:00:02 -07:00
|
|
|
col = ls->column;
|
2014-06-18 03:25:07 -07:00
|
|
|
check_next(ls, '{');
|
2014-08-27 07:38:28 -07:00
|
|
|
parse_class_body(ls, type);
|
2014-07-02 16:00:02 -07:00
|
|
|
check_match(ls, '}', '{', line, col);
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
|
|
|
|
2014-07-30 03:57:11 -07:00
|
|
|
static Eina_Bool
|
2014-06-24 05:45:51 -07:00
|
|
|
parse_unit(Eo_Lexer *ls, Eina_Bool eot)
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
|
|
|
switch (ls->t.kw)
|
|
|
|
{
|
2014-07-01 10:25:17 -07:00
|
|
|
case KW_abstract:
|
|
|
|
if (eot) goto def;
|
2014-08-27 07:38:28 -07:00
|
|
|
parse_class(ls, EOLIAN_CLASS_ABSTRACT);
|
2014-07-01 10:25:17 -07:00
|
|
|
goto found_class;
|
|
|
|
case KW_class:
|
|
|
|
if (eot) goto def;
|
2014-08-27 07:38:28 -07:00
|
|
|
parse_class(ls, EOLIAN_CLASS_REGULAR);
|
2014-07-01 10:25:17 -07:00
|
|
|
goto found_class;
|
|
|
|
case KW_mixin:
|
|
|
|
if (eot) goto def;
|
2014-08-27 07:38:28 -07:00
|
|
|
parse_class(ls, EOLIAN_CLASS_MIXIN);
|
2014-07-01 10:25:17 -07:00
|
|
|
goto found_class;
|
|
|
|
case KW_interface:
|
|
|
|
if (eot) goto def;
|
2014-08-27 07:38:28 -07:00
|
|
|
parse_class(ls, EOLIAN_CLASS_INTERFACE);
|
2014-07-01 10:25:17 -07:00
|
|
|
goto found_class;
|
2015-05-19 06:25:45 -07:00
|
|
|
case KW_import:
|
2018-04-20 05:45:07 -07:00
|
|
|
case KW_parse:
|
2015-05-19 06:25:45 -07:00
|
|
|
{
|
2018-04-20 05:45:07 -07:00
|
|
|
Eina_Bool isdep = (ls->t.kw == KW_import);
|
2018-03-15 06:12:18 -07:00
|
|
|
Eina_Strbuf *buf = eina_strbuf_new();
|
|
|
|
eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_strbuf_free), buf);
|
2015-05-19 07:26:53 -07:00
|
|
|
char errbuf[PATH_MAX];
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
check(ls, TOK_VALUE);
|
|
|
|
eina_strbuf_append(buf, ls->t.value.s);
|
|
|
|
eina_strbuf_append(buf, ".eot");
|
2018-04-18 06:23:07 -07:00
|
|
|
if (!eina_hash_find(ls->state->filenames_eot, eina_strbuf_string_get(buf)))
|
2015-05-19 07:26:53 -07:00
|
|
|
{
|
2015-05-22 08:34:48 -07:00
|
|
|
size_t buflen = eina_strbuf_length_get(buf);
|
|
|
|
eina_strbuf_remove(buf, buflen - 1, buflen);
|
2018-04-18 06:23:07 -07:00
|
|
|
if (!eina_hash_find(ls->state->filenames_eo, eina_strbuf_string_get(buf)))
|
2015-05-22 08:34:48 -07:00
|
|
|
{
|
2018-03-15 06:12:18 -07:00
|
|
|
eo_lexer_dtor_pop(ls);
|
2015-05-22 08:34:48 -07:00
|
|
|
snprintf(errbuf, sizeof(errbuf),
|
|
|
|
"unknown import '%s'", ls->t.value.s);
|
|
|
|
eo_lexer_syntax_error(ls, errbuf);
|
|
|
|
}
|
2015-05-19 07:26:53 -07:00
|
|
|
}
|
2018-04-20 05:45:07 -07:00
|
|
|
database_defer(ls->state, eina_strbuf_string_get(buf), isdep);
|
2018-03-15 06:12:18 -07:00
|
|
|
eo_lexer_dtor_pop(ls);
|
2015-05-19 06:25:45 -07:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
check_next(ls, ';');
|
|
|
|
break;
|
|
|
|
}
|
2014-07-01 10:25:17 -07:00
|
|
|
case KW_type:
|
|
|
|
{
|
2018-03-15 07:50:53 -07:00
|
|
|
database_type_add(ls->unit,
|
|
|
|
eo_lexer_typedecl_release(ls, parse_typedef(ls)));
|
2014-06-20 06:38:57 -07:00
|
|
|
break;
|
2014-07-01 10:25:17 -07:00
|
|
|
}
|
2017-04-07 09:54:55 -07:00
|
|
|
case KW_function:
|
|
|
|
{
|
2018-03-15 07:50:53 -07:00
|
|
|
database_type_add(ls->unit,
|
|
|
|
eo_lexer_typedecl_release(ls, parse_function_pointer(ls)));
|
2017-04-07 09:54:55 -07:00
|
|
|
break;
|
|
|
|
}
|
2014-08-08 07:57:39 -07:00
|
|
|
case KW_const:
|
|
|
|
case KW_var:
|
|
|
|
{
|
2018-03-15 07:50:53 -07:00
|
|
|
database_var_add(ls->unit, eo_lexer_variable_release(ls,
|
|
|
|
parse_variable(ls, ls->t.kw == KW_var)));
|
2014-08-08 07:57:39 -07:00
|
|
|
break;
|
|
|
|
}
|
2019-06-21 06:05:50 -07:00
|
|
|
case KW_error:
|
|
|
|
database_error_add(ls->unit, eo_lexer_error_release(ls, parse_error(ls)));
|
|
|
|
break;
|
2014-07-08 07:02:36 -07:00
|
|
|
case KW_struct:
|
2014-08-11 06:56:50 -07:00
|
|
|
case KW_enum:
|
2014-07-08 07:02:36 -07:00
|
|
|
{
|
2014-08-11 06:56:50 -07:00
|
|
|
Eina_Bool is_enum = (ls->t.kw == KW_enum);
|
2014-07-08 07:44:42 -07:00
|
|
|
const char *name;
|
2014-07-22 07:27:11 -07:00
|
|
|
int line, col;
|
2019-05-30 07:20:09 -07:00
|
|
|
const char *freefunc = NULL, *cname = NULL;
|
2014-07-21 07:11:19 -07:00
|
|
|
Eina_Strbuf *buf;
|
2014-07-08 07:02:36 -07:00
|
|
|
eo_lexer_get(ls);
|
2019-05-30 07:20:09 -07:00
|
|
|
Eina_Bool has_extern = EINA_FALSE, has_free = EINA_FALSE,
|
|
|
|
has_beta = EINA_FALSE, has_c_name = EINA_FALSE;
|
2019-02-16 17:20:35 -08:00
|
|
|
for (;;) switch (ls->t.kw)
|
|
|
|
{
|
|
|
|
case KW_at_extern:
|
|
|
|
CASE_LOCK(ls, extern, "@extern qualifier")
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
2019-03-08 05:17:01 -08:00
|
|
|
case KW_at_beta:
|
|
|
|
CASE_LOCK(ls, beta, "@beta qualifier")
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
2019-05-30 07:20:09 -07:00
|
|
|
case KW_at_c_name:
|
|
|
|
CASE_LOCK(ls, c_name, "@c_name specifier");
|
|
|
|
cname = parse_c_name(ls);
|
|
|
|
eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_stringshare_del), (void *)cname);
|
|
|
|
break;
|
2019-02-16 17:20:35 -08:00
|
|
|
case KW_at_free:
|
|
|
|
{
|
|
|
|
CASE_LOCK(ls, free, "@free qualifier")
|
|
|
|
if (is_enum)
|
|
|
|
eo_lexer_syntax_error(ls, "enums cannot have @free");
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
int pline = ls->line_number, pcol = ls->column;
|
|
|
|
check_next(ls, '(');
|
|
|
|
check(ls, TOK_VALUE);
|
|
|
|
freefunc = eina_stringshare_add(ls->t.value.s);
|
|
|
|
eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_stringshare_del), (void *)freefunc);
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
check_match(ls, ')', '(', pline, pcol);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
goto postparams;
|
|
|
|
}
|
|
|
|
postparams:
|
2018-03-15 06:12:18 -07:00
|
|
|
buf = eina_strbuf_new();
|
|
|
|
eo_lexer_dtor_push(ls, EINA_FREE_CB(eina_strbuf_free), buf);
|
2014-07-22 07:27:11 -07:00
|
|
|
eo_lexer_context_push(ls);
|
2014-07-21 08:53:25 -07:00
|
|
|
line = ls->line_number;
|
|
|
|
col = ls->column;
|
2014-07-21 07:11:19 -07:00
|
|
|
parse_name(ls, buf);
|
2014-07-22 06:48:08 -07:00
|
|
|
name = eina_stringshare_add(eina_strbuf_string_get(buf));
|
2018-03-08 14:59:40 -08:00
|
|
|
Eolian_Object *decl = _eolian_decl_get(ls, name);
|
2015-05-15 07:10:58 -07:00
|
|
|
if (decl)
|
2014-07-21 08:53:25 -07:00
|
|
|
{
|
2014-07-22 06:48:08 -07:00
|
|
|
eina_stringshare_del(name);
|
2014-07-22 07:27:11 -07:00
|
|
|
eo_lexer_context_restore(ls);
|
2018-03-08 14:59:40 -08:00
|
|
|
Eolian_Typedecl tdecl;
|
|
|
|
tdecl.base.type = EOLIAN_OBJECT_TYPEDECL;
|
2019-02-28 11:25:51 -08:00
|
|
|
tdecl.type =
|
eolian: add support for inlist structs
This adds support for inlist structs, a special type of struct
that can only be used with inlists. This differs from regular
structs in a couple ways:
1) They are stored separately. Just like structs, enums, aliases
have their own storage, so do inlist structs.
2) They can't be @extern, nor they can be opaque.
3) They are their own type of typedecl.
4) When they contain only one field, this field must be a value
type always, cannot be a pointer.
Like regular structs, they can have arbitrary fields, and they
can have a pre-set free function via @free().
In C, the inlist structs will be generated exactly like ordinary
ones, except they will have EINA_INLIST before the first field.
Other binding generators can deal with them as they wish, for
example to provide high level interfaces to them.
This does not yet do the plumbing necessary to hook these into
the type system, nor it adds generator support.
@feature
2019-01-29 06:46:05 -08:00
|
|
|
(is_enum ? EOLIAN_TYPEDECL_ENUM : EOLIAN_TYPEDECL_STRUCT);
|
2018-03-08 14:59:40 -08:00
|
|
|
redef_error(ls, decl, &tdecl.base);
|
2014-07-21 08:53:25 -07:00
|
|
|
}
|
2014-07-22 07:27:11 -07:00
|
|
|
eo_lexer_context_pop(ls);
|
2018-03-15 06:12:18 -07:00
|
|
|
eo_lexer_dtor_pop(ls);
|
2019-02-28 11:25:51 -08:00
|
|
|
if (!is_enum && ls->t.token == ';')
|
2014-08-13 08:43:18 -07:00
|
|
|
{
|
2018-03-15 07:50:53 -07:00
|
|
|
Eolian_Typedecl *def = eo_lexer_typedecl_new(ls);
|
2014-08-19 07:55:31 -07:00
|
|
|
def->is_extern = has_extern;
|
2019-03-08 05:17:01 -08:00
|
|
|
def->base.is_beta = has_beta;
|
2016-03-01 07:37:57 -08:00
|
|
|
def->type = EOLIAN_TYPEDECL_STRUCT_OPAQUE;
|
2018-03-15 08:34:08 -07:00
|
|
|
if (freefunc)
|
2019-07-03 06:03:59 -07:00
|
|
|
{
|
|
|
|
def->freefunc = eina_stringshare_ref(freefunc);
|
|
|
|
def->ownable = EINA_TRUE;
|
|
|
|
}
|
2019-05-30 07:20:09 -07:00
|
|
|
def->base.name = name;
|
|
|
|
if (cname)
|
|
|
|
def->base.c_name = cname;
|
|
|
|
/* we can't know the order, pop when both are filled */
|
|
|
|
if (freefunc && cname)
|
2018-03-15 08:34:08 -07:00
|
|
|
{
|
2019-05-30 07:20:09 -07:00
|
|
|
eo_lexer_dtor_pop(ls);
|
2018-03-15 08:34:08 -07:00
|
|
|
eo_lexer_dtor_pop(ls);
|
|
|
|
}
|
2019-05-30 07:20:09 -07:00
|
|
|
else if (freefunc || cname)
|
|
|
|
eo_lexer_dtor_pop(ls);
|
|
|
|
if (!def->base.c_name)
|
|
|
|
def->base.c_name = make_c_name(name);
|
2014-08-13 08:43:18 -07:00
|
|
|
eo_lexer_get(ls);
|
2015-06-03 07:35:13 -07:00
|
|
|
FILL_DOC(ls, def, doc);
|
2018-03-08 08:30:30 -08:00
|
|
|
FILL_BASE(def->base, ls, line, col, TYPEDECL);
|
2019-02-28 11:25:51 -08:00
|
|
|
database_struct_add(ls->unit, eo_lexer_typedecl_release(ls, def));
|
2014-08-13 08:43:18 -07:00
|
|
|
break;
|
|
|
|
}
|
2014-08-11 06:56:50 -07:00
|
|
|
if (is_enum)
|
2019-05-30 07:20:09 -07:00
|
|
|
parse_enum(ls, name, has_extern, has_beta, line, col, cname);
|
2014-08-11 06:56:50 -07:00
|
|
|
else
|
2019-05-30 07:20:09 -07:00
|
|
|
parse_struct(ls, name, has_extern, has_beta, line, col, freefunc, cname);
|
2014-07-08 17:31:49 -07:00
|
|
|
break;
|
2014-07-08 07:02:36 -07:00
|
|
|
}
|
2014-07-01 10:25:17 -07:00
|
|
|
def:
|
|
|
|
default:
|
|
|
|
eo_lexer_syntax_error(ls, "invalid token");
|
|
|
|
break;
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
2014-07-30 03:57:11 -07:00
|
|
|
return EINA_FALSE;
|
2014-06-20 06:38:57 -07:00
|
|
|
found_class:
|
2018-03-15 04:30:06 -07:00
|
|
|
database_object_add(ls->unit, &ls->klass->base);
|
2014-07-30 03:57:11 -07:00
|
|
|
return EINA_TRUE;
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-06-24 05:45:51 -07:00
|
|
|
parse_chunk(Eo_Lexer *ls, Eina_Bool eot)
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
2019-05-26 09:09:34 -07:00
|
|
|
Eina_Bool parsing_header = EINA_TRUE;
|
|
|
|
Eina_Bool has_version = EINA_FALSE;
|
2014-07-16 08:06:04 -07:00
|
|
|
while (ls->t.token >= 0)
|
2019-05-26 09:09:34 -07:00
|
|
|
switch (ls->t.kw)
|
|
|
|
{
|
|
|
|
case KW_hash_version:
|
|
|
|
{
|
|
|
|
CASE_LOCK(ls, version, "#version specifier");
|
|
|
|
if (!parsing_header)
|
|
|
|
eo_lexer_syntax_error(ls, "header keyword outside of unit header");
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
|
|
|
|
check(ls, TOK_NUMBER);
|
|
|
|
if (ls->t.kw != NUM_INT)
|
|
|
|
eo_lexer_syntax_error(ls, "invalid #version value");
|
|
|
|
if (ls->t.value.u > USHRT_MAX)
|
|
|
|
eo_lexer_syntax_error(ls, "#version too high");
|
2019-05-29 12:02:33 -07:00
|
|
|
else if (ls->t.value.u < 1)
|
2019-05-26 09:09:34 -07:00
|
|
|
eo_lexer_syntax_error(ls, "#version too low");
|
|
|
|
|
|
|
|
ls->unit->version = (unsigned short)(ls->t.value.u);
|
2019-05-26 09:30:02 -07:00
|
|
|
if (ls->unit->version > EOLIAN_FILE_FORMAT_VERSION)
|
|
|
|
eo_lexer_syntax_error(ls, "file version too new for this version of Eolian");
|
2019-05-26 09:09:34 -07:00
|
|
|
eo_lexer_get(ls);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
parsing_header = EINA_FALSE;
|
|
|
|
/* set eot to EINA_TRUE so that we only allow parsing of one class */
|
|
|
|
if (parse_unit(ls, eot))
|
|
|
|
eot = EINA_TRUE;
|
|
|
|
break;
|
|
|
|
}
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
|
|
|
|
2017-12-14 08:18:32 -08:00
|
|
|
Eolian_Unit *
|
2018-01-31 10:06:37 -08:00
|
|
|
eo_parser_database_fill(Eolian_Unit *parent, const char *filename, Eina_Bool eot)
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
2018-03-20 09:34:38 -07:00
|
|
|
int status = 0;
|
2018-01-31 10:14:15 -08:00
|
|
|
const char *fsl = strrchr(filename, '/');
|
|
|
|
const char *bsl = strrchr(filename, '\\');
|
|
|
|
const char *fname = NULL;
|
|
|
|
if (fsl || bsl)
|
|
|
|
fname = eina_stringshare_add((fsl > bsl) ? (fsl + 1) : (bsl + 1));
|
|
|
|
else
|
|
|
|
fname = eina_stringshare_add(filename);
|
|
|
|
|
2018-03-22 09:05:26 -07:00
|
|
|
Eolian_Unit *ret = eina_hash_find(parent->state->main.units, fname);
|
2018-03-22 10:01:31 -07:00
|
|
|
if (!ret)
|
|
|
|
ret = eina_hash_find(parent->state->staging.units, fname);
|
2018-01-31 10:14:15 -08:00
|
|
|
|
|
|
|
if (ret)
|
2018-02-21 07:36:08 -08:00
|
|
|
{
|
2018-03-15 16:09:43 -07:00
|
|
|
if ((parent != ret) && !eina_hash_find(parent->children, fname))
|
|
|
|
eina_hash_add(parent->children, fname, ret);
|
|
|
|
eina_stringshare_del(fname);
|
2018-02-21 07:36:08 -08:00
|
|
|
return ret;
|
|
|
|
}
|
2017-01-20 04:39:45 -08:00
|
|
|
|
2017-12-14 08:18:32 -08:00
|
|
|
Eo_Lexer *ls = eo_lexer_new(parent->state, filename);
|
2017-01-20 04:39:45 -08:00
|
|
|
if (!ls)
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
2018-03-20 09:05:22 -07:00
|
|
|
eolian_state_log(parent->state, "unable to create lexer for file '%s'",
|
|
|
|
filename);
|
2017-01-20 04:39:45 -08:00
|
|
|
goto error;
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
2017-01-20 04:39:45 -08:00
|
|
|
|
|
|
|
/* read first token */
|
|
|
|
eo_lexer_get(ls);
|
|
|
|
|
2018-03-20 09:34:38 -07:00
|
|
|
if ((status = setjmp(ls->err_jmp)))
|
2017-01-20 04:39:45 -08:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
parse_chunk(ls, eot);
|
|
|
|
if (eot) goto done;
|
|
|
|
|
2018-01-31 10:06:37 -08:00
|
|
|
Eolian_Class *cl;
|
2018-03-15 04:30:06 -07:00
|
|
|
if (!(cl = ls->klass))
|
2017-01-20 04:39:45 -08:00
|
|
|
{
|
2018-03-20 09:05:22 -07:00
|
|
|
eolian_state_log(ls->state, "no class for file '%s'", filename);
|
2017-01-20 04:39:45 -08:00
|
|
|
goto error;
|
|
|
|
}
|
2018-03-15 07:42:40 -07:00
|
|
|
ls->klass = NULL;
|
2018-03-08 10:30:40 -08:00
|
|
|
EOLIAN_OBJECT_ADD(ls->unit, cl->base.name, cl, classes);
|
2018-03-22 10:01:31 -07:00
|
|
|
eina_hash_set(ls->state->staging.classes_f, cl->base.file, cl);
|
2018-03-15 07:42:40 -07:00
|
|
|
eo_lexer_node_release(ls, &cl->base);
|
2017-01-20 04:39:45 -08:00
|
|
|
|
|
|
|
done:
|
2017-12-18 15:20:40 -08:00
|
|
|
ret = ls->unit;
|
2018-03-15 16:09:43 -07:00
|
|
|
eina_hash_add(parent->children, fname, ret);
|
|
|
|
eina_stringshare_del(fname);
|
2017-01-20 04:39:45 -08:00
|
|
|
|
|
|
|
eo_lexer_free(ls);
|
2017-12-18 15:20:40 -08:00
|
|
|
return ret;
|
2017-01-20 04:39:45 -08:00
|
|
|
|
|
|
|
error:
|
2018-03-15 16:09:43 -07:00
|
|
|
eina_stringshare_del(fname);
|
2017-01-20 04:39:45 -08:00
|
|
|
eo_lexer_free(ls);
|
2018-03-20 09:34:38 -07:00
|
|
|
switch (status)
|
|
|
|
{
|
|
|
|
case EO_LEXER_ERROR_OOM:
|
|
|
|
eolian_state_panic(parent->state, "out of memory");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2017-12-14 08:18:32 -08:00
|
|
|
return NULL;
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|