|
@@ -1025,6 +1025,7 @@ struct _node_t {
|
|
|
N_MVAR,
|
|
|
|
|
|
N_MIF,
|
|
|
+ N_MSET,
|
|
|
N_MSTMT,
|
|
|
N_MEXPR
|
|
|
} tag;
|
|
@@ -2446,9 +2447,9 @@ node_t *parse_mprimary(list_t *tokens, size_t *pos) {
|
|
|
}
|
|
|
|
|
|
return NODET(LITERAL, t);
|
|
|
- } else if (MATCH(NUMBER))
|
|
|
+ } else if (MATCH(NUMBER) || MATCH(STRING))
|
|
|
return NODET(LITERAL, tokens->data[(*pos)-1]);
|
|
|
-
|
|
|
+
|
|
|
PARSE_ERROR("expected m-expression");
|
|
|
|
|
|
return NULL;
|
|
@@ -2544,7 +2545,15 @@ node_t *parse_mif(list_t *tokens, size_t *pos, int sub) {
|
|
|
node_t *parse_mstmt(list_t *tokens, size_t *pos) {
|
|
|
if (MATCHM("if"))
|
|
|
return parse_mif(tokens, pos, 0);
|
|
|
- else if (MATCHM("$")) {
|
|
|
+ else if (MATCHM("set")) {
|
|
|
+ if(!AT(NAME))
|
|
|
+ PARSE_ERROR("expected identifier");
|
|
|
+
|
|
|
+ token_t *t = tokens->data[(*pos)++];
|
|
|
+ node_t *a = parse_mexpr(tokens, pos);
|
|
|
+
|
|
|
+ return NODE1t(MSET, a, t);
|
|
|
+ } else if (MATCHM("$")) {
|
|
|
node_t *a = parse_stmt(tokens, pos);
|
|
|
|
|
|
if (a->tag == N_EXPRSTMT)
|
|
@@ -3487,6 +3496,7 @@ node_t *YES;
|
|
|
|
|
|
#define IS_NUMBER(n) ((n) && (n)->tag == N_LITERAL && (n)->t->tag == T_NUMBER)
|
|
|
#define TO_DOUBLE(n) (strtod((n)->t->text, NULL))
|
|
|
+#define IS_STRING(n) ((n) && (n)->tag == N_LITERAL && (n)->t->tag == T_STRING)
|
|
|
|
|
|
node_t *make_number(double v) {
|
|
|
char buf[64];
|
|
@@ -3562,6 +3572,47 @@ node_t *mf_newList(list_t *t) {
|
|
|
return nodel(N_LIST, t);
|
|
|
}
|
|
|
|
|
|
+node_t *mf_newName(list_t *t) {
|
|
|
+ if (t->length != 1)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ node_t *a = t->data[0];
|
|
|
+ if (!IS_STRING(a))
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ char *text = a->t->text;
|
|
|
+ if (*text != '_' && !isalpha(*text))
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ for (size_t i = 0; i < strlen(text); i++)
|
|
|
+ if (text[i] != '_' && !isdigit(text[i]) && !isalpha(text[i]))
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ return nodet(N_LITERAL, token(T_NAME, text));
|
|
|
+}
|
|
|
+
|
|
|
+node_t *mf_newVar(list_t *t) {
|
|
|
+ if (t->length != 1 && t->length != 2)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ node_t *a = t->data[0];
|
|
|
+ if (!a || a->tag != N_LITERAL || a->t->tag != T_NAME)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ node_t *b = NULL;
|
|
|
+ if (t->length == 2) {
|
|
|
+ b = t->data[1];
|
|
|
+
|
|
|
+ if (!(b->tag > N_EXPRS_BEGIN && b->tag < N_EXPRS_END))
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ table_t *h = table_new();
|
|
|
+ table_set(h, a->t->text, b);
|
|
|
+
|
|
|
+ return nodeh(N_VAR, h);
|
|
|
+}
|
|
|
+
|
|
|
node_t *mf_len(list_t *t) {
|
|
|
if (t->length != 1)
|
|
|
return NULL;
|
|
@@ -3601,7 +3652,9 @@ struct {
|
|
|
{ "isExpr", mf_isExpr },
|
|
|
{ "isList", mf_isList },
|
|
|
|
|
|
+ { "newName", mf_newName },
|
|
|
{ "newList", mf_newList },
|
|
|
+ { "newVar", mf_newVar },
|
|
|
|
|
|
{ "len", mf_len },
|
|
|
{ "nth", mf_nth },
|
|
@@ -3666,7 +3719,7 @@ node_t *run_mexpr(node_t *node) {
|
|
|
case T_NAME:
|
|
|
return table_get(list_index(MVARS, -1), node->t->text);
|
|
|
|
|
|
- case T_NUMBER:
|
|
|
+ case T_NUMBER: case T_STRING:
|
|
|
return node;
|
|
|
|
|
|
default:
|
|
@@ -3765,6 +3818,10 @@ node_t *run_mnode(node_t *node) {
|
|
|
r = run_mnodes(node->l2);
|
|
|
break;
|
|
|
|
|
|
+ case N_MSET:
|
|
|
+ table_set(list_index(MVARS, -1), node->t->text, run_mexpr(node->a));
|
|
|
+ break;
|
|
|
+
|
|
|
case N_MSTMT:
|
|
|
r = node->a;
|
|
|
break;
|
|
@@ -3782,6 +3839,7 @@ node_t *run_mnode(node_t *node) {
|
|
|
|
|
|
node_t *run_macro(macro_t *macro, list_t *args) {
|
|
|
table_t *mvars = list_index(MVARS, -1);
|
|
|
+ table_set(mvars, "nil", NULL);
|
|
|
|
|
|
if (macro->variable)
|
|
|
table_set(mvars, "*", nodel(N_LIST, args));
|