diff --git a/libc3/buf_parse.c b/libc3/buf_parse.c
index b9393fe..015f502 100644
--- a/libc3/buf_parse.c
+++ b/libc3/buf_parse.c
@@ -204,36 +204,39 @@ sw buf_parse_call_op (s_buf *buf, s_call *dest)
sw buf_parse_call_op_rec (s_buf *buf, s_call *dest, u8 min_precedence)
{
- s_tag *new_left = NULL;
+ s_tag *left;
s_ident next_op;
s8 next_op_precedence;
s_ident op;
s8 op_precedence;
sw r;
sw result = 0;
- s_tag *right = NULL;
- s_tag *right_first = NULL;
- s_tag *right_left = NULL;
+ s_tag *right;
s_buf_save save;
s_call tmp;
+ s_call tmp2;
assert(buf);
assert(dest);
buf_save_init(buf, &save);
- if ((r = buf_parse_ident(buf, &next_op)) <= 0)
+ tmp = *dest;
+ left = &tmp.arguments->tag;
+ right = &list_next(tmp.arguments)->tag;
+ if ((r = buf_parse_ident_peek(buf, &next_op)) <= 0)
goto clean;
while (r && (op_precedence = operator_precedence(&next_op))
>= min_precedence) {
+ if ((r = buf_parse_ident(buf, &next_op)) <= 0)
+ goto clean;
result += r;
+ op = next_op;
if ((r = buf_ignore_spaces(buf)) < 0)
goto restore;
- op = next_op;
- right = tag_new();
if ((r = buf_parse_tag_primary(buf, right)) <= 0)
goto restore;
result += r;
if ((r = buf_ignore_spaces(buf)) < 0)
goto restore;
- if ((r = buf_parse_ident(buf, &next_op)) < 0)
+ if ((r = buf_parse_ident_peek(buf, &next_op)) < 0)
goto restore;
result += r;
while (r && ((next_op_precedence = operator_precedence(&next_op))
@@ -241,25 +244,22 @@ sw buf_parse_call_op_rec (s_buf *buf, s_call *dest, u8 min_precedence)
(operator_is_right_associative(&next_op) &&
next_op_precedence == op_precedence))) {
result += r;
- if (next_op_precedence > op_precedence)
- op_precedence++;
- right_left = right;
- right = tag_new();
- if ((r = buf_parse_call_op_rec(buf, &right->data.call,
- op_precedence)) <= 0)
+ call_init_op(&tmp2);
+ tmp2.arguments->tag = *right;
+ if ((r = buf_parse_call_op_rec(buf, &tmp2, (next_op_precedence > op_precedence) ? op_precedence + 1 : op_precedence)) <= 0)
goto restore;
- free(right_left);
+ tag_init_call(right, &tmp2);
result += r;
if ((r = buf_ignore_spaces(buf)) < 0)
goto restore;
- if ((r = buf_parse_ident(buf, &next_op)) < 0)
+ result += r;
+ if ((r = buf_parse_ident_peek(buf, &next_op)) < 0)
goto restore;
- new_left = tag_new_call_op(&op, left, right);
- free(left);
- left = new_left;
}
+ tmp.ident = op;
+ tag_init_call(left, &tmp);
}
- *dest = left->data.call;
+ *dest = tmp;
r = result;
goto clean;
restore:
@@ -872,6 +872,16 @@ sw buf_parse_ident (s_buf *buf, s_ident *dest)
return r;
}
+sw buf_parse_ident_peek (s_buf *buf, s_ident *dest)
+{
+ sw r;
+ s_buf_save save;
+ buf_save_init(buf, &save);
+ r = buf_parse_ident(buf, dest);
+ buf_save_restore_rpos(buf, &save);
+ return r;
+}
+
sw buf_parse_integer (s_buf *buf, s_integer *dest)
{
sw r;
diff --git a/libc3/buf_parse.h b/libc3/buf_parse.h
index bdd6206..664eea9 100644
--- a/libc3/buf_parse.h
+++ b/libc3/buf_parse.h
@@ -56,6 +56,7 @@ sw buf_parse_integer_unsigned_dec (s_buf *buf, s_integer *dest);
sw buf_parse_integer_unsigned_hex (s_buf *buf, s_integer *dest);
sw buf_parse_integer_unsigned_oct (s_buf *buf, s_integer *dest);
sw buf_parse_ident (s_buf *buf, s_ident *dest);
+sw buf_parse_ident_peek (s_buf *buf, s_ident *dest);
sw buf_parse_integer (s_buf *buf, s_integer *dest);
sw buf_parse_list (s_buf *buf, s_list **dest);
sw buf_parse_module_name (s_buf *buf, const s_sym **dest);
diff --git a/libc3/call.c b/libc3/call.c
index c82e3bf..2632575 100644
--- a/libc3/call.c
+++ b/libc3/call.c
@@ -12,6 +12,7 @@
* THIS SOFTWARE.
*/
#include <assert.h>
+#include <string.h>
#include "buf.h"
#include "buf_inspect.h"
#include "buf_parse.h"
@@ -45,10 +46,9 @@ s_call * call_init_1 (s_call *call, const s8 *p)
s_call * call_init_op (s_call *call)
{
- s_list *args;
assert(call);
assert(op);
- call->ident = NULL;
+ bzero(&call->ident, sizeof(s_ident));
call->arguments = list_new(list_new(NULL));
return call;
}
diff --git a/libc3/tag.c b/libc3/tag.c
index aee39a8..57c8045 100644
--- a/libc3/tag.c
+++ b/libc3/tag.c
@@ -290,6 +290,16 @@ s_tag * tag_init_bool (s_tag *tag, bool b)
return tag;
}
+s_tag * tag_init_call (s_tag *tag, const s_call *call)
+{
+ assert(tag);
+ assert(call);
+ bzero(tag, sizeof(s_tag));
+ tag->type.type = TAG_CALL;
+ tag->data.call = *call;
+ return tag;
+}
+
s_tag * tag_init_character (s_tag *tag, character c)
{
assert(tag);
diff --git a/libc3/tag.h b/libc3/tag.h
index 3be4811..ed23870 100644
--- a/libc3/tag.h
+++ b/libc3/tag.h
@@ -34,9 +34,8 @@ extern s_tag g_tag_last;
/* Stack allocation compatible functions */
s_tag * tag_init (s_tag *tag);
s_tag * tag_init_1 (s_tag *tag, const s8 *p);
-s_tag * tag_init_str (s_tag *tag, s8 *free, uw size, const s8 *p);
-s_tag * tag_init_str_1 (s_tag *tag, s8 *free, const s8 *p);
s_tag * tag_init_bool (s_tag *tag, bool p);
+s_tag * tag_init_call (s_tag *tag, const s_call *call);
s_tag * tag_init_character (s_tag *tag, character c);
s_tag * tag_init_f32 (s_tag *tag, f32 f);
s_tag * tag_init_f64 (s_tag *tag, f64 f);
@@ -50,6 +49,8 @@ s_tag * tag_init_s8 (s_tag *tag, s8 i);
s_tag * tag_init_s16 (s_tag *tag, s16 i);
s_tag * tag_init_s32 (s_tag *tag, s32 i);
s_tag * tag_init_s64 (s_tag *tag, s64 i);
+s_tag * tag_init_str (s_tag *tag, s8 *free, uw size, const s8 *p);
+s_tag * tag_init_str_1 (s_tag *tag, s8 *free, const s8 *p);
s_tag * tag_init_sym (s_tag *tag, const s_sym *p);
s_tag * tag_init_sym_1 (s_tag *tag, const s8 *p);
s_tag * tag_init_tuple (s_tag *tag, uw count);