Commit dbac4aff by Neil Booth Committed by Neil Booth

cppexp.c: Redefine priority constants.

        * cppexp.c: Redefine priority constants.
        (_cpp_parse_expr): Replace left and right priority scheme with
	single priority logic.  Move LOGICAL to same place as COMPARE.
	Remove bogus check for multiple unary +/- operators.

From-SVN: r32855
parent 9ee70313
2000-04-01 Neil Booth <NeilB@earthling.net> 2000-04-01 Neil Booth <NeilB@earthling.net>
* cppexp.c: Redefine priority constants.
(_cpp_parse_expr): Replace left and right priority scheme with
single priority logic. Move LOGICAL to same place as COMPARE.
Remove bogus check for multiple unary +/- operators.
2000-04-01 Neil Booth <NeilB@earthling.net>
* cppexp.c: (_cpp_parse_expr): Numerical constants are pushed * cppexp.c: (_cpp_parse_expr): Numerical constants are pushed
within the switch statement. Binary operations break out of within the switch statement. Binary operations break out of
the switch naturally. '(' tokens handled by forcing the switch naturally. '(' tokens handled by forcing
......
...@@ -106,7 +106,7 @@ static struct operation lex PARAMS ((cpp_reader *, int)); ...@@ -106,7 +106,7 @@ static struct operation lex PARAMS ((cpp_reader *, int));
struct operation struct operation
{ {
short op; short op;
U_CHAR rprio; /* Priority of op (relative to it right operand). */ U_CHAR prio; /* Priority of op (relative to it right operand). */
U_CHAR flags; U_CHAR flags;
U_CHAR unsignedp; /* true if value should be treated as unsigned */ U_CHAR unsignedp; /* true if value should be treated as unsigned */
HOST_WIDEST_INT value; /* The value logically "right" of op. */ HOST_WIDEST_INT value; /* The value logically "right" of op. */
...@@ -636,32 +636,60 @@ right_shift (pfile, a, unsignedp, b) ...@@ -636,32 +636,60 @@ right_shift (pfile, a, unsignedp, b)
return a >> b; return a >> b;
} }
/* These priorities are all even, so we can handle associatively. */ /* Operator precedence table.
#define PAREN_INNER_PRIO 2
#define COMMA_PRIO 4 After an operator is returned from the lexer, if it has priority less
#define COND_PRIO (COMMA_PRIO+2) than or equal to the operator on the top of the stack, we reduce the
#define OROR_PRIO (COND_PRIO+2) stack one operator and repeat the test. As equal priorities reduce,
#define ANDAND_PRIO (OROR_PRIO+2) this is naturally left-associative.
#define OR_PRIO (ANDAND_PRIO+2)
#define XOR_PRIO (OR_PRIO+2) We handle right-associative operators by clearing the lower bit of all
#define AND_PRIO (XOR_PRIO+2) left-associative operators, and setting it for right-associative ones.
#define EQUAL_PRIO (AND_PRIO+2) After the reduction phase, when an operator is pushed onto the stack,
#define LESS_PRIO (EQUAL_PRIO+2) its RIGHT_ASSOC bit is cleared. This means that at reduction time, a
#define SHIFT_PRIO (LESS_PRIO+2) right-associative operator of otherwise equal precedence to the
#define PLUS_PRIO (SHIFT_PRIO+2) operator on the top of the stack will have a greater priority by 1,
#define MUL_PRIO (PLUS_PRIO+2) avoiding a reduction pass and making the logic right-associative.
#define UNARY_PRIO (MUL_PRIO+2)
#define PAREN_OUTER_PRIO (UNARY_PRIO+2) The remaining cases are '(' and ')'. We handle '(' by skipping the
reduction phase completely. ')' is given lower priority than
everything else, including '(', effectively forcing a reduction of the
parenthesised expression. If there is no matching '(', the expression
will be reduced to the beginning, the ')' pushed, and the reduction
pass forced by the next ')', or the end of the expression, will meet
it and output an appropriate error message. */
#define RIGHT_ASSOC 1
#define PREVENT_REDUCE_PRIO (0 << 1)
#define FORCE_REDUCE_PRIO (1 << 1)
#define CLOSE_PAREN_PRIO (2 << 1)
#define OPEN_PAREN_PRIO (3 << 1)
#define COMMA_PRIO (4 << 1)
#define COND_PRIO ((5 << 1) + RIGHT_ASSOC)
#define COLON_PRIO (6 << 1)
#define OROR_PRIO (7 << 1)
#define ANDAND_PRIO (8 << 1)
#define OR_PRIO (9 << 1)
#define XOR_PRIO (10 << 1)
#define AND_PRIO (11 << 1)
#define EQUAL_PRIO (12 << 1)
#define LESS_PRIO (13 << 1)
#define SHIFT_PRIO (14 << 1)
#define PLUS_PRIO (15 << 1)
#define MUL_PRIO (16 << 1)
#define UNARY_PRIO ((17 << 1) + RIGHT_ASSOC)
#define LEFT_OPERAND_REQUIRED 1 #define LEFT_OPERAND_REQUIRED 1
#define RIGHT_OPERAND_REQUIRED 2 #define RIGHT_OPERAND_REQUIRED 2
#define HAVE_VALUE 4 #define HAVE_VALUE 4
#define SIGN_QUALIFIED 8
#define COMPARE(OP) \ #define COMPARE(OP) \
top->unsignedp = 0;\ top->unsignedp = 0;\
top->value = (unsigned1 || unsigned2) \ top->value = (unsigned1 || unsigned2) \
? (unsigned HOST_WIDEST_INT) v1 OP (unsigned HOST_WIDEST_INT) v2 : (v1 OP v2) ? (unsigned HOST_WIDEST_INT) v1 OP (unsigned HOST_WIDEST_INT) v2 : (v1 OP v2)
#define LOGICAL(OP) \
top->value = v1 OP v2;\
top->unsignedp = unsigned1 || unsigned2;
/* Parse and evaluate a C expression, reading from PFILE. /* Parse and evaluate a C expression, reading from PFILE.
Returns the truth value of the expression. */ Returns the truth value of the expression. */
...@@ -685,16 +713,16 @@ _cpp_parse_expr (pfile) ...@@ -685,16 +713,16 @@ _cpp_parse_expr (pfile)
struct operation *stack = init_stack; struct operation *stack = init_stack;
struct operation *limit = stack + INIT_STACK_SIZE; struct operation *limit = stack + INIT_STACK_SIZE;
register struct operation *top = stack; register struct operation *top = stack;
unsigned int lprio, rprio = 0;
int skip_evaluation = 0; int skip_evaluation = 0;
long old_written = CPP_WRITTEN (pfile); long old_written = CPP_WRITTEN (pfile);
int result; int result;
pfile->parsing_if_directive++; pfile->parsing_if_directive++;
top->rprio = 0; top->prio = PREVENT_REDUCE_PRIO;
top->flags = 0; top->flags = 0;
for (;;) for (;;)
{ {
unsigned int prio;
struct operation op; struct operation op;
U_CHAR flags = 0; U_CHAR flags = 0;
...@@ -730,59 +758,47 @@ _cpp_parse_expr (pfile) ...@@ -730,59 +758,47 @@ _cpp_parse_expr (pfile)
continue; continue;
case '+': case '-': case '+': case '-':
lprio = PLUS_PRIO; prio = PLUS_PRIO;
if (top->flags & HAVE_VALUE) if (top->flags & HAVE_VALUE)
break; break;
if (top->flags & SIGN_QUALIFIED)
{
cpp_error (pfile, "more than one sign operator given");
goto syntax_error;
}
flags = SIGN_QUALIFIED;
/* else fall through */ /* else fall through */
case '!': case '~': case '!': case '~':
flags |= RIGHT_OPERAND_REQUIRED; flags |= RIGHT_OPERAND_REQUIRED;
rprio = UNARY_PRIO; lprio = rprio + 1; goto maybe_reduce; prio = UNARY_PRIO; goto maybe_reduce;
case '*': case '/': case '%': case '*':
lprio = MUL_PRIO; break; case '/':
case '<': case '>': case LEQ: case GEQ: case '%': prio = MUL_PRIO; break;
lprio = LESS_PRIO; break; case '<':
case EQUAL: case NOTEQUAL: case '>':
lprio = EQUAL_PRIO; break; case LEQ:
case LSH: case RSH: case GEQ: prio = LESS_PRIO; break;
lprio = SHIFT_PRIO; break; case NOTEQUAL:
case '&': lprio = AND_PRIO; break; case EQUAL: prio = EQUAL_PRIO; break;
case '^': lprio = XOR_PRIO; break; case LSH:
case '|': lprio = OR_PRIO; break; case RSH: prio = SHIFT_PRIO; break;
case ANDAND: lprio = ANDAND_PRIO; break; case '&': prio = AND_PRIO; break;
case OROR: lprio = OROR_PRIO; break; case '^': prio = XOR_PRIO; break;
case ',': case '|': prio = OR_PRIO; break;
lprio = COMMA_PRIO; break; case ANDAND: prio = ANDAND_PRIO; break;
case '(': case OROR: prio = OROR_PRIO; break;
lprio = PAREN_OUTER_PRIO; rprio = PAREN_INNER_PRIO + 1; case ',': prio = COMMA_PRIO; break;
goto skip_reduction; case '(': prio = OPEN_PAREN_PRIO; goto skip_reduction;
case ')': case ')':
lprio = PAREN_INNER_PRIO; rprio = PAREN_OUTER_PRIO; prio = CLOSE_PAREN_PRIO;
flags = HAVE_VALUE; /* At least, we will have after reduction. */ flags = HAVE_VALUE; /* At least, we will have after reduction. */
goto maybe_reduce; goto maybe_reduce;
case ':': case ':': prio = COLON_PRIO; goto maybe_reduce;
lprio = COND_PRIO; rprio = COND_PRIO + 1; case '?': prio = COND_PRIO; goto maybe_reduce;
goto maybe_reduce; case 0: prio = FORCE_REDUCE_PRIO; goto maybe_reduce;
case '?':
lprio = COND_PRIO; rprio = COND_PRIO;
goto maybe_reduce;
case 0:
lprio = 0; goto maybe_reduce;
} }
/* Binary operation. */ /* Binary operation. */
flags = LEFT_OPERAND_REQUIRED|RIGHT_OPERAND_REQUIRED; flags = LEFT_OPERAND_REQUIRED|RIGHT_OPERAND_REQUIRED;
rprio = lprio + 1;
maybe_reduce: maybe_reduce:
/* Push an operator, and check if we can reduce now. */ /* Check for reductions. Then push the operator. */
while (top->rprio > lprio) while (prio <= top->prio)
{ {
HOST_WIDEST_INT v1 = top[-1].value, v2 = top[0].value; HOST_WIDEST_INT v1 = top[-1].value, v2 = top[0].value;
unsigned int unsigned1 = top[-1].unsignedp; unsigned int unsigned1 = top[-1].unsignedp;
...@@ -932,9 +948,6 @@ _cpp_parse_expr (pfile) ...@@ -932,9 +948,6 @@ _cpp_parse_expr (pfile)
else else
top->value = right_shift (pfile, v1, unsigned1, v2); top->value = right_shift (pfile, v1, unsigned1, v2);
break; break;
#define LOGICAL(OP) \
top->value = v1 OP v2;\
top->unsignedp = unsigned1 || unsigned2;
case '&': LOGICAL(&); break; case '&': LOGICAL(&); break;
case '^': LOGICAL(^); break; case '^': LOGICAL(^); break;
case '|': LOGICAL(|); break; case '|': LOGICAL(|); break;
...@@ -953,7 +966,7 @@ _cpp_parse_expr (pfile) ...@@ -953,7 +966,7 @@ _cpp_parse_expr (pfile)
top->unsignedp = unsigned2; top->unsignedp = unsigned2;
break; break;
case '?': case '?':
cpp_error (pfile, "syntax error in #if"); cpp_error (pfile, "syntax error '?' without following ':'");
goto syntax_error; goto syntax_error;
case ':': case ':':
if (top[0].op != '?') if (top[0].op != '?')
...@@ -1027,7 +1040,7 @@ _cpp_parse_expr (pfile) ...@@ -1027,7 +1040,7 @@ _cpp_parse_expr (pfile)
} }
top->flags = flags; top->flags = flags;
top->rprio = rprio; top->prio = prio & ~RIGHT_ASSOC;
top->op = op.op; top->op = op.op;
/* Handle short circuiting. */ /* Handle short circuiting. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment