2014-03-29 21:07:19 -07:00
|
|
|
#include <stdio.h>
|
2014-06-18 03:25:07 -07:00
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
#include <setjmp.h>
|
|
|
|
#include <assert.h>
|
2014-03-29 21:07:19 -07:00
|
|
|
|
|
|
|
#include "eo_lexer.h"
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
int _eo_lexer_log_dom = -1;
|
2014-03-29 21:07:19 -07:00
|
|
|
|
2014-07-02 15:39:35 -07:00
|
|
|
static int lastbytes = 0;
|
|
|
|
|
|
|
|
static void
|
|
|
|
next_char(Eo_Lexer *ls)
|
|
|
|
{
|
|
|
|
int nb;
|
2014-07-02 16:04:30 -07:00
|
|
|
Eina_Bool end = EINA_FALSE;
|
2014-07-02 15:39:35 -07:00
|
|
|
|
2014-06-20 02:45:55 -07:00
|
|
|
if (ls->stream == ls->stream_end)
|
2014-07-02 16:04:30 -07:00
|
|
|
{
|
|
|
|
end = EINA_TRUE;
|
|
|
|
ls->current = '\0';
|
|
|
|
}
|
2014-06-20 02:45:55 -07:00
|
|
|
else
|
|
|
|
ls->current = *(ls->stream++);
|
2014-07-02 15:39:35 -07:00
|
|
|
|
|
|
|
nb = lastbytes;
|
2014-07-02 16:04:30 -07:00
|
|
|
if (!nb && end) nb = 1;
|
|
|
|
if (!nb) eina_unicode_utf8_next_get(ls->stream - 1, &nb);
|
2014-07-02 15:39:35 -07:00
|
|
|
|
|
|
|
if (nb == 1)
|
|
|
|
{
|
|
|
|
nb = 0;
|
|
|
|
++ls->column;
|
|
|
|
}
|
|
|
|
else --nb;
|
|
|
|
|
|
|
|
lastbytes = nb;
|
2014-06-20 02:45:55 -07:00
|
|
|
}
|
2014-03-29 21:07:19 -07:00
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
#define KW(x) #x
|
|
|
|
#define KWAT(x) "@" #x
|
2014-03-29 21:07:19 -07:00
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
static const char * const tokens[] =
|
|
|
|
{
|
2014-06-20 02:45:55 -07:00
|
|
|
"<comment>", "<eof>", "<value>",
|
2014-03-29 21:07:19 -07:00
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
KEYWORDS
|
|
|
|
};
|
2014-03-29 21:07:19 -07:00
|
|
|
|
2014-06-26 04:02:19 -07:00
|
|
|
static const char * const ctypes[] =
|
|
|
|
{
|
|
|
|
"char", "unsigned char", "signed char", "short", "unsigned short",
|
|
|
|
"int", "unsigned int", "long", "unsigned long", "long long",
|
2014-06-26 06:11:52 -07:00
|
|
|
"unsigned long long",
|
|
|
|
|
|
|
|
"int8_t", "uint8_t", "int16_t", "uint16_t", "int32_t", "uint32_t",
|
|
|
|
"int64_t", "uint64_t", "int128_t", "uint128_t",
|
|
|
|
|
|
|
|
"float", "double", "long double",
|
|
|
|
|
|
|
|
"void"
|
2014-06-26 04:02:19 -07:00
|
|
|
};
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
#undef KW
|
|
|
|
#undef KWAT
|
2014-04-03 06:20:58 -07:00
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
static Eina_Hash *keyword_map = NULL;
|
2014-03-29 21:07:19 -07:00
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
static void
|
|
|
|
throw(Eo_Lexer *ls, const char *fmt, ...)
|
2014-03-29 21:07:19 -07:00
|
|
|
{
|
2014-06-18 03:25:07 -07:00
|
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
|
|
vfprintf(stderr, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
longjmp(ls->err_jmp, EINA_TRUE);
|
2014-03-29 21:07:19 -07:00
|
|
|
}
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
static void
|
|
|
|
init_hash(void)
|
2014-03-29 21:07:19 -07:00
|
|
|
{
|
2014-06-18 03:25:07 -07:00
|
|
|
unsigned int i;
|
|
|
|
if (keyword_map) return;
|
|
|
|
keyword_map = eina_hash_string_superfast_new(NULL);
|
2014-06-20 02:45:55 -07:00
|
|
|
for (i = 3; i < (sizeof(tokens) / sizeof(const char*)); ++i)
|
2014-03-29 21:07:19 -07:00
|
|
|
{
|
2014-06-20 02:45:55 -07:00
|
|
|
eina_hash_add(keyword_map, tokens[i], (void*)(size_t)(i - 2));
|
2014-03-29 21:07:19 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-06-18 03:25:07 -07:00
|
|
|
destroy_hash(void)
|
2014-03-29 21:07:19 -07:00
|
|
|
{
|
2014-06-18 03:25:07 -07:00
|
|
|
if (keyword_map)
|
2014-03-29 21:07:19 -07:00
|
|
|
{
|
2014-06-18 03:25:07 -07:00
|
|
|
eina_hash_free(keyword_map);
|
|
|
|
keyword_map = NULL;
|
2014-03-29 21:07:19 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
static void
|
|
|
|
txt_token(Eo_Lexer *ls, int token, char *buf)
|
2014-03-29 21:07:19 -07:00
|
|
|
{
|
2014-06-18 03:25:07 -07:00
|
|
|
if (token == TOK_VALUE)
|
2014-03-29 21:07:19 -07:00
|
|
|
{
|
2014-06-18 03:25:07 -07:00
|
|
|
const char *str = eina_strbuf_string_get(ls->buff);
|
|
|
|
memcpy(buf, str, strlen(str) + 1);
|
2014-03-29 21:07:19 -07:00
|
|
|
}
|
2014-06-18 03:25:07 -07:00
|
|
|
else
|
|
|
|
return eo_lexer_token_to_str(token, buf);
|
2014-03-29 21:07:19 -07:00
|
|
|
}
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
void eo_lexer_lex_error (Eo_Lexer *ls, const char *msg, int token);
|
|
|
|
void eo_lexer_syntax_error(Eo_Lexer *ls, const char *msg);
|
2014-03-29 21:07:19 -07:00
|
|
|
|
2014-06-20 02:45:55 -07:00
|
|
|
#define is_newline(c) ((c) == '\n' || (c) == '\r')
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
static void next_line(Eo_Lexer *ls)
|
2014-03-29 21:07:19 -07:00
|
|
|
{
|
2014-06-18 03:25:07 -07:00
|
|
|
int old = ls->current;
|
2014-06-20 02:45:55 -07:00
|
|
|
assert(is_newline(ls->current));
|
2014-06-18 03:25:07 -07:00
|
|
|
next_char(ls);
|
2014-06-20 02:45:55 -07:00
|
|
|
if (is_newline(ls->current) && ls->current != old)
|
2014-07-01 10:25:17 -07:00
|
|
|
next_char(ls);
|
2014-06-18 03:25:07 -07:00
|
|
|
if (++ls->line_number >= INT_MAX)
|
2014-07-01 10:25:17 -07:00
|
|
|
eo_lexer_syntax_error(ls, "chunk has too many lines");
|
2014-07-02 15:39:35 -07:00
|
|
|
ls->column = 0;
|
2014-03-29 21:07:19 -07:00
|
|
|
}
|
|
|
|
|
2014-06-18 04:59:22 -07:00
|
|
|
/* go to next line and strip leading whitespace */
|
|
|
|
static void next_line_ws(Eo_Lexer *ls)
|
|
|
|
{
|
|
|
|
next_line(ls);
|
2014-06-20 02:45:55 -07:00
|
|
|
while (isspace(ls->current) && !is_newline(ls->current))
|
2014-06-18 04:59:22 -07:00
|
|
|
next_char(ls);
|
|
|
|
}
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
static void
|
|
|
|
read_long_comment(Eo_Lexer *ls, const char **value)
|
2014-03-29 21:07:19 -07:00
|
|
|
{
|
2014-06-18 03:25:07 -07:00
|
|
|
eina_strbuf_reset(ls->buff);
|
2014-06-18 04:59:22 -07:00
|
|
|
|
2014-06-20 02:45:55 -07:00
|
|
|
if (is_newline(ls->current))
|
2014-07-01 10:25:17 -07:00
|
|
|
next_line_ws(ls);
|
2014-06-18 04:59:22 -07:00
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
for (;;)
|
2014-03-29 21:07:19 -07:00
|
|
|
{
|
2014-06-18 03:25:07 -07:00
|
|
|
if (!ls->current)
|
2014-07-01 10:25:17 -07:00
|
|
|
eo_lexer_lex_error(ls, "unfinished long comment", TOK_EOF);
|
2014-06-18 03:25:07 -07:00
|
|
|
if (ls->current == '*')
|
2014-03-29 21:07:19 -07:00
|
|
|
{
|
2014-06-18 03:25:07 -07:00
|
|
|
next_char(ls);
|
|
|
|
if (ls->current == '/')
|
|
|
|
{
|
|
|
|
next_char(ls);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
eina_strbuf_append_char(ls->buff, '*');
|
2014-03-29 21:07:19 -07:00
|
|
|
}
|
2014-06-20 02:45:55 -07:00
|
|
|
else if (is_newline(ls->current))
|
2014-03-29 21:07:19 -07:00
|
|
|
{
|
2014-06-18 03:25:07 -07:00
|
|
|
eina_strbuf_append_char(ls->buff, '\n');
|
2014-06-18 04:59:22 -07:00
|
|
|
next_line_ws(ls);
|
2014-03-29 21:07:19 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-06-18 03:25:07 -07:00
|
|
|
eina_strbuf_append_char(ls->buff, ls->current);
|
|
|
|
next_char(ls);
|
2014-03-29 21:07:19 -07:00
|
|
|
}
|
|
|
|
}
|
2014-06-18 04:59:22 -07:00
|
|
|
eina_strbuf_trim(ls->buff);
|
2014-06-18 03:25:07 -07:00
|
|
|
if (value) *value = eina_strbuf_string_get(ls->buff);
|
2014-03-29 21:07:19 -07:00
|
|
|
}
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
static int
|
|
|
|
lex(Eo_Lexer *ls, const char **value, int *kwid, const char *chars)
|
2014-03-29 21:07:19 -07:00
|
|
|
{
|
2014-06-18 03:25:07 -07:00
|
|
|
eina_strbuf_reset(ls->buff);
|
2014-07-01 10:25:17 -07:00
|
|
|
for (;;) switch (ls->current)
|
2014-03-29 21:07:19 -07:00
|
|
|
{
|
2014-07-01 10:25:17 -07:00
|
|
|
case '\n':
|
|
|
|
case '\r':
|
|
|
|
next_line(ls);
|
|
|
|
continue;
|
|
|
|
case '/':
|
|
|
|
next_char(ls);
|
|
|
|
if (ls->current == '*')
|
2014-06-18 03:25:07 -07:00
|
|
|
{
|
2014-07-01 10:25:17 -07:00
|
|
|
Eina_Bool doc;
|
|
|
|
next_char(ls);
|
|
|
|
if ((doc = (ls->current == '@')))
|
|
|
|
next_char(ls);
|
|
|
|
read_long_comment(ls, doc ? value : NULL);
|
|
|
|
if (doc)
|
|
|
|
return TOK_COMMENT;
|
|
|
|
else
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (ls->current != '/') return '/';
|
|
|
|
while (ls->current && !is_newline(ls->current))
|
|
|
|
next_char(ls);
|
|
|
|
continue;
|
|
|
|
case '\0':
|
|
|
|
return TOK_EOF;
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
if (isspace(ls->current))
|
|
|
|
{
|
|
|
|
assert(!is_newline(ls->current));
|
|
|
|
next_char(ls);
|
2014-06-18 03:25:07 -07:00
|
|
|
continue;
|
2014-07-01 10:25:17 -07:00
|
|
|
}
|
|
|
|
if (ls->current && (isalnum(ls->current)
|
|
|
|
|| ls->current == '@'
|
|
|
|
|| strchr(chars, ls->current)))
|
|
|
|
{
|
2014-07-02 15:39:35 -07:00
|
|
|
int col = ls->column;
|
2014-07-01 10:25:17 -07:00
|
|
|
Eina_Bool at_kw = (ls->current == '@');
|
|
|
|
const char *str;
|
|
|
|
eina_strbuf_reset(ls->buff);
|
|
|
|
do
|
|
|
|
{
|
|
|
|
eina_strbuf_append_char(ls->buff, ls->current);
|
2014-06-18 03:25:07 -07:00
|
|
|
next_char(ls);
|
2014-07-01 10:25:17 -07:00
|
|
|
}
|
|
|
|
while (ls->current && (isalnum(ls->current)
|
|
|
|
|| strchr(chars, ls->current)));
|
|
|
|
str = eina_strbuf_string_get(ls->buff);
|
|
|
|
*kwid = (int)(uintptr_t)eina_hash_find(keyword_map,
|
|
|
|
str);
|
2014-07-02 15:39:35 -07:00
|
|
|
ls->column = col;
|
2014-07-01 10:25:17 -07:00
|
|
|
if (at_kw && *kwid == 0)
|
|
|
|
eo_lexer_syntax_error(ls, "invalid keyword");
|
|
|
|
*value = str;
|
|
|
|
return TOK_VALUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int c = ls->current;
|
|
|
|
next_char(ls);
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
}
|
2014-03-29 21:07:19 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-19 07:05:24 -07:00
|
|
|
static int
|
|
|
|
lex_balanced(Eo_Lexer *ls, const char **value, int *kwid, char beg, char end)
|
|
|
|
{
|
2014-07-02 15:39:35 -07:00
|
|
|
int depth = 0, col;
|
2014-06-19 07:05:24 -07:00
|
|
|
const char *str;
|
|
|
|
eina_strbuf_reset(ls->buff);
|
2014-07-02 15:39:35 -07:00
|
|
|
while (isspace(ls->current))
|
|
|
|
next_char(ls);
|
|
|
|
col = ls->column;
|
2014-06-19 07:05:24 -07:00
|
|
|
while (ls->current)
|
|
|
|
{
|
|
|
|
if (ls->current == beg)
|
|
|
|
++depth;
|
|
|
|
else if (ls->current == end)
|
|
|
|
--depth;
|
|
|
|
|
|
|
|
if (depth == -1)
|
|
|
|
break;
|
|
|
|
|
|
|
|
eina_strbuf_append_char(ls->buff, ls->current);
|
|
|
|
next_char(ls);
|
|
|
|
}
|
|
|
|
eina_strbuf_trim(ls->buff);
|
|
|
|
str = eina_strbuf_string_get(ls->buff);
|
2014-06-19 09:28:19 -07:00
|
|
|
*kwid = (int)(uintptr_t)eina_hash_find(keyword_map, str);
|
2014-06-19 07:05:24 -07:00
|
|
|
*value = str;
|
2014-07-02 15:39:35 -07:00
|
|
|
ls->column = col;
|
2014-06-19 07:05:24 -07:00
|
|
|
return TOK_VALUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
lex_until(Eo_Lexer *ls, const char **value, int *kwid, char end)
|
|
|
|
{
|
2014-07-02 15:39:35 -07:00
|
|
|
int col;
|
2014-06-19 07:05:24 -07:00
|
|
|
const char *str;
|
|
|
|
eina_strbuf_reset(ls->buff);
|
2014-07-02 15:39:35 -07:00
|
|
|
while (isspace(ls->current))
|
|
|
|
next_char(ls);
|
|
|
|
col = ls->column;
|
2014-06-19 07:05:24 -07:00
|
|
|
while (ls->current)
|
|
|
|
{
|
|
|
|
if (ls->current == end)
|
|
|
|
break;
|
|
|
|
eina_strbuf_append_char(ls->buff, ls->current);
|
|
|
|
next_char(ls);
|
|
|
|
}
|
|
|
|
eina_strbuf_trim(ls->buff);
|
|
|
|
str = eina_strbuf_string_get(ls->buff);
|
2014-06-19 09:28:19 -07:00
|
|
|
*kwid = (int)(uintptr_t)eina_hash_find(keyword_map, str);
|
2014-06-19 07:05:24 -07:00
|
|
|
*value = str;
|
2014-07-02 15:39:35 -07:00
|
|
|
ls->column = col;
|
2014-06-19 07:05:24 -07:00
|
|
|
return TOK_VALUE;
|
|
|
|
}
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
static void
|
|
|
|
eo_lexer_set_input(Eo_Lexer *ls, const char *source)
|
2014-03-29 21:07:19 -07:00
|
|
|
{
|
2014-06-18 03:25:07 -07:00
|
|
|
Eina_File *f = eina_file_open(source, EINA_FALSE);
|
|
|
|
if (!f)
|
2014-07-01 10:25:17 -07:00
|
|
|
throw(ls, "%s\n", strerror(errno));
|
2014-06-18 03:25:07 -07:00
|
|
|
ls->lookahead.token = TOK_EOF;
|
|
|
|
ls->buff = eina_strbuf_new();
|
|
|
|
ls->handle = f;
|
|
|
|
ls->stream = eina_file_map_all(f, EINA_FILE_RANDOM);
|
2014-06-20 02:45:55 -07:00
|
|
|
ls->stream_end = ls->stream + eina_file_size_get(f);
|
2014-06-18 03:25:07 -07:00
|
|
|
ls->source = eina_stringshare_add(source);
|
|
|
|
ls->line_number = 1;
|
2014-07-02 15:39:35 -07:00
|
|
|
ls->column = 0;
|
2014-06-18 03:25:07 -07:00
|
|
|
next_char(ls);
|
2014-03-29 21:07:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-06-18 03:25:07 -07:00
|
|
|
eo_lexer_free(Eo_Lexer *ls)
|
2014-03-29 21:07:19 -07:00
|
|
|
{
|
2014-06-23 11:04:20 -07:00
|
|
|
Eo_Node *nd;
|
2014-03-29 21:07:19 -07:00
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
if (!ls) return;
|
|
|
|
if (ls->source) eina_stringshare_del(ls->source);
|
|
|
|
if (ls->buff ) eina_strbuf_free (ls->buff);
|
|
|
|
if (ls->handle) eina_file_close (ls->handle);
|
2014-03-29 21:07:19 -07:00
|
|
|
|
2014-06-23 11:04:20 -07:00
|
|
|
EINA_LIST_FREE(ls->nodes, nd)
|
|
|
|
{
|
|
|
|
switch (nd->type)
|
|
|
|
{
|
2014-07-01 10:25:17 -07:00
|
|
|
case NODE_CLASS:
|
|
|
|
eo_definitions_class_def_free(nd->def_class);
|
|
|
|
break;
|
|
|
|
case NODE_TYPEDEF:
|
|
|
|
eo_definitions_typedef_def_free(nd->def_typedef);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2014-06-23 11:04:20 -07:00
|
|
|
}
|
|
|
|
free(nd);
|
|
|
|
}
|
2014-03-29 21:07:19 -07:00
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
eo_definitions_temps_free(&ls->tmp);
|
2014-03-29 21:07:19 -07:00
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
free(ls);
|
2014-03-29 21:07:19 -07:00
|
|
|
}
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
Eo_Lexer *
|
|
|
|
eo_lexer_new(const char *source)
|
2014-04-16 06:17:27 -07:00
|
|
|
{
|
2014-06-18 03:25:07 -07:00
|
|
|
Eo_Lexer *ls = calloc(1, sizeof(Eo_Lexer));
|
|
|
|
if (!setjmp(ls->err_jmp))
|
2014-04-16 06:17:27 -07:00
|
|
|
{
|
2014-06-18 03:25:07 -07:00
|
|
|
eo_lexer_set_input(ls, source);
|
|
|
|
return ls;
|
2014-04-16 06:17:27 -07:00
|
|
|
}
|
2014-06-18 03:25:07 -07:00
|
|
|
eo_lexer_free(ls);
|
|
|
|
return NULL;
|
2014-04-16 06:17:27 -07:00
|
|
|
}
|
|
|
|
|
2014-06-19 07:05:24 -07:00
|
|
|
int
|
|
|
|
eo_lexer_get_balanced(Eo_Lexer *ls, char beg, char end)
|
|
|
|
{
|
|
|
|
assert(ls->lookahead.token == TOK_EOF);
|
|
|
|
return (ls->t.token == lex_balanced(ls, &ls->t.value, &ls->t.kw, beg, end));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
eo_lexer_get_until(Eo_Lexer *ls, char end)
|
|
|
|
{
|
|
|
|
assert(ls->lookahead.token == TOK_EOF);
|
|
|
|
return (ls->t.token == lex_until(ls, &ls->t.value, &ls->t.kw, end));
|
|
|
|
}
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
int
|
|
|
|
eo_lexer_get(Eo_Lexer *ls)
|
2014-03-29 21:07:19 -07:00
|
|
|
{
|
2014-06-19 07:17:56 -07:00
|
|
|
return eo_lexer_get_ident(ls, "_");
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
2014-03-29 21:07:19 -07:00
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
int
|
|
|
|
eo_lexer_lookahead(Eo_Lexer *ls)
|
|
|
|
{
|
2014-06-19 07:17:56 -07:00
|
|
|
return eo_lexer_lookahead_ident(ls, "_");
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
2014-03-29 21:07:19 -07:00
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
int
|
|
|
|
eo_lexer_lookahead_ident(Eo_Lexer *ls, const char *chars)
|
|
|
|
{
|
|
|
|
assert (ls->lookahead.token == TOK_EOF);
|
|
|
|
ls->lookahead.kw = 0;
|
|
|
|
return (ls->lookahead.token = lex(ls, &ls->lookahead.value,
|
|
|
|
&ls->lookahead.kw, chars));
|
|
|
|
}
|
2014-03-29 21:07:19 -07:00
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
int
|
|
|
|
eo_lexer_get_ident(Eo_Lexer *ls, const char *chars)
|
|
|
|
{
|
|
|
|
if (ls->lookahead.token != TOK_EOF)
|
2014-03-29 21:07:19 -07:00
|
|
|
{
|
2014-06-18 03:25:07 -07:00
|
|
|
ls->t = ls->lookahead;
|
|
|
|
ls->lookahead.token = TOK_EOF;
|
|
|
|
return ls->t.token;
|
2014-03-29 21:07:19 -07:00
|
|
|
}
|
2014-06-18 03:25:07 -07:00
|
|
|
ls->t.kw = 0;
|
|
|
|
return (ls->t.token = lex(ls, &ls->t.value, &ls->t.kw, chars));
|
|
|
|
}
|
2014-03-29 21:07:19 -07:00
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
void
|
|
|
|
eo_lexer_lex_error(Eo_Lexer *ls, const char *msg, int token)
|
|
|
|
{
|
|
|
|
if (token)
|
2014-03-29 21:07:19 -07:00
|
|
|
{
|
2014-06-18 03:25:07 -07:00
|
|
|
char buf[256];
|
|
|
|
txt_token(ls, token, buf);
|
2014-07-02 15:39:35 -07:00
|
|
|
throw(ls, "%s:%d:%d: %s near '%s'\n", ls->source, ls->line_number,
|
|
|
|
ls->column, msg, buf);
|
2014-03-29 21:07:19 -07:00
|
|
|
}
|
2014-06-18 03:25:07 -07:00
|
|
|
else
|
2014-07-02 15:39:35 -07:00
|
|
|
throw(ls, "%s:%d:%d: %s\n", ls->source, ls->line_number, ls->column, msg);
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
2014-03-29 21:07:19 -07:00
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
void
|
|
|
|
eo_lexer_syntax_error(Eo_Lexer *ls, const char *msg)
|
|
|
|
{
|
|
|
|
eo_lexer_lex_error(ls, msg, ls->t.token);
|
|
|
|
}
|
2014-03-29 21:07:19 -07:00
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
void
|
|
|
|
eo_lexer_token_to_str(int token, char *buf)
|
|
|
|
{
|
|
|
|
if (token < START_CUSTOM)
|
2014-03-29 21:07:19 -07:00
|
|
|
{
|
2014-06-18 03:25:07 -07:00
|
|
|
assert((unsigned char)token == token);
|
|
|
|
if (iscntrl(token))
|
2014-07-01 10:25:17 -07:00
|
|
|
sprintf(buf, "char(%d)", token);
|
2014-06-18 03:25:07 -07:00
|
|
|
else
|
2014-07-01 10:25:17 -07:00
|
|
|
sprintf(buf, "%c", token);
|
2014-03-29 21:07:19 -07:00
|
|
|
}
|
2014-06-18 03:25:07 -07:00
|
|
|
else
|
2014-03-29 21:07:19 -07:00
|
|
|
{
|
2014-06-18 03:25:07 -07:00
|
|
|
const char *v = tokens[token - START_CUSTOM];
|
|
|
|
memcpy(buf, v, strlen(v) + 1);
|
2014-03-29 21:07:19 -07:00
|
|
|
}
|
2014-06-18 03:25:07 -07:00
|
|
|
}
|
2014-03-29 21:07:19 -07:00
|
|
|
|
2014-06-20 07:31:45 -07:00
|
|
|
const char *
|
|
|
|
eo_lexer_keyword_str_get(int kw)
|
|
|
|
{
|
|
|
|
return tokens[kw + 2];
|
|
|
|
}
|
|
|
|
|
2014-06-26 04:02:19 -07:00
|
|
|
Eina_Bool
|
|
|
|
eo_lexer_is_type_keyword(int kw)
|
|
|
|
{
|
|
|
|
return (kw >= KW_char && kw <= KW_ullong);
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
eo_lexer_get_c_type(int kw)
|
|
|
|
{
|
|
|
|
if (!eo_lexer_is_type_keyword(kw)) return NULL;
|
|
|
|
return ctypes[kw - KW_char];
|
|
|
|
}
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
static int _init_counter = 0;
|
2014-03-29 21:07:19 -07:00
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
int
|
|
|
|
eo_lexer_init()
|
|
|
|
{
|
|
|
|
if (!_init_counter)
|
2014-04-30 02:03:09 -07:00
|
|
|
{
|
2014-06-18 03:25:07 -07:00
|
|
|
eina_init();
|
|
|
|
init_hash();
|
|
|
|
eina_log_color_disable_set(EINA_FALSE);
|
|
|
|
_eo_lexer_log_dom = eina_log_domain_register("eo_toknz", EINA_COLOR_CYAN);
|
2014-04-30 02:03:09 -07:00
|
|
|
}
|
2014-06-18 03:25:07 -07:00
|
|
|
return _init_counter++;
|
2014-03-29 21:07:19 -07:00
|
|
|
}
|
|
|
|
|
2014-06-18 03:25:07 -07:00
|
|
|
int
|
|
|
|
eo_lexer_shutdown()
|
2014-03-29 21:07:19 -07:00
|
|
|
{
|
2014-06-18 03:25:07 -07:00
|
|
|
if (_init_counter <= 0) return 0;
|
|
|
|
_init_counter--;
|
|
|
|
if (!_init_counter)
|
|
|
|
{
|
|
|
|
eina_log_domain_unregister(_eo_lexer_log_dom);
|
|
|
|
_eo_lexer_log_dom = -1;
|
|
|
|
destroy_hash();
|
|
|
|
eina_shutdown();
|
|
|
|
}
|
|
|
|
return _init_counter;
|
2014-03-29 21:07:19 -07:00
|
|
|
}
|