~emersion/mrsh

07e65a3a88e03c6d9e6f1f6ac4a1cfa9a74a9b09 — Simon Ser 1 year, 9 months ago 1010c7a
parser/arithm: fix && and ||

"&" and "|" have higher priority, so they were consuming the first character of
"&&" and "||", leaving a trailing "&" or "|".
2 files changed, 30 insertions(+), 3 deletions(-)

M parser/arithm.c
M test/arithm.sh
M parser/arithm.c => parser/arithm.c +24 -1
@@ 304,6 304,29 @@ static struct mrsh_arithm_expr *equal(struct mrsh_parser *state) {
	return &bo->expr;
}

static bool parse_binop(struct mrsh_parser *state, const char *str) {
	size_t len = strlen(str);

	for (size_t i = 0; i < len; ++i) {
		parser_peek(state, NULL, i + 1);

		if (state->buf.data[i] != str[i]) {
			return false;
		}
	}

	// Make sure we don't parse "&&" as "&"
	parser_peek(state, NULL, len + 1);
	switch (state->buf.data[len]) {
	case '|':
	case '&':
		return false;
	}

	parser_read(state, NULL, len);
	return true;
}

static struct mrsh_arithm_expr *binop(struct mrsh_parser *state,
		enum mrsh_arithm_binop_type type, const char *str,
		struct mrsh_arithm_expr *(*term)(struct mrsh_parser *state)) {


@@ 311,7 334,7 @@ static struct mrsh_arithm_expr *binop(struct mrsh_parser *state,
	if (left == NULL) {
		return NULL;
	}
	if (!parse_str(state, str)) {
	if (!parse_binop(state, str)) {
		return left;
	}
	consume_whitespace(state);

M test/arithm.sh => test/arithm.sh +6 -2
@@ 17,8 17,8 @@ echo "2!=5 =" $((2!=5))
echo "2&5 =" $((2&5))
echo "2^5 =" $((2^5))
echo "2|5 =" $((2|5))
#echo "2&&5 =" $((2&&5))
#echo "2||5 =" $((2||5))
echo "2&&5 =" $((2&&5))
echo "2||5 =" $((2||5))

# Associativity
# https://github.com/emersion/mrsh/issues/53


@@ 27,6 27,10 @@ echo "1+2+3 =" $((1+2+3))
echo "1+2*3 =" $((1+2*3))
echo "2*3+1 =" $((2*3+1))
#echo "2*(3+1) =" $((2*(3+1)))
#echo "2|(1||1)" $((2|(1||1))) # 3
#echo "(2|1)||1" $(((2|1)||1)) # 1
echo "2|1||1" $((2|1||1)) # 1
echo "1||1|2" $((1||1|2)) # 1

# Assignments
echo "(a=42) =" $((a=42)) "->" $a