Introducing new lexer/parser for Eolian

This set of changes introduces a new, handwritten lexer+parser in Eolian. This should
allow for easier maintenance as well as easier feature additions. Unlike the previous
effort, this separates lexer and parser part (but they still run at the same stage).

In long term some more APIs should get exposed (for IDEs and other tools). The parser
is also stricter and more conformant to the actual format so several issues with
existing Eo files were caught previously.

Merges branch 'devs/q66/eolian_new_parser'

@feature
This commit is contained in:
Daniel Kolesa 2014-06-19 16:32:13 +01:00
commit f6c13708c5
13 changed files with 1934 additions and 6412 deletions

View File

@ -334,11 +334,6 @@ fi
AM_CONDITIONAL([EFL_ENABLE_COVERAGE], [test "${want_coverage}" = "yes"])
# ragel
AC_CHECK_PROG([have_ragel], [ragel], [yes], [no])
AM_CONDITIONAL([EFL_HAVE_RAGEL], [test "${have_ragel}" = "yes"])
#### Checks for libraries
# check unit testing library

View File

@ -11,6 +11,8 @@ lib_eolian_libeolian_la_SOURCES = \
lib/eolian/eo_definitions.h \
lib/eolian/eo_lexer.c \
lib/eolian/eo_lexer.h \
lib/eolian/eo_parser.c \
lib/eolian/eo_parser.h \
lib/eolian/eolian.c \
lib/eolian/eolian_database.c \
lib/eolian/eolian_database.h
@ -43,21 +45,6 @@ bin_eolian_eolian_gen_DEPENDENCIES = @USE_EOLIAN_INTERNAL_LIBS@
### Helper for other modules using Eolian
include Makefile_Eolian_Helper.am
EXTRA_DIST += lib/eolian/eo_lexer.rl
if EFL_HAVE_RAGEL
SUFFIXES += .rl
AM_V_RAGEL = $(am__v_RAGEL_@AM_V@)
am__v_RAGEL_ = $(am__v_RAGEL_@AM_DEFAULT_V@)
am__v_RAGEL_0 = @echo " RAGEL " $@;
.rl.c:
$(AM_V_RAGEL) ragel -o $@ $<
lib/eolian/eo_lexer.c: lib/eolian/eo_lexer.rl
endif
### Unit tests
if EFL_ENABLE_TESTS

View File

@ -382,11 +382,11 @@ int main(int argc, char **argv)
ERR("Bad generation option\n");
break;
}
free(output_filename);
}
else ret = 0;
end:
free(output_filename);
eina_list_free(files4gen);
eina_log_timing(_eolian_gen_log_dom,

View File

@ -2,20 +2,21 @@
#include <stdlib.h>
#include "eo_definitions.h"
#include "eolian_database.h"
static void
eo_definitions_ret_free(Eo_Ret_Def *ret)
{
if (ret->type) eina_stringshare_del(ret->type);
if (ret->type) database_type_del(ret->type);
if (ret->comment) eina_stringshare_del(ret->comment);
if (ret->dflt_ret_val) free(ret->dflt_ret_val);
if (ret->dflt_ret_val) eina_stringshare_del(ret->dflt_ret_val);
free(ret);
}
static void
eo_definitions_param_free(Eo_Param_Def *param)
{
if (param->type) eina_stringshare_del(param->type);
if (param->type) database_type_del(param->type);
if (param->name) eina_stringshare_del(param->name);
if (param->comment) eina_stringshare_del(param->comment);
free(param);
@ -117,8 +118,9 @@ eo_definitions_type_def_free(Eo_Type_Def *type)
{
if (type->alias)
eina_stringshare_del(type->alias);
if (type->type)
eina_stringshare_del(type->type);
database_type_del(type->type);
free(type);
}
@ -127,7 +129,6 @@ void
eo_definitions_class_def_free(Eo_Class_Def *kls)
{
const char *s;
Eina_List *l;
Eo_Property_Def *prop;
Eo_Method_Def *meth;
Eo_Event_Def *sgn;
@ -144,7 +145,7 @@ eo_definitions_class_def_free(Eo_Class_Def *kls)
if (kls->data_type)
eina_stringshare_del(kls->data_type);
EINA_LIST_FOREACH(kls->inherits, l, s)
EINA_LIST_FREE(kls->inherits, s)
if (s) eina_stringshare_del(s);
EINA_LIST_FREE(kls->implements, impl)
@ -165,3 +166,55 @@ eo_definitions_class_def_free(Eo_Class_Def *kls)
free(kls);
}
void
eo_definitions_temps_free(Eo_Lexer_Temps *tmp)
{
Eina_Strbuf *buf;
Eo_Param_Def *par;
const char *s;
EINA_LIST_FREE(tmp->str_bufs, buf)
eina_strbuf_free(buf);
EINA_LIST_FREE(tmp->params, par)
eo_definitions_param_free(par);
if (tmp->legacy_def)
eina_stringshare_del(tmp->legacy_def);
if (tmp->kls)
eo_definitions_class_def_free(tmp->kls);
if (tmp->ret_def)
eo_definitions_ret_free(tmp->ret_def);
if (tmp->type_def)
eo_definitions_type_def_free(tmp->type_def);
if (tmp->prop)
eo_definitions_property_def_free(tmp->prop);
if (tmp->meth)
eo_definitions_method_def_free(tmp->meth);
if (tmp->param)
eo_definitions_param_free(tmp->param);
if (tmp->accessor)
eo_definitions_accessor_free(tmp->accessor);
if (tmp->accessor_param)
eo_definitions_accessor_param_free(tmp->accessor_param);
EINA_LIST_FREE(tmp->str_items, s)
if (s) eina_stringshare_del(s);
if (tmp->event)
eo_definitions_event_def_free(tmp->event);
if (tmp->impl)
eo_definitions_impl_def_free(tmp->impl);
if (tmp->type)
database_type_del(tmp->type);
}

View File

@ -8,9 +8,9 @@
typedef struct _eo_ret_def
{
const char *type;
Eolian_Type type;
const char *comment;
char *dflt_ret_val;
const char *dflt_ret_val;
Eina_Bool warn_unused:1;
} Eo_Ret_Def;
@ -27,7 +27,7 @@ typedef enum _param_way
typedef struct _eo_param_def
{
Param_Way way;
const char *type;
Eolian_Type type;
const char *name;
const char *comment;
Eina_Bool nonull:1;
@ -73,7 +73,6 @@ typedef struct _eo_property_def
typedef enum _eo_method_type {
METH_REGULAR,
METH_CONSTRUCTOR,
METH_DESTRUCTOR,
METH_TYPE_LAST
} Eo_Method_Type;
@ -100,13 +99,6 @@ typedef struct _eo_event_def
/* IMPLEMENT */
typedef struct _eo_implement_legacy_param_def
{
const char *eo_name;
const char *legacy_name;
const char *comment;
} Eo_Implement_Legacy_Param_Def;
typedef struct _eo_implement_def
{
const char *meth_name;
@ -135,10 +127,32 @@ typedef struct _eo_class_def
typedef struct _eo_type_def
{
const char *alias;
const char *type;
Eolian_Type type;
} Eo_Type_Def;
/* TEMPS */
typedef struct _Eo_Lexer_Temps
{
Eina_List *str_bufs;
Eina_List *params;
const char *legacy_def;
Eo_Class_Def *kls;
Eo_Ret_Def *ret_def;
Eo_Type_Def *type_def;
Eo_Property_Def *prop;
Eo_Method_Def *meth;
Eo_Param_Def *param;
Eo_Accessor_Def *accessor;
Eo_Accessor_Param *accessor_param;
Eina_List *str_items;
Eo_Event_Def *event;
Eo_Implement_Def *impl;
Eolian_Type type;
} Eo_Lexer_Temps;
void eo_definitions_class_def_free(Eo_Class_Def *kls);
void eo_definitions_type_def_free(Eo_Type_Def *type);
void eo_definitions_temps_free(Eo_Lexer_Temps *tmp);
#endif /* __EO_DEFINITIONS_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,72 +1,104 @@
#ifndef __EO_TOKENIZER_H__
#define __EO_TOKENIZER_H__
#ifndef __EO_LEXER_H__
#define __EO_LEXER_H__
#include <setjmp.h>
#include <Eina.h>
#include <Eolian.h>
#include "eo_definitions.h"
/* TOKENIZER */
#define START_CUSTOM 257
#define BUFSIZE 256*1024
typedef struct _eo_tokenizer
enum Tokens
{
/* ragel vars */
int cs; /* current machine state */
int act; /* last pattern matched */
char *ts; /* current token match start */
char *te; /* current token match end */
char *p; /* data start */
char *pe; /* data end */
char *eof; /* eof = (EOF ? pe : NULL) */
/* int stack[10]; /1* state stack used by fret fcall ... *1/ */
/* int top; /1* stack pointer *1/ */
TOK_DBCOLON = START_CUSTOM, TOK_COMMENT, TOK_EOF, TOK_VALUE
};
const char *source;
int current_line;
int current_nesting;
int max_nesting;
Eo_Method_Type current_methods_type;
char buf[BUFSIZE];
struct {
char *tok;
int line;
} saved;
#define KEYWORDS KW(class), KW(const), KW(private), KW(protected), \
KW(return), KW(signed), KW(struct), KW(unsigned), KW(virtual), \
KW(abstract), KW(constructor), KW(constructors), KW(data), \
KW(destructor), KW(eo_prefix), KW(events), KW(get), KW(implements), \
KW(interface), KW(keys), KW(legacy), KW(legacy_prefix), KW(methods), \
KW(mixin), KW(params), KW(properties), KW(set), KW(type), KW(values), \
KWAT(in), KWAT(inout), KWAT(nonull), KWAT(out), KWAT(own), KWAT(warn_unused)
Eina_List *classes;
Eina_List *typedefs;
struct {
Eina_List **params;
Eolian_Class_Type kls_type;
const char *typedef_alias;
Eo_Class_Def *kls;
Eo_Type_Def *type_def;
Eo_Property_Def *prop;
Eo_Method_Def *meth;
Eo_Param_Def *param;
Eo_Accessor_Def *accessor;
Eo_Accessor_Param *accessor_param;
Eina_List *str_items;
Eo_Event_Def *event;
Eo_Implement_Def *impl;
Eo_Implement_Legacy_Param_Def *impl_leg_param;
int fscope;
} tmp;
#define KW(x) KW_##x
#define KWAT(x) KW_at_##x
} Eo_Tokenizer;
enum Keywords
{
KW_UNKNOWN = 0,
KEYWORDS,
NUM_KEYWORDS
};
int eo_tokenizer_init();
#undef KW
#undef KWAT
int eo_tokenizer_shutdown();
typedef struct _Eo_Token
{
int token;
const char *value;
int kw;
} Eo_Token;
Eo_Tokenizer* eo_tokenizer_get(void);
typedef struct _Eo_Lexer
{
int current;
int line_number;
Eo_Token t, lookahead;
Eina_Strbuf *buff;
Eina_File *handle;
const char *source;
const char *stream;
jmp_buf err_jmp;
Eina_Bool eo_tokenizer_walk(Eo_Tokenizer *toknz, const char *source);
Eina_List *classes;
Eina_List *typedefs;
Eo_Lexer_Temps tmp;
} Eo_Lexer;
void eo_tokenizer_dump(Eo_Tokenizer *toknz);
int eo_lexer_init (void);
int eo_lexer_shutdown (void);
Eo_Lexer *eo_lexer_new (const char *source);
void eo_lexer_free (Eo_Lexer *ls);
int eo_lexer_get_balanced (Eo_Lexer *ls, char beg, char end);
int eo_lexer_get_until (Eo_Lexer *ls, char end);
int eo_lexer_get (Eo_Lexer *ls);
int eo_lexer_get_ident (Eo_Lexer *ls, const char *chars);
int eo_lexer_lookahead (Eo_Lexer *ls);
int eo_lexer_lookahead_ident(Eo_Lexer *ls, const char *chars);
void eo_lexer_lex_error (Eo_Lexer *ls, const char *msg, int token);
void eo_lexer_syntax_error (Eo_Lexer *ls, const char *msg);
void eo_lexer_token_to_str (int token, char *buf);
void eo_tokenizer_free(Eo_Tokenizer *toknz);
extern int _eo_lexer_log_dom;
#ifdef CRITICAL
#undef CRITICAL
#endif
#define CRITICAL(...) EINA_LOG_DOM_CRIT(_eo_lexer_log_dom, __VA_ARGS__)
Eina_Bool eo_tokenizer_database_fill(const char *filename);
#ifdef ERR
#undef ERR
#endif
#define ERR(...) EINA_LOG_DOM_ERR(_eo_lexer_log_dom, __VA_ARGS__)
#endif /* __EO_TOKENIZER_H__ */
#ifdef WRN
#undef WRN
#endif
#define WRN(...) EINA_LOG_DOM_WARN(_eo_lexer_log_dom, __VA_ARGS__)
#define INF_ENABLED EINA_FALSE
#ifdef INF
#undef INF
#endif
#define INF(...) if (INF_ENABLED) EINA_LOG_DOM_INFO(_eo_lexer_log_dom, __VA_ARGS__)
#define DBG_ENABLED EINA_FALSE
#ifdef DBG
#undef DBG
#endif
#define DBG(...) if (DBG_ENABLED) EINA_LOG_DOM_DBG(_eo_lexer_log_dom, __VA_ARGS__)
#endif /* __EO_LEXER_H__ */

File diff suppressed because it is too large Load Diff

1356
src/lib/eolian/eo_parser.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
#ifndef __EO_PARSER_H__
#define __EO_PARSER_H__
#include "eo_lexer.h"
Eina_Bool eo_parser_walk (Eo_Lexer *ls);
void eo_parser_dump (Eo_Lexer *ls);
Eina_Bool eo_parser_database_fill(const char *filename);
#endif /* __EO_PARSER_H__ */

View File

@ -1,4 +1,4 @@
#include "eo_lexer.h"
#include "eo_parser.h"
#include "eolian_database.h"
static int _eolian_init_counter = 0;
@ -23,7 +23,7 @@ EAPI int eolian_init(void)
INF("Init");
database_init();
eo_tokenizer_init();
eo_lexer_init();
return ++_eolian_init_counter;
}
@ -43,7 +43,7 @@ EAPI int eolian_shutdown(void)
EINA_LOG_STATE_START,
EINA_LOG_STATE_SHUTDOWN);
eo_tokenizer_shutdown();
eo_lexer_shutdown();
database_shutdown();
eina_log_domain_unregister(_eolian_log_dom);

View File

@ -1,5 +1,5 @@
#include <Eina.h>
#include "eo_lexer.h"
#include "eo_parser.h"
#include "eolian_database.h"
#define PROP_GET_RETURN_DFLT_VAL "property_get_return_dflt_val"
@ -1413,7 +1413,7 @@ EAPI Eina_Bool eolian_eo_file_parse(const char *filepath)
Eolian_Implement impl;
if (!class)
{
if (!eo_tokenizer_database_fill(filepath)) return EINA_FALSE;
if (!eo_parser_database_fill(filepath)) return EINA_FALSE;
class = eolian_class_find_by_file(filepath);
if (!class)
{

View File

@ -8,7 +8,7 @@ class Simple {
get {
}
}
public c {
c {
get {
}
}
@ -18,7 +18,7 @@ class Simple {
}
protected bar {
}
public foobar {
foobar {
}
}
};