/** * CTRParserReference * * Generates the nodes to respresent a variable or property. */ ctr_tnode* ctr_cparse_ref() { ctr_tnode* r; char* tmp; ctr_clex_tok(); r = CTR_PARSER_CREATE_NODE(); r->type = CTR_AST_NODE_REFERENCE; r->vlen = ctr_clex_tok_value_length(); tmp = ctr_clex_tok_value(); if (strncmp("my", tmp, 2)==0 && r->vlen == 2) { int t = ctr_clex_tok(); if (t != CTR_TOKEN_REF) { printf("'My' should always be followed by property name!\n"); exit(1); } tmp = ctr_clex_tok_value(); r->modifier = 1; r->vlen = ctr_clex_tok_value_length(); } if (strncmp("var", tmp, 3)==0 && r->vlen == 3) { int t = ctr_clex_tok(); if (t != CTR_TOKEN_REF) { printf("'var' should always be followed by property name!\n"); exit(1); } tmp = ctr_clex_tok_value(); r->modifier = 2; r->vlen = ctr_clex_tok_value_length(); } r->value = ctr_malloc(r->vlen, 0); memcpy(r->value, tmp, r->vlen); return r; }
/** * CTRParserReference * * Generates the nodes to respresent a variable or property. */ ctr_tnode * ctr_cparse_ref () { ctr_tnode *r; char *tmp; ctr_clex_tok (); r = ctr_cparse_create_node (CTR_AST_NODE); r->type = CTR_AST_NODE_REFERENCE; r->vlen = ctr_clex_tok_value_length (); tmp = ctr_clex_tok_value (); if (all_plains_private) r->modifier = (do_compare_locals) ? (ctr_paramlist_has_name (tmp, r->vlen) ? 0 : 3) : 3; if (strncmp (ctr_clex_keyword_my, tmp, ctr_clex_keyword_my_len) == 0 && r->vlen == ctr_clex_keyword_my_len) { int t = ctr_clex_tok (); if (t != CTR_TOKEN_REF) { ctr_cparse_emit_error_unexpected (t, "'My' should always be followed by a property name!\n"); } tmp = ctr_clex_tok_value (); r->modifier = 1; r->vlen = ctr_clex_tok_value_length (); } if (strncmp (ctr_clex_keyword_var, tmp, ctr_clex_keyword_var_len) == 0 && r->vlen == ctr_clex_keyword_var_len) { int t = ctr_clex_tok (); if (t != CTR_TOKEN_REF) { ctr_cparse_emit_error_unexpected (t, "Keyword 'var' should always be followed by property name!\n"); } tmp = ctr_clex_tok_value (); r->modifier = 2; r->vlen = ctr_clex_tok_value_length (); } if (strncmp (ctr_clex_keyword_const, tmp, ctr_clex_keyword_const_len) == 0 && r->vlen == ctr_clex_keyword_const_len) { int t = ctr_clex_tok (); if (t != CTR_TOKEN_REF) { ctr_cparse_emit_error_unexpected (t, "'const' must always be followed by a single reference/property\n"); } tmp = ctr_clex_tok_value (); r->modifier = 3; r->vlen = ctr_clex_tok_value_length (); } r->value = ctr_heap_allocate_tracked (r->vlen); memcpy (r->value, tmp, r->vlen); return r; }
/** * Prints the remaining part of the program. */ void ctr_translate_fin(char* codePointer) { char* e; char* p; p = codePointer; ctr_size l; e = ctr_clex_code_pointer(); l = ctr_clex_tok_value_length(); fwrite(p, ((e - l) - p),1, stdout); fwrite(e-l, l, 1, stdout); }
ctr_tnode* ctr_cparse_number() { char* n; ctr_tnode* r; long l; ctr_clex_tok(); r = CTR_PARSER_CREATE_NODE(); r->type = CTR_AST_NODE_LTRNUM; n = ctr_clex_tok_value(); l = ctr_clex_tok_value_length(); r->value = ctr_malloc(sizeof(char) * l, 0); memcpy(r->value, n, l); r->vlen = l; return r; }
ctr_tnode * ctr_cparse_number () { char *n; ctr_tnode *r; long l; ctr_clex_tok (); r = ctr_cparse_create_node (CTR_AST_NODE); r->type = CTR_AST_NODE_LTRNUM; n = ctr_clex_tok_value (); l = ctr_clex_tok_value_length (); r->value = ctr_heap_allocate_tracked (sizeof (char) * l); memcpy (r->value, n, l); r->vlen = l; return r; }
/** * CTRParserString * * Generates a node to represent a string. */ ctr_tnode* ctr_cparse_string() { ctr_tnode* r; char* n; ctr_size vlen; if (ctr_mode_debug) printf("Parsing STRING. \n"); ctr_clex_tok(); r = CTR_PARSER_CREATE_NODE(); r->type = CTR_AST_NODE_LTRSTRING; n = ctr_clex_readstr(); vlen = ctr_clex_tok_value_length(); r->value = ctr_malloc(sizeof(char) * vlen, 0); memcpy(r->value, n, vlen); r->vlen = vlen; ctr_clex_tok(); /* eat trailing quote. */ return r; }
/** * CTRParserString * * Generates a node to represent a string. */ ctr_tnode * ctr_cparse_string () { ctr_tnode *r; char *n; ctr_size vlen; ctr_clex_tok (); r = ctr_cparse_create_node (CTR_AST_NODE); r->type = CTR_AST_NODE_LTRSTRING; n = ctr_clex_readstr (); vlen = ctr_clex_tok_value_length (); r->value = ctr_heap_allocate_tracked (sizeof (char) * vlen); memcpy (r->value, n, vlen); r->vlen = vlen; ctr_clex_tok (); /* eat trailing quote. */ return r; }
/** * CTRParserSymbol * * Generates a symbol or pulls it from the static symbol list. */ ctr_tnode * ctr_cparse_symbol () { ctr_tnode *r; ctr_tlistitem *li; r = ctr_cparse_create_node (CTR_AST_NODE); int t = ctr_clex_tok (); if (t != CTR_TOKEN_SYMBOL) return NULL; ctr_clex_tok (); r->type = CTR_AST_NODE_SYMBOL; li = (ctr_tlistitem *) ctr_heap_allocate_tracked (sizeof (ctr_tlistitem)); ctr_size vlen = ctr_clex_tok_value_length (); r->value = (char *) ctr_get_or_create_symbol_table_entry (ctr_clex_tok_value (), vlen); r->vlen = -1; //sig return r; }
/** * Prints translatable strings in the program. */ char* ctr_translate_string(char* codePointer, ctr_dict* dictionary) { char* s; ctr_size l; char* e; char* p; p = codePointer; if (ctr_string_interpolation) { ctr_string_interpolation = 0; } s = ctr_clex_readstr(); l = ctr_clex_tok_value_length(s); e = ctr_clex_code_pointer(); if (ctr_string_interpolation) { e -= 3; } fwrite(p, e-p-l, 1, stdout); if (!ctr_translate_translate(s,l,dictionary,'s',NULL)) { fwrite(s,l,1,stdout); } if (!ctr_string_interpolation) { ctr_clex_tok(); } return e; }
ctr_tnode * ctr_cparse_block_ (int autocap) { ctr_tnode *r; ctr_tlistitem *codeBlockPart1; ctr_tlistitem *codeBlockPart2; ctr_tnode *paramList; ctr_tnode *codeList; ctr_tlistitem *previousListItem; ctr_tlistitem *previousCodeListItem; int t; int first; ctr_clex_tok (); r = ctr_cparse_create_node (CTR_AST_NODE); r->type = CTR_AST_NODE_CODEBLOCK; codeBlockPart1 = (ctr_tlistitem *) ctr_heap_allocate_tracked (sizeof (ctr_tlistitem)); r->nodes = codeBlockPart1; codeBlockPart2 = (ctr_tlistitem *) ctr_heap_allocate_tracked (sizeof (ctr_tlistitem)); r->nodes->next = codeBlockPart2; paramList = ctr_cparse_create_node (CTR_AST_NODE); codeList = ctr_cparse_create_node (CTR_AST_NODE); codeBlockPart1->node = paramList; codeBlockPart2->node = codeList; paramList->type = CTR_AST_NODE_PARAMLIST; codeList->type = CTR_AST_NODE_INSTRLIST; t = ctr_clex_tok (); first = 1; while (t == CTR_TOKEN_COLON) { /* okay we have new parameter, load it */ t = ctr_clex_tok (); ctr_tlistitem *paramListItem = (ctr_tlistitem *) ctr_heap_allocate_tracked (sizeof (ctr_tlistitem)); ctr_tnode *paramItem = ctr_cparse_create_node (CTR_AST_NODE); long l = ctr_clex_tok_value_length (); paramItem->value = ctr_heap_allocate_tracked (sizeof (char) * l); memcpy (paramItem->value, ctr_clex_tok_value (), l); paramItem->vlen = l; paramListItem->node = paramItem; if (first) { paramList->nodes = paramListItem; previousListItem = paramListItem; first = 0; } else { previousListItem->next = paramListItem; previousListItem = paramListItem; } t = ctr_clex_tok (); } first = 1; int oldallpl = all_plains_private; int olddcl = do_compare_locals; do_compare_locals = autocap; int oldcalltime = ctr_cparse_calltime_name_id; ctr_cparse_calltime_names[++ctr_cparse_calltime_name_id] = paramList; all_plains_private = autocap; if (ctr_transform_lambda_shorthand) { ctr_transform_lambda_shorthand = 0; ctr_tlistitem *codeListItem; ctr_tnode *codeNode; ctr_clex_putback (); codeListItem = (ctr_tlistitem *) ctr_heap_allocate_tracked (sizeof (ctr_tlistitem)); codeNode = ctr_cparse_create_node (CTR_AST_NODE); codeNode = ctr_cparse_expr (0); //parse a single expression codeListItem->node = codeNode; codeList->nodes = codeListItem; previousCodeListItem = codeListItem; } else { while ((first || t == CTR_TOKEN_DOT)) { ctr_tlistitem *codeListItem; ctr_tnode *codeNode; if (first) { ctr_clex_putback (); } t = ctr_clex_tok (); if (t == CTR_TOKEN_BLOCKCLOSE) break; ctr_clex_putback (); codeListItem = (ctr_tlistitem *) ctr_heap_allocate_tracked (sizeof (ctr_tlistitem)); codeNode = ctr_cparse_create_node (CTR_AST_NODE); if (t == CTR_TOKEN_RET) { codeNode = ctr_cparse_ret (); } else { codeNode = ctr_cparse_expr (0); } codeListItem->node = codeNode; if (first) { codeList->nodes = codeListItem; previousCodeListItem = codeListItem; first = 0; } else { previousCodeListItem->next = codeListItem; previousCodeListItem = codeListItem; } t = ctr_clex_tok (); if (t != CTR_TOKEN_DOT && !autocap) { ctr_cparse_emit_error_unexpected (t, "Expected a dot (.).\n"); } } } all_plains_private = oldallpl; do_compare_locals = olddcl; ctr_cparse_calltime_name_id = oldcalltime; r->modifier = /*CTR_MODIFIER_AUTOCAPTURE */ autocap == 1; return r; }
/** * CTRParserMessage * * Creates the AST nodes for sending a message. * * - precedence mode 0: no argument (allows processing of unary message, binary message and keyword message) * - precedence mode 1: as argument of keyword message (allows processing of unary message and binary message) * - precedence mode 2: as argument of binary message (only allows processing of unary message) */ ctr_tnode * ctr_cparse_message (int mode) { long msgpartlen; /* length of part of message string */ ctr_tnode *m; int t; char *s; char *msg; ctr_tlistitem *li; ctr_tlistitem *curlistitem; int lookAhead; int isBin; int first; t = ctr_clex_tok (); msgpartlen = ctr_clex_tok_value_length (); if ((msgpartlen) > 255) { ctr_cparse_emit_error_unexpected (t, "Message too long\n"); } m = ctr_cparse_create_node (CTR_AST_NODE); m->type = -1; s = ctr_clex_tok_value (); msg = ctr_heap_allocate_tracked (255 * sizeof (char)); memcpy (msg, s, msgpartlen); isBin = ctr_utf8_is_one_cluster (msg, msgpartlen); if (mode == 2 && isBin) { ctr_clex_putback (); return m; } if (isBin) { m->type = CTR_AST_NODE_BINMESSAGE; m->value = msg; m->vlen = msgpartlen; li = (ctr_tlistitem *) ctr_heap_allocate_tracked (sizeof (ctr_tlistitem)); li->node = ctr_cparse_expr (2); m->nodes = li; return m; } lookAhead = ctr_clex_tok (); ctr_clex_putback (); if (lookAhead == CTR_TOKEN_COLON) { if (mode > 0) { ctr_clex_putback (); return m; } *(msg + msgpartlen) = ':'; msgpartlen += 1; if ((msgpartlen) > 255) { ctr_cparse_emit_error_unexpected (t, "Message too long\n"); } m->type = CTR_AST_NODE_KWMESSAGE; t = ctr_clex_tok (); first = 1; while (1) { li = (ctr_tlistitem *) ctr_heap_allocate_tracked (sizeof (ctr_tlistitem)); li->node = ctr_cparse_expr (1); if (first) { m->nodes = li; curlistitem = m->nodes; first = 0; } else { curlistitem->next = li; curlistitem = li; } t = ctr_clex_tok (); if (t == CTR_TOKEN_DOT) break; if (t == CTR_TOKEN_FIN) break; if (t == CTR_TOKEN_CHAIN) break; if (t == CTR_TOKEN_PARCLOSE) break; if (t == CTR_TOKEN_REF) { long l = ctr_clex_tok_value_length (); if ((msgpartlen + l) > 255) { ctr_cparse_emit_error_unexpected (t, "Message too long\n"); } memcpy ((msg + msgpartlen), ctr_clex_tok_value (), l); msgpartlen = msgpartlen + l; *(msg + msgpartlen) = ':'; msgpartlen++; t = ctr_clex_tok (); if (t != CTR_TOKEN_COLON) { ctr_cparse_emit_error_unexpected (t, "Expected colon.\n"); } } } ctr_clex_putback (); /* not a colon so put back */ m->value = msg; m->vlen = msgpartlen; } else { m->type = CTR_AST_NODE_UNAMESSAGE; m->value = msg; m->vlen = msgpartlen; } return m; }
/** * Prints a translatable reference in the program. */ char* ctr_translate_ref(char* codePointer, ctr_dict* dictionary) { char* message; int noteCount; char skipColon; char* remainder; char* p = codePointer; char* e; ctr_size l; ctr_size ol; ctr_note* foundNote; skipColon = 0; e = ctr_clex_code_pointer(); l = ctr_clex_tok_value_length(); ol = l; message = ctr_clex_tok_value(); fwrite(p, ((e - l ) - p),1, stdout); noteCount = 0; /* is this part of a keyword message (end with colon?) */ if (*(e)==':') { ctr_notebook_clear_marks(); skipColon = 1; ctr_size q; message = calloc(CTR_TRANSLATE_MAX_WORD_LEN,1); if (l+1 > CTR_TRANSLATE_MAX_WORD_LEN) { ctr_print_error(CTR_TERR_TOK, 1); } memcpy(message, e-l,l+1); ctr_size i = 1; while(ctr_clex_forward_scan(e, ":.,)\"", &i)) { if (*(e+i)=='.' || *(e+i)==')' || *(e+i)==',') break; if (*(e+i)==':') { ctr_notebook_add( ctr_note_create(e+i), noteCount ); noteCount++; q = 0; if (ctr_clex_backward_scan(e+i, "\n\t )}", &q, CTR_TRANSLATE_MAX_WORD_LEN)) { if ((l+1)+((e+i+1)-(e+i-q+1))>CTR_TRANSLATE_MAX_WORD_LEN) { ctr_print_error(CTR_TERR_PART, 1); } memcpy(message+l+1,e+i-q+1, (e+i+1)-(e+i-q+1)); l += ((e+i+1)-(e+i-q+1)); } else { ctr_print_error(CTR_MSG_ERROR,1); } } i++; } l++; } foundNote = ctr_notebook_search( e ); if (foundNote) { fwrite(foundNote->attachment, strlen(foundNote->attachment),1,stdout); } else { remainder = calloc(CTR_TRANSLATE_MAX_WORD_LEN,1); if (!ctr_translate_translate( message, l, dictionary, 't', remainder )) { skipColon = 0; fwrite(e-ol, ol, 1, stdout); ctr_notebook_remove(); } else { if (noteCount>0) ctr_note_collect(remainder); } free(remainder); } return (e + skipColon); }
/** * CTRParserBlock * * Generates a set of AST nodes to represent a block of code. */ ctr_tnode* ctr_cparse_block() { ctr_tnode* r; ctr_tlistitem* codeBlockPart1; ctr_tlistitem* codeBlockPart2; ctr_tnode* paramList; ctr_tnode* codeList; ctr_tlistitem* previousListItem; ctr_tlistitem* previousCodeListItem; int t; int first; if (ctr_mode_debug) printf("Parsing code block.\n"); ctr_clex_tok(); r = CTR_PARSER_CREATE_NODE(); r->type = CTR_AST_NODE_CODEBLOCK; codeBlockPart1 = CTR_PARSER_CREATE_LISTITEM(); r->nodes = codeBlockPart1; codeBlockPart2 = CTR_PARSER_CREATE_LISTITEM(); r->nodes->next = codeBlockPart2; paramList = CTR_PARSER_CREATE_NODE(); codeList = CTR_PARSER_CREATE_NODE(); codeBlockPart1->node = paramList; codeBlockPart2->node = codeList; paramList->type = CTR_AST_NODE_PARAMLIST; codeList->type = CTR_AST_NODE_INSTRLIST; t = ctr_clex_tok(); first = 1; while(t == CTR_TOKEN_REF) { ctr_tlistitem* paramListItem = CTR_PARSER_CREATE_LISTITEM(); ctr_tnode* paramItem = CTR_PARSER_CREATE_NODE(); long l = ctr_clex_tok_value_length(); paramItem->value = ctr_malloc(sizeof(char) * l, 0); memcpy(paramItem->value, ctr_clex_tok_value(), l); paramItem->vlen = l; paramListItem->node = paramItem; if (first) { paramList->nodes = paramListItem; previousListItem = paramListItem; first = 0; } else { previousListItem->next = paramListItem; previousListItem = paramListItem; } t = ctr_clex_tok(); } if (t != CTR_TOKEN_BLOCKPIPE) { printf("Error expected blockpipe."); exit(1); } t = ctr_clex_tok(); first = 1; while((first || t == CTR_TOKEN_DOT)) { ctr_tlistitem* codeListItem; ctr_tnode* codeNode; if (first) { if (ctr_mode_debug) printf("First, so put back\n"); ctr_clex_putback(); } t = ctr_clex_tok(); if (t == CTR_TOKEN_BLOCKCLOSE) break; ctr_clex_putback(); codeListItem = CTR_PARSER_CREATE_LISTITEM(); codeNode = CTR_PARSER_CREATE_NODE(); if (ctr_mode_debug) printf("--------> %d %s \n", t, ctr_clex_tok_value()); if (t == CTR_TOKEN_RET) { codeNode = ctr_cparse_ret(); } else { codeNode = ctr_cparse_expr(0); } codeListItem->node = codeNode; if (first) { codeList->nodes = codeListItem; previousCodeListItem = codeListItem; first = 0; } else { previousCodeListItem->next = codeListItem; previousCodeListItem = codeListItem; } t = ctr_clex_tok(); if (t != CTR_TOKEN_DOT) { printf("Expected . but got: %d.\n", t); exit(1); } } return r; }
/** * CTRParserMessage * * Creates the AST nodes for sending a message. * * - precedence mode 0: no argument (allows processing of unary message, binary message and keyword message) * - precedence mode 1: as argument of keyword message (allows processing of unary message and binary message) * - precedence mode 2: as argument of binary message (only allows processing of unary message) */ ctr_tnode* ctr_cparse_message(int mode) { long msgpartlen; /* length of part of message string */ ctr_tnode* m; int t; char* s; char* msg; ctr_tlistitem* li; ctr_tlistitem* curlistitem; int lookAhead; int isBin; int first; ctr_size ulen; t = ctr_clex_tok(); msgpartlen = ctr_clex_tok_value_length(); if ((msgpartlen) > 255) { printf("Message too long\n"); exit(1); } m = CTR_PARSER_CREATE_NODE(); m->type = -1; s = ctr_clex_tok_value(); msg = ctr_malloc(255*sizeof(char), 0); memcpy(msg, s, msgpartlen); ulen = ctr_getutf8len(msg, msgpartlen); isBin = (ulen == 1); if (mode == 2 && isBin) { ctr_clex_putback(); return m; } if (isBin) { if (ctr_mode_debug) printf("Parsing binary message: '%s' (mode: %d)\n", msg, mode); m->type = CTR_AST_NODE_BINMESSAGE; m->value = msg; m->vlen = msgpartlen; li = CTR_PARSER_CREATE_LISTITEM(); if (ctr_mode_debug) printf("Binary argument start..\n"); li->node = ctr_cparse_expr(2); if (ctr_mode_debug) printf("Binary argument end..\n"); m->nodes = li; return m; } lookAhead = ctr_clex_tok(); ctr_clex_putback(); if (lookAhead == CTR_TOKEN_COLON) { if (mode > 0) { ctr_clex_putback(); if (ctr_mode_debug) printf("> End of argument, next token: %s .\n", msg); return m; } *(msg + msgpartlen) = ':'; msgpartlen += 1; if ((msgpartlen) > 255) { printf("Message too long\n"); exit(1); } if (ctr_mode_debug) printf("Message so far: %s\n", msg); m->type = CTR_AST_NODE_KWMESSAGE; t = ctr_clex_tok(); first = 1; while(1) { li = CTR_PARSER_CREATE_LISTITEM(); if (ctr_mode_debug) printf("Next arg, message so far: %s \n", msg); li->node = ctr_cparse_expr(1); if (ctr_mode_debug) printf("Argument of keyword message has been parsed.\n"); if (first) { m->nodes = li; curlistitem = m->nodes; first = 0; } else { curlistitem->next = li; curlistitem = li; } t = ctr_clex_tok(); if (ctr_mode_debug) printf("Next token after argument = %d \n", t); if (t == CTR_TOKEN_DOT) break; if (t == CTR_TOKEN_FIN) break; if (t == CTR_TOKEN_CHAIN) break; if (t == CTR_TOKEN_PARCLOSE) break; if (t == CTR_TOKEN_REF) { long l = ctr_clex_tok_value_length(); if ((msgpartlen + l) > 255) { printf("Message too long\n"); exit(1); } memcpy( (msg+msgpartlen), ctr_clex_tok_value(), l); msgpartlen = msgpartlen + l; *(msg + msgpartlen) = ':'; msgpartlen ++; t = ctr_clex_tok(); if (t != CTR_TOKEN_COLON) { printf("Expected colon. %s \n",msg); exit(1); } } } if (ctr_mode_debug) printf("Putting back.\n"); ctr_clex_putback(); /* not a colon so put back */ if (ctr_mode_debug) printf("Parsing keyword message: '%s' (mode: %d) \n", msg, mode); m->value = msg; m->vlen = msgpartlen; } else { m->type = CTR_AST_NODE_UNAMESSAGE; m->value = msg; m->vlen = msgpartlen; if (ctr_mode_debug) printf("Parsing unary message: '%s' (mode: %d) token = %d \n", msg, mode, lookAhead); } return m; }