mirror of
https://github.com/uffejakobsen/acme.git
synced 2024-11-28 13:49:22 +00:00
fixed operator priority bug (see test program added in svn rev 232)
git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@238 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
parent
326f36fd4f
commit
64aa52da35
53
src/alu.c
53
src/alu.c
@ -173,7 +173,7 @@ static int arg_sp;
|
|||||||
enum alu_state {
|
enum alu_state {
|
||||||
STATE_EXPECT_ARG_OR_MONADIC_OP,
|
STATE_EXPECT_ARG_OR_MONADIC_OP,
|
||||||
STATE_EXPECT_DYADIC_OP,
|
STATE_EXPECT_DYADIC_OP,
|
||||||
STATE_TRY_TO_REDUCE_STACKS, // FIXME - get rid of this state
|
STATE_TRY_TO_REDUCE_STACKS,
|
||||||
STATE_MAX_GO_ON, // "border value" to find the stoppers:
|
STATE_MAX_GO_ON, // "border value" to find the stoppers:
|
||||||
STATE_ERROR, // error has occurred
|
STATE_ERROR, // error has occurred
|
||||||
STATE_END // standard end
|
STATE_END // standard end
|
||||||
@ -699,6 +699,8 @@ static void list_append_list(struct listitem *selfhead, struct listitem *otherhe
|
|||||||
|
|
||||||
// expression parser
|
// expression parser
|
||||||
|
|
||||||
|
// prototype (FIXME, re-arrange code so this is no longer needed!)
|
||||||
|
static void push_dyadic_and_check(struct expression *expression, struct op *op);
|
||||||
|
|
||||||
// helper function for "monadic &" (either octal value or "unpseudo" operator)
|
// helper function for "monadic &" (either octal value or "unpseudo" operator)
|
||||||
// returns nonzero on error
|
// returns nonzero on error
|
||||||
@ -741,7 +743,7 @@ static int parse_octal_or_unpseudo(void) // now GotByte = '&'
|
|||||||
// Expect argument or monadic operator (hopefully inlined)
|
// Expect argument or monadic operator (hopefully inlined)
|
||||||
// returns TRUE if it ate any non-space (-> so expression isn't empty)
|
// returns TRUE if it ate any non-space (-> so expression isn't empty)
|
||||||
// returns FALSE if first non-space is delimiter (-> end of expression)
|
// returns FALSE if first non-space is delimiter (-> end of expression)
|
||||||
static boolean expect_argument_or_monadic_operator(void)
|
static boolean expect_argument_or_monadic_operator(struct expression *expression)
|
||||||
{
|
{
|
||||||
struct op *op;
|
struct op *op;
|
||||||
int ugly_length_kluge;
|
int ugly_length_kluge;
|
||||||
@ -808,9 +810,8 @@ static boolean expect_argument_or_monadic_operator(void)
|
|||||||
} else {
|
} else {
|
||||||
// non-empty list literal
|
// non-empty list literal
|
||||||
PUSH_OP(&ops_start_list); // quasi-monadic "start of list", makes sure earlier ops do not process empty list
|
PUSH_OP(&ops_start_list); // quasi-monadic "start of list", makes sure earlier ops do not process empty list
|
||||||
PUSH_OP(&ops_list_append); // dyadic "append to list", so next arg will be appended to list
|
push_dyadic_and_check(expression, &ops_list_append); // dyadic "append to list", so next arg will be appended to list
|
||||||
// no need to TRY_TO_REDUCE_STACKS, because we know the one pushed first has a lower priority anyway
|
//now we're back in STATE_EXPECT_ARG_OR_MONADIC_OP
|
||||||
//stay in STATE_EXPECT_ARG_OR_MONADIC_OP
|
|
||||||
}
|
}
|
||||||
break;//goto done;
|
break;//goto done;
|
||||||
|
|
||||||
@ -918,8 +919,7 @@ static boolean expect_argument_or_monadic_operator(void)
|
|||||||
// that's either an empty expression or an erroneous one!
|
// that's either an empty expression or an erroneous one!
|
||||||
PUSH_INT_ARG(0, 0, 0); // push dummy argument so stack checking code won't bark FIXME - use undefined?
|
PUSH_INT_ARG(0, 0, 0); // push dummy argument so stack checking code won't bark FIXME - use undefined?
|
||||||
if (op_stack[op_sp - 1] == &ops_start_expression) {
|
if (op_stack[op_sp - 1] == &ops_start_expression) {
|
||||||
PUSH_OP(&ops_end_expression);
|
push_dyadic_and_check(expression, &ops_end_expression);
|
||||||
alu_state = STATE_TRY_TO_REDUCE_STACKS;
|
|
||||||
} else {
|
} else {
|
||||||
Throw_error(exception_syntax);
|
Throw_error(exception_syntax);
|
||||||
alu_state = STATE_ERROR;
|
alu_state = STATE_ERROR;
|
||||||
@ -948,7 +948,7 @@ now_expect_dyadic_op:
|
|||||||
|
|
||||||
|
|
||||||
// Expect dyadic operator (hopefully inlined)
|
// Expect dyadic operator (hopefully inlined)
|
||||||
static void expect_dyadic_operator(void)
|
static void expect_dyadic_operator(struct expression *expression)
|
||||||
{
|
{
|
||||||
void *node_body;
|
void *node_body;
|
||||||
struct op *op;
|
struct op *op;
|
||||||
@ -1004,17 +1004,11 @@ static void expect_dyadic_operator(void)
|
|||||||
|
|
||||||
case '[': // indexing operator
|
case '[': // indexing operator
|
||||||
GetByte(); // eat char
|
GetByte(); // eat char
|
||||||
PUSH_OP(&ops_atindex); // first put high-priority dyadic on stack,
|
// first put high-priority dyadic on stack,
|
||||||
// FIXME - reduce stacks!
|
// then low-priority special ops_subexpr_bracket
|
||||||
PUSH_OP(&ops_subexpr_bracket); // then low-priority special ops_subexpr_bracket
|
push_dyadic_and_check(expression, &ops_atindex);
|
||||||
// FIXME! this would work reliably if "atindex" had the highest priority.
|
// now we're in STATE_EXPECT_ARG_OR_MONADIC_OP
|
||||||
// but function calls have higher priority than indexing:
|
PUSH_OP(&ops_subexpr_bracket);
|
||||||
// fn(a+b)[c] -> fn d [c] -> e [c], but the code above would return fn(d[c]) instead
|
|
||||||
// atm, it's not a problem, because all functions return numbers, and numbers cannot
|
|
||||||
// be indexed anyway, but in the long run, this must be fixed.
|
|
||||||
// maybe call "try_to_reduce_stacks" inbetween the two PUSH_OPs above?
|
|
||||||
// or maybe add a PUSH_DYADIC_AND_TRY_TO_REDUCE(op) macro?
|
|
||||||
alu_state = STATE_EXPECT_ARG_OR_MONADIC_OP;
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Multi-character dyadic operators
|
// Multi-character dyadic operators
|
||||||
@ -1099,8 +1093,7 @@ static void expect_dyadic_operator(void)
|
|||||||
get_byte_and_push_dyadic:
|
get_byte_and_push_dyadic:
|
||||||
GetByte();
|
GetByte();
|
||||||
push_dyadic_op:
|
push_dyadic_op:
|
||||||
PUSH_OP(op);
|
push_dyadic_and_check(expression, op);
|
||||||
alu_state = STATE_TRY_TO_REDUCE_STACKS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2230,14 +2223,15 @@ static boolean handle_special_operator(struct expression *expression, enum op_id
|
|||||||
|
|
||||||
// Try to reduce stacks by performing high-priority operations
|
// Try to reduce stacks by performing high-priority operations
|
||||||
// (if the previous operator has a higher priority than the current one, do it)
|
// (if the previous operator has a higher priority than the current one, do it)
|
||||||
// FIXME - rename to "push_dyadic_op" and add operator arg?
|
static void push_dyadic_and_check(struct expression *expression, struct op *op)
|
||||||
static void try_to_reduce_stacks(struct expression *expression)
|
|
||||||
{
|
{
|
||||||
struct op *previous_op;
|
struct op *previous_op;
|
||||||
struct op *current_op;
|
struct op *current_op;
|
||||||
|
|
||||||
|
PUSH_OP(op);
|
||||||
|
if (alu_state < STATE_MAX_GO_ON)
|
||||||
|
alu_state = STATE_TRY_TO_REDUCE_STACKS;
|
||||||
while (alu_state == STATE_TRY_TO_REDUCE_STACKS) {
|
while (alu_state == STATE_TRY_TO_REDUCE_STACKS) {
|
||||||
|
|
||||||
if (op_sp < 2) {
|
if (op_sp < 2) {
|
||||||
// we only have one operator, which must be "start of expression",
|
// we only have one operator, which must be "start of expression",
|
||||||
// so there isn't anything left to do, so go on trying to parse the expression
|
// so there isn't anything left to do, so go on trying to parse the expression
|
||||||
@ -2319,23 +2313,22 @@ static int parse_expression(struct expression *expression)
|
|||||||
op_sp = 0; // operator stack pointer
|
op_sp = 0; // operator stack pointer
|
||||||
arg_sp = 0; // argument stack pointer
|
arg_sp = 0; // argument stack pointer
|
||||||
// begin by reading an argument (or a monadic operator)
|
// begin by reading an argument (or a monadic operator)
|
||||||
alu_state = STATE_EXPECT_ARG_OR_MONADIC_OP;
|
|
||||||
PUSH_OP(&ops_start_expression);
|
PUSH_OP(&ops_start_expression);
|
||||||
|
alu_state = STATE_EXPECT_ARG_OR_MONADIC_OP;
|
||||||
do {
|
do {
|
||||||
// check stack sizes. enlarge if needed
|
// check stack sizes. enlarge if needed
|
||||||
if (arg_sp >= argstack_size)
|
if (arg_sp >= argstack_size)
|
||||||
enlarge_argument_stack();
|
enlarge_argument_stack();
|
||||||
switch (alu_state) {
|
switch (alu_state) {
|
||||||
case STATE_EXPECT_ARG_OR_MONADIC_OP:
|
case STATE_EXPECT_ARG_OR_MONADIC_OP:
|
||||||
if (expect_argument_or_monadic_operator())
|
if (expect_argument_or_monadic_operator(expression))
|
||||||
expression->is_empty = FALSE;
|
expression->is_empty = FALSE;
|
||||||
break;
|
break;
|
||||||
case STATE_EXPECT_DYADIC_OP:
|
case STATE_EXPECT_DYADIC_OP:
|
||||||
expect_dyadic_operator();
|
expect_dyadic_operator(expression);
|
||||||
break; // no fallthrough; state might
|
break;
|
||||||
// have been changed to END or ERROR
|
|
||||||
case STATE_TRY_TO_REDUCE_STACKS:
|
case STATE_TRY_TO_REDUCE_STACKS:
|
||||||
try_to_reduce_stacks(expression);
|
Bug_found("TryToReduce", 0); // FIXME - add to docs or remove!
|
||||||
break;
|
break;
|
||||||
case STATE_MAX_GO_ON: // suppress
|
case STATE_MAX_GO_ON: // suppress
|
||||||
case STATE_ERROR: // compiler
|
case STATE_ERROR: // compiler
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
;ACME 0.96.5
|
;ACME 0.96.5
|
||||||
li = [[9,8], 7, 3,4]
|
li = [[9,8], 7, 3,4]
|
||||||
a = len(li)[0] ; this should give an "Operation not supported" error, but doesn't
|
a = len(li)[0] ; this should give an "Operation not supported" error
|
Loading…
Reference in New Issue
Block a user