This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

cpplib: expression parser patch 3


[Apologies, I forgot to reset the mail's charset encoding again]. This follows on from the (still uncommitted) patch 2. The main point of this patch is to replace the left and right priorities by a single priority, which achieves some simplification. See the embedded comment for an explanation. * 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. Neil. --- cppexp.c Sat Apr 1 12:38:07 2000 +++ /usr/src/egcs/gcc/cppexp.c Sat Apr 1 12:56:55 2000 @@ -106,7 +106,7 @@ struct operation { 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 unsignedp; /* true if value should be treated as unsigned */ HOST_WIDEST_INT value; /* The value logically "right" of op. */ @@ -636,22 +636,48 @@ return a >> b; } -/* These priorities are all even, so we can handle associatively. */ -#define PAREN_INNER_PRIO 2 -#define COMMA_PRIO 4 -#define COND_PRIO (COMMA_PRIO+2) -#define OROR_PRIO (COND_PRIO+2) -#define ANDAND_PRIO (OROR_PRIO+2) -#define OR_PRIO (ANDAND_PRIO+2) -#define XOR_PRIO (OR_PRIO+2) -#define AND_PRIO (XOR_PRIO+2) -#define EQUAL_PRIO (AND_PRIO+2) -#define LESS_PRIO (EQUAL_PRIO+2) -#define SHIFT_PRIO (LESS_PRIO+2) -#define PLUS_PRIO (SHIFT_PRIO+2) -#define MUL_PRIO (PLUS_PRIO+2) -#define UNARY_PRIO (MUL_PRIO+2) -#define PAREN_OUTER_PRIO (UNARY_PRIO+2) +/* Operator precedence table. + +After an operator is returned from the lexer, if it has priority less +than or equal to the operator on the top of the stack, we reduce the +stack one operator and repeat the test. As equal priorities reduce, +this is naturally left-associative. + +We handle right-associative operators by clearing the lower bit of all +left-associative operators, and setting it for right-associative ones. +After the reduction phase, when an operator is pushed onto the stack, +its RIGHT_ASSOC bit is cleared. This means that at reduction time, a +right-associative operator of otherwise equal precedence to the +operator on the top of the stack will have a greater priority by 1, +avoiding a reduction pass and making the logic right-associative. + +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 RIGHT_OPERAND_REQUIRED 2 @@ -662,6 +688,9 @@ top->unsignedp = 0;\ top->value = (unsigned1 || unsigned2) \ ? (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. Returns the truth value of the expression. */ @@ -685,16 +714,16 @@ struct operation *stack = init_stack; struct operation *limit = stack + INIT_STACK_SIZE; register struct operation *top = stack; - unsigned int lprio, rprio = 0; int skip_evaluation = 0; long old_written = CPP_WRITTEN (pfile); int result; pfile->parsing_if_directive++; - top->rprio = 0; + top->prio = PREVENT_REDUCE_PRIO; top->flags = 0; for (;;) { + unsigned int prio; struct operation op; U_CHAR flags = 0; @@ -730,59 +759,55 @@ continue; case '+': case '-': - lprio = PLUS_PRIO; + prio = PLUS_PRIO; if (top->flags & HAVE_VALUE) break; +#if 0 if (top->flags & SIGN_QUALIFIED) { cpp_error (pfile, "more than one sign operator given"); goto syntax_error; } flags = SIGN_QUALIFIED; +#endif /* else fall through */ case '!': case '~': flags |= RIGHT_OPERAND_REQUIRED; - rprio = UNARY_PRIO; lprio = rprio + 1; goto maybe_reduce; + prio = UNARY_PRIO; goto maybe_reduce; - case '*': case '/': case '%': - lprio = MUL_PRIO; break; - case '<': case '>': case LEQ: case GEQ: - lprio = LESS_PRIO; break; - case EQUAL: case NOTEQUAL: - lprio = EQUAL_PRIO; break; - case LSH: case RSH: - lprio = SHIFT_PRIO; break; - case '&': lprio = AND_PRIO; break; - case '^': lprio = XOR_PRIO; break; - case '|': lprio = OR_PRIO; break; - case ANDAND: lprio = ANDAND_PRIO; break; - case OROR: lprio = OROR_PRIO; break; - case ',': - lprio = COMMA_PRIO; break; - case '(': - lprio = PAREN_OUTER_PRIO; rprio = PAREN_INNER_PRIO + 1; - goto skip_reduction; + case '*': + case '/': + case '%': prio = MUL_PRIO; break; + case '<': + case '>': + case LEQ: + case GEQ: prio = LESS_PRIO; break; + case NOTEQUAL: + case EQUAL: prio = EQUAL_PRIO; break; + case LSH: + case RSH: prio = SHIFT_PRIO; break; + case '&': prio = AND_PRIO; break; + case '^': prio = XOR_PRIO; break; + case '|': prio = OR_PRIO; break; + case ANDAND: prio = ANDAND_PRIO; break; + case OROR: prio = OROR_PRIO; break; + case ',': prio = COMMA_PRIO; break; + case '(': prio = OPEN_PAREN_PRIO; goto skip_reduction; case ')': - lprio = PAREN_INNER_PRIO; rprio = PAREN_OUTER_PRIO; + prio = CLOSE_PAREN_PRIO; flags = HAVE_VALUE; /* At least, we will have after reduction. */ goto maybe_reduce; - case ':': - lprio = COND_PRIO; rprio = COND_PRIO + 1; - goto maybe_reduce; - case '?': - lprio = COND_PRIO; rprio = COND_PRIO; - goto maybe_reduce; - case 0: - lprio = 0; goto maybe_reduce; + case ':': prio = COLON_PRIO; goto maybe_reduce; + case '?': prio = COND_PRIO; goto maybe_reduce; + case 0: prio = FORCE_REDUCE_PRIO; goto maybe_reduce; } /* Binary operation. */ flags = LEFT_OPERAND_REQUIRED|RIGHT_OPERAND_REQUIRED; - rprio = lprio + 1; maybe_reduce: - /* Push an operator, and check if we can reduce now. */ - while (top->rprio > lprio) + /* Check for reductions. Then push the operator. */ + while (prio <= top->prio) { HOST_WIDEST_INT v1 = top[-1].value, v2 = top[0].value; unsigned int unsigned1 = top[-1].unsignedp; @@ -932,9 +957,6 @@ else top->value = right_shift (pfile, v1, unsigned1, v2); break; -#define LOGICAL(OP) \ - top->value = v1 OP v2;\ - top->unsignedp = unsigned1 || unsigned2; case '&': LOGICAL(&); break; case '^': LOGICAL(^); break; case '|': LOGICAL(|); break; @@ -953,7 +975,7 @@ top->unsignedp = unsigned2; break; case '?': - cpp_error (pfile, "syntax error in #if"); + cpp_error (pfile, "syntax error '?' without following ':'"); goto syntax_error; case ':': if (top[0].op != '?') @@ -1027,7 +1049,7 @@ } top->flags = flags; - top->rprio = rprio; + top->prio = prio & ~RIGHT_ASSOC; top->op = op.op; /* Handle short circuiting. */
Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]