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 2


This is the second of a set of patches to the preprocessor's expression parser. Most of the patch is code rearrangement and regrouping, which does not affect parsing logic. There is however one major change: the handling of '(' and ')'. Previously, these were handled with the standard shift / reduce logic based on left- and right priorities. The current patch forces an immediate shift of '(' without considering reductions, and an immediate reduction of ')' to the previous '(' without shifting. This paves the way for simplification of the priority scheme in the next patch. Error reporting is improved for parentheses mismatches, parentheses containing a void expression, and consecutive immediate values in an expression without a separating binary operator. I'm bootstrapping gcc at the moment. If it succeeds, OK to commit? * cppexp.c: (_cpp_parse_expr): Numerical constants are pushed within the switch statement. Binary operations break out of the switch naturally. '(' tokens handled by forcing immediate shift. ')' handled by forcing immediate reduce to the previous '('. New error messages. Neil. Index: cppexp.c =================================================================== RCS file: /cvs/gcc/egcs/gcc/cppexp.c,v retrieving revision 1.40 diff -u -p -r1.40 cppexp.c --- cppexp.c 2000/03/31 22:23:59 1.40 +++ cppexp.c 2000/03/31 23:03:51 @@ -699,7 +699,7 @@ _cpp_parse_expr (pfile) U_CHAR flags = 0; /* Read a token */ - op = lex (pfile, skip_evaluation); + op = lex (pfile, skip_evaluation); /* See if the token is an operand, in which case go to set_value. If the token is an operator, figure out its left and right @@ -710,16 +710,29 @@ _cpp_parse_expr (pfile) case NAME: cpp_ice (pfile, "lex returns a NAME"); goto syntax_error; + case ERROR: + goto syntax_error; + default: + cpp_error (pfile, "invalid character in #if"); + goto syntax_error; + case INT: case CHAR: - goto set_value; - case 0: - lprio = 0; goto maybe_reduce; - case '+': case '-': + push_immediate: + /* Push a value onto the stack. */ if (top->flags & HAVE_VALUE) { - lprio = PLUS_PRIO; - goto binop; + cpp_error (pfile, "suspected missing binary operator in #if"); + goto syntax_error; } + top->value = op.value; + top->unsignedp = op.unsignedp; + top->flags |= HAVE_VALUE; + continue; + + case '+': case '-': + lprio = PLUS_PRIO; + if (top->flags & HAVE_VALUE) + break; if (top->flags & SIGN_QUALIFIED) { cpp_error (pfile, "more than one sign operator given"); @@ -730,24 +743,25 @@ _cpp_parse_expr (pfile) case '!': case '~': flags |= RIGHT_OPERAND_REQUIRED; rprio = UNARY_PRIO; lprio = rprio + 1; goto maybe_reduce; + case '*': case '/': case '%': - lprio = MUL_PRIO; goto binop; + lprio = MUL_PRIO; break; case '<': case '>': case LEQ: case GEQ: - lprio = LESS_PRIO; goto binop; + lprio = LESS_PRIO; break; case EQUAL: case NOTEQUAL: - lprio = EQUAL_PRIO; goto binop; + lprio = EQUAL_PRIO; break; case LSH: case RSH: - lprio = SHIFT_PRIO; goto binop; - case '&': lprio = AND_PRIO; goto binop; - case '^': lprio = XOR_PRIO; goto binop; - case '|': lprio = OR_PRIO; goto binop; - case ANDAND: lprio = ANDAND_PRIO; goto binop; - case OROR: lprio = OROR_PRIO; goto binop; + 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; goto binop; + lprio = COMMA_PRIO; break; case '(': - lprio = PAREN_OUTER_PRIO; rprio = PAREN_INNER_PRIO; - goto maybe_reduce; + lprio = PAREN_OUTER_PRIO; rprio = PAREN_INNER_PRIO + 1; + goto skip_reduction; case ')': lprio = PAREN_INNER_PRIO; rprio = PAREN_OUTER_PRIO; flags = HAVE_VALUE; /* At least, we will have after reduction. */ @@ -758,26 +772,11 @@ _cpp_parse_expr (pfile) case '?': lprio = COND_PRIO; rprio = COND_PRIO; goto maybe_reduce; - case ERROR: - goto syntax_error; - default: - cpp_error (pfile, "invalid character in #if"); - goto syntax_error; - } - - set_value: - /* Push a value onto the stack. */ - if (top->flags & HAVE_VALUE) - { - cpp_error (pfile, "syntax error in #if"); - goto syntax_error; + case 0: + lprio = 0; goto maybe_reduce; } - top->value = op.value; - top->unsignedp = op.unsignedp; - top->flags |= HAVE_VALUE; - continue; - binop: + /* Binary operation. */ flags = LEFT_OPERAND_REQUIRED|RIGHT_OPERAND_REQUIRED; rprio = lprio + 1; @@ -953,7 +952,7 @@ _cpp_parse_expr (pfile) top->value = v2; top->unsignedp = unsigned2; break; - case '(': case '?': + case '?': cpp_error (pfile, "syntax error in #if"); goto syntax_error; case ':': @@ -979,21 +978,22 @@ _cpp_parse_expr (pfile) } break; case ')': - if (! (top[0].flags & HAVE_VALUE) - || top[0].op != '(' - || (top[-1].flags & HAVE_VALUE)) + cpp_error (pfile, "missing '(' in expression"); + goto syntax_error; + case '(': + if (op.op == ')') { - cpp_error (pfile, "mismatched parentheses in #if"); + if (top[1].flags & HAVE_VALUE) + { + op.value = v2; + op.unsignedp = unsigned2; + goto push_immediate; + } + cpp_error (pfile, "void expression between '(' and ')'"); goto syntax_error; - } - else - { - top--; - top->value = v1; - top->unsignedp = unsigned1; - top->flags |= HAVE_VALUE; } - break; + cpp_error (pfile, "missing ')' in expression"); + goto syntax_error; default: if (ISGRAPH (top[1].op)) cpp_error (pfile, "unimplemented operator '%c'\n", top[1].op); @@ -1002,18 +1002,13 @@ _cpp_parse_expr (pfile) top[1].op); } } + if (op.op == 0) - { - if (top != stack) - cpp_ice (pfile, "unbalanced stack in #if expression"); - if (!(top->flags & HAVE_VALUE)) - cpp_error (pfile, "#if with no expression"); - result = (top->value != 0); - goto done; - } - top++; - + break; + + skip_reduction: /* Check for and handle stack overflow. */ + top++; if (top == limit) { struct operation *new_stack; @@ -1034,6 +1029,8 @@ _cpp_parse_expr (pfile) top->flags = flags; top->rprio = rprio; top->op = op.op; + + /* Handle short circuiting. */ if ((op.op == OROR && top[-1].value) || (op.op == ANDAND && !top[-1].value) || (op.op == '?' && !top[-1].value)) @@ -1048,13 +1045,22 @@ _cpp_parse_expr (pfile) skip_evaluation--; } } - syntax_error: - _cpp_skip_rest_of_line (pfile); - result = 0; - done: + + if (top != stack) + cpp_ice (pfile, "unbalanced stack in #if expression"); + if (!(top->flags & HAVE_VALUE)) + cpp_error (pfile, "#if with no expression"); + result = (top->value != 0); + + tidy_up: pfile->parsing_if_directive--; CPP_SET_WRITTEN (pfile, old_written); if (stack != init_stack) free (stack); return result; + + syntax_error: + _cpp_skip_rest_of_line (pfile); + result = 0; + goto tidy_up; }
Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]