07e65a3a88e03c6d9e6f1f6ac4a1cfa9a74a9b09 — Simon Ser a month 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 @@ 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 @@ 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))
  
  # Associativity
  # https://github.com/emersion/mrsh/issues/53


@@ 27,6 27,10 @@ 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