Commits

PioneerAxon committed 435ee5b

Merging to gcalctool Phase:2

Added: In l_check_if_number(), check if rollback few characters yeilds a number.
Added: In HEX_DEC_STATE:, return T_NUMBER, if substring contains a number.
Added: Set result (if any) into ParserState return value.
Added: In parserfunc.c, every function checks if function pointers are assigned.
Added: In parserfunc.c, every function checks if its child has returned NULL.
Fixed: In l_check_if_function() make sure function pointer function_is_defined() is pointing proper function.
Updated: l_insert_all_tokens() is now exposed to parser, and is called from p_parse() instead of l_create_lexer().
Removed: CHOICE() temp code from lexer.c.

  • Participants
  • Parent commits b1cedf4

Comments (0)

Files changed (4)

 #include <stdlib.h>
 #include <assert.h>
+#include <string.h>
 
 #include <lexer.h>
 #include <parserfunc.h>
 #include<stdio.h>
 #define PR_ERROR(x) printf("ERROR : %s at string \"%s\"...\n",x,pl_get_marked_substring (state)); return l_insert_token (lstate, T_UNKNOWN);
 
-#define CHOICE(x) get_choice(state, x)
-
-gint get_choice (PreLexerState *state, gchar *string)
-{
-	gint choice;
-	printf("Is \"%s\" %s(1) or not (0)? :",pl_get_marked_substring (state), string);
-	scanf ("%d",&choice);
-	return choice;
-}
-
-
 /*---------END TEMP code---------*/
 
 static gint
 l_check_if_function (LexerState* state)
 {
 	gchar* name = pl_get_marked_substring (state->prelexer);
+	if (!state->parent->function_is_defined) {
+		free (name);
+		return 0;
+	}
 	if ((*(state->parent->function_is_defined)) (state->parent, name)) {
 		free (name);
 		return 1;
 l_check_if_number (LexerState* state)
 {
 	MPNumber tmp;
+	int count = 0;
 	gchar* text = pl_get_marked_substring (state->prelexer);
-	if (mp_set_from_string (text, state->parent->options->base, &tmp)) {
+	if (mp_set_from_string (text, state->parent->options->base, &tmp) == 0) {
 		free (text);
 		return 1;
 	}
 	else {
-		/* FIXME: try to rollback several characters to see, if this fits any number. */
+		/* Try to rollback several characters to see, if that yeilds any number. */
+		while (strlen (text) > 0) {
+			if (mp_set_from_string (text, state->parent->options->base, &tmp) == 0) {
+				free (text);
+				return 1;
+			}
+			free (text);
+			count++;
+			pl_roll_back (state->prelexer);
+			text = pl_get_marked_substring (state->prelexer);
+		}
+		/* Undo all rollbacks. */
+		while (count--) pl_get_next_token (state->prelexer);
 		free (text);
 		return 0;
 	}
 					return l_insert_token (lstate, T_NUMBER);
 				}
 				else {
+					if (l_check_if_number (lstate))
+						return l_insert_token (lstate, T_NUMBER);
 					//TODO: ERROR
 					PR_ERROR ("expected PL_DECIMAL | PL_DIGIT | PL_HEX.");
 				}
 }
 
 /* Call l_insert_next_token() as many times as needed to completely tokenize the string. */
-static void
+void
 l_insert_all_tokens(LexerState* state)
 {
 	LexerToken* token;
 	ret->token_count = 0;
 	ret->next_token = 0;
 	ret->parent = parent;
-	l_insert_all_tokens (ret);
 	return ret;
 }
 
 /* Destroy LexerState object and free up space. */
 void l_destroy_lexer (LexerState *);
 
+/* Tokanize complete string. */
+void l_insert_all_tokens (LexerState *);
+
 /* Return next, to be sent, token. */
 LexerToken *l_get_next_token (LexerState *);
 
 {
 	guint ret;
 	LexerToken* token;
-	printf ("Parsing completed with return value = %d (1 = success).. :D \n", ret = statement (state));
+	MPNumber* ans;
+	l_insert_all_tokens (state->lexer);
+	ret = statement (state);
 	token = l_get_next_token (state->lexer);
 	if (token->token_type != PL_EOS && token->token_type != T_ASSIGN) {
-		printf("Full string not parsed.. :(\n");
-		return 0;
+		/* Full string is not parsed. */
+		return PARSER_ERR_INVALID;
 	}
 	if (ret == 0)
-		return 0;
-	p_display (state->root);
-	(*(state->root->evaluate)) (state->root);
-	return 1;
+	{
+		/* Input can't be parsed with grammar. */
+		return PARSER_ERR_INVALID;
+	}
+	ans = (MPNumber *) (*(state->root->evaluate)) (state->root);
+	if (ans) {
+		mp_set_from_mp (ans, &state->ret);
+		free (ans);
+		return PARSER_ERR_NONE;
+	}
+	return PARSER_ERR_INVALID;
 }
 
 /* Destroy parser state. */
 #include<stdio.h>
 
 #include<parser.h>
+#include<parserfunc.h>
 
 /* Register error variables in ParserState structure. */
 void set_error (ParserState* state, gint errorno, const gchar *token)
 {
 	MPNumber* val;
 	val = (MPNumber *)(*(self->right->evaluate)) (self->right);
+	if (!val || !(self->state->set_variable)) {
+		if (val) free (val);
+		return NULL;
+	}
 	(*(self->state->set_variable)) (self->state, self->left->token->string, val);
 	return val;
 }
 	else
 		to = self->right->token->string;
 
-	mp_set_from_string (self->left->left->token->string, self->state->options->base, &tmp);
+	if (mp_set_from_string (self->left->left->token->string, self->state->options->base, &tmp) != 0) {
+		free (ans);
+		ans = NULL;
+		goto END_PF_CONVERT_NUMBER;
+	}
+	if (!(self->state->convert)) {
+		free (ans);
+		ans = NULL;
+		goto END_PF_CONVERT_NUMBER;
+	}
 	if (!(*(self->state->convert)) (self->state, &tmp, from, to, ans)) {
 		set_error (self->state, PARSER_ERR_UNKNOWN_CONVERSION, NULL);
 		free (ans);
 		ans = NULL;
 	}
+END_PF_CONVERT_NUMBER:
 	if (free_from) {
 		g_free (self->left->value);
 		self->left->value = NULL;
 	else
 		to = self->right->token->string;
 	mp_set_from_integer (1, &tmp);
+	if (!(self->state->convert)) {
+		free (ans);
+		return NULL;
+	}
 	if (!(*(self->state->convert)) (self->state, &tmp, from, to, ans)) {
 		set_error (self->state, PARSER_ERR_UNKNOWN_CONVERSION, NULL);
 		free (ans);
 	MPNumber* ans;
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 
+	if (!(self->state->get_variable)) {
+		free (ans);
+		return NULL;
+	}
+
 	/* If defined, then get the variable */
 	if ((*(self->state->get_variable)) (self->state, self->token->string, ans)) {
 		return ans;
 	/* No need to free the memory. It is allocated and freed somewhere else. */
 	self->value = NULL;
 
+	if (!(self->state->get_variable)) {
+		free (ans);
+		return NULL;
+	}
+
 	/* If defined, then get the variable */
 	if ((*(self->state->get_variable)) (self->state, self->token->string, ans)) {
 		mp_xpowy_integer(ans, pow, ans);
 		ans = NULL;
 		set_error(self->state, PARSER_ERR_UNKNOWN_VARIABLE, self->token->string);
 	}
-	/* No need to free the memory. It is allocated and freed somewhere else. */
-	self->value = NULL;
 	return ans;
 }
 
 	MPNumber* ans;
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	val = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!(self->state->get_function)) {
+		free (val);
+		free (ans);
+		return NULL;
+	}
+	if (!val) {
+		free (ans);
+		return NULL;
+	}
 	if (!(*(self->state->get_function)) (self->state, self->token->string, val, ans)) {
+		free (val);
 		free (ans);
-		ans = NULL;
 		set_error (self->state, PARSER_ERR_UNKNOWN_FUNCTION, self->token->string);
+		return NULL;
 	}
+	free (val);
 	return ans;
 }
 
 	tmp = (MPNumber*) malloc (sizeof (MPNumber));
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	val = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!(self->state->get_function)) {
+		free (tmp);
+		free (ans);
+		free (val);
+		self->value = NULL;
+		return NULL;
+	}
+	if (!val) {
+		free (tmp);
+		free (ans);
+		self->value = NULL;
+		return NULL;
+	}
 	if (!(*(self->state->get_function)) (self->state, self->token->string, val, tmp)) {
 		free (tmp);
 		free (ans);
 		free (val);
+		self->value = NULL;
 		set_error (self->state, PARSER_ERR_UNKNOWN_FUNCTION, self->token->string);
 		return NULL;
 	}
 	mp_xpowy_integer (tmp, pow, ans);
 	free (val);
 	free (tmp);
+	self->value = NULL;
 	return ans;
 }
 
 	tmp = (MPNumber*) malloc (sizeof (MPNumber));
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	val = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!val) {
+		free (tmp);
+		free (inv_name);
+		free (ans);
+		self->value = NULL;
+		return NULL;
+	}
+	if (!(self->state->get_function)) {
+		free (tmp);
+		free (ans);
+		free (inv_name);
+		self->value = NULL;
+		return NULL;
+	}
 	if (!(*(self->state->get_function)) (self->state, inv_name, val, tmp)) {
 		free (tmp);
 		free (ans);
 		free (val);
 		free (inv_name);
+		self->value = NULL;
 		set_error (self->state, PARSER_ERR_UNKNOWN_FUNCTION, self->token->string);
 		return NULL;
 	}
 	free (val);
 	free (tmp);
 	free (inv_name);
+	self->value = NULL;
 	return ans;
 }
 
 	self->value = NULL;
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	val = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!val) {
+		free (ans);
+		return NULL;
+	}
 	mp_root (val, pow, ans);
 	free (val);
 	return ans;
 	MPNumber* ans;
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	val = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!val) {
+		free (ans);
+		return NULL;
+	}
 	mp_sqrt (val, ans);
 	free (val);
 	return ans;
 	MPNumber* ans;
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	val = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!val) {
+		free (ans);
+		return NULL;
+	}
 	mp_root (val, 3, ans);
 	free (val);
 	return ans;
 	MPNumber* ans;
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	val = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!val) {
+		free (ans);
+		return NULL;
+	}
 	mp_root (val, 4, ans);
 	free (val);
 	return ans;
 	MPNumber* ans;
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	val = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if(!val) {
+		free (ans);
+		return NULL;
+	}
 	mp_floor (val, ans);
 	free (val);
 	return ans;
 	MPNumber* ans;
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	val = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!val) {
+		free (ans);
+		return NULL;
+	}
 	mp_ceiling (val, ans);
 	free (val);
 	return ans;
 	MPNumber* ans;
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	val = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!val) {
+		free (ans);
+		return NULL;
+	}
 	mp_round (val, ans);
 	free (val);
 	return ans;
 	MPNumber* ans;
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	val = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!val) {
+		free (ans);
+		return NULL;
+	}
 	mp_fractional_part (val, ans);
 	free (val);
 	return ans;
 	MPNumber* ans;
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	val = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!val) {
+		free (ans);
+		return NULL;
+	}
 	mp_abs (val, ans);
 	free (val);
 	return ans;
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	val = (MPNumber*) (*(self->left->evaluate)) (self->left);
 	pow = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!val || !pow) {
+		if (val) free (val);
+		if (pow) free (pow);
+		free (ans);
+		return NULL;
+	}
 	mp_xpowy (val, pow, ans);
 	free (val);
 	free (pow);
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	val = (MPNumber*) (*(self->left->evaluate)) (self->left);
 	pow = super_atoi (self->right->token->string);
+	if (!val) {
+		free (ans);
+		return NULL;
+	}
 	mp_xpowy_integer (val, pow, ans);
 	free (val);
 	return ans;
 	MPNumber* ans;
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	val = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!val) {
+		free (ans);
+		return NULL;
+	}
 	mp_factorial (val, ans);
 	free (val);
 	return ans;
 	MPNumber* ans;
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	val = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!val) {
+		free (ans);
+		return NULL;
+	}
 	mp_invert_sign (val, ans);
 	free (val);
 	return ans;
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	left = (MPNumber*) (*(self->left->evaluate)) (self->left);
 	right = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!left || !right) {
+		if (left) free (left);
+		if (right) free (right);
+		free (ans);
+		return NULL;
+	}
 	mp_divide (left, right, ans);
 	free (left);
 	free (right);
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	left = (MPNumber*) (*(self->left->evaluate)) (self->left);
 	right = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!left || !right) {
+		if (left) free (left);
+		if (right) free (right);
+		free (ans);
+		return NULL;
+	}
 	mp_modulus_divide (left, right, ans);
 	free (left);
 	free (right);
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	left = (MPNumber*) (*(self->left->evaluate)) (self->left);
 	right = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!left || !right) {
+		if (left) free (left);
+		if (right) free (right);
+		free (ans);
+		return NULL;
+	}
 	mp_multiply (left, right, ans);
 	free (left);
 	free (right);
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	left = (MPNumber*) (*(self->left->evaluate)) (self->left);
 	right = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!left || !right) {
+		if (left) free (left);
+		if (right) free (right);
+		free (ans);
+		return NULL;
+	}
 	mp_subtract (left, right, ans);
 	free (left);
 	free (right);
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	left = (MPNumber*) (*(self->left->evaluate)) (self->left);
 	right = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!left || !right) {
+		if (left) free (left);
+		if (right) free (right);
+		free (ans);
+		return NULL;
+	}
 	mp_add (left, right, ans);
 	free (left);
 	free (right);
 	MPNumber* ans;
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	val = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!val) {
+		free (ans);
+		return NULL;
+	}
 	mp_divide_integer (val, 100, ans);
 	free (val);
 	return ans;
 	MPNumber* ans;
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	val = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!val) {
+		free (ans);
+		return NULL;
+	}
 	if (!mp_is_overflow (val, self->state->options->wordlen)) {
 		set_error (self->state, PARSER_ERR_OVERFLOW, NULL);
 		free (ans);
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	left = (MPNumber*) (*(self->left->evaluate)) (self->left);
 	right = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!left || !right) {
+		if (left) free (left);
+		if (right) free (right);
+		free (ans);
+		return NULL;
+	}
 	mp_and (left, right, ans);
 	free (left);
 	free (right);
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	left = (MPNumber*) (*(self->left->evaluate)) (self->left);
 	right = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!left || !right) {
+		if (left) free (left);
+		if (right) free (right);
+		free (ans);
+		return NULL;
+	}
 	mp_or (left, right, ans);
 	free (left);
 	free (right);
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
 	left = (MPNumber*) (*(self->left->evaluate)) (self->left);
 	right = (MPNumber*) (*(self->right->evaluate)) (self->right);
+	if (!left || !right) {
+		if (left) free (left);
+		if (right) free (right);
+		free (ans);
+		return NULL;
+	}
 	mp_xor (left, right, ans);
 	free (left);
 	free (right);
 {
 	MPNumber* ans;
 	ans = (MPNumber*) malloc (sizeof (MPNumber));
-	mp_set_from_string (self->token->string, self->state->options->base, ans);
+	if (mp_set_from_string (self->token->string, self->state->options->base, ans) != 0) {
+	/* This should never happen, as l_check_if_number() has already passed the number. */
+	/* If the code reaches this point, something is really wrong. X( */
+		free (ans);
+		set_error (self->state, PARSER_ERR_INVALID, self->token->string);
+		return NULL;
+	}
 	return ans;
 }