summaryrefslogtreecommitdiff
path: root/src/parser.c
diff options
context:
space:
mode:
authorSteve Zesch <[email protected]>2012-11-24 20:44:45 -0500
committerSteve Zesch <[email protected]>2012-11-24 20:44:45 -0500
commit6b24c91d3aa81fdb99500c8c2c12f830fabaefb6 (patch)
tree6a0038ecfaa77e156ee2cc9059220685091217d7 /src/parser.c
parenta10375c2851e8569353c0da9921b8d0d9cbea2e6 (diff)
downloadmate-calc-6b24c91d3aa81fdb99500c8c2c12f830fabaefb6.tar.bz2
mate-calc-6b24c91d3aa81fdb99500c8c2c12f830fabaefb6.tar.xz
Update codebase.
Diffstat (limited to 'src/parser.c')
-rw-r--r--src/parser.c1228
1 files changed, 1228 insertions, 0 deletions
diff --git a/src/parser.c b/src/parser.c
new file mode 100644
index 0000000..fb4fd12
--- /dev/null
+++ b/src/parser.c
@@ -0,0 +1,1228 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+#include "parser.h"
+#include "parserfunc.h"
+#include "mp-equation.h"
+
+/* Converts LexerTokenType to Precedence value. */
+static guint
+p_get_precedence(LexerTokenType type)
+{
+ /* WARNING: This function doesn't work for Unary Plus and Unary Minus. Use their precedence directly while inserting them in tree. */
+ if(type == T_ADD
+ ||type == T_SUBTRACT)
+ return P_AddSubtract;
+ if(type == T_MULTIPLY)
+ return P_Multiply;
+ if(type == T_MOD)
+ return P_Mod;
+ if(type == T_DIV)
+ return P_Divide;
+ if(type == T_NOT)
+ return P_Not;
+ if(type == T_ROOT
+ ||type == T_ROOT_3
+ ||type == T_ROOT_4)
+ return P_Root;
+ if(type == T_FUNCTION)
+ return P_Function;
+ if(type == T_AND
+ ||type == T_OR
+ ||type == T_XOR)
+ return P_Boolean;
+ if(type == T_PERCENTAGE)
+ return P_Percentage;
+ if(type == T_POWER)
+ return P_Power;
+ if(type == T_FACTORIAL)
+ return P_Factorial;
+ if(type == T_NUMBER
+ ||type == T_VARIABLE)
+ return P_NumberVariable;
+ return P_Unknown;
+}
+
+/* Return associativity of specific token type from precedence. */
+static Associativity
+p_get_associativity_p(Precedence type)
+{
+ if(type == P_Boolean
+ ||type == P_Divide
+ ||type == P_Mod
+ ||type == P_Multiply
+ ||type == P_AddSubtract)
+ return LEFT_ASSOCIATIVE;
+ if(type == P_Power)
+ return RIGHT_ASSOCIATIVE;
+ /* For all remaining / non-associative operators, return Left Associativity. */
+ return LEFT_ASSOCIATIVE;
+}
+
+/* Return associativity of specific token by converting it to precedence first. */
+static Associativity
+p_get_associativity(LexerToken* token)
+{
+ return p_get_associativity_p(p_get_precedence(token->token_type));
+}
+
+/* Generate precedence for a node from precedence value. Includes depth_level. */
+static guint
+p_make_precedence_p(ParserState* state, Precedence p)
+{
+ return (p + (state->depth_level * P_Depth));
+}
+
+/* Generate precedence for a node from lexer token type. Includes depth_level. */
+static guint
+p_make_precedence_t(ParserState* state, LexerTokenType type)
+{
+ return (p_get_precedence(type) + (state->depth_level * P_Depth));
+}
+
+/* Allocate and create a new node. */
+static ParseNode*
+p_create_node(ParserState* state, LexerToken* token, guint precedence, Associativity associativity, void* value, void* (*function)(ParseNode*))
+{
+ ParseNode* new;
+ new = (ParseNode*) malloc(sizeof(ParseNode));
+ assert(new != NULL);
+ new->parent = NULL;
+ new->left = NULL;
+ new->right = NULL;
+ new->token = token;
+ new->precedence = precedence;
+ new->associativity = associativity;
+ new->value = value;
+ new->state = state;
+ new->evaluate = function;
+ return new;
+}
+
+/* Compares two nodes to decide, which will be parent and which willbe child. */
+static gint
+p_cmp_nodes(ParseNode* left, ParseNode* right)
+{
+ /* Return values.
+ 1 = right goes up (near root) in parse tree.
+ 0 = left goes up (near root) in parse tree.
+ */
+ if(left == NULL)
+ return 0;
+ if(left->precedence > right->precedence)
+ {
+ return 1;
+ }
+ else if(left->precedence < right->precedence)
+ {
+ return 0;
+ }
+ else
+ {
+ if(right->associativity == RIGHT_ASSOCIATIVE)
+ {
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+}
+
+/* Unified interface (unary and binary nodes) to insert node into parse tree. */
+static void
+p_insert_into_tree_all(ParserState* state, ParseNode* node, guint unary_function)
+{
+ if(state->root == NULL)
+ {
+ state->root = node;
+ state->right_most = state->root;
+ return;
+ }
+ ParseNode* tmp = state->right_most;
+ while(p_cmp_nodes(tmp, node))
+ tmp = tmp->parent;
+ if(unary_function)
+ {
+ /* If tmp is null, that means, we have to insert new node at root. */
+ if(tmp == NULL)
+ {
+ node->right = state->root;
+ node->right->parent = node;
+
+ state->root = node;
+ }
+ else
+ {
+ node->right = tmp->right;
+ if(node->right)
+ node->right->parent = node;
+
+ tmp->right = node;
+ if(tmp->right)
+ tmp->right->parent = tmp;
+
+ }
+ state->right_most = node;
+ while(state->right_most->right != NULL)
+ state->right_most = state->right_most->right;
+ }
+ else
+ {
+ /* If tmp is null, that means, we have to insert new node at root. */
+ if(tmp == NULL)
+ {
+ node->left = state->root;
+ node->left->parent = node;
+
+ state->root = node;
+ }
+ else
+ {
+ node->left = tmp->right;
+ if(node->left)
+ node->left->parent = node;
+
+ tmp->right = node;
+ if(tmp->right)
+ tmp->right->parent = tmp;
+
+ }
+ state->right_most = node;
+ }
+}
+
+/* Insert binary node into the parse tree. */
+static void
+p_insert_into_tree(ParserState* state, ParseNode* node)
+{
+ p_insert_into_tree_all(state, node, 0);
+}
+
+/* Insert unary node into the parse tree. */
+static void
+p_insert_into_tree_unary(ParserState* state, ParseNode* node)
+{
+ p_insert_into_tree_all(state, node, 1);
+}
+
+/* Recursive call to free every node of parse-tree. */
+static void
+p_destroy_all_nodes(ParseNode* node)
+{
+ if(node == NULL)
+ return;
+ p_destroy_all_nodes(node->left);
+ p_destroy_all_nodes(node->right);
+ /* Don't call free for tokens, as they are allocated and freed in lexer. */
+ /* WARNING: If node->value is freed elsewhere, please assign it NULL before calling p_destroy_all_nodes(). */
+ if(node->value)
+ free(node->value);
+ free(node);
+}
+
+/* Create parser state. */
+ParserState*
+p_create_parser(const gchar* input, MPEquationOptions* options)
+{
+ ParserState* state;
+ state = (ParserState*) malloc(sizeof(ParserState));
+ assert(state != NULL);
+ state->lexer = l_create_lexer(input, state);
+ state->root = NULL;
+ state->depth_level = 0;
+ state->right_most = NULL;
+ state->options = options;
+ state->error = 0;
+ state->error_token = NULL;
+ return state;
+}
+
+static guint statement (ParserState*);
+/* Start parsing input string. And call evaluate on success. */
+guint
+p_parse(ParserState* state)
+{
+ guint ret;
+ LexerToken* token;
+ MPNumber* ans;
+ l_insert_all_tokens(state->lexer);
+ ret = statement(state);
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == T_ASSIGN)
+ {
+ token = l_get_next_token(state->lexer);
+ if(token->token_type != PL_EOS)
+ {
+ /* Full string is not parsed. */
+ if(!state->error)
+ set_error(state, PARSER_ERR_INVALID, token->string);
+ return PARSER_ERR_INVALID;
+ }
+ }
+ if(token->token_type != PL_EOS)
+ {
+ /* Full string is not parsed. */
+ if(!state->error)
+ set_error(state, PARSER_ERR_INVALID, token->string);
+ return PARSER_ERR_INVALID;
+ }
+ if(ret == 0)
+ /* 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. */
+void
+p_destroy_parser(ParserState* state)
+{
+ /* If state has a parse tree, destroy it first. */
+ if(state->root)
+ {
+ p_destroy_all_nodes(state->root);
+ }
+ l_destroy_lexer(state->lexer);
+ free(state);
+}
+
+/* LL (*) parser. Lookahead count depends on tokens. Handle with care. :P */
+
+static guint expression(ParserState* state);
+static guint expression_1(ParserState* state);
+static guint expression_2(ParserState* state);
+static guint unit(ParserState* state);
+static guint variable(ParserState* state);
+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 gboolean
+p_check_variable(ParserState* state, gchar* name)
+{
+ gint result = 0;
+
+ const gchar *c, *next;
+ gchar *buffer;
+ MPNumber temp;
+
+ if(!(state->get_variable))
+ {
+ return FALSE;
+ }
+
+ /* If defined, then get the variable */
+ if((*(state->get_variable))(state, name, &temp))
+ {
+ return TRUE;
+ }
+
+ /* 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 FALSE;
+ }
+ return TRUE;
+}
+
+static guint
+statement(ParserState* state)
+{
+ LexerToken* token;
+ LexerToken* token_old;
+ ParseNode* node;
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == T_VARIABLE)
+ {
+ token_old = token;
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == T_ASSIGN)
+ {
+ /* VARIABLE = expression. */
+
+ node = p_create_node(state, token_old, p_make_precedence_p(state, P_NumberVariable), p_get_associativity(token_old), NULL, pf_none);
+ p_insert_into_tree(state, node);
+
+ node = p_create_node(state, token, 0, p_get_associativity(token), NULL, pf_set_var);
+ p_insert_into_tree(state, node);
+
+ if(!expression(state))
+ return 0;
+ return 1;
+ }
+ else if(token->token_type == T_IN)
+ {
+ /* UNIT in UNIT. */
+ l_roll_back(state->lexer);
+ l_roll_back(state->lexer);
+ if(!unit(state))
+ return 0;
+ l_get_next_token(state->lexer);
+
+ node = p_create_node(state, token, 0, p_get_associativity(token), NULL, pf_convert_1);
+ p_insert_into_tree(state, node);
+
+ if(!unit(state))
+ return 0;
+ return 1;
+ }
+ else if(token->token_type == T_SUP_NUMBER)
+ {
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == T_IN)
+ {
+ /* UNIT in UNIT */
+ l_roll_back(state->lexer);
+ l_roll_back(state->lexer);
+ l_roll_back(state->lexer);
+ if(!unit(state))
+ return 0;
+ l_get_next_token(state->lexer);
+
+ node = p_create_node(state, token, 0, p_get_associativity(token), NULL, pf_convert_1);
+ p_insert_into_tree(state, node);
+
+ if(!unit(state))
+ return 0;
+ return 1;
+ }
+ else
+ {
+ l_roll_back(state->lexer);
+ l_roll_back(state->lexer);
+ l_roll_back(state->lexer);
+ if(!expression(state))
+ return 0;
+ return 1;
+ }
+ }
+ else
+ {
+ l_roll_back(state->lexer);
+ l_roll_back(state->lexer);
+ if(!expression(state))
+ return 0;
+ return 1;
+ }
+ }
+ else if(token->token_type == T_NUMBER)
+ {
+ token_old = token;
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == T_VARIABLE)
+ {
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == T_IN)
+ {
+ /* NUMBER UNIT in UNIT */
+ l_roll_back(state->lexer);
+ l_roll_back(state->lexer);
+
+ node = p_create_node(state, token_old, p_make_precedence_t(state, token_old->token_type), p_get_associativity(token), NULL, pf_constant);
+ p_insert_into_tree(state, node);
+
+ if(!unit(state))
+ return 0;
+ token = l_get_next_token(state->lexer);
+
+ node = p_create_node(state, token, 0, p_get_associativity(token), NULL, pf_convert_number);
+ p_insert_into_tree(state, node);
+
+ if(!unit(state))
+ return 0;
+ return 1;
+ }
+ else if(token->token_type == T_SUP_NUMBER)
+ {
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == T_IN)
+ {
+ /* NUMBER UNIT in UNIT */
+ l_roll_back(state->lexer);
+ l_roll_back(state->lexer);
+ l_roll_back(state->lexer);
+
+ node = p_create_node(state, token_old, p_make_precedence_t(state, token_old->token_type), p_get_associativity(token), NULL, pf_constant);
+ p_insert_into_tree(state, node);
+
+ if(!unit(state))
+ return 0;
+ token = l_get_next_token(state->lexer);
+
+ node = p_create_node(state, token, 0, p_get_associativity(token), NULL, pf_convert_number);
+ p_insert_into_tree(state, node);
+
+ if(!unit(state))
+ return 0;
+ return 1;
+ }
+ else
+ {
+ l_roll_back(state->lexer);
+ l_roll_back(state->lexer);
+ l_roll_back(state->lexer);
+ l_roll_back(state->lexer);
+ if(!expression(state))
+ return 0;
+ return 1;
+ }
+ }
+ else
+ {
+ l_roll_back(state->lexer);
+ l_roll_back(state->lexer);
+ l_roll_back(state->lexer);
+ if(!expression(state))
+ return 0;
+ return 1;
+ }
+ }
+ else
+ {
+ l_roll_back(state->lexer);
+ l_roll_back(state->lexer);
+ if(!expression(state))
+ return 0;
+ return 1;
+ }
+ }
+ else
+ {
+ l_roll_back(state->lexer);
+ if(!expression(state))
+ return 0;
+ return 1;
+ }
+}
+
+static guint
+unit(ParserState* state)
+{
+ LexerToken* token;
+ LexerToken* token_old;
+ ParseNode* node;
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == T_VARIABLE)
+ {
+ token_old = token;
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == T_SUP_NUMBER)
+ {
+ /* VARIABLE POWER */
+
+ node = p_create_node(state, token_old, p_make_precedence_t(state, token_old->token_type), p_get_associativity(token_old), pf_make_unit(token_old->string, token->string), pf_none);
+ p_insert_into_tree(state, node);
+
+ return 1;
+ }
+ else
+ {
+ l_roll_back(state->lexer);
+ /* VARIABLE */
+
+ node = p_create_node(state, token_old, p_make_precedence_t(state, token_old->token_type), p_get_associativity(token_old), NULL, pf_none);
+ p_insert_into_tree(state, node);
+
+ return 1;
+ }
+ }
+ else
+ {
+ l_roll_back(state->lexer);
+ return 0;
+ }
+}
+
+static guint
+expression(ParserState* state)
+{
+ if(!expression_1(state))
+ return 0;
+ if(!expression_2(state))
+ return 0;
+ return 1;
+}
+
+static guint
+expression_1(ParserState* state)
+{
+ LexerToken* token;
+ ParseNode* node;
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == PL_EOS
+ ||token->token_type == T_ASSIGN)
+ {
+ l_roll_back(state->lexer);
+ return 0;
+ }
+ if(token->token_type == T_L_R_BRACKET)
+ {
+ state->depth_level++;
+ if(!expression(state))
+ return 0;
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == T_R_R_BRACKET)
+ {
+ state->depth_level--;
+ return 1;
+ }
+ else
+ //Expected ")" here...
+ return 0;
+ }
+ else if(token->token_type == T_L_S_BRACKET)
+ {
+ state->depth_level++;
+
+ /* Give round, preference of P_Unknown aka 0, to keep it on the top of expression. */
+
+ node = p_create_node(state, token, p_make_precedence_p(state, P_Unknown), p_get_associativity(token), NULL, pf_do_round);
+ p_insert_into_tree_unary(state, node);
+
+ if(!expression(state))
+ return 0;
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == T_R_S_BRACKET)
+ {
+ state->depth_level--;
+ return 1;
+ }
+ else
+ //Expected "]" here...
+ return 0;
+ }
+ else if(token->token_type == T_L_C_BRACKET)
+ {
+ state->depth_level++;
+
+ /* Give fraction, preference of P_Unknown aka 0, to keep it on the top of expression. */
+
+ node = p_create_node(state, token, p_make_precedence_p(state, P_Unknown), p_get_associativity(token), NULL, pf_do_fraction);
+ p_insert_into_tree_unary(state, node);
+
+ if(!expression(state))
+ return 0;
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == T_R_C_BRACKET)
+ {
+ state->depth_level--;
+ return 1;
+ }
+ else
+ //Expected "}" here...
+ return 0;
+ }
+ else if(token->token_type == T_ABS)
+ {
+ state->depth_level++;
+
+ /* Give abs, preference of P_Unknown aka 0, to keep it on the top of expression. */
+
+ node = p_create_node(state, token, p_make_precedence_p(state, P_Unknown), p_get_associativity(token), NULL, pf_do_abs);
+ p_insert_into_tree_unary(state, node);
+
+ if(!expression(state))
+ return 0;
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == T_ABS)
+ {
+ state->depth_level--;
+ return 1;
+ }
+ else
+ //Expected "|" here...
+ return 0;
+ }
+ else if(token->token_type == T_NOT)
+ {
+ /* NOT expression */
+
+ node = p_create_node(state, token, p_make_precedence_p(state, P_Not), p_get_associativity(token), NULL, pf_do_not);
+ p_insert_into_tree_unary(state, node);
+
+ if(!expression(state))
+ return 0;
+ return 1;
+ }
+ else if(token->token_type == T_NUMBER)
+ {
+ /* NUMBER */
+
+ node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_constant);
+ p_insert_into_tree(state, node);
+
+ token = l_get_next_token(state->lexer);
+ l_roll_back(state->lexer);
+
+ if(token->token_type == T_FUNCTION
+ ||token->token_type == T_VARIABLE
+ ||token->token_type == T_SUB_NUMBER
+ ||token->token_type == T_ROOT
+ ||token->token_type == T_ROOT_3
+ ||token->token_type == T_ROOT_4)
+ {
+ /* NUMBER variable. */
+
+ node = p_create_node(state, NULL, p_make_precedence_p(state, P_Multiply), p_get_associativity_p(P_Multiply), NULL, pf_do_multiply);
+ p_insert_into_tree(state, node);
+
+ if(!variable(state))
+ return 0;
+ else
+ return 1;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+ else if(token->token_type == T_L_FLOOR)
+ {
+ state->depth_level++;
+ /* Give floor, preference of P_Unknown aka 0, to keep it on the top of expression. */
+
+ node = p_create_node(state, NULL, p_make_precedence_p(state, P_Unknown), p_get_associativity_p(P_Unknown), NULL, pf_do_floor);
+ p_insert_into_tree_unary(state, node);
+
+ if(!expression(state))
+ return 0;
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == T_R_FLOOR)
+ {
+ state->depth_level--;
+ return 1;
+ }
+ else
+ //Expected ⌋ here...
+ return 0;
+ }
+ else if(token->token_type == T_L_CEILING)
+ {
+ state->depth_level++;
+ /* Give ceiling, preference of P_Unknown aka 0, to keep it on the top of expression. */
+
+ node = p_create_node(state, NULL, p_make_precedence_p(state, P_Unknown), p_get_associativity_p(P_Unknown), NULL, pf_do_ceiling);
+ p_insert_into_tree_unary(state, node);
+
+ if(!expression(state))
+ return 0;
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == T_R_CEILING)
+ {
+ state->depth_level--;
+ return 1;
+ }
+ else
+ //Expected ⌉ here...
+ return 0;
+ }
+ else if(token->token_type == T_SUBTRACT)
+ {
+ /* UnaryMinus expression */
+
+ node = p_create_node(state, token, p_make_precedence_p(state, P_UnaryMinus), p_get_associativity_p(P_UnaryMinus), NULL, pf_unary_minus);
+ p_insert_into_tree_unary(state, node);
+
+ if(!expression_1(state))
+ return 0;
+ return 1;
+ }
+ else if(token->token_type == T_ADD)
+ {
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == T_NUMBER)
+ {
+ /* UnaryPlus expression */
+ /* Ignore T_ADD. It is not required. */
+
+ node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_constant);
+ p_insert_into_tree(state, node);
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ else
+ {
+ l_roll_back(state->lexer);
+ if(!variable(state))
+ return 0;
+ else
+ return 1;
+ }
+}
+
+static guint
+expression_2(ParserState* state)
+{
+ LexerToken* token;
+ ParseNode* node;
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == T_L_R_BRACKET)
+ {
+ /* expression "(" expression ")" */
+
+ node = p_create_node(state, NULL, p_make_precedence_p(state, P_Multiply), p_get_associativity_p(P_Multiply), NULL, pf_do_multiply);
+ p_insert_into_tree(state, node);
+
+ state->depth_level++;
+ if(!expression(state))
+ return 0;
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == T_R_R_BRACKET)
+ {
+ state->depth_level--;
+ if(!expression_2(state))
+ return 0;
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ else if(token->token_type == T_POWER)
+ {
+ /* expression "^" expression */
+
+ node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_x_pow_y);
+ p_insert_into_tree(state, node);
+
+ if(!expression_1(state))
+ return 0;
+ if(!expression_2(state))
+ return 0;
+ return 1;
+ }
+ else if(token->token_type == T_SUP_NUMBER)
+ {
+ /* expression T_SUP_NUMBER */
+
+ node = p_create_node(state, NULL, p_make_precedence_p(state, P_Power), p_get_associativity_p(P_Power), NULL, pf_do_x_pow_y_int);
+ p_insert_into_tree(state, node);
+
+ node = p_create_node(state, token, p_make_precedence_p(state, P_NumberVariable), p_get_associativity_p(P_NumberVariable), NULL, pf_none);
+ p_insert_into_tree(state, node);
+
+ if(!expression_2(state))
+ return 0;
+ return 1;
+ }
+ else if(token->token_type == T_NSUP_NUMBER)
+ {
+ /* expression T_NSUP_NUMBER */
+
+ node = p_create_node(state, NULL, p_make_precedence_p(state, P_Power), p_get_associativity_p(P_Power), NULL, pf_do_x_pow_y_int);
+ p_insert_into_tree(state, node);
+
+ node = p_create_node(state, token, p_make_precedence_p(state, P_NumberVariable), p_get_associativity_p(P_NumberVariable), NULL, pf_none);
+ p_insert_into_tree(state, node);
+
+ if(!expression_2(state))
+ return 0;
+ return 1;
+ }
+ else if(token->token_type == T_FACTORIAL)
+ {
+ /* expression T_FACTORIAL */
+
+ node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_factorial);
+ p_insert_into_tree_unary(state, node);
+
+ if(!expression_2(state))
+ return 0;
+ return 1;
+ }
+ else if(token->token_type == T_MULTIPLY)
+ {
+ /* expression T_MULTIPLY expression */
+
+ node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_multiply);
+ p_insert_into_tree(state, node);
+
+ if(!expression_1(state))
+ return 0;
+ if(!expression_2(state))
+ return 0;
+ return 1;
+ }
+ else if(token->token_type == T_PERCENTAGE)
+ {
+ /* expression % */
+
+ node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_percent);
+ p_insert_into_tree_unary(state, node);
+
+ if(!expression_2(state))
+ return 0;
+ return 1;
+ }
+ else if(token->token_type == T_AND)
+ {
+ /* expression T_AND expression */
+
+ node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_and);
+ p_insert_into_tree(state, node);
+
+ if(!expression_1(state))
+ return 0;
+ if(!expression_2(state))
+ return 0;
+ return 1;
+ }
+ else if(token->token_type == T_OR)
+ {
+ /* expression T_OR expression */
+
+ node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_or);
+ p_insert_into_tree(state, node);
+
+ if(!expression_1(state))
+ return 0;
+ if(!expression_2(state))
+ return 0;
+ return 1;
+ }
+ else if(token->token_type == T_XOR)
+ {
+ /* expression T_XOR expression */
+
+ node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_xor);
+ p_insert_into_tree(state, node);
+
+ if(!expression_1(state))
+ return 0;
+ if(!expression_2(state))
+ return 0;
+ return 1;
+ }
+ else if(token->token_type == T_DIV)
+ {
+ /* expression T_DIV expression */
+
+ node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_divide);
+ p_insert_into_tree(state, node);
+
+ if(!expression_1(state))
+ return 0;
+ if(!expression_2(state))
+ return 0;
+ return 1;
+ }
+ else if(token->token_type == T_MOD)
+ {
+ /* expression T_MOD expression */
+
+ node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_mod);
+ p_insert_into_tree(state, node);
+
+ if(!expression_1(state))
+ return 0;
+ if(!expression_2(state))
+ return 0;
+ return 1;
+ }
+ else if(token->token_type == T_ADD)
+ {
+ /* expression T_ADD expression */
+
+ node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_add);
+ p_insert_into_tree(state, node);
+
+ if(!expression_1(state))
+ return 0;
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == T_PERCENTAGE)
+ {
+ //FIXME: This condition needs to be verified for all cases.. :(
+ if(node->right->precedence > P_Percentage)
+ {
+ node->precedence = P_Percentage;
+ node->evaluate = pf_do_add_percent;
+ return 1;
+ }
+ else
+ {
+ /* Assume '%' to be part of 'expression T_PERCENTAGE' statement. */
+ l_roll_back(state->lexer);
+ if(!expression_2(state))
+ return 1;
+ }
+ }
+ else
+ {
+ l_roll_back(state->lexer);
+ }
+ if(!expression_2(state))
+ return 0;
+ return 1;
+ }
+ else if(token->token_type == T_SUBTRACT)
+ {
+ /* expression T_SUBTRACT expression */
+
+ node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_subtract);
+ p_insert_into_tree(state, node);
+
+ if(!expression_1(state))
+ return 0;
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == T_PERCENTAGE)
+ {
+ //FIXME: This condition needs to be verified for all cases.. :(
+ if(node->right->precedence > P_Percentage)
+ {
+ node->precedence = P_Percentage;
+ node->evaluate = pf_do_subtract_percent;
+ return 1;
+ }
+ else
+ {
+ /* Assume '%' to be part of 'expression T_PERCENTAGE' statement. */
+ l_roll_back(state->lexer);
+ if(!expression_2 (state))
+ return 1;
+ }
+ }
+ else
+ {
+ l_roll_back(state->lexer);
+ }
+ if(!expression_2(state))
+ return 0;
+ return 1;
+ }
+ else
+ {
+ l_roll_back(state->lexer);
+ return 1;
+ }
+}
+
+static guint
+variable(ParserState* state)
+{
+ LexerToken* token;
+ LexerToken* token_old;
+ ParseNode* node;
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == T_FUNCTION)
+ {
+ token_old = token;
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == T_SUP_NUMBER)
+ {
+ /* FUNCTION SUP_NUMBER expression */
+ /* Pass power as void * value. That will be taken care in pf_apply_func_with_powre. */
+
+ node = p_create_node(state, token_old, p_make_precedence_t(state, token_old->token_type), p_get_associativity(token_old), token, pf_apply_func_with_power);
+ p_insert_into_tree_unary(state, node);
+
+ if(!expression(state))
+ return 0;
+ return 1;
+ }
+ else if(token->token_type == T_NSUP_NUMBER)
+ {
+ /* FUNCTION NSUP_NUMBER expression */
+ /* Pass power as void * value. That will be taken care in pf_apply_func_with_npowre. */
+
+ node = p_create_node(state, token_old, p_make_precedence_t(state, token_old->token_type), p_get_associativity(token_old), token, pf_apply_func_with_npower);
+ p_insert_into_tree_unary(state, node);
+
+ if(!expression(state))
+ return 0;
+ return 1;
+ }
+ else
+ {
+ l_roll_back(state->lexer);
+ /* FUNCTION expression */
+
+ node = p_create_node(state, token_old, p_make_precedence_t(state, token_old->token_type), p_get_associativity(token_old), NULL, pf_apply_func);
+ p_insert_into_tree_unary(state, node);
+
+ if(!expression(state))
+ return 0;
+ return 1;
+ }
+ }
+ else if(token->token_type == T_SUB_NUMBER)
+ {
+ token_old = token;
+ token = l_get_next_token(state->lexer);
+ if(token->token_type == T_ROOT)
+ {
+ /* SUB_NUM ROOT expression */
+ /* Pass SUB_NUM as void* value in node. pf_do_nth_root will take care of it. */
+
+ node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), token_old, pf_do_nth_root);
+ p_insert_into_tree_unary(state, node);
+
+ if(!expression (state))
+ return 0;
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ else if(token->token_type == T_ROOT)
+ {
+ /* ROOT expression */
+
+ node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_sqrt);
+ p_insert_into_tree_unary(state, node);
+
+ if(!expression(state))
+ return 0;
+ return 1;
+ }
+ else if(token->token_type == T_ROOT_3)
+ {
+ /* ROOT_3 expression */
+
+ node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_root_3);
+ p_insert_into_tree_unary(state, node);
+
+ if(!expression(state))
+ return 0;
+ return 1;
+ }
+ else if(token->token_type == T_ROOT_4)
+ {
+ /* ROOT_4 expression */
+
+ node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_root_4);
+ p_insert_into_tree_unary(state, node);
+
+ if(!expression(state))
+ return 0;
+ return 1;
+ }
+ else if(token->token_type == T_VARIABLE)
+ {
+ l_roll_back(state->lexer);
+ //TODO: unknown function ERROR for (T_VARIABLE T_SUP_NUMBER expression).
+ if(!term(state))
+ return 0;
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static guint
+term(ParserState* state)
+{
+ LexerToken* token;
+ LexerToken* token_old;
+ ParseNode* node;
+ 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 */
+ /* Pass power as void* value. pf_get_variable_with_power will take care of it. */
+
+ node = p_create_node(state, token_old, p_make_precedence_t(state, token_old->token_type), p_get_associativity(token_old), token, pf_get_variable_with_power);
+ p_insert_into_tree(state, node);
+
+ }
+ else
+ {
+ l_roll_back(state->lexer);
+ /* VARIABLE */
+
+ node = p_create_node(state, token_old, p_make_precedence_t(state, token_old->token_type), p_get_associativity(token_old), NULL, pf_get_variable);
+ p_insert_into_tree(state, node);
+
+ }
+ if(!term_2(state))
+ return 0;
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static guint
+term_2(ParserState* state)
+{
+ LexerToken* token;
+ ParseNode* node;
+ token = l_get_next_token(state->lexer);
+ l_roll_back(state->lexer);
+ if(token->token_type == PL_EOS
+ ||token->token_type == T_ASSIGN)
+ {
+ return 1;
+ }
+ if(token->token_type == T_VARIABLE)
+ {
+ /* Insert multiply in between two distinct (variable). */
+
+ node = p_create_node(state, NULL, p_make_precedence_p(state, P_Multiply), p_get_associativity_p(P_Multiply), NULL, pf_do_multiply);
+ p_insert_into_tree(state, node);
+
+ if(!term(state))
+ return 0;
+ return 1;
+ }
+ else
+ {
+ return 1;
+ }
+}