Exemple #1
0
/**
 * 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;
}
Exemple #2
0
/**
 * 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;
}
Exemple #3
0
/**
 * 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);
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}
Exemple #6
0
/**
 * 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;
}
Exemple #7
0
/**
 * 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;
}
Exemple #8
0
/**
 * 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;
}
Exemple #9
0
/**
 * 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;
}
Exemple #10
0
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;
}
Exemple #11
0
/**
 * 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;
}
Exemple #12
0
/**
 * 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);
}
Exemple #13
0
/**
 * 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;
}
Exemple #14
0
/**
 * 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;
}