diff --git a/libc3/buf_parse.c b/libc3/buf_parse.c
index ecbe2ba..9605cf9 100644
--- a/libc3/buf_parse.c
+++ b/libc3/buf_parse.c
@@ -207,6 +207,7 @@ sw buf_parse_call_op_rec (s_buf *buf, s_call *dest, s_tag *left,
sw r;
sw result = 0;
s_tag *right;
+ s_tag *right_left;
s_buf_save save;
assert(buf);
assert(dest);
@@ -217,21 +218,23 @@ sw buf_parse_call_op_rec (s_buf *buf, s_call *dest, s_tag *left,
>= min_precedence) {
result += r;
op = next_op;
- if ((r = buf_parse_tag_primary(buf, &right)) <= 0)
+ if ((r = buf_parse_tag_primary(buf, right)) <= 0)
goto restore;
result += r;
if ((r = buf_parse_ident(buf, &next_op)) < 0)
goto restore;
result += r;
- while (r && (next_op_precedence = operator_precedence(&next_op))
- >= op_precedence ||
- (operator_is_right_associative(&next_op) &&
- next_op_precedence == op_precedence)) {
+ while (r && ((next_op_precedence = operator_precedence(&next_op))
+ >= op_precedence ||
+ (operator_is_right_associative(&next_op) &&
+ next_op_precedence == op_precedence))) {
result += r;
if (next_op_precedence > op_precedence)
op_precedence++;
- if ((r = buf_parse_call_op_rec(buf, (right = tag_new()), right,
- op_precedence)) <= 0)
+ right_left = right;
+ right = tag_new();
+ if ((r = buf_parse_call_op_rec(buf, &right->data.call,
+ right_left, op_precedence)) <= 0)
goto restore;
result += r;
if ((r = buf_parse_ident(buf, &next_op)) < 0)
@@ -239,6 +242,7 @@ sw buf_parse_call_op_rec (s_buf *buf, s_call *dest, s_tag *left,
left = tag_new_call_op(&op, left, right);
}
}
+ *dest = left->data.call;
r = result;
goto clean;
restore:
@@ -1498,7 +1502,7 @@ sw buf_parse_tag (s_buf *buf, s_tag *dest)
goto restore;
result += r;
}
- if ((r = buf_parse_call_op(buf, dest)) != 0 ||
+ if ((r = buf_parse_tag_call_op(buf, dest)) != 0 ||
(r = buf_parse_tag_primary(buf, dest)) != 0)
goto end;
end:
@@ -1534,6 +1538,14 @@ sw buf_parse_tag_call (s_buf *buf, s_tag *dest)
return r;
}
+sw buf_parse_tag_call_op (s_buf *buf, s_tag *dest)
+{
+ sw r;
+ if ((r = buf_parse_call_op(buf, &dest->data.call)) > 0)
+ dest->type.type = TAG_CALL;
+ return r;
+}
+
sw buf_parse_tag_cfn (s_buf *buf, s_tag *dest)
{
sw r;
diff --git a/libc3/buf_parse.h b/libc3/buf_parse.h
index 8f2db29..fc37050 100644
--- a/libc3/buf_parse.h
+++ b/libc3/buf_parse.h
@@ -69,6 +69,7 @@ sw buf_parse_sym (s_buf *buf, const s_sym **dest);
sw buf_parse_tag (s_buf *buf, s_tag *dest);
sw buf_parse_tag_bool (s_buf *buf, s_tag *dest);
sw buf_parse_tag_call (s_buf *buf, s_tag *dest);
+sw buf_parse_tag_call_op (s_buf *buf, s_tag *dest);
sw buf_parse_tag_cfn (s_buf *buf, s_tag *dest);
sw buf_parse_tag_character (s_buf *buf, s_tag *dest);
sw buf_parse_tag_fn (s_buf *buf, s_tag *dest);
diff --git a/libc3/env.c b/libc3/env.c
index e460488..efbd14a 100644
--- a/libc3/env.c
+++ b/libc3/env.c
@@ -486,7 +486,7 @@ s_module * env_module_load (s_env *env, s_module *module,
return module;
}
-bool env_operator_is_right_associative (const s_env *env, const s_ident *op)
+bool env_operator_is_right_associative (const s_env *env, s_ident *op)
{
s_facts_with_cursor cursor;
s_tag tag_ident;
@@ -504,14 +504,11 @@ bool env_operator_is_right_associative (const s_env *env, const s_ident *op)
NULL, NULL });
if (! facts_with_cursor_next(&cursor))
return false;
- if (tag_var.type.type != TAG_U8)
- errx(1, "%s.%s: invalid operator_precedence type",
- op->module_name->str.ptr.ps8,
- op->sym->str.ptr.ps8);
- return tag_var.data.u8;
+ facts_with_cursor_clean(&cursor);
+ return true;
}
-s8 env_operator_precedence (const s_env *env, const s_ident *op)
+s8 env_operator_precedence (const s_env *env, s_ident *op)
{
s_facts_with_cursor cursor;
s_tag tag_ident;
@@ -535,6 +532,7 @@ s8 env_operator_precedence (const s_env *env, const s_ident *op)
errx(1, "%s.%s: invalid operator_precedence type",
op->module_name->str.ptr.ps8,
op->sym->str.ptr.ps8);
+ facts_with_cursor_clean(&cursor);
return tag_var.data.u8;
}
diff --git a/libc3/env.h b/libc3/env.h
index 48b57b4..43ce7ef 100644
--- a/libc3/env.h
+++ b/libc3/env.h
@@ -45,8 +45,10 @@ bool env_eval_progn (s_env *env, const s_list *program,
bool env_eval_tag (s_env *env, const s_tag *tag, s_tag *dest);
s_module * env_module_load (s_env *env, s_module *module,
const s_sym *name, s_facts *facts);
+bool env_operator_is_right_associative (const s_env *env,
+ s_ident *op);
s8 env_operator_precedence (const s_env *env,
- const s_ident *op);
+ s_ident *op);
/* control structures */
void env_error_f (s_env *env, const char *fmt, ...);
diff --git a/libc3/operator.c b/libc3/operator.c
index 4041419..739f6cb 100644
--- a/libc3/operator.c
+++ b/libc3/operator.c
@@ -12,14 +12,14 @@
* THIS SOFTWARE.
*/
#include <assert.h>
-#include "types.h"
+#include "c3.h"
-bool operator_is_right_associative (const s_ident *op)
+bool operator_is_right_associative (s_ident *op)
{
return env_operator_is_right_associative(&g_c3_env, op);
}
-s8 operator_precedence (const s_ident *op)
+s8 operator_precedence (s_ident *op)
{
return env_operator_precedence(&g_c3_env, op);
}
diff --git a/libc3/operator.h b/libc3/operator.h
index afe3ae7..8167efd 100644
--- a/libc3/operator.h
+++ b/libc3/operator.h
@@ -17,7 +17,7 @@
#include "types.h"
/* Observers */
-bool operator_is_right_associative (const s_ident *op);
-s8 operator_precedence (const s_ident *op);
+bool operator_is_right_associative (s_ident *op);
+s8 operator_precedence (s_ident *op);
#endif /* OPERATOR_H */