2007-12-30 17:41:49 +01:00
|
|
|
/***************************************************************************
|
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
eval_analyze.c
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2018-02-12 02:53:46 +01:00
|
|
|
(c) 2000-2017 Benoît Minisini <g4mba5@gmail.com>
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2, or (at your option)
|
|
|
|
any later version.
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
|
|
MA 02110-1301, USA.
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#define __EVAL_ANALYZE_C
|
|
|
|
|
|
|
|
#include "gambas.h"
|
|
|
|
#include "gb_common.h"
|
2015-09-06 14:36:33 +02:00
|
|
|
#include "gb_array.h"
|
2007-12-30 17:41:49 +01:00
|
|
|
#include "eval_analyze.h"
|
|
|
|
|
2018-08-31 15:58:53 +02:00
|
|
|
#include "c_system.h"
|
2007-12-30 17:41:49 +01:00
|
|
|
/*#define DEBUG*/
|
|
|
|
|
2018-09-01 00:46:48 +02:00
|
|
|
static const uchar _utf8_char_length[256] =
|
|
|
|
{
|
|
|
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
|
|
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
|
|
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
|
|
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
|
|
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
|
|
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
|
|
|
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
|
|
|
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1
|
|
|
|
};
|
|
|
|
|
2011-09-01 20:50:07 +02:00
|
|
|
static char _analyze_buffer[256];
|
|
|
|
static int _analyze_buffer_pos;
|
|
|
|
|
2015-09-06 14:36:33 +02:00
|
|
|
#define COLOR_BUFFER_SIZE 256
|
|
|
|
static EVAL_COLOR _colors[COLOR_BUFFER_SIZE];
|
|
|
|
static int _colors_len = 0;
|
|
|
|
static EVAL_COLOR *_color_buffer = NULL;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2018-09-01 00:46:48 +02:00
|
|
|
#define NEXT_UTF8_CHAR(_p) (_p += _utf8_char_length[(uchar)*(_p)])
|
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
static int get_type(PATTERN *pattern)
|
|
|
|
{
|
2012-07-29 17:50:27 +02:00
|
|
|
int type = PATTERN_type(*pattern);
|
|
|
|
int index = PATTERN_index(*pattern);
|
|
|
|
|
2018-08-31 15:58:53 +02:00
|
|
|
if (type == RT_RESERVED)
|
2012-07-29 17:50:27 +02:00
|
|
|
{
|
|
|
|
if (index >= RS_COLON)
|
|
|
|
{
|
|
|
|
if (!((index == RS_AND || index == RS_OR) && PATTERN_is(pattern[1], RS_IF)))
|
2018-08-31 15:58:53 +02:00
|
|
|
type = RT_OPERATOR;
|
2012-07-29 17:50:27 +02:00
|
|
|
}
|
|
|
|
else if (RES_is_type(index))
|
2018-08-31 15:58:53 +02:00
|
|
|
type = RT_DATATYPE;
|
2009-09-27 11:28:52 +02:00
|
|
|
else if (index == RS_WITH && pattern > EVAL->pattern)
|
|
|
|
{
|
|
|
|
index = PATTERN_index(pattern[-1]);
|
|
|
|
if (index == RS_BEGINS || index == RS_ENDS)
|
2018-08-31 15:58:53 +02:00
|
|
|
type = RT_OPERATOR;
|
2009-09-27 11:28:52 +02:00
|
|
|
}
|
2012-07-29 17:50:27 +02:00
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
return type;
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
2012-09-04 09:29:39 +02:00
|
|
|
static int is_me_last_kind(PATTERN pattern)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2012-07-29 17:50:27 +02:00
|
|
|
return PATTERN_is(pattern, RS_ME)
|
|
|
|
|| PATTERN_is(pattern, RS_SUPER)
|
2012-09-05 01:11:11 +02:00
|
|
|
|| PATTERN_is(pattern, RS_LAST)
|
|
|
|
|| PATTERN_is(pattern, RS_TRUE)
|
|
|
|
|| PATTERN_is(pattern, RS_FALSE)
|
|
|
|
|| PATTERN_is(pattern, RS_PINF)
|
|
|
|
|| PATTERN_is(pattern, RS_MINF)
|
|
|
|
|| PATTERN_is(pattern, RS_NULL);
|
2012-09-04 09:29:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static int is_optional_kind(PATTERN pattern)
|
|
|
|
{
|
|
|
|
return PATTERN_is(pattern, RS_OPTIONAL)
|
2012-07-29 17:50:27 +02:00
|
|
|
|| PATTERN_is(pattern, RS_BYREF);
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void get_symbol(PATTERN pattern, const char **symbol, int *len)
|
|
|
|
{
|
2019-03-14 02:47:36 +01:00
|
|
|
static char keyword[32];
|
2012-07-29 17:50:27 +02:00
|
|
|
int i;
|
|
|
|
SYMBOL *sym;
|
|
|
|
int type = PATTERN_type(pattern);
|
|
|
|
int index = PATTERN_index(pattern);
|
|
|
|
|
|
|
|
switch(type)
|
|
|
|
{
|
|
|
|
case RT_RESERVED:
|
2010-05-25 13:19:00 +02:00
|
|
|
*symbol = COMP_res_info[index].name;
|
|
|
|
*len = strlen(*symbol);
|
2010-05-27 15:51:09 +02:00
|
|
|
if (!EVAL->rewrite)
|
|
|
|
{
|
|
|
|
memcpy(keyword, *symbol, *len);
|
|
|
|
for (i = 0; i < *len; i++)
|
|
|
|
keyword[i] = toupper(keyword[i]);
|
|
|
|
*symbol = keyword;
|
|
|
|
}
|
2012-07-29 17:50:27 +02:00
|
|
|
return;
|
2010-06-05 01:48:53 +02:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
case RT_NUMBER:
|
|
|
|
case RT_IDENTIFIER:
|
|
|
|
sym = TABLE_get_symbol(EVAL->table, index);
|
|
|
|
break;
|
2010-06-05 01:48:53 +02:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
case RT_CLASS:
|
|
|
|
sym = TABLE_get_symbol(EVAL->table, index);
|
|
|
|
break;
|
2010-06-05 01:48:53 +02:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
case RT_STRING:
|
|
|
|
case RT_TSTRING:
|
|
|
|
case RT_COMMENT:
|
2018-08-31 15:58:53 +02:00
|
|
|
case RT_ERROR:
|
2012-07-29 17:50:27 +02:00
|
|
|
sym = TABLE_get_symbol(EVAL->string, index);
|
|
|
|
break;
|
2010-06-05 01:48:53 +02:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
case RT_SUBR:
|
|
|
|
*symbol = COMP_subr_info[index].name;
|
|
|
|
*len = strlen(*symbol);
|
|
|
|
return;
|
2010-06-05 01:48:53 +02:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
default:
|
|
|
|
*symbol = NULL;
|
|
|
|
*len = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
*symbol = sym->name;
|
|
|
|
*len = sym->len;
|
|
|
|
if (*len > EVAL_COLOR_MAX_LEN)
|
|
|
|
*len = EVAL_COLOR_MAX_LEN;
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void add_data(int state, int len)
|
|
|
|
{
|
2012-07-29 17:50:27 +02:00
|
|
|
EVAL_COLOR *color;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2015-09-06 14:36:33 +02:00
|
|
|
if (len == 0)
|
2012-07-29 17:50:27 +02:00
|
|
|
return;
|
2015-09-06 14:36:33 +02:00
|
|
|
|
|
|
|
if (_colors_len >= COLOR_BUFFER_SIZE)
|
|
|
|
{
|
|
|
|
if (!_color_buffer)
|
|
|
|
ARRAY_create_inc(&_color_buffer, COLOR_BUFFER_SIZE);
|
|
|
|
|
|
|
|
color = ARRAY_add_many(&_color_buffer, COLOR_BUFFER_SIZE);
|
|
|
|
memcpy(color, _colors, sizeof(EVAL_COLOR) * COLOR_BUFFER_SIZE);
|
|
|
|
_colors_len = 0;
|
|
|
|
}
|
2018-08-31 15:58:53 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
color = &_colors[_colors_len];
|
|
|
|
color->state = state;
|
|
|
|
color->len = len;
|
|
|
|
color->alternate = FALSE;
|
|
|
|
_colors_len++;
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
2018-09-01 12:16:24 +02:00
|
|
|
static void add_data_merge(int state, int len)
|
|
|
|
{
|
|
|
|
if (_colors_len > 0 && _colors[_colors_len - 1].state == state && (_colors[_colors_len - 1].len + len) < EVAL_COLOR_MAX_LEN)
|
|
|
|
_colors[_colors_len - 1].len += len;
|
|
|
|
else
|
|
|
|
add_data(state, len);
|
|
|
|
}
|
|
|
|
|
2015-09-06 14:36:33 +02:00
|
|
|
static void flush_colors(EVAL_ANALYZE *result)
|
|
|
|
{
|
|
|
|
EVAL_COLOR *color;
|
|
|
|
|
|
|
|
if (_color_buffer)
|
|
|
|
{
|
|
|
|
if (_colors_len)
|
|
|
|
{
|
|
|
|
color = ARRAY_add_many(&_color_buffer, _colors_len);
|
|
|
|
memcpy(color, _colors, sizeof(EVAL_COLOR) * _colors_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
result->color = _color_buffer;
|
|
|
|
result->len = ARRAY_count(_color_buffer);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result->color = _colors;
|
|
|
|
result->len = _colors_len;
|
|
|
|
}
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
static int is_proc(void)
|
|
|
|
{
|
2012-07-29 17:50:27 +02:00
|
|
|
PATTERN pattern;
|
|
|
|
int i;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
if (!EVAL->pattern)
|
|
|
|
return FALSE;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
for (i = 0;; i++)
|
|
|
|
{
|
|
|
|
pattern = EVAL->pattern[i];
|
|
|
|
if (PATTERN_is_end(pattern))
|
|
|
|
return FALSE;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
if (PATTERN_is(pattern, RS_PRIVATE) || PATTERN_is(pattern, RS_PUBLIC) || PATTERN_is(pattern, RS_STATIC) || PATTERN_is(pattern, RS_FAST))
|
|
|
|
continue;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
return (PATTERN_is(pattern, RS_SUB) || PATTERN_is(pattern, RS_PROCEDURE) || PATTERN_is(pattern, RS_FUNCTION));
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static int get_indent(bool *empty)
|
|
|
|
{
|
2012-07-29 17:50:27 +02:00
|
|
|
int i;
|
|
|
|
unsigned char c;
|
|
|
|
|
|
|
|
*empty = TRUE;
|
|
|
|
|
|
|
|
for (i = 0; i < (int)EVAL->len; i++)
|
|
|
|
{
|
|
|
|
c = EVAL->source[i];
|
|
|
|
if (c > ' ')
|
|
|
|
{
|
|
|
|
*empty = FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return i;
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
2009-12-15 01:06:54 +01:00
|
|
|
static int get_symbol_indent(const char *symbol, int len)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
{
|
|
|
|
if (!(symbol[i] > 0 && symbol[i] < 33))
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
static bool symbol_starts_with(const char *symbol, int len, int from, const char *comp)
|
|
|
|
{
|
|
|
|
int l = strlen(comp);
|
|
|
|
return (from < (len - l) && strncmp(&symbol[from], comp, l) == 0);
|
|
|
|
}
|
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
static int get_utf8_length(const char *s, int l)
|
|
|
|
{
|
2012-07-29 17:50:27 +02:00
|
|
|
int len;
|
|
|
|
int i;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
for (i = 0, len = 0; i < l; i++)
|
|
|
|
{
|
|
|
|
if ((s[i] & 0xC0) != 0x80)
|
|
|
|
len++;
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
return len;
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
2011-09-01 20:50:07 +02:00
|
|
|
static void init_result()
|
|
|
|
{
|
|
|
|
_analyze_buffer_pos = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void flush_result(EVAL_ANALYZE *result)
|
|
|
|
{
|
|
|
|
if (_analyze_buffer_pos > 0)
|
|
|
|
{
|
2011-09-07 21:43:11 +02:00
|
|
|
result->str = GB.AddString(result->str, _analyze_buffer, _analyze_buffer_pos);
|
2011-09-01 20:50:07 +02:00
|
|
|
_analyze_buffer_pos = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void add_result(EVAL_ANALYZE *result, const char *str, int len)
|
|
|
|
{
|
|
|
|
if ((_analyze_buffer_pos + len) > sizeof(_analyze_buffer))
|
|
|
|
flush_result(result);
|
|
|
|
|
|
|
|
if (len > sizeof(_analyze_buffer))
|
2011-09-07 21:43:11 +02:00
|
|
|
result->str = GB.AddString(result->str, str, len);
|
2011-09-01 20:50:07 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy(&_analyze_buffer[_analyze_buffer_pos], str, len);
|
|
|
|
_analyze_buffer_pos += len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void add_result_char(EVAL_ANALYZE *result, char c)
|
|
|
|
{
|
|
|
|
if ((_analyze_buffer_pos + 1) > sizeof(_analyze_buffer))
|
|
|
|
flush_result(result);
|
|
|
|
|
|
|
|
_analyze_buffer[_analyze_buffer_pos++] = c;
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
static void analyze(EVAL_ANALYZE *result)
|
|
|
|
{
|
2012-07-29 17:50:27 +02:00
|
|
|
PATTERN *pattern;
|
|
|
|
int nspace;
|
|
|
|
bool empty = FALSE;
|
|
|
|
int type, old_type, next_type;
|
|
|
|
const char *symbol;
|
2018-09-01 00:46:48 +02:00
|
|
|
const char *p;
|
2013-01-06 17:13:31 +01:00
|
|
|
bool space_before, space_after;
|
2018-08-31 15:58:53 +02:00
|
|
|
int len, i, l;
|
2010-12-18 05:27:59 +01:00
|
|
|
bool preprocessor;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2015-09-06 14:36:33 +02:00
|
|
|
_colors_len = 0;
|
|
|
|
EVAL_analyze_exit();
|
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
pattern = EVAL->pattern;
|
2010-12-05 21:17:24 +01:00
|
|
|
nspace = 0;
|
2010-12-18 05:27:59 +01:00
|
|
|
preprocessor = FALSE;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
if (EVAL->len <= 0)
|
|
|
|
return;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2009-07-14 04:24:54 +02:00
|
|
|
if (!EVAL->comment)
|
|
|
|
{
|
|
|
|
nspace = get_indent(&empty);
|
2018-08-31 15:58:53 +02:00
|
|
|
add_data(RT_END, nspace);
|
2009-07-14 04:24:54 +02:00
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
if (empty)
|
|
|
|
return;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
if (!pattern)
|
|
|
|
return;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-09-01 20:50:07 +02:00
|
|
|
init_result();
|
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
if (nspace)
|
|
|
|
add_result(result, EVAL->source, nspace);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2018-08-31 15:58:53 +02:00
|
|
|
type = EVAL->comment ? RT_COMMENT : RT_END;
|
|
|
|
next_type = RT_END;
|
|
|
|
old_type = RT_END;
|
2012-07-29 17:50:27 +02:00
|
|
|
space_after = FALSE;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
for(;;)
|
|
|
|
{
|
|
|
|
old_type = next_type;
|
|
|
|
type = get_type(pattern);
|
|
|
|
next_type = type;
|
|
|
|
get_symbol(*pattern, &symbol, &len);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
space_before = space_after;
|
|
|
|
space_after = FALSE;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2018-08-31 15:58:53 +02:00
|
|
|
if (type == RT_END)
|
2012-07-29 17:50:27 +02:00
|
|
|
break;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2018-08-31 15:58:53 +02:00
|
|
|
//if (in_quote && (type == RT_RESERVED || type == RT_DATATYPE || type == RT_SUBR))
|
|
|
|
// type = RT_IDENTIFIER;
|
2008-04-17 12:18:25 +02:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
switch(type)
|
|
|
|
{
|
2018-08-31 15:58:53 +02:00
|
|
|
case RT_RESERVED:
|
2012-07-29 17:50:27 +02:00
|
|
|
//state = Keyword;
|
2018-08-31 15:58:53 +02:00
|
|
|
//if (old_type != RT_OPERATOR)
|
2012-07-29 17:50:27 +02:00
|
|
|
//me = is_me_last(*pattern);
|
2012-09-04 09:29:39 +02:00
|
|
|
|
|
|
|
if (is_me_last_kind(*pattern))
|
2012-07-29 17:50:27 +02:00
|
|
|
{
|
2018-08-31 15:58:53 +02:00
|
|
|
if (old_type != RT_OPERATOR)
|
2012-09-04 09:29:39 +02:00
|
|
|
space_before = TRUE;
|
2018-08-31 15:58:53 +02:00
|
|
|
next_type = RT_IDENTIFIER;
|
2012-09-04 09:29:39 +02:00
|
|
|
}
|
|
|
|
else if (is_optional_kind(*pattern))
|
|
|
|
{
|
2018-08-31 15:58:53 +02:00
|
|
|
if (old_type != RT_OPERATOR)
|
2012-07-29 17:50:27 +02:00
|
|
|
space_before = TRUE;
|
|
|
|
}
|
2012-09-04 09:29:39 +02:00
|
|
|
else
|
|
|
|
space_before = TRUE;
|
|
|
|
|
|
|
|
/*if (!is_me_last_kind(*pattern))
|
|
|
|
space_before = TRUE;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (*pattern != RS_OPTIONAL)
|
2018-08-31 15:58:53 +02:00
|
|
|
if (old_type != RT_OPERATOR)
|
2012-09-04 09:29:39 +02:00
|
|
|
space_before = TRUE;
|
|
|
|
}*/
|
2012-07-29 17:50:27 +02:00
|
|
|
|
|
|
|
if (preprocessor && PATTERN_is(pattern[-1], RS_SHARP))
|
2010-12-18 05:27:59 +01:00
|
|
|
space_before = FALSE;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
/*if (PATTERN_index(*pattern) >= RS_COLON)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
usym[i] = GB.toupper(symbol[i]);
|
|
|
|
usym[len] = 0;
|
|
|
|
|
|
|
|
symbol = usym;
|
|
|
|
}*/
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2018-08-31 15:58:53 +02:00
|
|
|
case RT_DATATYPE:
|
2012-07-29 17:50:27 +02:00
|
|
|
//state = Datatype;
|
2013-11-04 16:17:01 +01:00
|
|
|
if (PATTERN_is(pattern[-1], RS_OPEN))
|
2018-08-31 15:58:53 +02:00
|
|
|
type = RT_RESERVED;
|
2013-11-04 16:17:01 +01:00
|
|
|
|
2018-08-31 15:58:53 +02:00
|
|
|
if (old_type != RT_OPERATOR)
|
2012-07-29 17:50:27 +02:00
|
|
|
space_before = TRUE;
|
2013-11-04 16:17:01 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
break;
|
|
|
|
|
2018-08-31 15:58:53 +02:00
|
|
|
case RT_IDENTIFIER:
|
|
|
|
case RT_CLASS:
|
2012-07-29 17:50:27 +02:00
|
|
|
//state = Symbol;
|
2018-08-31 15:58:53 +02:00
|
|
|
if (old_type != RT_OPERATOR)
|
2012-07-29 17:50:27 +02:00
|
|
|
space_before = TRUE;
|
|
|
|
break;
|
|
|
|
|
2018-08-31 15:58:53 +02:00
|
|
|
case RT_NUMBER:
|
2012-07-29 17:50:27 +02:00
|
|
|
//state = Number;
|
2018-08-31 15:58:53 +02:00
|
|
|
if (old_type != RT_OPERATOR)
|
2012-07-29 17:50:27 +02:00
|
|
|
space_before = TRUE;
|
|
|
|
break;
|
|
|
|
|
2018-08-31 15:58:53 +02:00
|
|
|
case RT_STRING:
|
2012-07-29 17:50:27 +02:00
|
|
|
//state = String;
|
2018-08-31 15:58:53 +02:00
|
|
|
if (old_type != RT_OPERATOR)
|
2012-07-29 17:50:27 +02:00
|
|
|
space_before = TRUE;
|
|
|
|
break;
|
|
|
|
|
2018-08-31 15:58:53 +02:00
|
|
|
case RT_SUBR:
|
2012-07-29 17:50:27 +02:00
|
|
|
//state = Subr;
|
2018-08-31 15:58:53 +02:00
|
|
|
if (old_type != RT_OPERATOR)
|
2012-07-29 17:50:27 +02:00
|
|
|
space_before = TRUE;
|
|
|
|
break;
|
|
|
|
|
2018-08-31 15:58:53 +02:00
|
|
|
case RT_COMMENT:
|
2012-07-29 17:50:27 +02:00
|
|
|
//state = Commentary;
|
|
|
|
space_before = *symbol != ' ';
|
2009-12-15 01:06:54 +01:00
|
|
|
i = get_symbol_indent(symbol, len);
|
|
|
|
if (i <= (len - 2) && symbol[i + 1] == '\'')
|
2018-08-31 15:58:53 +02:00
|
|
|
type = RT_HELP;
|
2012-07-29 17:50:27 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
while (i < len && (uchar)symbol[i] == '\'')
|
|
|
|
i++;
|
|
|
|
|
|
|
|
while (i < len && (uchar)symbol[i] <= ' ')
|
|
|
|
i++;
|
|
|
|
|
|
|
|
if (i < len)
|
|
|
|
{
|
|
|
|
if (symbol_starts_with(symbol, len, i, "NOTE:")
|
|
|
|
|| symbol_starts_with(symbol, len, i, "TODO:")
|
|
|
|
|| symbol_starts_with(symbol, len, i, "FIXME:"))
|
2018-08-31 15:58:53 +02:00
|
|
|
type = RT_HELP;
|
2012-07-29 17:50:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2018-08-31 15:58:53 +02:00
|
|
|
case RT_OPERATOR:
|
2012-07-29 17:50:27 +02:00
|
|
|
|
|
|
|
if (index("([)]@", *symbol))
|
|
|
|
{
|
|
|
|
space_after = FALSE;
|
|
|
|
}
|
|
|
|
else if (index(":;,", *symbol))
|
|
|
|
{
|
|
|
|
space_before = FALSE;
|
|
|
|
space_after = TRUE;
|
|
|
|
}
|
|
|
|
else if (index("#{", *symbol))
|
|
|
|
{
|
2018-08-31 15:58:53 +02:00
|
|
|
if (old_type != RT_OPERATOR)
|
2012-07-29 17:50:27 +02:00
|
|
|
space_before = TRUE;
|
|
|
|
space_after = FALSE;
|
|
|
|
//in_quote = *symbol == '{';
|
2010-12-18 05:27:59 +01:00
|
|
|
|
2018-08-31 15:58:53 +02:00
|
|
|
if (!preprocessor && *symbol == '#' && old_type == RT_END)
|
2010-12-18 05:27:59 +01:00
|
|
|
preprocessor = TRUE;
|
2012-07-29 17:50:27 +02:00
|
|
|
}
|
|
|
|
else if (index("}", *symbol))
|
|
|
|
{
|
|
|
|
space_before = FALSE;
|
|
|
|
space_after = FALSE;
|
|
|
|
//in_quote = FALSE;
|
|
|
|
}
|
|
|
|
else if (index(".!", *symbol)) //symbol[0] == '.' && symbol[1] == 0)
|
|
|
|
{
|
|
|
|
//space_before = FALSE;
|
|
|
|
space_after = FALSE;
|
|
|
|
}
|
2019-03-14 02:47:36 +01:00
|
|
|
else if (*symbol == '-' && len == 1)
|
2019-03-14 01:52:37 +01:00
|
|
|
{
|
|
|
|
if (old_type == RT_OPERATOR && (PATTERN_is(pattern[-1], RS_LBRA) || PATTERN_is(pattern[-1],RS_LSQR)))
|
|
|
|
space_before = FALSE;
|
2019-03-14 02:47:36 +01:00
|
|
|
else
|
|
|
|
space_before = TRUE;
|
|
|
|
|
|
|
|
if (old_type == RT_RESERVED || old_type == RT_DATATYPE)
|
2019-03-14 01:52:37 +01:00
|
|
|
space_after = FALSE;
|
2019-03-14 02:47:36 +01:00
|
|
|
else if (old_type == RT_OPERATOR)
|
|
|
|
{
|
|
|
|
get_symbol(pattern[-1], &symbol, &len);
|
|
|
|
if (index(")]}", *symbol))
|
|
|
|
space_after = TRUE;
|
|
|
|
else
|
|
|
|
space_after = FALSE;
|
|
|
|
get_symbol(*pattern, &symbol, &len);
|
2019-03-14 01:52:37 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
space_after = TRUE;
|
|
|
|
}
|
|
|
|
else if (PATTERN_is(*pattern, RS_NOT))
|
2012-07-29 17:50:27 +02:00
|
|
|
{
|
2018-08-31 15:58:53 +02:00
|
|
|
if (old_type == RT_OPERATOR && (PATTERN_is(pattern[-1], RS_LBRA) || PATTERN_is(pattern[-1],RS_LSQR)))
|
2012-07-29 17:50:27 +02:00
|
|
|
space_before = FALSE;
|
2007-12-30 17:41:49 +01:00
|
|
|
else
|
2012-07-29 17:50:27 +02:00
|
|
|
space_before = TRUE;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
space_after = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
space_before = TRUE;
|
|
|
|
space_after = TRUE;
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
2018-08-31 15:58:53 +02:00
|
|
|
if (old_type == RT_RESERVED)
|
2012-07-29 17:50:27 +02:00
|
|
|
space_before = TRUE;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
break;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2018-08-31 15:58:53 +02:00
|
|
|
case RT_ERROR:
|
2012-07-29 17:50:27 +02:00
|
|
|
space_before = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2018-08-31 15:58:53 +02:00
|
|
|
if (space_before && old_type != RT_END)
|
2012-07-29 17:50:27 +02:00
|
|
|
{
|
2011-09-01 20:50:07 +02:00
|
|
|
add_result_char(result, ' ');
|
2018-08-31 15:58:53 +02:00
|
|
|
add_data(preprocessor ? RT_PREPROCESSOR : RT_END, 1);
|
2012-07-29 17:50:27 +02:00
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2018-08-31 15:58:53 +02:00
|
|
|
if (type == RT_STRING)
|
2011-09-01 20:50:07 +02:00
|
|
|
add_result_char(result, '"');
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
if (len)
|
|
|
|
{
|
2018-08-31 15:58:53 +02:00
|
|
|
if (EVAL->rewrite && type == RT_CLASS)
|
2010-06-05 01:48:53 +02:00
|
|
|
{
|
2011-09-01 20:50:07 +02:00
|
|
|
add_result_char(result, toupper(symbol[0]));
|
|
|
|
if (len > 1) add_result(result, &symbol[1], len - 1);
|
2010-06-05 01:48:53 +02:00
|
|
|
}
|
|
|
|
else
|
2011-09-01 20:50:07 +02:00
|
|
|
add_result(result, symbol, len);
|
2012-07-29 17:50:27 +02:00
|
|
|
//printf("add: %.*s\n", len, symbol);
|
|
|
|
len = get_utf8_length(symbol, len);
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2018-08-31 15:58:53 +02:00
|
|
|
if (type == RT_STRING)
|
2012-07-29 17:50:27 +02:00
|
|
|
{
|
|
|
|
add_result_char(result, '"');
|
|
|
|
len += 2;
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2018-08-31 15:58:53 +02:00
|
|
|
if (EVAL->rewrite)
|
|
|
|
{
|
|
|
|
if (type == RT_STRING)
|
|
|
|
{
|
|
|
|
add_data(RT_STRING, 1);
|
|
|
|
len -= 2;
|
2018-09-01 00:46:48 +02:00
|
|
|
for (i = 0, p = symbol; i < len; i++)
|
2018-08-31 15:58:53 +02:00
|
|
|
{
|
2018-09-01 00:46:48 +02:00
|
|
|
if (*p == '\\')
|
2018-08-31 15:58:53 +02:00
|
|
|
{
|
|
|
|
i++;
|
2018-09-01 00:46:48 +02:00
|
|
|
NEXT_UTF8_CHAR(p);
|
|
|
|
|
2018-09-01 12:16:24 +02:00
|
|
|
add_data_merge(RT_ESCAPE, 1);
|
2018-08-31 15:58:53 +02:00
|
|
|
if (i < len)
|
|
|
|
{
|
2018-09-01 00:46:48 +02:00
|
|
|
if (*p == 'x' && i < (len - 2) && isxdigit(p[1]) && isxdigit(p[2]))
|
2018-10-01 10:48:24 +02:00
|
|
|
{
|
2018-09-01 00:46:48 +02:00
|
|
|
l = 3;
|
2018-10-01 10:48:24 +02:00
|
|
|
i += 2;
|
|
|
|
}
|
2018-08-31 15:58:53 +02:00
|
|
|
else
|
|
|
|
l = 1;
|
2018-09-01 12:16:24 +02:00
|
|
|
add_data_merge(RT_ESCAPE, l);
|
2018-09-01 00:46:48 +02:00
|
|
|
|
|
|
|
while (l--)
|
|
|
|
NEXT_UTF8_CHAR(p);
|
2018-08-31 15:58:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2018-09-01 00:46:48 +02:00
|
|
|
{
|
|
|
|
NEXT_UTF8_CHAR(p);
|
2018-09-01 12:16:24 +02:00
|
|
|
add_data_merge(RT_STRING, 1);
|
2018-09-01 00:46:48 +02:00
|
|
|
}
|
2018-08-31 15:58:53 +02:00
|
|
|
}
|
2018-09-01 12:16:24 +02:00
|
|
|
add_data_merge(RT_STRING, 1);
|
2018-08-31 15:58:53 +02:00
|
|
|
goto __NEXT_PATTERN;
|
|
|
|
}
|
|
|
|
else if (type == RT_IDENTIFIER)
|
|
|
|
{
|
|
|
|
if (PATTERN_is(pattern[1], RS_COLON))
|
|
|
|
{
|
|
|
|
add_result_char(result, ':');
|
|
|
|
add_data(RT_LABEL, len + 1);
|
|
|
|
space_after = TRUE;
|
|
|
|
pattern ++;
|
|
|
|
goto __NEXT_PATTERN;
|
|
|
|
}
|
|
|
|
else if (old_type == RT_RESERVED && (PATTERN_is(pattern[-1], RS_GOTO) || PATTERN_is(pattern[-1], RS_GOSUB)))
|
|
|
|
{
|
|
|
|
type = RT_LABEL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (type == RT_RESERVED)
|
|
|
|
{
|
|
|
|
if (PATTERN_is(*pattern, RS_NULL)
|
|
|
|
|| PATTERN_is(*pattern, RS_TRUE)
|
|
|
|
|| PATTERN_is(*pattern, RS_FALSE)
|
|
|
|
|| PATTERN_is(*pattern, RS_PINF)
|
|
|
|
|| PATTERN_is(*pattern, RS_MINF))
|
|
|
|
{
|
|
|
|
type = RT_CONSTANT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (preprocessor && type != RT_COMMENT && type != RT_HELP)
|
|
|
|
add_data(RT_PREPROCESSOR, len);
|
2010-12-18 05:27:59 +01:00
|
|
|
else
|
|
|
|
add_data(type, len);
|
2012-07-29 17:50:27 +02:00
|
|
|
//printf("add_data: %.d (%d)\n", type, len);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2018-08-31 15:58:53 +02:00
|
|
|
__NEXT_PATTERN:
|
2012-07-29 17:50:27 +02:00
|
|
|
pattern++;
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-09-01 20:50:07 +02:00
|
|
|
flush_result(result);
|
2015-09-06 14:36:33 +02:00
|
|
|
flush_colors(result);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
//fprintf(stderr, "analyze: %d %s\n", strlen(result->str), result->str);
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define add_pattern(_type, _index) EVAL->pattern[EVAL->pattern_count++] = PATTERN_make((_type), (_index));
|
|
|
|
|
|
|
|
static void add_end_pattern(void)
|
|
|
|
{
|
2012-07-29 17:50:27 +02:00
|
|
|
int index;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
len = EVAL->len - (READ_source_ptr - EVAL->source);
|
|
|
|
if (len > 0)
|
|
|
|
{
|
2019-05-08 06:13:04 +02:00
|
|
|
index = TABLE_add_symbol(EVAL->string, READ_source_ptr, len);
|
2018-08-31 15:58:53 +02:00
|
|
|
add_pattern(RT_ERROR, index);
|
2012-07-29 17:50:27 +02:00
|
|
|
}
|
|
|
|
|
2018-08-31 15:58:53 +02:00
|
|
|
add_pattern(RT_END, 0);
|
|
|
|
//get_symbol(PATTERN_make(RT_ERROR, index), &sym, &len);
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-07-14 04:24:54 +02:00
|
|
|
PUBLIC void EVAL_analyze(const char *src, int len, int state, EVAL_ANALYZE *result, bool rewrite)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
|
|
|
int nspace = 0;
|
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
#ifdef DEBUG
|
|
|
|
printf("EVAL: %*.s\n", expr->len, expr->source);
|
|
|
|
#endif
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
CLEAR(result);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
while (len > 0 && src[len - 1] == ' ')
|
|
|
|
{
|
|
|
|
len--;
|
|
|
|
nspace++;
|
|
|
|
}
|
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
result->len = 0;
|
|
|
|
result->str = NULL;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
if (len > 0)
|
|
|
|
{
|
2007-12-30 17:41:49 +01:00
|
|
|
EVAL = &EVAL_read_expr;
|
|
|
|
|
2010-08-29 22:51:10 +02:00
|
|
|
EVAL_clear(EVAL, FALSE);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2010-06-05 01:48:53 +02:00
|
|
|
EVAL->source = GB.NewString(src, len);
|
2012-04-01 03:28:24 +02:00
|
|
|
EVAL->source = GB.AddString(EVAL->source, "\0\0", 2);
|
2007-12-30 17:41:49 +01:00
|
|
|
EVAL->len = len;
|
|
|
|
|
|
|
|
EVAL->analyze = TRUE;
|
2008-03-27 17:27:24 +01:00
|
|
|
EVAL->rewrite = rewrite;
|
2018-08-31 15:58:53 +02:00
|
|
|
EVAL->comment = state == RT_COMMENT;
|
2009-07-14 04:24:54 +02:00
|
|
|
|
|
|
|
//fprintf(stderr, "EVAL_analyze: [%d] %.*s\n", EVAL->comment, len, src);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
EVAL_start(EVAL);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
TRY
|
|
|
|
{
|
|
|
|
EVAL_read();
|
|
|
|
}
|
|
|
|
CATCH
|
|
|
|
{
|
|
|
|
add_end_pattern();
|
|
|
|
}
|
|
|
|
END_TRY
|
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
analyze(result);
|
2009-07-14 04:24:54 +02:00
|
|
|
result->proc = is_proc();
|
2018-08-31 15:58:53 +02:00
|
|
|
result->state = EVAL->comment ? RT_COMMENT : RT_END;
|
2009-07-14 04:24:54 +02:00
|
|
|
|
|
|
|
//fprintf(stderr, "--> [%d]\n", EVAL->comment);
|
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
GB.FreeString(&EVAL->source);
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result->proc = FALSE;
|
|
|
|
}
|
|
|
|
|
2012-07-29 17:50:27 +02:00
|
|
|
while (nspace > 0)
|
|
|
|
{
|
|
|
|
result->str = GB.AddString(result->str, " ", nspace > 8 ? 8 : nspace);
|
|
|
|
nspace -= 8;
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-09-06 14:36:33 +02:00
|
|
|
void EVAL_analyze_exit(void)
|
|
|
|
{
|
|
|
|
if (_color_buffer)
|
|
|
|
ARRAY_delete(&_color_buffer);
|
2017-09-15 00:28:24 +02:00
|
|
|
}
|