return res;
}
-struct stmt *stmt_assign(char *ident, struct expr *expr)
+struct stmt *stmt_assign(char *ident, struct list *fields, struct expr *expr)
{
struct stmt *res = safe_malloc(sizeof(struct stmt));
res->type = sassign;
res->data.sassign.ident = ident;
+ res->data.sassign.fields = (char **)
+ list_to_array(fields, &res->data.sassign.nfield, true);
res->data.sassign.expr = expr;
return res;
}
struct expr *res = safe_malloc(sizeof(struct expr));
res->type = echar;
//regular char
- if (strlen(c) == 3)
+ if (c[0] == '\'' && c[2] == '\'')
res->data.echar = c[1];
//escape
- if (strlen(c) == 4)
+ else if (c[0] == '\'' && c[1] == '\\' && c[3] == '\'')
switch(c[2]) {
case '0': res->data.echar = '\0'; break;
+ case '\'': res->data.echar = '\''; break;
+ case '\\': res->data.echar = '\\'; break;
case 'a': res->data.echar = '\a'; break;
case 'b': res->data.echar = '\b'; break;
case 't': res->data.echar = '\t'; break;
case 'r': res->data.echar = '\r'; break;
}
//hex escape
- if (strlen(c) == 6)
+ else if (c[0] == '\'' && c[1] == '\\' && c[2] == 'x' && c[5] == '\'')
res->data.echar = (fromHex(c[3])<<4)+fromHex(c[4]);
+ else
+ die("malformed character: %s\n", c);
return res;
}
return res;
}
+struct expr *expr_string(char *str)
+{
+ struct expr *res = safe_malloc(sizeof(struct expr));
+ res->type = estring;
+ res->data.estring = safe_strdup(str+1);
+ res->data.estring[strlen(res->data.estring)-1] = '\0';
+ //TODO escapes
+ return res;
+}
+
struct expr *expr_unop(enum unop op, struct expr *l)
{
struct expr *res = safe_malloc(sizeof(struct expr));
const char *cescapes[] = {
- [0] = "\\0", [1] = "\\x01", [2] = "\\x02", [3] = "\\x03",
- [4] = "\\x04", [5] = "\\x05", [6] = "\\x06", [7] = "\\a", [8] = "\\b",
- [9] = "\\t", [10] = "\\n", [11] = "\\v", [12] = "\\f", [13] = "\\r",
- [14] = "\\x0E", [15] = "\\x0F", [16] = "\\x10", [17] = "\\x11",
- [18] = "\\x12", [19] = "\\x13", [20] = "\\x14", [21] = "\\x15",
- [22] = "\\x16", [23] = "\\x17", [24] = "\\x18", [25] = "\\x19",
- [26] = "\\x1A", [27] = "\\x1B", [28] = "\\x1C", [29] = "\\x1D",
- [30] = "\\x1E", [31] = "\\x1F",
- [127] = "\\x7F"
+ [0] = "0", [1] = "x01", [2] = "x02", [3] = "x03",
+ [4] = "x04", [5] = "x05", [6] = "x06", [7] = "a", [8] = "b",
+ [9] = "t", [10] = "n", [11] = "v", [12] = "f", [13] = "r",
+ [14] = "x0E", [15] = "x0F", [16] = "x10", [17] = "x11",
+ [18] = "x12", [19] = "x13", [20] = "x14", [21] = "x15",
+ [22] = "x16", [23] = "x17", [24] = "x18", [25] = "x19",
+ [26] = "x1A", [27] = "x1B", [28] = "x1C", [29] = "x1D",
+ [30] = "x1E", [31] = "x1F",
+ ['\\'] = "\\", ['\''] = "'",
+ [127] = "x7F"
};
void ast_print(struct ast *ast, FILE *out)
case sassign:
pindent(indent, out);
fprintf(out, "%s", stmt->data.sassign.ident);
+ for (int i = 0; i<stmt->data.sassign.nfield; i++)
+ fprintf(out, ".%s", stmt->data.sassign.fields[i]);
safe_fprintf(out, " = ");
expr_print(stmt->data.sassign.expr, out);
safe_fprintf(out, ";\n");
safe_fprintf(out, "%s", expr->data.ebool ? "true" : "false");
break;
case echar:
- if (expr->data.echar < 0)
+ if (expr->data.echar < 0) {
safe_fprintf(out, "'?'");
- if (expr->data.echar < ' ' || expr->data.echar == 127)
- safe_fprintf(out, "'%s'",
+ } else if (expr->data.echar < ' ' || expr->data.echar == 127
+ || expr->data.echar == '\\'
+ || expr->data.echar == '\'') {
+ safe_fprintf(out, "'\\%s'",
cescapes[(int)expr->data.echar]);
- else
+ } else {
safe_fprintf(out, "'%c'", expr->data.echar);
+ }
break;
case efuncall:
safe_fprintf(out, "%s(", expr->data.efuncall.ident);
expr_print(expr->data.etuple.right, out);
safe_fprintf(out, ")");
break;
+ case estring:
+ safe_fprintf(out, "\"%s\"", expr->data.estring);
+ break;
case eunop:
safe_fprintf(out, "(%s", unop_str[expr->data.eunop.op]);
expr_print(expr->data.eunop.l, out);
switch(stmt->type) {
case sassign:
free(stmt->data.sassign.ident);
+ for (int i = 0; i<stmt->data.sassign.nfield; i++)
+ free(stmt->data.sassign.fields[i]);
expr_free(stmt->data.sassign.expr);
break;
case sif:
expr_free(expr->data.etuple.left);
expr_free(expr->data.etuple.right);
break;
+ case estring:
+ free(expr->data.estring);
+ break;
case eunop:
expr_free(expr->data.eunop.l);
break;