/** * 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; }
/** * 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; }
/** * 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; }
/** * Translates a program from one human language to another. */ void ctr_translate_program(char* prg, char* programPath) { ctr_dict* dictionary; int t; char* p; dictionary = ctr_translate_load_dictionary(); ctr_clex_set_ignore_modes(1); ctr_clex_load(prg); t = ctr_clex_tok(); p = prg; while ( 1 ) { if ( t == CTR_TOKEN_FIN ) { ctr_translate_fin(p); break; } else if ( t == CTR_TOKEN_QUOTE ) { p = ctr_translate_string(p, dictionary); } else if ( t == CTR_TOKEN_REF || t == CTR_TOKEN_BOOLEANYES || t == CTR_TOKEN_BOOLEANNO || t == CTR_TOKEN_NIL ) { p = ctr_translate_ref(p,dictionary); } else { p = ctr_translate_rest(p); } t = ctr_clex_tok(); } ctr_translate_unload_dictionary( dictionary ); }
/** * 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; }
/** * 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; }
/** * CTRParserFin * * Generates a node to represent the end of a program. */ ctr_tnode* ctr_cparse_fin() { ctr_tnode* f; ctr_clex_tok(); f = CTR_PARSER_CREATE_NODE(); f->type = CTR_AST_NODE_ENDOFPROGRAM; return f; }
/** * 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); } }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }
/** * CTRParserNil * * Generates a node to represent Nil */ ctr_tnode* ctr_cparse_nil() { ctr_tnode* r; ctr_clex_tok(); r = CTR_PARSER_CREATE_NODE(); r->type = CTR_AST_NODE_LTRNIL; r->value = "Nil"; r->vlen = 3; return r; }
/** * CTRParserBooleanTrue * * Generates a node to represent a boolean True. */ ctr_tnode* ctr_cparse_true() { ctr_tnode* r; ctr_clex_tok(); r = CTR_PARSER_CREATE_NODE(); r->type = CTR_AST_NODE_LTRBOOLTRUE; ASSIGN_STRING(r, value,"True",4); r->vlen = 4; return r; }
/** * CTRParserBooleanFalse * * Generates a node to represent a boolean False. */ ctr_tnode* ctr_cparse_false() { ctr_tnode* r; ctr_clex_tok(); r = CTR_PARSER_CREATE_NODE(); r->type = CTR_AST_NODE_LTRBOOLFALSE; ASSIGN_STRING(r, value, "False", 5); r->vlen = 5; return r; }
/** * CTRParserPOpen * * Generates a set of nested nodes. */ ctr_tnode* ctr_cparse_popen() { ctr_tnode* r; ctr_tlistitem* li; int t; ctr_clex_tok(); if (ctr_mode_debug) printf("Parsing paren open (.\n"); r = CTR_PARSER_CREATE_NODE(); r->type = CTR_AST_NODE_NESTED; li = CTR_PARSER_CREATE_LISTITEM(); r->nodes = li; li->node = ctr_cparse_expr(0); t = ctr_clex_tok(); if (t != CTR_TOKEN_PARCLOSE) { printf("Error, expected ). \n"); exit(1); } return r; }
/** * CTRParserFin * * Generates a node to represent the end of a program. */ ctr_tnode * ctr_cparse_fin () { ctr_tnode *f; ctr_clex_tok (); f = ctr_cparse_create_node (CTR_AST_NODE); f->type = CTR_AST_NODE_ENDOFPROGRAM; return f; }
/** * CTRParserPOpen * * Generates a set of nested nodes. */ ctr_tnode * ctr_cparse_popen () { ctr_tnode *r; ctr_tlistitem *li; int t; ctr_clex_tok (); r = ctr_cparse_create_node (CTR_AST_NODE); r->type = CTR_AST_NODE_NESTED; li = (ctr_tlistitem *) ctr_heap_allocate_tracked (sizeof (ctr_tlistitem)); r->nodes = li; li->node = ctr_cparse_expr (0); t = ctr_clex_tok (); if (t != CTR_TOKEN_PARCLOSE) { ctr_cparse_emit_error_unexpected (t, "Expected ).\n"); } return r; }
/** * CTRParserNil * * Generates a node to represent Nil */ ctr_tnode * ctr_cparse_nil () { ctr_tnode *r; ctr_clex_tok (); r = ctr_cparse_create_node (CTR_AST_NODE); r->type = CTR_AST_NODE_LTRNIL; r->value = "Nil"; r->vlen = 3; return r; }
/** * CTRParserReturn * * Generates a node to represent a return from a block of code. */ ctr_tnode* ctr_cparse_ret() { ctr_tlistitem* li; ctr_tnode* r; ctr_clex_tok(); r = CTR_PARSER_CREATE_NODE(); r->type = CTR_AST_NODE_RETURNFROMBLOCK; li = CTR_PARSER_CREATE_LISTITEM(); r->nodes = li; li->node = ctr_cparse_expr(0); return r; }
/** * 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; }
/** * CTRParserBooleanTrue * * Generates a node to represent a boolean True. */ ctr_tnode * ctr_cparse_true () { ctr_tnode *r; ctr_clex_tok (); r = ctr_cparse_create_node (CTR_AST_NODE); r->type = CTR_AST_NODE_LTRBOOLTRUE; r->value = ctr_heap_allocate_tracked (sizeof (char) * 4); memcpy (r->value, "True", 4); r->vlen = 4; return r; }
/** * CTRParserBooleanFalse * * Generates a node to represent a boolean False. */ ctr_tnode * ctr_cparse_false () { ctr_tnode *r; ctr_clex_tok (); r = ctr_cparse_create_node (CTR_AST_NODE); r->type = CTR_AST_NODE_LTRBOOLFALSE; r->value = ctr_heap_allocate_tracked (sizeof (char) * 5); memcpy (r->value, "False", 5); r->vlen = 5; return r; }
/** * CTRParserReturn * * Generates a node to represent a return from a block of code. */ ctr_tnode * ctr_cparse_ret () { ctr_tlistitem *li; ctr_tnode *r; ctr_clex_tok (); r = ctr_cparse_create_node (CTR_AST_NODE); r->type = CTR_AST_NODE_RETURNFROMBLOCK; li = (ctr_tlistitem *) ctr_heap_allocate_tracked (sizeof (ctr_tlistitem)); r->nodes = li; li->node = ctr_cparse_expr (0); return r; }
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; }
/** * CTRParserAssignment * * Generates a node to represent an assignment. */ ctr_tnode* ctr_cparse_assignment(ctr_tnode* r) { ctr_tnode* a; ctr_tlistitem* li; ctr_tlistitem* liAssignExpr; ctr_clex_tok(); a = CTR_PARSER_CREATE_NODE(); li = CTR_PARSER_CREATE_LISTITEM(); liAssignExpr = CTR_PARSER_CREATE_LISTITEM(); a->type = CTR_AST_NODE_EXPRASSIGNMENT; a->nodes = li; li->node = r; liAssignExpr->node = ctr_cparse_expr(0); li->next = liAssignExpr; return a; }
/** * 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); }
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; }
/** * CTRParserAssignment * * Generates a node to represent an assignment. */ ctr_tnode * ctr_cparse_assignment (ctr_tnode * r) { ctr_tnode *a; ctr_tlistitem *li; ctr_tlistitem *liAssignExpr; ctr_clex_tok (); a = ctr_cparse_create_node (CTR_AST_NODE); li = (ctr_tlistitem *) ctr_heap_allocate_tracked (sizeof (ctr_tlistitem)); liAssignExpr = (ctr_tlistitem *) ctr_heap_allocate_tracked (sizeof (ctr_tlistitem)); a->type = CTR_AST_NODE_EXPRASSIGNMENT; a->nodes = li; li->node = r; liAssignExpr->node = ctr_cparse_expr (0); li->next = liAssignExpr; return a; }
/** * 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; } }