char *tl_expression_join (struct tl_compiler *C, struct tl_expression *E, int output_magic) { struct tl_token *T; struct tl_buffer b; tl_string_buffer_init (&b); for (T = E->left; T != NULL; T = T->next) { if (b.pos) { tl_string_buffer_append_char (&b, ' '); } tl_string_buffer_append_cstr (&b, T->text); if (output_magic && T == E->left) { tl_string_buffer_printf (&b, "#%x", E->magic); } } if (E->right) { tl_string_buffer_append_char (&b, ' '); tl_string_buffer_append_char (&b, '='); for (T = E->right; T != NULL; T = T->next) { tl_string_buffer_append_char (&b, ' '); tl_string_buffer_append_cstr (&b, T->text); } } tl_string_buffer_append_char (&b, 0); int r = tl_expression_remove_sugar (C, E, b.buff); if (r < 0) { tl_string_buffer_free (&b); return NULL; } char *res = cstr_dup (b.buff); tl_string_buffer_free (&b); return res; }
struct tl_token *tl_expresion_split (struct tl_compiler *C, struct tl_expression *E, const char *const expression, int remove_sugar) { int l = strlen (expression) + 1; char *s = zmalloc (l); strcpy (s, expression); if (remove_sugar) { if (tl_expression_remove_sugar (C, E, s) < 0) { return NULL; } } char *p; struct tl_token *head = NULL; for (p = strtok (s, " "); p != NULL; p = strtok (NULL, " ")) { struct tl_token *T = zmalloc0 (sizeof (struct tl_token)); #define ZHUKOV_BYTES_HACK #ifdef ZHUKOV_BYTES_HACK /* dirty hack for Zhukov request */ if (!strcmp (p, "bytes")) { T->text = cstr_dup ("string"); } else if (!strcmp (p, "Bytes")) { T->text = cstr_dup ("String"); } else { int l = strlen (p); if (l >= 6 && !strcmp (p + l - 6, ":bytes")) { T->text = zmalloc (l + 2); strcpy (T->text, p); strcpy (T->text + l - 6, ":string"); } else if (l >= 6 && !strcmp (p + l - 6, ":Bytes")) { T->text = zmalloc (l + 2); strcpy (T->text, p); strcpy (T->text + l - 6, ":String"); } else { T->text = cstr_dup (p); } } #else T->text = cstr_dup (p); #endif T->next = head; head = T; } zfree (s, l); return list_token_reverse (head); }
static struct tl_token *tl_token_clone (struct tl_token *T) { struct tl_token *head = NULL; while (T != NULL) { struct tl_token *A = zmalloc0 (sizeof (struct tl_token)); A->text = cstr_dup (T->text); A->next = head; head = A; T = T->next; } return list_token_reverse (head); }
static void tl_add_expression (struct tl_compiler *C, int section, const char *text) { vkprintf (3, "tl_add_expression (section:%d, text:%s)\n", section, text); assert (section >= 0 && section < 2); struct tl_expression *E = zmalloc0 (sizeof (struct tl_expression)); E->section = section; E->flag_builtin = C->flag_reading_builtin_schema; struct tl_expression *L = &C->expr[section]; E->text = cstr_dup (text); struct tl_expression *A = L->prev; A->next = E; E->prev = A; E->next = L; L->prev = E; }
char *cstr_join_with_sugar (struct tl_token *T) { int i, n, l; tl_token_length (T, &n, &l); assert (n >= 1); if (n == 1) { return cstr_dup (T->text); } l += n + 1; char *buf = tl_zzmalloc (l), *p = buf; for (i = 0; T != NULL; T = T->next, i++) { p += sprintf (p, "%s", T->text); *p++ = i ? ((i == n - 1) ? '>' : ',') : '<'; } *p++ = 0; assert (p == buf + l); return buf; }
void tl_expression_expand (struct tl_expression *E, struct tl_expression *R) { assert (R->type == tlet_polymorphic); assert (E->type == tlet_polymorphic_instance); struct tl_token *L = tl_token_clone (R->left); struct tl_token *x, *y, *z; for (x = L->next; x != NULL; x = x->next) { for (y = R->right->next, z = E->left->next; y != NULL; y = y->next, z = z->next) { if (!strcmp (x->text, y->text)) { cstr_free (&x->text); x->text = cstr_dup (z->text); } } } E->right = E->left; E->left = L; E->type = tlet_simple; E->right_name = cstr_join_with_sugar (E->right); E->flag_expanded = 1; }
struct token token_stream_read(struct token_stream * ts) { if(ts->end) return token_new(TOKEN_TYPE_END); enum states{ READ_NEXT = 0, SCAN, SCAN_ERR, BUILD_SECTION, BUILD_SECTION1, BUILD_SECTION_END, BUILD_NAME, BUILD_NAME1, BUILD_NAME_END, BUILD_ASSIGNMENT, BUILD_STRING, BUILD_STRING1, BUILD_STRING_END, BUILD_COMMENT, BUILD_NEWLINE, BUILD_END, ERROR, SKIP_LINE, } state = ts->next_state; struct varstr * buf = varstr_new(); struct char_stream * cs = ts->cs; struct token tok; int running = 1; do switch(state){ case READ_NEXT: next_char(cs); state = SCAN; case SCAN: if(!cs->escaped) { if(cs->c == ' ' || cs->c == '\t') state = READ_NEXT; else if(cs->c == '[') state = BUILD_SECTION; else if(char_is_name(cs)) state = BUILD_NAME; else if(cs->c == '=') state = BUILD_ASSIGNMENT; else if(cs->c == '"') state = BUILD_STRING; else if(cs->c == '#') state = BUILD_COMMENT; else if(cs->c == '\n') state = BUILD_NEWLINE; else if(cs->c == EOF) state = BUILD_END; else state = SCAN_ERR; } else state = SCAN_ERR; break; case SCAN_ERR: fprintf(stderr,"next_token: " "bad token at row %d, column %d\n", cs->row, cs->col); state = SKIP_LINE; break; case BUILD_SECTION: // [section] varstr_clear(buf); tok = token_new(TOKEN_TYPE_SECTION); state = BUILD_SECTION1; case BUILD_SECTION1: next_char(cs); if(char_is_name(cs)) varstr_append(buf, cs->c); else state = BUILD_SECTION_END; break; case BUILD_SECTION_END: if(cs->c == ']' && !cs->escaped) { ts->next_state = READ_NEXT; tok.text = cstr_dup(varstr_view(buf)); running = 0; } else { fprintf(stderr, "next_token: " "bad section name at row %d, column %d, " "expected ']'\n", cs->row, cs->col); state = ERROR; } break; case BUILD_NAME: // name tok = token_new(TOKEN_TYPE_NAME); varstr_clear(buf); varstr_append(buf, cs->c); state = BUILD_NAME1; case BUILD_NAME1: next_char(cs); if(char_is_name(cs)) varstr_append(buf, cs->c); else state = BUILD_NAME_END; break; case BUILD_NAME_END: ts->next_state = SCAN; tok.text = cstr_dup(varstr_view(buf)); running = 0; break; case BUILD_ASSIGNMENT: // = tok = token_new(TOKEN_TYPE_ASSIGNMENT); ts->next_state = READ_NEXT; running = 0; break; case BUILD_STRING: /* "multi line string with escape /"/n" */ tok = token_new(TOKEN_TYPE_STRING); varstr_clear(buf); state = BUILD_STRING1; case BUILD_STRING1: next_char(cs); if(cs->c == EOF) state = BUILD_STRING_END; else if(cs->c == '"' && !cs->escaped) state = BUILD_STRING_END; else varstr_append(buf, cs->c); break; case BUILD_STRING_END: if(cs->c == '"' && !cs->escaped) { ts->next_state = READ_NEXT; tok.text = cstr_dup(varstr_view(buf)); running = 0; } else if(cs->c == EOF) { fprintf(stderr, "next_token" "bad string at row %d, column %d, " "expected '\"'\n", cs->row, cs->col); state = ERROR; } break; case BUILD_COMMENT: // # comment state = SKIP_LINE; break; case BUILD_NEWLINE: tok = token_new(TOKEN_TYPE_NEWLINE); ts->next_state = READ_NEXT; running = 0; break; case BUILD_END: tok = token_new(TOKEN_TYPE_NEWLINE); ts->end = 1; running = 0; break; case ERROR: state = SKIP_LINE; case SKIP_LINE: if(cs->c == '\n' && !cs->escaped) state = BUILD_NEWLINE; else if(cs->c == EOF) state = BUILD_END; else next_char(cs); break; }while(running); varstr_del(buf); return tok; }