3 2

[PATCH 1/2] Fix parser choking on certain arithmetic operators

Cristian Adrián Ontivero
Details
Message ID
<20190131164849.7302-1-cristianontivero@gmail.com>
DKIM signature
pass
Download raw message
Patch: +9 -16
Specifically '&', '|', '/', '<', and '>' in arithmetic expressions.
---
 parser/arithm.c |  2 +-
 parser/word.c   | 23 ++++++++---------------
 2 files changed, 9 insertions(+), 16 deletions(-)

diff --git a/parser/arithm.c b/parser/arithm.c
index b7d9248..49b35b4 100644
--- a/parser/arithm.c
+++ b/parser/arithm.c
@@ -153,7 +153,7 @@ static struct mrsh_arithm_expr *factor(struct mrsh_parser *state) {
 	enum mrsh_arithm_binop_type type;
 	if (parse_char(state, '*')) {
 		type = MRSH_ARITHM_BINOP_ASTERISK;
-	} else if (parse_char(state, '-')) {
+	} else if (parse_char(state, '/')) {
 		type = MRSH_ARITHM_BINOP_SLASH;
 	} else if (parse_char(state, '%')) {
 		type = MRSH_ARITHM_BINOP_PERCENT;
diff --git a/parser/word.c b/parser/word.c
index 99ab2e2..f5a2024 100644
--- a/parser/word.c
+++ b/parser/word.c
@@ -356,7 +356,7 @@ static struct mrsh_word_arithmetic *expect_word_arithmetic(
 	c = parser_read_char(state);
 	assert(c == '(');
 
-	struct mrsh_word *body = word_list(state, ')', arithmetic_word);
+	struct mrsh_word *body = word_list(state, 0, arithmetic_word);
 	if (body == NULL) {
 		if (!mrsh_parser_error(state, NULL)) {
 			parser_set_error(state, "expected an arithmetic expression");
@@ -698,16 +698,8 @@ struct mrsh_word *word(struct mrsh_parser *state, char end) {
 
 /* TODO remove end parameter when no *_word function takes it */
 struct mrsh_word *arithmetic_word(struct mrsh_parser *state, char end) {
-	if (!symbol(state, TOKEN)) {
-		return NULL;
-	}
-
-	char c = parser_peek_char(state);
-	if (is_operator_start(c)) {
-		return NULL;
-	}
-
 	char next[3] = {0};
+	char c = parser_peek_char(state);
 	if (c == ')') {
 		parser_peek(state, next, sizeof(*next) * 2);
 		if (!strcmp(next, "))")) {
@@ -726,7 +718,9 @@ struct mrsh_word *arithmetic_word(struct mrsh_parser *state, char end) {
 
 		parser_peek(state, next, sizeof(*next) * 2);
 		c = next[0];
-		if (c == '\0' || c == '\n' || !strcmp(next, "))")) {
+		if (c == '\0' || c == '\n' || c == ';'
+				|| isblank(c)
+				|| !strcmp(next, "))")) {
 			break;
 		}
 
@@ -779,10 +773,9 @@ struct mrsh_word *arithmetic_word(struct mrsh_parser *state, char end) {
 				read_continuation_line(state);
 				continue;
 			}
-		} else if (is_operator_start(c) || isblank(c)) {
-			if (strcmp(next, "<<") && strcmp(next, ">>")) {
-				break;
-			}
+
+		}
+		if (!strcmp(next, "<<") || !strcmp(next, ">>")) {
 			parser_read_char(state);
 			mrsh_buffer_append_char(&buf, c);
 		}
-- 
-- 
2.20.1

[PATCH 2/2] Accept spaces inside arithmetic expressions

Cristian Adrián Ontivero
Details
Message ID
<20190131164849.7302-2-cristianontivero@gmail.com>
In-Reply-To
<20190131164849.7302-1-cristianontivero@gmail.com> (view parent)
DKIM signature
pass
Download raw message
Patch: +28 -0
Fixes #52.
---
 parser/arithm.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/parser/arithm.c b/parser/arithm.c
index 49b35b4..c53ebfd 100644
--- a/parser/arithm.c
+++ b/parser/arithm.c
@@ -14,6 +14,19 @@ static bool parse_char(struct mrsh_parser *state, char c) {
 	return true;
 }
 
+static bool parse_whitespace(struct mrsh_parser *state) {
+	if (!isspace(parser_peek_char(state))) {
+		return false;
+	}
+	parser_read_char(state);
+	return true;
+}
+
+static inline void consume_whitespace(struct mrsh_parser *state) {
+	while (parse_whitespace(state))
+		;
+}
+
 static bool expect_char(struct mrsh_parser *state, char c) {
 	if (parse_char(state, c)) {
 		return true;
@@ -115,7 +128,10 @@ static struct mrsh_arithm_expr *paren(struct mrsh_parser *state) {
 		return NULL;
 	}
 
+	consume_whitespace(state);
 	struct mrsh_arithm_expr *expr = arithm_expr(state);
+	// consume_whitespace() is not needed here, since the call to arithm_expr()
+	// consumes the trailing whitespace.
 
 	if (!expect_char(state, ')')) {
 		mrsh_arithm_expr_destroy(expr);
@@ -150,6 +166,7 @@ static struct mrsh_arithm_expr *factor(struct mrsh_parser *state) {
 		return NULL;
 	}
 
+	consume_whitespace(state);
 	enum mrsh_arithm_binop_type type;
 	if (parse_char(state, '*')) {
 		type = MRSH_ARITHM_BINOP_ASTERISK;
@@ -160,6 +177,7 @@ static struct mrsh_arithm_expr *factor(struct mrsh_parser *state) {
 	} else {
 		return left;
 	}
+	consume_whitespace(state);
 
 	struct mrsh_arithm_expr *right = factor(state);
 	if (right == NULL) {
@@ -177,6 +195,8 @@ static struct mrsh_arithm_expr *addend(struct mrsh_parser *state) {
 		return NULL;
 	}
 
+	// consume_whitespace() is not needed here, since the call to factor()
+	// consumes trailing whitespace.
 	enum mrsh_arithm_binop_type type;
 	if (parse_char(state, '+')) {
 		type = MRSH_ARITHM_BINOP_PLUS;
@@ -185,6 +205,7 @@ static struct mrsh_arithm_expr *addend(struct mrsh_parser *state) {
 	} else {
 		return left;
 	}
+	consume_whitespace(state);
 
 	struct mrsh_arithm_expr *right = addend(state);
 	if (right == NULL) {
@@ -202,6 +223,8 @@ static struct mrsh_arithm_expr *shift(struct mrsh_parser *state) {
 		return NULL;
 	}
 
+	// consume_whitespace() is not needed here, since the call to addend()
+	// consumes the trailing whitespace.
 	enum mrsh_arithm_binop_type type;
 	if (parse_str(state, "<<")) {
 		type = MRSH_ARITHM_BINOP_DLESS;
@@ -210,6 +233,7 @@ static struct mrsh_arithm_expr *shift(struct mrsh_parser *state) {
 	} else {
 		return left;
 	}
+    consume_whitespace(state);
 
 	struct mrsh_arithm_expr *right = shift(state);
 	if (right == NULL) {
@@ -240,6 +264,7 @@ static struct mrsh_arithm_expr *comp(struct mrsh_parser *state) {
 	} else {
 		return left;
 	}
+    consume_whitespace(state);
 
 	struct mrsh_arithm_expr *right = comp(state);
 	if (left == NULL) {
@@ -288,6 +313,7 @@ static struct mrsh_arithm_expr *binop(struct mrsh_parser *state,
 	if (!parse_str(state, str)) {
 		return left;
 	}
+    consume_whitespace(state);
 
 	struct mrsh_arithm_expr *right = binop(state, type, str, term);
 	if (left == NULL) {
@@ -419,6 +445,8 @@ static struct mrsh_arithm_expr *arithm_expr(struct mrsh_parser *state) {
 }
 
 struct mrsh_arithm_expr *mrsh_parse_arithm_expr(struct mrsh_parser *state) {
+    consume_whitespace(state);
+
 	struct mrsh_arithm_expr *expr = arithm_expr(state);
 	if (expr == NULL) {
 		return NULL;
-- 
-- 
2.20.1

Re: [PATCH 2/2] Accept spaces inside arithmetic expressions

Details
Message ID
<K6Zz0Ht6C0I0JaG33_b1dE9dFHpN4IlmaIB8tgClBRHWkmkCJnMyE7tou-9VNIpH_hFVzVstD8cj4jWT5KoMw04-d4kYj2iYzNVZERHwylk=@emersion.fr>
In-Reply-To
<20190131164849.7302-2-cristianontivero@gmail.com> (view parent)
DKIM signature
pass
Download raw message
Maybe this could be improved by adding a simple lexer layer, or by
moving parse_whitespace into parse_char? Anyway, this LGTM.

Pushed with two minor edits (see below):

To git.sr.ht:~emersion/mrsh
   d28f531..8660d8d  master -> master

Thanks!

On Thursday, January 31, 2019 5:48 PM, Cristian Adrián Ontivero <cristianontivero@gmail.com> wrote:
> +static inline void consume_whitespace(struct mrsh_parser *state) {
> +	while (parse_whitespace(state))
> +		;

Changed to use braces.

> +	// consume_whitespace() is not needed here, since the call to addend()
> +	// consumes the trailing whitespace.
>  	enum mrsh_arithm_binop_type type;
>  	if (parse_str(state, "<<")) {
>  		type = MRSH_ARITHM_BINOP_DLESS;
> @@ -210,6 +233,7 @@ static struct mrsh_arithm_expr *shift(struct mrsh_parser *state) {
>  	} else {
>  		return left;
>  	}
> +    consume_whitespace(state);

Style: this uses spaces instead of tabs.
Details
Message ID
<dciZoOUZp6HdRqbJzjkyWD6f4lnFV876mRuAyhAL5MFY1dpohf37nxUkRL7ahNEUejbKxjBcYv_gG5HzoO3bbR-ldV5Xnzg9zUFYaFdAVdg=@emersion.fr>
In-Reply-To
<20190131164849.7302-1-cristianontivero@gmail.com> (view parent)
DKIM signature
pass
Download raw message
Nice catch. This LGTM, pushed:

To git.sr.ht:~emersion/mrsh
   21468df..d28f531  master -> master

Thanks!