Commits

PioneerAxon  committed 7ec7baf

Check variable at parse-tree generation.

Added: p_check_variable() checks variable before parsing further.
This fixes issues with "Unknown variable" being reported after "Malformed expression" in specific cases.

  • Participants
  • Parent commits 23221e3

Comments (0)

Files changed (1)

File src/parser.c

 #include<stdlib.h>
 #include<stdio.h>
 #include<assert.h>
+#include<string.h>
 
 #include<parser.h>
 #include<parserfunc.h>
 static guint term (ParserState* state);
 static guint term_2 (ParserState* state);
 
+/* Helping function to p_check_variable. */
+static gchar*
+utf8_next_char (const gchar* c)
+{
+    c++;
+    while ((*c & 0xC0) == 0x80)
+        c++;
+    return (gchar *)c;
+}
+
+/* Check if string "name" is a valid variable for given ParserState. It is the same code, used to get the value of variable in parserfunc.c. */
+static gint
+p_check_variable (ParserState* state, gchar* name)
+{
+	gint result = 0;
+
+	const gchar *c, *next;
+	gchar *buffer;
+	MPNumber temp;
+
+	if (!(state->get_variable)) {
+		return 0;
+	}
+
+	/* If defined, then get the variable */
+	if ((*(state->get_variable)) (state, name, &temp)) {
+		return 1;
+	}
+
+	/* If has more than one character then assume a multiplication of variables */
+	if (utf8_next_char (name)[0] != '\0') {
+		result = 1;
+		buffer = (gchar*) malloc (sizeof (gchar) * strlen (name));
+		for (c = name; *c != '\0'; c = next) {
+			next = utf8_next_char(c);
+			snprintf(buffer, next - c + 1, "%s", c);
+			if (!(*(state->get_variable)) (state, buffer, &temp)) {
+				result = 0;
+				break;
+			}
+		}
+		free(buffer);
+	}
+	if (!result) {
+		return 0;
+	}
+	return 1;
+}
+
 static guint
 statement (ParserState* state)
 {
 	token = l_get_next_token (state->lexer);
 	if (token->token_type == T_VARIABLE) {
 		token_old = token;
+		/* Check if the token is a valid variable or not. */
+		if (!p_check_variable (state, token->string)) {
+			set_error (state, PARSER_ERR_UNKNOWN_VARIABLE, token->string);
+			return 0;
+		}
 		token = l_get_next_token (state->lexer);
 		if (token->token_type == T_SUP_NUMBER) {
 			/* VARIABLE SUP_NUMBER */