| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 | 
							- /*
 
-  * Copyright (c) 2014 Hugh Bailey <[email protected]>
 
-  *
 
-  * Permission to use, copy, modify, and distribute this software for any
 
-  * purpose with or without fee is hereby granted, provided that the above
 
-  * copyright notice and this permission notice appear in all copies.
 
-  *
 
-  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 
-  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 
-  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 
-  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 
-  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 
-  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 
-  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-  */
 
- #include "../util/cf-parser.h"
 
- #include "decl.h"
 
- static inline void err_specifier_exists(struct cf_parser *cfp,
 
- 					const char *storage)
 
- {
 
- 	cf_adderror(cfp, "'$1' specifier already exists", LEX_ERROR, storage,
 
- 		    NULL, NULL);
 
- }
 
- static inline void err_reserved_name(struct cf_parser *cfp, const char *name)
 
- {
 
- 	cf_adderror(cfp, "'$1' is a reserved name", LEX_ERROR, name, NULL,
 
- 		    NULL);
 
- }
 
- static inline void err_existing_name(struct cf_parser *cfp, const char *name)
 
- {
 
- 	cf_adderror(cfp, "'$1' already exists", LEX_ERROR, name, NULL, NULL);
 
- }
 
- static bool is_in_out_specifier(struct cf_parser *cfp, struct strref *name,
 
- 				uint32_t *type)
 
- {
 
- 	if (strref_cmp(name, "in") == 0) {
 
- 		if (*type & CALL_PARAM_IN)
 
- 			err_specifier_exists(cfp, "in");
 
- 		*type |= CALL_PARAM_IN;
 
- 	} else if (strref_cmp(name, "out") == 0) {
 
- 		if (*type & CALL_PARAM_OUT)
 
- 			err_specifier_exists(cfp, "out");
 
- 		*type |= CALL_PARAM_OUT;
 
- 	} else {
 
- 		return false;
 
- 	}
 
- 	return true;
 
- }
 
- #define TYPE_OR_STORAGE "type or storage specifier"
 
- static bool get_type(struct strref *ref, enum call_param_type *type,
 
- 		     bool is_return)
 
- {
 
- 	if (strref_cmp(ref, "int") == 0)
 
- 		*type = CALL_PARAM_TYPE_INT;
 
- 	else if (strref_cmp(ref, "float") == 0)
 
- 		*type = CALL_PARAM_TYPE_FLOAT;
 
- 	else if (strref_cmp(ref, "bool") == 0)
 
- 		*type = CALL_PARAM_TYPE_BOOL;
 
- 	else if (strref_cmp(ref, "ptr") == 0)
 
- 		*type = CALL_PARAM_TYPE_PTR;
 
- 	else if (strref_cmp(ref, "string") == 0)
 
- 		*type = CALL_PARAM_TYPE_STRING;
 
- 	else if (is_return && strref_cmp(ref, "void") == 0)
 
- 		*type = CALL_PARAM_TYPE_VOID;
 
- 	else
 
- 		return false;
 
- 	return true;
 
- }
 
- static bool is_reserved_name(const char *str)
 
- {
 
- 	return (strcmp(str, "int") == 0) || (strcmp(str, "float") == 0) ||
 
- 	       (strcmp(str, "bool") == 0) || (strcmp(str, "ptr") == 0) ||
 
- 	       (strcmp(str, "string") == 0) || (strcmp(str, "void") == 0) ||
 
- 	       (strcmp(str, "return") == 0);
 
- }
 
- static bool name_exists(struct decl_info *decl, const char *name)
 
- {
 
- 	for (size_t i = 0; i < decl->params.num; i++) {
 
- 		const char *param_name = decl->params.array[i].name;
 
- 		if (strcmp(name, param_name) == 0)
 
- 			return true;
 
- 	}
 
- 	return false;
 
- }
 
- static int parse_param(struct cf_parser *cfp, struct decl_info *decl)
 
- {
 
- 	struct strref ref;
 
- 	int code;
 
- 	struct decl_param param = {0};
 
- 	/* get storage specifiers */
 
- 	code = cf_next_name_ref(cfp, &ref, TYPE_OR_STORAGE, ",");
 
- 	if (code != PARSE_SUCCESS)
 
- 		return code;
 
- 	while (is_in_out_specifier(cfp, &ref, ¶m.flags)) {
 
- 		code = cf_next_name_ref(cfp, &ref, TYPE_OR_STORAGE, ",");
 
- 		if (code != PARSE_SUCCESS)
 
- 			return code;
 
- 	}
 
- 	/* parameters not marked with specifiers are input parameters */
 
- 	if (param.flags == 0)
 
- 		param.flags = CALL_PARAM_IN;
 
- 	if (!get_type(&ref, ¶m.type, false)) {
 
- 		cf_adderror_expecting(cfp, "type");
 
- 		cf_go_to_token(cfp, ",", ")");
 
- 		return PARSE_CONTINUE;
 
- 	}
 
- 	/* name */
 
- 	code = cf_next_name(cfp, ¶m.name, "parameter name", ",");
 
- 	if (code != PARSE_SUCCESS)
 
- 		return code;
 
- 	if (name_exists(decl, param.name))
 
- 		err_existing_name(cfp, param.name);
 
- 	if (is_reserved_name(param.name))
 
- 		err_reserved_name(cfp, param.name);
 
- 	da_push_back(decl->params, ¶m);
 
- 	return PARSE_SUCCESS;
 
- }
 
- static void parse_params(struct cf_parser *cfp, struct decl_info *decl)
 
- {
 
- 	struct cf_token peek;
 
- 	int code;
 
- 	if (!cf_peek_valid_token(cfp, &peek))
 
- 		return;
 
- 	while (peek.type == CFTOKEN_NAME) {
 
- 		code = parse_param(cfp, decl);
 
- 		if (code == PARSE_EOF)
 
- 			return;
 
- 		if (code != PARSE_CONTINUE && !cf_next_valid_token(cfp))
 
- 			return;
 
- 		if (cf_token_is(cfp, ")"))
 
- 			break;
 
- 		else if (cf_token_should_be(cfp, ",", ",", NULL) == PARSE_EOF)
 
- 			return;
 
- 		if (!cf_peek_valid_token(cfp, &peek))
 
- 			return;
 
- 	}
 
- 	if (!cf_token_is(cfp, ")"))
 
- 		cf_next_token_should_be(cfp, ")", NULL, NULL);
 
- }
 
- static void print_errors(struct cf_parser *cfp, const char *decl_string)
 
- {
 
- 	char *errors = error_data_buildstring(&cfp->error_list);
 
- 	if (errors) {
 
- 		blog(LOG_WARNING, "Errors/warnings for '%s':\n\n%s",
 
- 		     decl_string, errors);
 
- 		bfree(errors);
 
- 	}
 
- }
 
- bool parse_decl_string(struct decl_info *decl, const char *decl_string)
 
- {
 
- 	struct cf_parser cfp;
 
- 	struct strref ret_type;
 
- 	struct decl_param ret_param = {0};
 
- 	int code;
 
- 	bool success;
 
- 	decl->decl_string = decl_string;
 
- 	ret_param.flags = CALL_PARAM_OUT;
 
- 	cf_parser_init(&cfp);
 
- 	if (!cf_parser_parse(&cfp, decl_string, "declaration"))
 
- 		goto fail;
 
- 	code = cf_get_name_ref(&cfp, &ret_type, "return type", NULL);
 
- 	if (code == PARSE_EOF)
 
- 		goto fail;
 
- 	if (!get_type(&ret_type, &ret_param.type, true))
 
- 		cf_adderror_expecting(&cfp, "return type");
 
- 	code = cf_next_name(&cfp, &decl->name, "function name", "(");
 
- 	if (code == PARSE_EOF)
 
- 		goto fail;
 
- 	if (is_reserved_name(decl->name))
 
- 		err_reserved_name(&cfp, decl->name);
 
- 	code = cf_next_token_should_be(&cfp, "(", "(", NULL);
 
- 	if (code == PARSE_EOF)
 
- 		goto fail;
 
- 	parse_params(&cfp, decl);
 
- fail:
 
- 	success = !error_data_has_errors(&cfp.error_list);
 
- 	if (success && ret_param.type != CALL_PARAM_TYPE_VOID) {
 
- 		ret_param.name = bstrdup("return");
 
- 		da_push_back(decl->params, &ret_param);
 
- 	}
 
- 	if (!success)
 
- 		decl_info_free(decl);
 
- 	print_errors(&cfp, decl_string);
 
- 	cf_parser_free(&cfp);
 
- 	return success;
 
- }
 
 
  |