Beispiel #1
0
static struct ast_node*
access_node(char *name)
{
	struct ast_node_stub *stub_node;
	struct ast_node_access *ac_node;
	struct ast_node *idx;
	struct symbol *sym;

	sym = symbol_table_lookup_all(name);
	
	if (sym == NULL) {
		error_msg("error: no such symbol");
		sync_stream();
		stub_node = ast_node_stub();
		return AST_NODE(stub_node);
	}
	/* `[' */
	consume_token();
	
	ac_node = ast_node_access(sym->v_type, sym->name);

	do {
		idx = or_expr();
			
		if (idx == NULL) {	
			error_msg("error: empty index");
			sync_stream();
			goto ac_error;
		}
		
		ast_node_access_add(ac_node, idx);

		if (current_token != TOKEN_RBRACKET) {
			error_msg("error: missed `]'");	
			sync_stream();
			goto ac_error;
		}
		/* `]' */
		consume_token();

	} while (match(TOKEN_LBRACKET));

	return AST_NODE(ac_node);

ac_error:
	ast_node_unref(AST_NODE(ac_node));
	stub_node = ast_node_stub();

	return AST_NODE(stub_node);		
}
/**
 * Print a string constant or a variable value (no newline).
 * PUT <expression>
 */
void cmd_put(char *args) {
  int number_value;
  char *string_value;
  unsigned char token;
  while (! error) {
    token = next_token(args);
    if (token == TOKEN_STRING || token == TOKEN_VAR_STRING) {
      if (args = parse_string_expression(args, &string_value)) {
        lcd_puts(string_value);
      }
    } else if (token == TOKEN_DIGITS || token == TOKEN_PLUS || token == TOKEN_MINUS ||
               token == TOKEN_VAR_NUMBER) {
      if (args = parse_number_expression(args, &number_value)) {
        sprintf(print_buffer, "%d", number_value);
        lcd_puts(print_buffer);
      }
    } else if (token == TOKEN_COMMA) {
      args = consume_token(args, token);
    } else if (token == TOKEN_END) {
      return;
    } else {
      syntax_error();
      return;
    }
  }
}
Beispiel #3
0
static struct ast_node*
rest_or(struct ast_node *node)
{
	struct ast_node *ret_node;	
	struct ast_node *left;
	struct ast_node *right;

	ret_node = node;
	
	while (TRUE) {
		switch(current_token) {
		case TOKEN_OR :
			consume_token();

			left  = ret_node;
			right = and_expr();
			
			if (right == NULL) {
				error_msg("error: expression expected after ||");	
				right = (struct ast_node *)ast_node_stub();
				sync_stream();
			}
			ret_node = (struct ast_node *)ast_node_logic_op(OPCODE_OR, left, right);
			continue;
		default:
			goto exit_or;
		}
	}

exit_or:	
	return ret_node;
}
Beispiel #4
0
static struct ast_node*
rest_and(struct ast_node *node)
{
	struct ast_node *ret_node;
	struct ast_node *left;
	struct ast_node *right;

	ret_node = node;
	
	while (TRUE) {
		switch (current_token) {
		case TOKEN_AND:
			consume_token();

			left  = ret_node;
			right = rel_expr();

			if (right == NULL) {
				error_msg("error: missed expression");
				right = (struct ast_node *)ast_node_stub();
				sync_stream();
			}	
			ret_node = (struct ast_node *)ast_node_logic_op(OPCODE_AND, left, right);
			continue;
		default:
			goto exit_and;
		}
	}

exit_and:
	return ret_node;
}
Beispiel #5
0
// Consume an expected semicolon, complaining if one was not found.
void gobble_semicolon(std::vector<unique_ptr<Token>>::iterator* it, bool* ok) {
  *ok = consume_token(it, token::semiColon);
  if (!*ok) {
    cerr << "Expecting a semicolon but found " << (**it)->show() << " at line "
         << (**it)->line << std::endl;
    return;
  }
}
/**
 * Conditional execution of a command.
 * IF <condition> THEN <command>
 */
void cmd_if(char *args) {
  int condition;
  if (args = parse_number_expression(args, &condition)) {
    if (condition) {
      if (args = consume_token(args, TOKEN_THEN)) {
        execute(args);
      }
    }
  }
}
Beispiel #7
0
static void
process_args(char *name)
{
	struct function *func;
	struct symbol *arg;

	/*(*/
	consume_token();

	func = function_table_lookup(name);

	/* Delete an old function and make a new one */
	if (func != NULL) 
		function_table_delete_function(name);	

	func = function_new(name);
	
	while (!match(TOKEN_RPARENTH)) {
		if (match(TOKEN_EOL)) {
			error_msg("error: new line in function definition");
			return;	
		}
		
		if (!match(TOKEN_ID)) {
			error_msg("error: unexpected symbol in definition");
			sync_stream();
			ufree(func);
			return;
		}
	
		arg = symbol_new(lex_prev.id, VALUE_TYPE_UNKNOWN);
		
		function_add_arg(func, arg);
		
		if (current_token != TOKEN_RPARENTH && !match(TOKEN_COMMA)) {
			error_msg("error: comma expected");
			sync_stream();
			return;
		}			
	}

	switch(current_token) {
	case TOKEN_LBRACE:
		function_table_insert(func);
		process_function_body(name);
		break;
	default:
		error_msg("error: `{' expected");
		sync_stream();
		break;
	}	
}
/**
 * Set the cursor to a specific screen position.
 * AT <x>,<y>
 */
void cmd_at(char *args) {
  int x;
  int y;
  unsigned char token;

  args = parse_number_expression(args, &x);
  if (!args || x < 0 || x > 39) {
    syntax_error_invalid_argument();
    return;
  }

  args = consume_token(args, TOKEN_COMMA);
  if (! args) {
    return;
  }

  args = parse_number_expression(args, &y);
  if (!args || y < 0 || y > 3) {
    syntax_error_invalid_argument();
    return;
  }

  if (next_token(args) == TOKEN_COMMA) {
    args = consume_token(args, TOKEN_COMMA);
    if ((token = next_token(args)) == TOKEN_VAR_STRING) {
      unsigned int var_name;
      unsigned char var_type;
      if (args = parse_variable(args, &var_name, &var_type)) {
        char c = lcd_getc(x, y);
        sprintf (print_buffer, "%c", c);
        create_variable(var_name, VAR_TYPE_STRING, print_buffer);
      }
    } else {
      syntax_error_invalid_token(token);
    }
  } else {
    lcd_goto(x, y);
  }
}
Beispiel #9
0
int
programme(struct ast_node **root, int *eof)
{
	struct ast_node *tree;
	
	errors = 0;
	
	consume_token();

	tree  = stmts(NULL);
	*root = (struct ast_node *)ast_node_root(tree);
	
	check_eof(eof);

	return errors;
}
Beispiel #10
0
static struct ast_node*
rel_expr(void)
{
	struct ast_node *left;
	struct ast_node *right;
	struct ast_node_op *op_node;
	opcode_type_t opcode;

	left = sum_expr();

	if (left == NULL)
		return NULL;

	switch(current_token) {
	case TOKEN_EQ:
		consume_token();
		opcode = OPCODE_EQ;
		break;	
	case TOKEN_LT:
		consume_token();
		opcode = OPCODE_LT;
		break; 
	case TOKEN_GT:
		consume_token();
		opcode = OPCODE_GT;
		break;
	case TOKEN_LE:
		consume_token();
		opcode = OPCODE_LE;
		break;
	case TOKEN_GE:
		consume_token();
		opcode = OPCODE_GE;
		break;
	case TOKEN_NE:
		consume_token();
		opcode = OPCODE_NE;
		break;
	default:
		return left;
	}
	
	right = sum_expr();

	if (right == NULL) {
		error_msg("error: expression expected");
		right = (struct ast_node *)ast_node_stub();
		sync_stream();
	}
		
	op_node = ast_node_rel_op(opcode, left, right);
	
	return AST_NODE(op_node);		
}
/**
 * Assign a value to a variable or delete the variable if no assignment is given.
 * List all variables if no arguments are given.
 */
void cmd_let(char *args) {
  unsigned char token;
  unsigned int var_name;
  unsigned char var_type;

  skip_whitespace(args);

  if (*args == '\0') {
    print_all_variables();
    print_ready();
    return;
  }

  if (args = parse_variable(args, &var_name, &var_type)) {
    if (next_token(args) == TOKEN_ASSIGN) {
      token = next_token(args);
      args = consume_token(args, token);
      switch (var_type) {
        case VAR_TYPE_INTEGER: {
          int value;
          if (parse_number_expression(args, &value)) {
            create_variable(var_name, var_type, &value);
          }
          break;
        }
        case VAR_TYPE_STRING: {
          char *value;
          if (parse_string_expression(args, &value)) {
            create_variable(var_name, var_type, value);
          }
          break;
        }
      }
    } else {
      if (*args == '\0') {
        delete_variable(var_name, var_type);
      }
    }
  } else {
    syntax_error();
  }
}
Beispiel #12
0
static struct ast_node*
stmts(void *opaque)
{
	struct ast_node *ret_node;
	struct ast_node *stmt_head;
	struct ast_node *prev_node;

	stmt_head = NULL;
	prev_node = NULL;

	while (current_token != TOKEN_EOF) {	
		if (opaque != NULL && current_token == TOKEN_EOL)
			consume_token();

		if (opaque == NULL && current_token == TOKEN_EOL)
			break;

		ret_node = stmt(opaque);

		if (errors)
			break;
	
		if (ret_node == NULL)
			continue;

		if (stmt_head == NULL)
			stmt_head = ret_node;

		if (prev_node != NULL) {
			prev_node->next  = ret_node;
			ret_node->parent = prev_node;
		}

		prev_node = ret_node;
		
		if (ret_node->type == NODE_TYPE_END_SCOPE) 
			break;			
	}

	return  stmt_head;
}
Beispiel #13
0
static struct ast_node*
rest_mult(struct ast_node *node)
{
	struct ast_node *expr_node;
	struct ast_node *prev_node;
	struct ast_node *ret_node;
	char op;

	prev_node = node;
	
	while (TRUE) {
		switch(current_token) {	
		case TOKEN_ASTERIK:
			op = '*';
			break;
		case TOKEN_SLASH:
			op = '/';
			break;
		default:
			goto exit_mult;
		}

		consume_token();
		expr_node = exp_expr();

		if (expr_node == NULL) {
			error_msg("error: syntax error");
			expr_node = (struct ast_node *)ast_node_stub();
		}
	
		prev_node = (struct ast_node *)ast_node_op(op, prev_node, expr_node);
	}

exit_mult:	
	ret_node = prev_node;
	return ret_node;
	
}
/**
 * Input a variable from the keyboard.
 * INPUT <variable> [ONERROR <command]
 */
void cmd_input(char *args) {
  unsigned int var_name;
  unsigned char var_type;

  args = parse_variable(args, &var_name, &var_type);
  if (args) {
    if (var_type == VAR_TYPE_STRING) {
      char *line = readline(INTERRUPTIBLE);
      create_variable(var_name, var_type, line);
    } else if (var_type == VAR_TYPE_INTEGER) {
      for (;;) {
        int value = 0;
        char *line = readline(INTERRUPTIBLE);
        if (is_interrupted()) {
          break;
        }
        if (parse_integer(line, &value)) {
          create_variable(var_name, var_type, &value);
          break;
        } else {
          if (next_token(args) == TOKEN_ONERROR) {
            args = consume_token(args, TOKEN_ONERROR);
            execute(args);
            break;
          } else {
            syntax_error_invalid_number();
            lcd_puts("Enter again: ");
          }
        }
      }
    } else {
      syntax_error_invalid_argument();
    }
  } else {
    syntax_error_invalid_argument();
  }
}
Beispiel #15
0
static struct ast_node*
rest_sum(struct ast_node *node)
{
	struct ast_node *prev_node;
	struct ast_node *ret_node;
	struct ast_node *mult_node;
	char op;
	
	prev_node = node;
	
	while (TRUE) {
		switch(current_token) {
		case TOKEN_PLUS:
			op = '+';
			break;
		case TOKEN_MINUS:
			op = '-';
			break;
		default:
			goto exit_sum;
		}

		consume_token();
		mult_node = mult_expr();
		
		if (mult_node == NULL) {
			error_msg("error: syntax error");
			mult_node = (struct ast_node *)ast_node_stub();
		}
		
		prev_node = (struct ast_node *)ast_node_op(op, prev_node, mult_node);	
	}

exit_sum:
	ret_node = prev_node;
	return ret_node;
}
Beispiel #16
0
static void
process_function_body(char *name)
{
	struct scope_ctx helper;
	struct ast_node *body;
	struct function *func_ctx;
	struct symbol_table *scope;
	int i;

	consume_token();
	
	func_ctx = function_table_lookup(name);

	symbol_table_push();
	/* insert arguments in function scope */	
	for (i = 0; i < func_ctx->nargs; i++)
		symbol_table_put_symbol(func_ctx->args[i]);
	
	
	memset(&helper, 0, sizeof(helper));
	
	helper.is_func = 1;
	
	body  = stmts(&helper);
	
	scope = symbol_table_get_current_table();
	
	func_ctx->body  = body;		
	func_ctx->scope = scope;
	
	symbol_table_pop();	

	if(errors) {
		error_msg("->redefine your function");
		function_table_delete_function(name);
	}	
}
Beispiel #17
0
static struct ast_node*
rest_exp(struct ast_node *node)
{
	struct ast_node *expr_node;
	struct ast_node *prev_node;
	struct ast_node *ret_node;
	char op;

	prev_node = node;

	while(TRUE) {
		switch(current_token) {
		case TOKEN_CARET:
			op = '^';
			break;
		default:
			goto exit_exp;			
		}

		consume_token();
		expr_node = term_expr();
	
		if (expr_node == NULL) {
			error_msg("error: syntax error");
			expr_node = (struct ast_node *)ast_node_stub();
			sync_stream();
			goto exit_exp;
		}
	
		prev_node = (struct ast_node *)ast_node_op(op, prev_node, expr_node);
	}
	
exit_exp:
	ret_node = prev_node;
	return ret_node;	
}
Beispiel #18
0
static struct ast_node*
expr(void)
{
	struct ast_node *lvalue;
	struct ast_node *rvalue;
	struct ast_node_assign *assign;

	lvalue = or_expr();
	
	if (current_token != TOKEN_EQUALITY)
		return lvalue;	
	/* `=' */
	consume_token();
	
	switch(lvalue->type) {
	case NODE_TYPE_ID:
	case NODE_TYPE_ACCESS:
		break;
	default:	
		error_msg("error: rvalue assignmet");
		sync_stream();
		return lvalue;
	}
	
	rvalue = or_expr();

	if (!rvalue) {
		error_msg("error: expression expected `='");
		sync_stream();
		rvalue = (struct ast_node *)ast_node_stub();
	}
	
	assign = ast_node_assign(lvalue, rvalue);

	return AST_NODE(assign);
}
/**
 * Parse a number expression 's' (that contains only number values) and return its
 * resulting value in 'value'.
 * Return a pointer behind the last character of the expression.
 * Return NULL if a syntax error occurred.
 */
char *parse_number_expression(char *s, int *value) {
  unsigned char token = next_token(s);

  if (token == TOKEN_DIGITS || token == TOKEN_PLUS || token == TOKEN_MINUS ||
      token == TOKEN_VAR_NUMBER) {
    int operand;
    if (s = parse_number_term(s, value)) {
      for (;;) {
        token = next_token(s);
        switch (token) {
          case TOKEN_PLUS:
          case TOKEN_MINUS:
          case TOKEN_MUL:
          case TOKEN_DIV:
          case TOKEN_MOD:
          case TOKEN_EQUAL:
          case TOKEN_LESS:
          case TOKEN_LESSEQUAL:
          case TOKEN_GREATER:
          case TOKEN_GREATEREQUAL:
            s = consume_token(s, token);
            if (s = parse_number_term(s, &operand)) {
              switch (token) {
                case TOKEN_PLUS:
                  *value += operand;
                  break;
                case TOKEN_MINUS:
                  *value -= operand;
                  break;
                case TOKEN_MUL:
                  *value *= operand;
                  break;
                case TOKEN_DIV:
                  *value /= operand;
                  break;
                case TOKEN_MOD:
                  *value %= operand;
                  break;
                case TOKEN_EQUAL:
                  *value = *value == operand;
                  break;
                case TOKEN_NOTEQUAL:
                  *value = *value != operand;
                  break;
                case TOKEN_LESS:
                  *value = *value < operand;
                  break;
                case TOKEN_LESSEQUAL:
                  *value = *value <= operand;
                  break;
                case TOKEN_GREATER:
                  *value = *value > operand;
                  break;
                case TOKEN_GREATEREQUAL:
                  *value = *value >= operand;
                  break;
              }
            }
            break;
          default:
            return s;
        }
      }
      return s;
    }
  } else if (token == TOKEN_STRING || token == TOKEN_VAR_STRING) {
    char *string;
    if (s = parse_string_expression(s, &string)) {
      token = next_token(s);
      if (token == TOKEN_EQUAL || token == TOKEN_NOTEQUAL ||
          token == TOKEN_LESS || token == TOKEN_LESSEQUAL ||
          token == TOKEN_GREATER || token == TOKEN_GREATEREQUAL) {
        s = consume_token(s, token);
        strcpy(tmpbuf, string);
        if (s = parse_string_expression(s, &string)) {
          switch (token) {
            case TOKEN_EQUAL:
              *value = strcmp(tmpbuf, string) == 0;
              break;
            case TOKEN_NOTEQUAL:
              *value = strcmp(tmpbuf, string) != 0;
              break;
            case TOKEN_LESS:
              *value = strcmp(tmpbuf, string) < 0;
              break;
            case TOKEN_LESSEQUAL:
              *value = strcmp(tmpbuf, string) <= 0;
              break;
            case TOKEN_GREATER:
              *value = strcmp(tmpbuf, string) > 0;
              break;
            case TOKEN_GREATEREQUAL:
              *value = strcmp(tmpbuf, string) >= 0;
              break;
          }
          return s;
        }
      } else {
        syntax_error_invalid_token(token);
      }
    }
  }
  return NULL;
}
Beispiel #20
0
int
yylex(void)
{
	int		c;

	while ((c = scanc()) != EOF) {

		/* special handling for quoted string */
		if (instring) {
			if (escaped) {
				escaped = 0;

				/* if newline, just eat and forget it */
				if (c == '\n')
					continue;

				if (strchr("xXd01234567", c)) {
					unscanc(c);
					unscanc(esc_char);
					return (get_wide());
				}
				yylval.wc = get_escaped(c);
				return (T_CHAR);
			}
			if (c == esc_char) {
				escaped = 1;
				continue;
			}
			switch (c) {
			case '<':
				return (get_symbol());
			case '>':
				/* oops! should generate syntax error  */
				return (T_GT);
			case '"':
				instring = 0;
				return (T_QUOTE);
			default:
				yylval.wc = c;
				return (T_CHAR);
			}
		}

		/* escaped characters first */
		if (escaped) {
			escaped = 0;
			if (c == '\n') {
				/* eat the newline */
				continue;
			}
			hadtok = 1;
			if (tokidx) {
				/* an escape mid-token is nonsense */
				return (T_NULL);
			}

			/* numeric escapes are treated as wide characters */
			if (strchr("xXd01234567", c)) {
				unscanc(c);
				unscanc(esc_char);
				return (get_wide());
			}

			add_tok(get_escaped(c));
			continue;
		}

		/* if it is the escape charter itself note it */
		if (c == esc_char) {
			escaped = 1;
			continue;
		}

		/* remove from the comment char to end of line */
		if (c == com_char) {
			while (c != '\n') {
				if ((c = scanc()) == EOF) {
					/* end of file without newline! */
					return (EOF);
				}
			}
			assert(c == '\n');
			if (!hadtok) {
				/*
				 * If there were no tokens on this line,
				 * then just pretend it didn't exist at all.
				 */
				continue;
			}
			hadtok = 0;
			return (T_NL);
		}

		if (strchr(" \t\n;()<>,\"", c) && (tokidx != 0)) {
			/*
			 * These are all token delimiters.  If there
			 * is a token already in progress, we need to
			 * process it.
			 */
			unscanc(c);
			return (consume_token());
		}

		switch (c) {
		case '\n':
			if (!hadtok) {
				/*
				 * If the line was completely devoid of tokens,
				 * then just ignore it.
				 */
				continue;
			}
			/* we're starting a new line, reset the token state */
			hadtok = 0;
			return (T_NL);
		case ',':
			hadtok = 1;
			return (T_COMMA);
		case ';':
			hadtok = 1;
			return (T_SEMI);
		case '(':
			hadtok = 1;
			return (T_LPAREN);
		case ')':
			hadtok = 1;
			return (T_RPAREN);
		case '>':
			hadtok = 1;
			return (T_GT);
		case '<':
			/* symbol start! */
			hadtok = 1;
			return (get_symbol());
		case ' ':
		case '\t':
			/* whitespace, just ignore it */
			continue;
		case '"':
			hadtok = 1;
			instring = 1;
			return (T_QUOTE);
		default:
			hadtok = 1;
			add_tok(c);
			continue;
		}
	}
	return (EOF);
}
Beispiel #21
0
static struct ast_node*
process_matrix(void)
{	
	struct ast_node_stub *stub_node;
	struct ast_node **elem;
	struct ast_node *node;	
	int row, col, len;
	int prev_col;
	int i;

	elem = NULL;
	node = NULL;

	row = col = 1;
	len = prev_col = 0;

	while (TRUE) {
		node = or_expr();

		if (node == NULL) {
			error_msg("expr expected");
			sync_stream();
			goto err;
		}		
		
		elem = urealloc(elem, ++len*sizeof(struct ast_node *));
		elem[len - 1] = node;

		switch(current_token) {
		case TOKEN_COMMA:
			consume_token();
			col++;
			continue;
		case TOKEN_SEMICOLON:
			consume_token();
			if (prev_col == 0)
				prev_col = col;
			else if (prev_col != col) {
				error_msg("incompatible column count");
				sync_stream();
				goto err;
			}
			col = 1;
			row++;
			continue;
		case TOKEN_RBRACKET:
			consume_token();
			break;
		default:
			error_msg("syntax error");
			sync_stream();
			goto err;
		} 
		break;							
	}

	if (row == 1 || col == 1)
		node = (struct ast_node *)ast_node_vector(elem, len);
	else
		node = (struct ast_node *) ast_node_matrix(elem, row, col);

	return node;

err:
	if (node != NULL)
		ast_node_unref(node);
	
	if (elem != NULL) 
		for (i = 0; i < len; i++)
			ast_node_unref(elem[i]);

	stub_node = ast_node_stub();

	return AST_NODE(stub_node);	
}
Beispiel #22
0
/* Check if current token matches any in given set and consume on match.
 * Args:
 *    terminating is the description of the structure this token terminates,
 *      NULL for none. Used only for error messages.
 *    id_set is a TK_NONE terminated list.
 *    make_ast specifies whether to construct an AST node on match or discard
 *      consumed token.
 *    out_found reports whether an optional token was found. Only set on
 *      success. May be set to NULL if this information is not needed.
 *
 * Returns:
 *    PARSE_OK on success.
 *    PARSE_ERROR to propogate a lexer error.
 *    RULE_NOT_FOUND if current token is not is specified set.
 *    NULL to propogate a restarted error.
 */
ast_t* parse_token_set(parser_t* parser, rule_state_t* state, const char* desc,
  const char* terminating, const token_id* id_set, bool make_ast,
  bool* out_found)
{
  assert(parser != NULL);
  assert(state != NULL);
  assert(id_set != NULL);

  token_id id = current_token_id(parser);

  if(id == TK_LEX_ERROR)
    return propogate_error(parser, state);

  if(desc == NULL)
    desc = token_id_desc(id_set[0]);

  if(trace_enable)
  {
    printf("Rule %s: Looking for %s token%s %s. Found %s. ",
      state->fn_name,
      (state->deflt_id == TK_LEX_ERROR) ? "required" : "optional",
      (id_set[1] == TK_NONE) ? "" : "s", desc,
      token_print(parser->token));
  }

  for(const token_id* p = id_set; *p != TK_NONE; p++)
  {
    // Match new line if the next token is the first on a line
    if(*p == TK_NEWLINE)
    {
      assert(parser->token != NULL);
      size_t last_token_line = parser->last_token_line;
      size_t next_token_line = token_line_number(parser->token);
      bool is_newline = (next_token_line != last_token_line);

      if(out_found != NULL)
        *out_found = is_newline;

      if(trace_enable)
        printf("\\n %smatched\n", is_newline ? "" : "not ");

      state->deflt_id = TK_LEX_ERROR;
      return PARSE_OK;
    }

    if(id == *p)
    {
      // Current token matches one in set
      if(trace_enable)
        printf("Compatible\n");

      parser->last_matched = token_print(parser->token);

      if(make_ast)
        return handle_found(parser, state, consume_token(parser),
          default_builder, out_found);

      // AST not needed, discard token
      consume_token_no_ast(parser);
      return handle_found(parser, state, NULL, NULL, out_found);
    }
  }

  // Current token does not match any in current set
  if(trace_enable)
    printf("Not compatible\n");

  return handle_not_found(parser, state, desc, terminating, out_found);
}
Beispiel #23
0
void parse_member_specification(std::vector<unique_ptr<Token>>::iterator* it,
                                ClassSpecification* class_spec,
                                bool* ok) {
  MemberSpecification member_specification;
  *ok = true;
  member_specification.annotationType = parse_annotation_type(it);
  if (!parse_access_flags(it,
                          member_specification.requiredSetAccessFlags,
                          member_specification.requiredUnsetAccessFlags)) {
    // There was a problem parsing the access flags. Return an empty class spec
    // for now.
    cerr << "Problem parsing access flags for member specification.\n";
    *ok = false;
    skip_to_semicolon(it);
    return;
  }
  // The next token better be an identifier.
  if ((**it)->type != token::identifier) {
    cerr << "Expecting field or member specification but got " << (**it)->show()
         << " at line " << (**it)->line << endl;
    *ok = false;
    skip_to_semicolon(it);
    return;
  }
  std::string ident = static_cast<Identifier*>((*it)->get())->ident;
  // Check for "*".
  if (ident == "*") {
    member_specification.name = "";
    member_specification.descriptor = "";
    ++(*it);
    gobble_semicolon(it, ok);
    class_spec->methodSpecifications.push_back(member_specification);
    class_spec->fieldSpecifications.push_back(member_specification);
    return;
  }
  // Check for <methods>
  if (ident == "<methods>") {
    member_specification.name = "";
    member_specification.descriptor = "";
    ++(*it);
    gobble_semicolon(it, ok);
    class_spec->methodSpecifications.push_back(member_specification);
    return;
  }
  // Check for <fields>
  if (ident == "<fields>") {
    member_specification.name = "";
    member_specification.descriptor = "";
    ++(*it);
    gobble_semicolon(it, ok);
    class_spec->fieldSpecifications.push_back(member_specification);
    return;
  }
  // Check for <init>
  if (ident == "<init>") {
    member_specification.name = "<init>";
    member_specification.descriptor = "V";
    set_access_flag(member_specification.requiredSetAccessFlags,
                    ACC_CONSTRUCTOR);
    ++(*it);
  } else {
    // This token is the type for the member specification.
    if ((**it)->type != token::identifier) {
      cerr << "Expecting type identifier but got " << (**it)->show()
           << " at line " << (**it)->line << endl;
      *ok = false;
      skip_to_semicolon(it);
      return;
    }
    std::string typ = static_cast<Identifier*>((*it)->get())->ident;
    ++(*it);
    member_specification.descriptor = convert_wildcard_type(typ);
    if ((**it)->type != token::identifier) {
      cerr << "Expecting identifier name for class member but got "
           << (**it)->show() << " at line " << (**it)->line << endl;
      *ok = false;
      skip_to_semicolon(it);
      return;
    }
    member_specification.name = static_cast<Identifier*>((*it)->get())->ident;
    ++(*it);
  }
  // Check to see if this is a method specification.
  if ((**it)->type == token::openBracket) {
    consume_token(it, token::openBracket);
    std::string arg = "(";
    while (true) {
      // If there is a ")" next we are done.
      if ((**it)->type == token::closeBracket) {
        consume_token(it, token::closeBracket);
        break;
      }
      if ((**it)->type != token::identifier) {
        std::cerr << "Expecting type identifier but got " << (**it)->show()
                  << " at line " << (**it)->line << std::endl;
        *ok = false;
        return;
      }
      std::string typ = static_cast<Identifier*>((*it)->get())->ident;
      consume_token(it, token::identifier);
      arg += convert_wildcard_type(typ);
      // The next token better be a comma or a closing bracket.
      if ((**it)->type != token::comma && (**it)->type != token::closeBracket) {
        std::cerr << "Expecting comma or ) but got " << (**it)->show()
                  << " at line " << (**it)->line << std::endl;
        *ok = false;
        return;
      }
      // If the next token is a comma (rather than closing bracket) consume
      // it and check that it is followed by an identifier.
      if ((**it)->type == token::comma) {
        consume_token(it, token::comma);
        if ((**it)->type != token::identifier) {
          std::cerr << "Expecting type identifier after comma but got "
                    << (**it)->show() << " at line " << (**it)->line
                    << std::endl;
          *ok = false;
          return;
        }
      }
    }
    arg += ")";
    arg += member_specification.descriptor;
    member_specification.descriptor = arg;
  }
  // Make sure member specification ends with a semicolon.
  gobble_semicolon(it, ok);
  if (!ok) {
    return;
  }
  if (member_specification.descriptor[0] == '(') {
    class_spec->methodSpecifications.push_back(member_specification);
  } else {
    class_spec->fieldSpecifications.push_back(member_specification);
  }
  return;
}
Beispiel #24
0
static struct ast_node*
function_call(char *name)
{
	struct function *func_ctx;
	struct ast_node_func_call *func_call;
	struct ast_node_stub *stub_node;	
	struct ast_node *arg;
	int nargs = 0;

	func_ctx = function_table_lookup(name);

	consume_token();
	
	if (func_ctx == NULL) {
		error_msg("unknown function");
		sync_stream();
		stub_node = ast_node_stub();
		return AST_NODE(stub_node);	
	}

	func_call = ast_node_func_call(func_ctx->name);

	while (!match(TOKEN_RPARENTH)) {
		if (match(TOKEN_EOL)) {
			error_msg("EOL in function call");
			sync_stream();
			goto free;
			
		}
		
		arg = or_expr();

		if (arg == NULL) {
			error_msg("error: function argument expected");
			sync_stream();
			goto free;
		}
			
		nargs++;

		ast_node_func_call_add_arg(func_call, arg);
		
		if (current_token != TOKEN_RPARENTH && !match(TOKEN_COMMA)) {
			error_msg("error: missed comma");
			sync_stream();
			goto free;
		}				
	}
	
	if (func_ctx->nargs != nargs) {
		error_msg("error: unmatched arguments count");
		sync_stream();
		goto free;
	}

	return AST_NODE(func_call);	
free:
	ast_node_unref(AST_NODE(func_call));	
	stub_node = ast_node_stub();
	return	AST_NODE(stub_node);
}