2007-12-30 17:41:49 +01:00
|
|
|
|
/***************************************************************************
|
|
|
|
|
|
2011-12-31 03:39:20 +01:00
|
|
|
|
eval_trans_tree.c
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2013-08-03 17:38:01 +02:00
|
|
|
|
(c) 2000-2013 Benoît Minisini <gambas@users.sourceforge.net>
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2011-12-31 03:39:20 +01: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
|
|
|
|
|
2011-12-31 03:39:20 +01: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
|
|
|
|
|
2011-12-31 03:39:20 +01: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 __TRANS_TREE_C
|
|
|
|
|
|
|
|
|
|
#include "gb_common.h"
|
|
|
|
|
#include "gb_error.h"
|
|
|
|
|
#include "gb_reserved.h"
|
|
|
|
|
|
|
|
|
|
#include "eval_trans.h"
|
|
|
|
|
#include "eval_read.h"
|
|
|
|
|
#include "eval.h"
|
|
|
|
|
|
2016-01-03 17:44:24 +01:00
|
|
|
|
//#define DEBUG
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
|
|
static short level;
|
|
|
|
|
static PATTERN *current;
|
|
|
|
|
/*PRIVATE PATTERN last_pattern;*/
|
|
|
|
|
|
|
|
|
|
static void analyze_expr(short priority, short op_main);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void inc_level()
|
|
|
|
|
{
|
2010-12-29 09:21:51 +01:00
|
|
|
|
level++;
|
|
|
|
|
if (level > MAX_EXPR_LEVEL)
|
2014-12-22 18:41:16 +01:00
|
|
|
|
THROW("Expression too complex");
|
2007-12-30 17:41:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void dec_level()
|
|
|
|
|
{
|
2010-12-29 09:21:51 +01:00
|
|
|
|
level--;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void add_pattern(PATTERN pattern)
|
|
|
|
|
{
|
2010-12-29 09:21:51 +01:00
|
|
|
|
PATTERN *node;
|
|
|
|
|
short index;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
index = (short)ARRAY_count(EVAL->tree);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
if (index >= MAX_EXPR_PATTERN)
|
|
|
|
|
THROW("Expression too complex");
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
node = ARRAY_add(&EVAL->tree);
|
|
|
|
|
*node = pattern;
|
|
|
|
|
/*last_pattern = pattern;*/
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
/*#ifdef DEBUG
|
|
|
|
|
READ_dump_pattern(&pattern);
|
|
|
|
|
#endif*/
|
2007-12-30 17:41:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void remove_last_pattern()
|
|
|
|
|
{
|
2010-12-29 09:21:51 +01:00
|
|
|
|
if (!ARRAY_count(EVAL->tree))
|
|
|
|
|
return;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
ARRAY_remove_last(&EVAL->tree);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static PATTERN get_last_pattern(int dep)
|
|
|
|
|
{
|
2010-12-29 09:21:51 +01:00
|
|
|
|
short index;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
index = (short)ARRAY_count(EVAL->tree);
|
|
|
|
|
if (index < dep)
|
|
|
|
|
return NULL_PATTERN;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
return EVAL->tree[index - dep];
|
2007-12-30 17:41:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void change_last_pattern(int dep, PATTERN pattern)
|
|
|
|
|
{
|
2010-12-29 09:21:51 +01:00
|
|
|
|
short index;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
index = (short)ARRAY_count(EVAL->tree);
|
|
|
|
|
if (index < dep)
|
|
|
|
|
return;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
EVAL->tree[index - dep] = pattern;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void check_last_first(int dep)
|
|
|
|
|
{
|
2010-12-29 09:21:51 +01:00
|
|
|
|
if (PATTERN_is_identifier(get_last_pattern(dep)))
|
|
|
|
|
change_last_pattern(dep, PATTERN_set_flag(get_last_pattern(dep), RT_FIRST));
|
2007-12-30 17:41:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void add_reserved_pattern(int reserved)
|
|
|
|
|
{
|
2010-12-29 09:21:51 +01:00
|
|
|
|
add_pattern(PATTERN_make(RT_RESERVED, reserved));
|
2007-12-30 17:41:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-01-28 00:46:37 +01:00
|
|
|
|
static void add_operator_output(short op, short nparam)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
2010-12-29 09:21:51 +01:00
|
|
|
|
PATTERN pattern;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
/*
|
|
|
|
|
Why this test?
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
add_operator() can be called without operator. See:
|
|
|
|
|
if (RES_priority(op) < prio) ...
|
|
|
|
|
*/
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
if (op == RS_NONE || op == RS_UNARY)
|
|
|
|
|
return;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
if (op == RS_EXCL)
|
|
|
|
|
{
|
|
|
|
|
op = RS_LSQR;
|
|
|
|
|
nparam = 2;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
check_last_first(2);
|
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
pattern = PATTERN_make(RT_RESERVED, op);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2014-01-28 00:46:37 +01:00
|
|
|
|
/*if (op == RS_LBRA && has_output)
|
|
|
|
|
pattern = PATTERN_set_flag(pattern, RT_OUTPUT);*/
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
add_pattern(pattern);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
pattern = PATTERN_make(RT_PARAM, nparam);
|
|
|
|
|
add_pattern(pattern);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void add_operator(short op, short nparam)
|
|
|
|
|
{
|
2014-01-28 00:46:37 +01:00
|
|
|
|
add_operator_output(op, nparam);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-01-28 00:46:37 +01:00
|
|
|
|
static void add_subr(PATTERN subr_pattern, short nparam)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
2010-12-29 09:21:51 +01:00
|
|
|
|
PATTERN pattern;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2014-01-28 00:46:37 +01:00
|
|
|
|
/*if (has_output)
|
|
|
|
|
subr_pattern = PATTERN_set_flag(subr_pattern, RT_OUTPUT);*/
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
add_pattern(subr_pattern);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
pattern = PATTERN_make(RT_PARAM, nparam);
|
|
|
|
|
add_pattern(pattern);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void analyze_make_array()
|
|
|
|
|
{
|
2010-12-29 09:21:51 +01:00
|
|
|
|
int n = 0;
|
|
|
|
|
bool checked = FALSE;
|
|
|
|
|
bool collection = FALSE;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2012-10-31 00:44:24 +01:00
|
|
|
|
if (!PATTERN_is(*current, RS_RSQR))
|
2010-12-29 09:21:51 +01:00
|
|
|
|
{
|
2012-10-31 00:44:24 +01:00
|
|
|
|
for(;;)
|
2010-12-29 09:21:51 +01:00
|
|
|
|
{
|
2008-11-11 18:22:38 +01:00
|
|
|
|
n++;
|
2014-01-28 00:46:37 +01:00
|
|
|
|
/*if (n > MAX_PARAM_OP)
|
|
|
|
|
THROW("Too many arguments");*/
|
2010-12-29 09:21:51 +01:00
|
|
|
|
analyze_expr(0, RS_NONE);
|
2016-01-03 17:44:24 +01:00
|
|
|
|
|
2012-10-31 00:44:24 +01:00
|
|
|
|
if (!checked)
|
|
|
|
|
{
|
|
|
|
|
collection = PATTERN_is(*current, RS_COLON);
|
|
|
|
|
checked = TRUE;
|
|
|
|
|
}
|
2016-01-03 17:44:24 +01:00
|
|
|
|
|
2012-10-31 00:44:24 +01:00
|
|
|
|
if (collection)
|
|
|
|
|
{
|
|
|
|
|
if (!PATTERN_is(*current, RS_COLON))
|
|
|
|
|
THROW("Missing ':'");
|
|
|
|
|
current++;
|
|
|
|
|
n++;
|
2014-01-28 00:46:37 +01:00
|
|
|
|
/*if (n > MAX_PARAM_OP)
|
|
|
|
|
THROW("Too many arguments");*/
|
2012-10-31 00:44:24 +01:00
|
|
|
|
analyze_expr(0, RS_NONE);
|
|
|
|
|
}
|
2016-01-03 17:44:24 +01:00
|
|
|
|
|
2012-10-31 00:44:24 +01:00
|
|
|
|
if (!PATTERN_is(*current, RS_COMMA))
|
|
|
|
|
break;
|
|
|
|
|
current++;
|
2014-01-28 00:46:37 +01:00
|
|
|
|
|
|
|
|
|
if (collection)
|
|
|
|
|
{
|
|
|
|
|
if (n == (MAX_PARAM_OP - 1))
|
|
|
|
|
{
|
2014-01-28 17:17:40 +01:00
|
|
|
|
add_operator(RS_COLON, MAX_PARAM_OP + 1);
|
2014-01-28 00:46:37 +01:00
|
|
|
|
n = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (n == MAX_PARAM_OP)
|
|
|
|
|
{
|
2014-01-28 17:17:40 +01:00
|
|
|
|
add_operator(RS_RSQR, MAX_PARAM_OP + 1);
|
2014-01-28 00:46:37 +01:00
|
|
|
|
n = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-12-29 09:21:51 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!PATTERN_is(*current, RS_RSQR))
|
|
|
|
|
THROW("Missing ']'");
|
|
|
|
|
current++;
|
|
|
|
|
|
|
|
|
|
add_operator(collection ? RS_COLON : RS_RSQR, n);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void analyze_single(int op)
|
|
|
|
|
{
|
2010-12-29 09:21:51 +01:00
|
|
|
|
PATTERN *pattern;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
if (PATTERN_is_newline(*current))
|
|
|
|
|
current++;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
if (op == RS_PT && !PATTERN_is_identifier(*current))
|
2007-12-30 17:41:49 +01:00
|
|
|
|
THROW("The '.' operator must be followed by an identifier");
|
|
|
|
|
else if (op == RS_EXCL && !PATTERN_is_string(*current))
|
|
|
|
|
THROW("The '!' operator must be followed by an identifier");
|
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
/* ( expr ) */
|
|
|
|
|
|
|
|
|
|
if (PATTERN_is(*current, RS_LBRA))
|
|
|
|
|
{
|
|
|
|
|
int index = ARRAY_count(EVAL->tree);
|
|
|
|
|
PATTERN last;
|
|
|
|
|
|
|
|
|
|
current++;
|
|
|
|
|
analyze_expr(0, RS_NONE);
|
|
|
|
|
|
|
|
|
|
if (!PATTERN_is(*current, RS_RBRA))
|
|
|
|
|
THROW("Missing ')'");
|
|
|
|
|
current++;
|
|
|
|
|
|
|
|
|
|
if (ARRAY_count(EVAL->tree) == (index + 1))
|
|
|
|
|
{
|
|
|
|
|
last = get_last_pattern(1);
|
|
|
|
|
if (PATTERN_is_string(last))
|
|
|
|
|
change_last_pattern(1, PATTERN_make(RT_TSTRING, PATTERN_index(last)));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* [ expr, expr, ... ] */
|
|
|
|
|
|
|
|
|
|
else if (PATTERN_is(*current, RS_LSQR))
|
|
|
|
|
{
|
|
|
|
|
current++;
|
|
|
|
|
analyze_make_array();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* - expr | NOT expr */
|
|
|
|
|
|
|
|
|
|
else if (PATTERN_is(*current, RS_MINUS) || PATTERN_is(*current, RS_NOT))
|
|
|
|
|
{
|
|
|
|
|
pattern = current;
|
|
|
|
|
current++;
|
|
|
|
|
|
|
|
|
|
analyze_expr(RES_priority(RS_NOT), RS_UNARY);
|
|
|
|
|
add_operator(PATTERN_index(*pattern), 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* . symbol
|
|
|
|
|
|
|
|
|
|
else if (PATTERN_is(*current, RS_PT) && PATTERN_is_identifier(current[1]))
|
|
|
|
|
{
|
|
|
|
|
add_operator(PATTERN_index(current[0]), 0);
|
|
|
|
|
add_pattern(PATTERN_set_flag(current[1], RT_POINT));
|
|
|
|
|
current += 2;
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
/* NULL, TRUE, FALSE, ME, LAST */
|
|
|
|
|
/* nombre, chaine ou symbole */
|
|
|
|
|
|
|
|
|
|
else if (PATTERN_is(*current, RS_NULL)
|
|
|
|
|
|| PATTERN_is(*current, RS_ME)
|
|
|
|
|
|| PATTERN_is(*current, RS_LAST)
|
|
|
|
|
|| PATTERN_is(*current, RS_TRUE)
|
|
|
|
|
|| PATTERN_is(*current, RS_FALSE)
|
2012-01-31 03:33:01 +01:00
|
|
|
|
|| PATTERN_is(*current, RS_PINF)
|
|
|
|
|
|| PATTERN_is(*current, RS_MINF)
|
2010-12-29 09:21:51 +01:00
|
|
|
|
//|| PATTERN_is(*current, RS_ERROR)
|
|
|
|
|
|| (!PATTERN_is_reserved(*current) && !PATTERN_is_newline(*current) && !PATTERN_is_end(*current)))
|
|
|
|
|
{
|
|
|
|
|
add_pattern(*current);
|
|
|
|
|
|
|
|
|
|
if (PATTERN_is_identifier(*current))
|
|
|
|
|
{
|
|
|
|
|
/*if ((op == RS_NONE || op == RS_UNARY) && (PATTERN_is_identifier(*current)))
|
|
|
|
|
change_last_pattern(1, PATTERN_set_flag(get_last_pattern(1), RT_FIRST));*/
|
|
|
|
|
if (op == RS_PT)
|
|
|
|
|
{
|
|
|
|
|
change_last_pattern(1, PATTERN_set_flag(get_last_pattern(1), RT_POINT));
|
|
|
|
|
check_last_first(2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
current++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else
|
|
|
|
|
THROW2("Unexpected &1", READ_get_pattern(current));
|
2007-12-30 17:41:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void analyze_call()
|
|
|
|
|
{
|
2010-12-29 09:21:51 +01:00
|
|
|
|
int nparam_post = 0;
|
|
|
|
|
PATTERN subr_pattern = NULL_PATTERN;
|
|
|
|
|
PATTERN last_pattern = get_last_pattern(1);
|
|
|
|
|
SUBR_INFO *info;
|
2011-05-16 04:16:22 +02:00
|
|
|
|
bool optional = TRUE;
|
2010-12-29 09:21:51 +01:00
|
|
|
|
|
|
|
|
|
if (PATTERN_is_subr(last_pattern))
|
|
|
|
|
{
|
|
|
|
|
subr_pattern = last_pattern;
|
|
|
|
|
remove_last_pattern();
|
|
|
|
|
optional = FALSE;
|
|
|
|
|
}
|
|
|
|
|
else if (PATTERN_is_identifier(last_pattern))
|
|
|
|
|
{
|
2016-01-03 17:44:24 +01:00
|
|
|
|
if (EVAL->custom)
|
|
|
|
|
{
|
|
|
|
|
change_last_pattern(1, PATTERN_make(RT_IDENTIFIER, EVAL->var[0]));
|
|
|
|
|
add_reserved_pattern(RS_PT);
|
|
|
|
|
add_pattern(PATTERN_set_flag(last_pattern, RT_POINT));
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
check_last_first(1);
|
|
|
|
|
}
|
|
|
|
|
else if (PATTERN_is_string(last_pattern) || PATTERN_is_number(last_pattern))
|
|
|
|
|
THROW(E_SYNTAX);
|
|
|
|
|
|
|
|
|
|
/* N.B. Le cas où last_pattern = "." n'a pas de test spécifique */
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2008-01-19 02:36:38 +01:00
|
|
|
|
if (subr_pattern && subr_pattern == PATTERN_make(RT_SUBR, SUBR_VarPtr))
|
|
|
|
|
THROW("VarPtr() cannot be used with Eval()");
|
2016-01-03 17:44:24 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
for (;;)
|
|
|
|
|
{
|
|
|
|
|
if (PATTERN_is(*current, RS_RBRA))
|
|
|
|
|
{
|
|
|
|
|
current++;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nparam_post > 0)
|
|
|
|
|
{
|
|
|
|
|
if (!PATTERN_is(*current, RS_COMMA))
|
|
|
|
|
THROW("Missing ')'");
|
|
|
|
|
current++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (optional && (PATTERN_is(*current, RS_COMMA) || PATTERN_is(*current, RS_RBRA)))
|
|
|
|
|
{
|
|
|
|
|
add_reserved_pattern(RS_OPTIONAL);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
analyze_expr(0, RS_NONE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nparam_post++;
|
|
|
|
|
|
|
|
|
|
if (nparam_post > MAX_PARAM_FUNC)
|
|
|
|
|
THROW("Too many arguments");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (get_last_pattern(1) == PATTERN_make(RT_RESERVED, RS_OPTIONAL))
|
|
|
|
|
THROW("Syntax error. Needless arguments");
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
while (nparam_post > 0)
|
|
|
|
|
{
|
|
|
|
|
if (get_last_pattern(1) != PATTERN_make(RT_RESERVED, RS_OPTIONAL))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
remove_last_pattern();
|
|
|
|
|
nparam_post--;
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (subr_pattern == NULL_PATTERN)
|
2014-01-28 00:46:37 +01:00
|
|
|
|
add_operator_output(RS_LBRA, nparam_post);
|
2010-12-29 09:21:51 +01:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
info = &COMP_subr_info[PATTERN_index(subr_pattern)];
|
|
|
|
|
|
|
|
|
|
if (nparam_post < info->min_param)
|
|
|
|
|
THROW2("Not enough arguments to &1", info->name);
|
|
|
|
|
else if (nparam_post > info->max_param)
|
|
|
|
|
THROW2("Too many arguments to &1", info->name);
|
|
|
|
|
|
2014-01-28 00:46:37 +01:00
|
|
|
|
add_subr(subr_pattern, nparam_post);
|
2010-12-29 09:21:51 +01:00
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void analyze_array()
|
|
|
|
|
{
|
2010-12-29 09:21:51 +01:00
|
|
|
|
int i;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
check_last_first(1);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
for(i = 0; i < MAX_ARRAY_DIM; i++)
|
|
|
|
|
{
|
|
|
|
|
analyze_expr(0, RS_NONE);
|
|
|
|
|
if (!PATTERN_is(*current, RS_COMMA))
|
|
|
|
|
break;
|
|
|
|
|
current++;
|
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
if (!PATTERN_is(*current, RS_RSQR))
|
|
|
|
|
THROW("Missing ']'");
|
|
|
|
|
current++;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
add_operator(RS_LSQR, i + 2);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
static void analyze_expr_check_first(int op_curr)
|
|
|
|
|
{
|
2010-12-29 09:21:51 +01:00
|
|
|
|
/* On laisse le marqueur RT_FIRST que si on a affaire <20>l'op<6F>ateur '.' */
|
|
|
|
|
/*
|
|
|
|
|
last = get_last_pattern();
|
|
|
|
|
if (PATTERN_is_first(last))
|
|
|
|
|
{
|
|
|
|
|
if (op_curr != RS_PT)
|
|
|
|
|
change_last_pattern(PATTERN_unset_flag(last, RT_FIRST));
|
|
|
|
|
}
|
|
|
|
|
*/
|
2007-12-30 17:41:49 +01:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static void analyze_expr(short priority, short op_main)
|
|
|
|
|
{
|
2010-12-29 09:21:51 +01:00
|
|
|
|
int op, op_curr, op_not;
|
|
|
|
|
int prio;
|
|
|
|
|
int nparam;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
inc_level();
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
op_curr = op_main;
|
|
|
|
|
nparam = (op_main == RS_NONE || op_main == RS_UNARY) ? 0 : 1;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2016-01-03 17:44:24 +01:00
|
|
|
|
/* Special NEW case */
|
|
|
|
|
/* It should never be used, analysis is done elsewhere */
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
if (PATTERN_is(*current, RS_NEW))
|
|
|
|
|
THROW("Cannot use NEW operator there");
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2016-01-03 17:44:24 +01:00
|
|
|
|
// Operand analysis
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
|
|
READ_OPERAND:
|
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
//analyze_expr_check_first(op_curr);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
analyze_single(op_curr);
|
|
|
|
|
nparam++;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
if (nparam > MAX_PARAM_OP)
|
|
|
|
|
THROW("Expression too complex. Too many operands");
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2016-01-03 17:44:24 +01:00
|
|
|
|
// operator
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
|
|
READ_OPERATOR:
|
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
if (!PATTERN_is_reserved(*current))
|
|
|
|
|
goto OPERATOR_END;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
op = PATTERN_index(*current);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
if (!RES_is_operator(op))
|
|
|
|
|
goto OPERATOR_END;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
current++;
|
|
|
|
|
|
|
|
|
|
if (op == RS_NOT && PATTERN_is_reserved(*current))
|
|
|
|
|
{
|
|
|
|
|
op_not = PATTERN_index(*current);
|
|
|
|
|
if (RES_is_operator(op_not) && RES_can_have_not_before(op_not))
|
|
|
|
|
{
|
|
|
|
|
op = op_not + 1;
|
|
|
|
|
current++;
|
|
|
|
|
}
|
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2009-09-27 11:28:52 +02:00
|
|
|
|
/*if ((op == RS_BEGINS || op == RS_ENDS) && PATTERN_is(*current, RS_WITH))
|
|
|
|
|
current++;*/
|
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
if (priority)
|
|
|
|
|
prio = priority;
|
|
|
|
|
else if (op_curr == RS_NONE)
|
|
|
|
|
prio = 0;
|
|
|
|
|
else
|
|
|
|
|
prio = RES_priority(op_curr);
|
|
|
|
|
|
|
|
|
|
if (op_curr == RS_NONE)
|
|
|
|
|
{
|
|
|
|
|
if (RES_is_binary(op) || RES_is_n_ary(op))
|
|
|
|
|
{
|
|
|
|
|
op_curr = op;
|
|
|
|
|
goto READ_OPERAND;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (op_curr == op)
|
|
|
|
|
{
|
|
|
|
|
if (!(RES_is_binary(op) && nparam == 2))
|
|
|
|
|
goto READ_OPERAND;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (RES_priority(op) > prio)
|
|
|
|
|
{
|
|
|
|
|
if (op == RS_LSQR)
|
|
|
|
|
analyze_array();
|
|
|
|
|
else if (op == RS_LBRA)
|
|
|
|
|
analyze_call();
|
|
|
|
|
else
|
|
|
|
|
analyze_expr(RES_priority(op), op);
|
|
|
|
|
|
|
|
|
|
goto READ_OPERATOR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (RES_priority(op) == prio)
|
|
|
|
|
{
|
|
|
|
|
add_operator(op_curr, nparam);
|
|
|
|
|
|
|
|
|
|
if (op == RS_LSQR)
|
|
|
|
|
{
|
|
|
|
|
analyze_array();
|
|
|
|
|
goto READ_OPERATOR;
|
|
|
|
|
}
|
|
|
|
|
else if (op == RS_LBRA)
|
|
|
|
|
{
|
|
|
|
|
analyze_call();
|
|
|
|
|
goto READ_OPERATOR;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (RES_is_only(op_curr) || RES_is_only(op))
|
|
|
|
|
THROW("Ambiguous expression. Please use braces");
|
|
|
|
|
|
|
|
|
|
nparam = 1;
|
|
|
|
|
op_curr = op;
|
|
|
|
|
goto READ_OPERAND;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (RES_priority(op) < prio)
|
|
|
|
|
{
|
|
|
|
|
if ((op_main != RS_NONE) || (priority > 0))
|
|
|
|
|
{
|
|
|
|
|
add_operator(op_curr, nparam);
|
|
|
|
|
current--;
|
|
|
|
|
goto END;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
add_operator(op_curr, nparam);
|
|
|
|
|
|
|
|
|
|
if (op == RS_LSQR)
|
|
|
|
|
{
|
|
|
|
|
analyze_array();
|
|
|
|
|
nparam = 1;
|
|
|
|
|
op_curr = op_main;
|
|
|
|
|
goto READ_OPERATOR;
|
|
|
|
|
}
|
|
|
|
|
else if (op == RS_LBRA)
|
|
|
|
|
{
|
|
|
|
|
analyze_call();
|
|
|
|
|
nparam = 1;
|
|
|
|
|
op_curr = op_main;
|
|
|
|
|
goto READ_OPERATOR;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
nparam = 1;
|
|
|
|
|
op_curr = op;
|
|
|
|
|
goto READ_OPERAND;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dec_level();
|
|
|
|
|
return;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
|
|
OPERATOR_END:
|
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
//analyze_expr_check_first(op_curr);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
add_operator(op_curr, nparam);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
|
|
END:
|
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
dec_level();
|
|
|
|
|
return;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PUBLIC void TRANS_tree()
|
|
|
|
|
{
|
2010-12-29 09:21:51 +01:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
int i;
|
|
|
|
|
#endif
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
/*last_pattern = NULL_PATTERN;*/
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
ARRAY_create(&EVAL->tree);
|
|
|
|
|
/*ARRAY_add(&tree);*/
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
current = EVAL->current; //EVAL->pattern;
|
2014-12-22 18:41:16 +01:00
|
|
|
|
level = 0;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
if (PATTERN_is_newline(*current) || PATTERN_is_end(*current))
|
|
|
|
|
THROW(E_SYNTAX);
|
2016-01-03 17:44:24 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
analyze_expr(0, RS_NONE);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
while (PATTERN_is_newline(*current))
|
|
|
|
|
current++;
|
2016-01-03 17:44:24 +01:00
|
|
|
|
|
2009-05-27 00:34:39 +02:00
|
|
|
|
EVAL->current = current;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
2010-12-29 09:21:51 +01:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("\n");
|
|
|
|
|
for (i = 0; i < ARRAY_count(EVAL->tree); i++)
|
|
|
|
|
READ_dump_pattern(&EVAL->tree[i]);
|
|
|
|
|
#endif
|
2007-12-30 17:41:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if 0
|
2011-05-16 04:16:22 +02:00
|
|
|
|
PUBLIC bool TRANS_is_statement(TRANS_TREE *tree)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
{
|
2010-12-29 09:21:51 +01:00
|
|
|
|
PATTERN last;
|
|
|
|
|
int count;
|
|
|
|
|
|
|
|
|
|
count = ARRAY_count(tree);
|
|
|
|
|
|
|
|
|
|
if (count == 0)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
count--;
|
|
|
|
|
last = tree[count];
|
|
|
|
|
|
|
|
|
|
if (PATTERN_is_param(last) && (count > 0))
|
|
|
|
|
{
|
|
|
|
|
count--;
|
|
|
|
|
last = tree[count];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (PATTERN_is(last, RS_PT) || (PATTERN_is_identifier(last) && count == 0))
|
|
|
|
|
{
|
|
|
|
|
add_operator(RS_LBRA, 0);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (PATTERN_is_subr(last)
|
|
|
|
|
|| PATTERN_is(last, RS_LBRA)
|
|
|
|
|
|| PATTERN_is(last, RS_RBRA)
|
|
|
|
|
|| PATTERN_is(last, RS_AT)
|
|
|
|
|
|| PATTERN_is(last, RS_COMMA))
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("Last = ");
|
|
|
|
|
READ_dump_pattern(&last);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|