/** * CTRParserExpression * * Generates a set of nodes to represent an expression. */ ctr_tnode* ctr_cparse_expr(int mode) { ctr_tnode* r; ctr_tnode* e; int t2; ctr_tlistitem* nodes; ctr_tlistitem* rli; if (ctr_mode_debug) printf("Parsing expression (mode: %d).\n", mode); r = ctr_cparse_receiver(); t2 = ctr_clex_tok(); if (ctr_mode_debug) printf("First token after receiver = %d \n", t2); ctr_clex_putback(); if (r->type == CTR_AST_NODE_REFERENCE && t2 == CTR_TOKEN_ASSIGNMENT) { e = ctr_cparse_assignment(r); } else if (t2 != CTR_TOKEN_DOT && t2 != CTR_TOKEN_PARCLOSE && t2 != CTR_TOKEN_CHAIN) { e = CTR_PARSER_CREATE_NODE(); e->type = CTR_AST_NODE_EXPRMESSAGE; nodes = ctr_cparse_messages(r, mode); if (nodes == NULL) { int t = ctr_clex_tok(); ctr_clex_putback(); if (ctr_mode_debug) printf("No messages, return. Next token: %d.\n", t); return r; /* no messages, then just return receiver (might be in case of argument). */ } rli = CTR_PARSER_CREATE_LISTITEM(); rli->node = r; rli->next = nodes; e->nodes = rli; } else { if (ctr_mode_debug) printf("Returning receiver. \n"); return r; } return e; }
/** * CTRParserMessages * * Manages the creation of nodes to send a message, uses CTRParserMessage * to create the actual nodes. */ ctr_tlistitem * ctr_cparse_messages (ctr_tnode * r, int mode) { int t = ctr_clex_tok (); ctr_tlistitem *pli = NULL; ctr_tlistitem *li = NULL; ctr_tlistitem *fli = NULL; int first = 1; ctr_tnode *node = NULL; /* explicit chaining (,) only allowed for keyword message: Console write: 3 factorial, write: 3 factorial is not possible otherwise. */ while ((t == CTR_TOKEN_REF || (t == CTR_TOKEN_CHAIN && node && node->type == CTR_AST_NODE_KWMESSAGE))) { if (t == CTR_TOKEN_CHAIN) { t = ctr_clex_tok (); if (t != CTR_TOKEN_REF) { ctr_cparse_emit_error_unexpected (t, "Expected message.\n"); } } li = (ctr_tlistitem *) ctr_heap_allocate_tracked (sizeof (ctr_tlistitem)); ctr_clex_putback (); node = ctr_cparse_message (mode); if (node->type == -1) { if (first) { return NULL; } ctr_clex_tok (); break; } li->node = node; if (first) { first = 0; pli = li; fli = li; } else { pli->next = li; pli = li; } t = ctr_clex_tok (); } ctr_clex_putback (); return fli; }
/** * CTRParserStatement * * Generates a set of nodes representing a statement. */ ctr_tlistitem * ctr_cparse_statement () { ctr_tlistitem *li = (ctr_tlistitem *) ctr_heap_allocate_tracked (sizeof (ctr_tlistitem)); int t = ctr_clex_tok (); ctr_clex_putback (); if (t == CTR_TOKEN_FIN) { li->node = ctr_cparse_fin (); return li; } else if (t == CTR_TOKEN_RET) { li->node = ctr_cparse_ret (); } else { li->node = ctr_cparse_expr (0); } t = ctr_clex_tok (); if (t != CTR_TOKEN_DOT) { ctr_cparse_emit_error_unexpected (t, "Expected a dot (.).\n"); li->node = ctr_cparse_fin (); } return li; }
/** * CTRParserReceiver * * Generates a node to represent a receiver (of a message). */ ctr_tnode* ctr_cparse_receiver() { int t; if (ctr_mode_debug) printf("Parsing receiver.\n"); t = ctr_clex_tok(); ctr_clex_putback(); switch(t){ case CTR_TOKEN_NIL: return ctr_cparse_nil(); case CTR_TOKEN_BOOLEANYES: return ctr_cparse_true(); case CTR_TOKEN_BOOLEANNO: return ctr_cparse_false(); case CTR_TOKEN_NUMBER: return ctr_cparse_number(); case CTR_TOKEN_QUOTE: return ctr_cparse_string(); case CTR_TOKEN_REF: return ctr_cparse_ref(); case CTR_TOKEN_BLOCKOPEN: return ctr_cparse_block(); case CTR_TOKEN_PAROPEN: return ctr_cparse_popen(); default: printf("Error, unexpected token: %d.\n", t); exit(1); } }
/** * CTRParserMessages * * Manages the creation of nodes to send a message, uses CTRParserMessage * to create the actual nodes. */ ctr_tlistitem* ctr_cparse_messages(ctr_tnode* r, int mode) { int t = ctr_clex_tok(); ctr_tlistitem* pli; ctr_tlistitem* li; ctr_tlistitem* fli; int first = 1; ctr_tnode* node; if (ctr_mode_debug) printf("Parsing messages.\n"); /* explicit chaining (,) only allowed for keyword message: Console write: 3 factorial, write: 3 factorial is not possible otherwise. */ while ((t == CTR_TOKEN_REF || (t == CTR_TOKEN_CHAIN && node && node->type == CTR_AST_NODE_KWMESSAGE))) { if (t == CTR_TOKEN_CHAIN) { t = ctr_clex_tok(); if (t != CTR_TOKEN_REF) { printf("Expected message.\n"); exit(1); } } li = CTR_PARSER_CREATE_LISTITEM(); if (ctr_mode_debug) printf("Next message...\n"); ctr_clex_putback(); node = ctr_cparse_message(mode); if (node->type == -1) { if (ctr_mode_debug) printf("Ending message sequence.\n"); if (first) { if (ctr_mode_debug) printf("First so return NULL.\n"); return NULL; } ctr_clex_tok(); break; } li->node = node; if (first) { first = 0; pli = li; fli = li; } else { pli->next = li; pli = li; } t = ctr_clex_tok(); if (ctr_mode_debug) printf("Next token in message line is: %d \n",t); } if (ctr_mode_debug) printf("Putting back token... \n"); ctr_clex_putback(); return fli; }
/** * CTRParserReceiver * * Generates a node to represent a receiver (of a message). */ ctr_tnode* ctr_cparse_receiver() { int t; if (ctr_mode_debug) printf("Parsing receiver.\n"); t = ctr_clex_tok(); ctr_clex_putback(); if (t == CTR_TOKEN_NIL) return ctr_cparse_nil(); if (t == CTR_TOKEN_BOOLEANYES) return ctr_cparse_true(); if (t == CTR_TOKEN_BOOLEANNO) return ctr_cparse_false(); if (t == CTR_TOKEN_NUMBER) return ctr_cparse_number(); if (t == CTR_TOKEN_QUOTE) return ctr_cparse_string(); if (t == CTR_TOKEN_REF) return ctr_cparse_ref(); if (t == CTR_TOKEN_BLOCKOPEN) return ctr_cparse_block(); if (t == CTR_TOKEN_PAROPEN) return ctr_cparse_popen(); printf("Error, unexpected token: %d.\n", t); exit(1); }
/** * CTRParserStatement * * Generates a set of nodes representing a statement. */ ctr_tlistitem* ctr_cparse_statement() { ctr_tlistitem* li = CTR_PARSER_CREATE_LISTITEM(); int t = ctr_clex_tok(); if (ctr_mode_debug) printf("Parsing next statement of program, token = %d (%s).\n", t, ctr_clex_tok_value()); ctr_clex_putback(); if (t == CTR_TOKEN_FIN) { li->node = ctr_cparse_fin(); return li; } else if (t == CTR_TOKEN_RET) { li->node = ctr_cparse_ret(); } else { li->node = ctr_cparse_expr(0); } t = ctr_clex_tok(); if (t != CTR_TOKEN_DOT) { printf("Expected . but got: %d.\n", t); exit(1); } return li; }
/** * CTRParserReceiver * * Generates a node to represent a receiver (of a message). */ ctr_tnode * ctr_cparse_receiver () { int t; t = ctr_clex_tok (); ctr_clex_putback (); switch (t) { case CTR_TOKEN_NIL: return ctr_cparse_nil (); case CTR_TOKEN_BOOLEANYES: return ctr_cparse_true (); case CTR_TOKEN_BOOLEANNO: return ctr_cparse_false (); case CTR_TOKEN_NUMBER: return ctr_cparse_number (); case CTR_TOKEN_QUOTE: return ctr_cparse_string (); case CTR_TOKEN_REF: return ctr_cparse_ref (); case CTR_TOKEN_BLOCKOPEN: return ctr_cparse_block (); case CTR_TOKEN_BLOCKOPEN_MAP: { ctr_tnode *t = ctr_cparse_block_capture (); t->lexical = 1; t->nodes->next->node->lexical = 1; return t; } case CTR_TOKEN_PAROPEN: return ctr_cparse_popen (); case CTR_TOKEN_TUPOPEN: return ctr_cparse_tuple (); case CTR_TOKEN_SYMBOL: return ctr_cparse_symbol (); default: /* This function always exits, so return a dummy value. */ ctr_cparse_emit_error_unexpected (t, "Expected a message recipient.\n"); return NULL; } }
ctr_tnode * ctr_cparse_expr (int mode) { ctr_tnode *r; ctr_tnode *e; int t2; ctr_tlistitem *nodes; ctr_tlistitem *rli; struct lexer_state lexer_state; ctr_clex_dump_state (&lexer_state); r = ctr_cparse_receiver (); t2 = ctr_clex_tok (); ctr_clex_putback (); /* user tries to put colon directly after recipient */ if (t2 == CTR_TOKEN_COLON) { /* Parse as if we had a "me" before this */ ctr_clex_load_state (lexer_state); if (ctr_clex_inject_token (CTR_TOKEN_REF, me_s, 2)) ctr_cparse_emit_error_unexpected (t2, "Recipient cannot be followed by a colon in this state.\n"); return ctr_cparse_expr (mode); } if (t2 == CTR_TOKEN_ASSIGNMENT) { // if ( r->type != CTR_AST_NODE_REFERENCE ) { // ctr_cparse_emit_error_unexpected( t2, "Invalid left-hand assignment.\n" ); // exit(1); // } e = ctr_cparse_assignment (r); } else if (t2 == CTR_TOKEN_PASSIGNMENT) { if (r->type != CTR_AST_NODE_REFERENCE) { ctr_cparse_emit_error_unexpected (t2, "Invalid left-hand assignment.\n"); exit (1); } r->modifier = 1; //set private */ e = ctr_cparse_assignment (r); //go as usual /*r->nodes->node->type = CTR_AST_NODE_LTRSTRING; e = ctr_cparse_create_node(CTR_AST_NODE); e->type = CTR_AST_NODE_EXPRMESSAGE; e->nodes = ctr_heap_allocate(sizeof(ctr_tlistitem)); e->nodes->node = ctr_cparse_create_node(CTR_AST_NODE); e->nodes->node->value = ctr_heap_allocate(sizeof(char)*7); //Reflect memcpy(e->nodes->node->value, "Reflect", 7); e->nodes->node->vlen = 7; e->nodes->node->type = CTR_AST_NODE_REFERENCE; e->nodes->next = ctr_heap_allocate(sizeof(ctr_tlistitem)); e->nodes->next->node = ctr_cparse_create_node(CTR_AST_NODE); e->nodes->next->node->type = CTR_AST_NODE_KWMESSAGE; e->nodes->next->node->value = ctr_heap_allocate(sizeof(char)*7); //set:to: memcpy(e->nodes->next->node->value, "set:to:", 7); e->nodes->next->node->vlen = 7; e->nodes->next->node->nodes = ctr_heap_allocate(sizeof(ctr_tlistitem)); e->nodes->next->node->nodes->node = r->nodes->node; e->nodes->next->node->nodes->next = ctr_heap_allocate(sizeof(ctr_tlistitem)); e->nodes->next->node->nodes->next->node = r->nodes->next->node; */ } else if (t2 != CTR_TOKEN_DOT && t2 != CTR_TOKEN_PARCLOSE && (t2 != CTR_TOKEN_CHAIN && mode != CTR_AST_NODE_IMMUTABLE)) { e = ctr_cparse_create_node (CTR_AST_NODE); e->type = CTR_AST_NODE_EXPRMESSAGE; nodes = ctr_cparse_messages (r, mode == CTR_AST_NODE_IMMUTABLE ? 0 : mode); if (nodes == NULL) { ctr_clex_tok (); ctr_clex_putback (); return r; /* no messages, then just return receiver (might be in case of argument). */ } rli = (ctr_tlistitem *) ctr_heap_allocate_tracked (sizeof (ctr_tlistitem)); rli->node = r; rli->next = nodes; e->nodes = rli; } else { return r; } 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; }
/** * CTRParserTuple * * Generates a node to represent an immutable array (tuple) */ ctr_tnode * ctr_cparse_tuple () { ctr_tnode *r; ctr_tlistitem *codeBlockPart1; ctr_tnode *paramList; ctr_tlistitem *previousListItem; int t; ctr_clex_tok (); //eat the [ r = ctr_cparse_create_node (CTR_AST_NODE); r->type = CTR_AST_NODE_IMMUTABLE; codeBlockPart1 = (ctr_tlistitem *) ctr_heap_allocate_tracked (sizeof (ctr_tlistitem)); r->nodes = codeBlockPart1; paramList = ctr_cparse_create_node (CTR_AST_NODE); codeBlockPart1->node = paramList; paramList->type = CTR_AST_NODE_NESTED; t = ctr_clex_tok (); ctr_clex_putback (); if (t == CTR_TOKEN_TUPCLOSE) { ctr_clex_tok (); //eat the ending ] return r; } ctr_tlistitem *paramListItem = (ctr_tlistitem *) ctr_heap_allocate_tracked (sizeof (ctr_tlistitem)); paramList->nodes = paramListItem; paramListItem->node = ctr_cparse_expr (0); previousListItem = paramListItem; int restore_id = ctr_clex_save_state (); //save lexer state if (restore_id == -1) { ctr_cparse_emit_error_unexpected (0, "Lexer stack overflow"); return NULL; } //try for a list comprehension: expect ,, t = ctr_clex_tok (); if (t != CTR_TOKEN_CHAIN && t != CTR_TOKEN_TUPCLOSE) { //common element ctr_cparse_emit_error_unexpected (t, "Expected a ',' or a ']'"); return r; } if (t == CTR_TOKEN_TUPCLOSE) { return r; } t = ctr_clex_tok (); if (t == CTR_TOKEN_CHAIN) { //list comp return ctr_cparse_list_comp (r->nodes->node); } ctr_clex_restore_state (restore_id); //restore before checking for listcomp while ((t = ctr_clex_tok ()) == CTR_TOKEN_CHAIN) { /* okay we have new parameter, load it */ ctr_tlistitem *paramListItem = (ctr_tlistitem *) ctr_heap_allocate_tracked (sizeof (ctr_tlistitem)); paramListItem->node = ctr_cparse_expr (0); previousListItem->next = paramListItem; previousListItem = paramListItem; } if (t != CTR_TOKEN_TUPCLOSE) ctr_cparse_emit_error_unexpected (t, "Expected ]."); return r; }
/** * CTRParserListComp * * generates a node to represent a list comprehension * * @param ctr_tnode * main_expr -- the main expression of the comprehension * Lexer state at this point: * [ expression ,, expression* ,, expression* ] * ^ */ ctr_tnode * ctr_cparse_list_comp (ctr_tnode * main_expr) { ctr_tnode *r; ctr_tlistitem *part0, *part1, *part2, *prev; int t; r = ctr_cparse_create_node (CTR_AST_NODE); r->type = CTR_AST_NODE_LISTCOMP; part0 = ctr_heap_allocate_tracked (sizeof (ctr_tlistitem)); part1 = ctr_heap_allocate_tracked (sizeof (ctr_tlistitem)); part2 = ctr_heap_allocate_tracked (sizeof (ctr_tlistitem)); /* r |_ part0 -- main expression |_ part1 -- generator | |_ gen0 | |_ gen1, etc |_ part2 -- predicate |_ p0 |_ p1, etc */ r->nodes = part0; part0->next = part1; part1->next = part2; part0->node = main_expr; //save main expression t = ctr_clex_tok (); ctr_clex_putback (); //[ expression ,,, predicate* ] (skipped generators) // ^ if (t == CTR_TOKEN_CHAIN) { ctr_clex_tok (); //eat the ',' part1->node = NULL; goto parse_predicates; } //[ expression ,, expression* (,,)? expression* ] // ^ //parse a series of expressions, separated by CHAIN, put into part1 ctr_tnode *gen = ctr_heap_allocate_tracked (sizeof (*gen)); gen->nodes = ctr_heap_allocate_tracked (sizeof (*part1)); part1->node = gen; part1 = gen->nodes; part1->node = ctr_cparse_expr (0); while ((t = ctr_clex_tok ()) == CTR_TOKEN_CHAIN) { if (ctr_clex_tok () == CTR_TOKEN_CHAIN) { ctr_clex_tok (); break; //we're going into the predicates now } ctr_clex_putback (); part1->next = ctr_heap_allocate_tracked (sizeof (*part1)); part1 = part1->next; part1->node = ctr_cparse_expr (0); } ctr_clex_putback (); parse_predicates:; t = ctr_clex_tok (); ctr_clex_putback (); // [ expression ,, expression* ,, ] // ^ if (t == CTR_TOKEN_TUPCLOSE) //no predicates, so a length-one tuple if it has no gens { ctr_clex_tok (); //eat the ']' // printf("%s\n", ctr_code); if (r->nodes->next->node == NULL) { //didn't have generators //replace with a tuple and move on r->type = CTR_AST_NODE_IMMUTABLE; r->nodes->next = NULL; } else { r->nodes->next->next->node = NULL; } return r; } // [ expression ,, expression* ,, expression+ ] // ^ //parse a series of expressions, separated by CHAIN, put into part2 ctr_tnode *pred = ctr_heap_allocate_tracked (sizeof (*pred)); pred->nodes = ctr_heap_allocate_tracked (sizeof (*part2)); part2->node = pred; part2 = pred->nodes; part2->node = ctr_cparse_expr (0); while ((t = ctr_clex_tok ()) == CTR_TOKEN_CHAIN) { part2->next = ctr_heap_allocate_tracked (sizeof (*part1)); part2 = part2->next; part2->node = ctr_cparse_expr (0); } if (t != CTR_TOKEN_TUPCLOSE) { //bitch about it ctr_cparse_emit_error_unexpected (t, "Expected a ']'"); } 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; }
/** * 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; }