{ "||", 2, opid2('|','|'), ASSOC_LEFT, 4, 0 },
{ "?", 3, opid2('?',':'), ASSOC_RIGHT, 3, 0 },
+ { ":", 3, opid2(':','?'), ASSOC_RIGHT, 3, 0 },
{ "=", 2, opid1('='), ASSOC_RIGHT, 2, 0 },
{ "+=", 2, opid2('+','='), ASSOC_RIGHT, 2, 0 },
{ "&&", 2, opid2('&','&'), ASSOC_LEFT, 5, 0 },
{ "||", 2, opid2('|','|'), ASSOC_LEFT, 5, 0 },
- { ",", 2, opid1(','), ASSOC_LEFT, 2, 0 }
+ { ",", 2, opid1(','), ASSOC_LEFT, 2, 0 },
{ "?", 3, opid2('?',':'), ASSOC_RIGHT, 1, 0 },
+ { ":", 3, opid2(':','?'), ASSOC_RIGHT, 1, 0 }
};
static const size_t qcc_operator_count = (sizeof(qcc_operators) / sizeof(qcc_operators[0]));
* end of a condition is an unmatched closing paren
*/
int parens = 0;
+ int ternaries = 0;
sy.out = NULL;
sy.ops = NULL;
break;
}
+ /* a colon without a pervious question mark cannot be a ternary */
+ if (op->id == opid2(':','?')) {
+ parser->tok = ':';
+ break;
+ }
+
if (vec_size(sy.ops) && !vec_last(sy.ops).paren)
olast = &operators[vec_last(sy.ops).etype-1];
vec_push(sy.ops, syop(parser_ctx(parser), op));
vec_push(sy.ops, syparen(parser_ctx(parser), SY_PAREN_INDEX, 0));
wantop = false;
+ } else if (op->id == opid2('?',':')) {
+ wantop = false;
+ vec_push(sy.ops, syop(parser_ctx(parser), op));
+ wantop = false;
+ --ternaries;
+ } else if (op->id == opid2(':','?')) {
+ /* we don't push this operator */
+ wantop = false;
+ ++ternaries;
} else {
DEBUGSHUNTDO(con_out("push operator %s\n", op->op));
vec_push(sy.ops, syop(parser_ctx(parser), op));
goto onerr;
}
if (parser->tok == ';' ||
- (!parens && parser->tok == ']') ||
- parser->tok == ':')
+ (!parens && parser->tok == ']'))
{
break;
}