Fixed the operator precedence of several operators.

This commit is contained in:
John Wiegley 2009-02-09 18:02:05 -04:00
parent 47567307ce
commit 3925240c7b

View file

@ -169,19 +169,22 @@ expr_t::parser_t::parse_mul_expr(std::istream& in,
ptr_op_t node(parse_unary_expr(in, tflags)); ptr_op_t node(parse_unary_expr(in, tflags));
if (node && ! tflags.has_flags(PARSE_SINGLE)) { if (node && ! tflags.has_flags(PARSE_SINGLE)) {
token_t& tok = next_token(in, tflags); while (true) {
token_t& tok = next_token(in, tflags);
if (tok.kind == token_t::STAR || tok.kind == token_t::KW_DIV) { if (tok.kind == token_t::STAR || tok.kind == token_t::KW_DIV) {
ptr_op_t prev(node); ptr_op_t prev(node);
node = new op_t(tok.kind == token_t::STAR ? node = new op_t(tok.kind == token_t::STAR ?
op_t::O_MUL : op_t::O_DIV); op_t::O_MUL : op_t::O_DIV);
node->set_left(prev); node->set_left(prev);
node->set_right(parse_mul_expr(in, tflags)); node->set_right(parse_unary_expr(in, tflags));
if (! node->right()) if (! node->right())
throw_(parse_error, throw_(parse_error,
tok.symbol << " operator not followed by argument"); tok.symbol << " operator not followed by argument");
} else { } else {
push_token(tok); push_token(tok);
break;
}
} }
} }
@ -195,20 +198,23 @@ expr_t::parser_t::parse_add_expr(std::istream& in,
ptr_op_t node(parse_mul_expr(in, tflags)); ptr_op_t node(parse_mul_expr(in, tflags));
if (node && ! tflags.has_flags(PARSE_SINGLE)) { if (node && ! tflags.has_flags(PARSE_SINGLE)) {
token_t& tok = next_token(in, tflags); while (true) {
token_t& tok = next_token(in, tflags);
if (tok.kind == token_t::PLUS || if (tok.kind == token_t::PLUS ||
tok.kind == token_t::MINUS) { tok.kind == token_t::MINUS) {
ptr_op_t prev(node); ptr_op_t prev(node);
node = new op_t(tok.kind == token_t::PLUS ? node = new op_t(tok.kind == token_t::PLUS ?
op_t::O_ADD : op_t::O_SUB); op_t::O_ADD : op_t::O_SUB);
node->set_left(prev); node->set_left(prev);
node->set_right(parse_add_expr(in, tflags)); node->set_right(parse_mul_expr(in, tflags));
if (! node->right()) if (! node->right())
throw_(parse_error, throw_(parse_error,
tok.symbol << " operator not followed by argument"); tok.symbol << " operator not followed by argument");
} else { } else {
push_token(tok); push_token(tok);
break;
}
} }
} }
@ -222,67 +228,70 @@ expr_t::parser_t::parse_logic_expr(std::istream& in,
ptr_op_t node(parse_add_expr(in, tflags)); ptr_op_t node(parse_add_expr(in, tflags));
if (node && ! tflags.has_flags(PARSE_SINGLE)) { if (node && ! tflags.has_flags(PARSE_SINGLE)) {
op_t::kind_t kind = op_t::LAST; while (true) {
parse_flags_t _flags = tflags; op_t::kind_t kind = op_t::LAST;
token_t& tok = next_token(in, tflags); parse_flags_t _flags = tflags;
bool negate = false; token_t& tok = next_token(in, tflags);
bool negate = false;
switch (tok.kind) { switch (tok.kind) {
case token_t::DEFINE: case token_t::DEFINE:
kind = op_t::O_DEFINE; kind = op_t::O_DEFINE;
break; break;
case token_t::EQUAL: case token_t::EQUAL:
if (tflags.has_flags(PARSE_NO_ASSIGN)) if (tflags.has_flags(PARSE_NO_ASSIGN))
tok.rewind(in); tok.rewind(in);
else else
kind = op_t::O_EQ;
break;
case token_t::NEQUAL:
kind = op_t::O_EQ; kind = op_t::O_EQ;
break; negate = true;
case token_t::NEQUAL: break;
kind = op_t::O_EQ; case token_t::MATCH:
negate = true; kind = op_t::O_MATCH;
break; break;
case token_t::MATCH: case token_t::NMATCH:
kind = op_t::O_MATCH; kind = op_t::O_MATCH;
break; negate = true;
case token_t::NMATCH: break;
kind = op_t::O_MATCH; case token_t::LESS:
negate = true; kind = op_t::O_LT;
break; break;
case token_t::LESS: case token_t::LESSEQ:
kind = op_t::O_LT; kind = op_t::O_LTE;
break; break;
case token_t::LESSEQ: case token_t::GREATER:
kind = op_t::O_LTE; kind = op_t::O_GT;
break; break;
case token_t::GREATER: case token_t::GREATEREQ:
kind = op_t::O_GT; kind = op_t::O_GTE;
break; break;
case token_t::GREATEREQ: default:
kind = op_t::O_GTE; push_token(tok);
break; goto exit_loop;
default: }
push_token(tok);
break;
}
if (kind != op_t::LAST) { if (kind != op_t::LAST) {
ptr_op_t prev(node); ptr_op_t prev(node);
node = new op_t(kind); node = new op_t(kind);
node->set_left(prev);
node->set_right(parse_add_expr(in, _flags));
if (! node->right())
throw_(parse_error,
tok.symbol << " operator not followed by argument");
if (negate) {
prev = node;
node = new op_t(op_t::O_NOT);
node->set_left(prev); node->set_left(prev);
node->set_right(parse_add_expr(in, _flags));
if (! node->right())
throw_(parse_error,
tok.symbol << " operator not followed by argument");
if (negate) {
prev = node;
node = new op_t(op_t::O_NOT);
node->set_left(prev);
}
} }
} }
} }
exit_loop:
return node; return node;
} }
@ -293,18 +302,21 @@ expr_t::parser_t::parse_and_expr(std::istream& in,
ptr_op_t node(parse_logic_expr(in, tflags)); ptr_op_t node(parse_logic_expr(in, tflags));
if (node && ! tflags.has_flags(PARSE_SINGLE)) { if (node && ! tflags.has_flags(PARSE_SINGLE)) {
token_t& tok = next_token(in, tflags); while (true) {
token_t& tok = next_token(in, tflags);
if (tok.kind == token_t::KW_AND) { if (tok.kind == token_t::KW_AND) {
ptr_op_t prev(node); ptr_op_t prev(node);
node = new op_t(op_t::O_AND); node = new op_t(op_t::O_AND);
node->set_left(prev); node->set_left(prev);
node->set_right(parse_and_expr(in, tflags)); node->set_right(parse_logic_expr(in, tflags));
if (! node->right()) if (! node->right())
throw_(parse_error, throw_(parse_error,
tok.symbol << " operator not followed by argument"); tok.symbol << " operator not followed by argument");
} else { } else {
push_token(tok); push_token(tok);
break;
}
} }
} }
return node; return node;
@ -317,18 +329,21 @@ expr_t::parser_t::parse_or_expr(std::istream& in,
ptr_op_t node(parse_and_expr(in, tflags)); ptr_op_t node(parse_and_expr(in, tflags));
if (node && ! tflags.has_flags(PARSE_SINGLE)) { if (node && ! tflags.has_flags(PARSE_SINGLE)) {
token_t& tok = next_token(in, tflags); while (true) {
token_t& tok = next_token(in, tflags);
if (tok.kind == token_t::KW_OR) { if (tok.kind == token_t::KW_OR) {
ptr_op_t prev(node); ptr_op_t prev(node);
node = new op_t(op_t::O_OR); node = new op_t(op_t::O_OR);
node->set_left(prev); node->set_left(prev);
node->set_right(parse_or_expr(in, tflags)); node->set_right(parse_and_expr(in, tflags));
if (! node->right()) if (! node->right())
throw_(parse_error, throw_(parse_error,
tok.symbol << " operator not followed by argument"); tok.symbol << " operator not followed by argument");
} else { } else {
push_token(tok); push_token(tok);
break;
}
} }
} }
return node; return node;