A Step-by-Step Solution Methodology for Mathematical Expressions

: In this paper, we propose a methodology for the step-by-step solution of problems, which can be incorporated into a computer algebra system. Our main aim is to show all the intermediate evaluation steps of mathematical expressions from the start to the end of the solution. The ﬁrst stage of the methodology covers the development of a formal grammar that describes the syntax and semantics of mathematical expressions. Using a compiler generation tool, the second stage produces a parser from the grammar description. The parser is used to convert a particular mathematical expression into an Abstract Syntax Tree (AST), which is evaluated in the third stage by traversing al its nodes. After every evaluation of some nodes, which corresponds to an intermediate solution step of the related expression, the resulting AST is transformed into the corresponding mathematical expression and then displayed. Many other algebra-related issues such as simpliﬁcation, factorization, distribution and substitution can be covered by the solution methodology. We currently focuses on the solutions of various problems associated with the subject of derivative, equations, single variable polynomials, and operations on functions. However, it can easily be extended to cover the other subjects of general mathematics.


Introduction
Mathematics has an important root in human evolutionary history. Computers are very good at solving problems if right commands are used. The first generation of programming languages, namely assembly, did not have special statements to work with mathematical expressions except for four basic operations of add, subtract, multiply and divide. Although the basic operations can be used to work with the hardware, given high-level programming languages, more sophisticated expressions are supported and break down to those operations. The breaking-down process is generally controlled by compilers which translate all statements and expressions in a high-level programming language into low-level or machine code. Due to very effective outcomes of the process, many advanced languages and systems have been introduced [1,2]. Mathematics systems are categorized into two main groups such as numerical computation and symbolic computation. Although numeric computation is widely used [3], the output is always an approximated value. Unfortunately the difference between the exact value and the approximate value can cause errors and failures. Error propagation happens in various forms such as floating-point calculation, estimated values, uncertainty, etc. For very accurate systems, using numeric computation is not preferred. Symbolic computation or algebraic computation refers to the development and evaluation of mathematical expressions. Symbolic computation offers mathematics (e.g., Mathway) [41,42] and electronics (e.g., CHARLIE) [43] is widespread. The literature also has systems that emerged for generating and solving the questions [44,45].
Many methods have been developed for solving algebraic equations and some of them have been used with automatic computers [46,47]. The methods which are most suitable for use with automatic computers are ones that are applied to a wide class of equations and that are relatively rapid when the degree of the equation is large.
In addition to general-purpose computer algebra systems, there is some special-purpose software for mathematics and physics, developed to solve problems in a particular area. Typical examples are Cayley and GAP software, developed for group theory [48,49], PARI, SIMATH, and KANT for number theory, CoCoA for commutative algebra [50], Macaulay for algebraic geometry and LiE for Lie theory [51].
Math software tools used in mathematics curriculum can serve in the five categories as: practical, public, private, environment, and communications [52]. Besides, Handal and Herrington [53] have identified exercises, lessons, games, simulations, hypermedia, and tools as other computer-based mathematics education categories.

Methodology Illustration
In this paper we propose a grammar based methodology to solve mathematical expressions step-by-step, which is designed as a multi-party system. The system uses an extended grammar to parse input data, and then converts it into a tree data structure, which provides an appropriate model for easily processing a particular mathematical expression. Each node of the tree includes a symbol or term of the input expression, and its relations with other symbols or terms, where symbols can be operators, numbers, etc.
The tree representation also helps to apply recursive operations over a node and its children. For example, the evaluation of a node requires firstly evaluating the children of that node. Besides a certain combination of nodes can define a pattern to which some other specific operations needs applying. A typical example would be a basic distributive transformation where a complex representation of summation expression is simplified to a simple one.
The methodology consists of the following phases and steps:

Phase 1: Parser definition
Steps: Grammar design, grammar conversion, compiler-compiler input construction, code generation Phase 2: Input data analysis Steps: Token generation, syntax analysis, AST generation

Phase 3: Evaluation and interpretation
Steps: Solving expressions, simplification, printing intermediate evaluation results.
Some of these phases and steps are also shown in Figure 1. Many methods have been developed for solving algebraic equations and some of them have been used with automatic computers [46,47]. The methods which are most suitable for use with automatic computers are ones that are applied to a wide class of equations and that are relatively rapid when the degree of the equation is large.
In addition to general-purpose computer algebra systems, there is some special-purpose software for mathematics and physics, developed to solve problems in a particular area. Typical examples are Cayley and GAP software, developed for group theory [48,49], PARI, SIMATH, and KANT for number theory, CoCoA for commutative algebra [50], Macaulay for algebraic geometry and LiE for Lie theory [51].
Math software tools used in mathematics curriculum can serve in the five categories as: practical, public, private, environment, and communications [52]. Besides, Handal and Herrington [53] have identified exercises, lessons, games, simulations, hypermedia, and tools as other computer-based mathematics education categories.

Methodology Illustration
In this paper we propose a grammar based methodology to solve mathematical expressions stepby-step, which is designed as a multi-party system. The system uses an extended grammar to parse input data, and then converts it into a tree data structure, which provides an appropriate model for easily processing a particular mathematical expression. Each node of the tree includes a symbol or term of the input expression, and its relations with other symbols or terms, where symbols can be operators, numbers, etc.
The tree representation also helps to apply recursive operations over a node and its children. For example, the evaluation of a node requires firstly evaluating the children of that node. Besides a certain combination of nodes can define a pattern to which some other specific operations needs applying. A typical example would be a basic distributive transformation where a complex representation of summation expression is simplified to a simple one.
The methodology consists of the following phases and steps:

Phase 1: Parser definition
Steps: Grammar design, grammar conversion, compiler-compiler input construction, code generation

Phase 2: Input data analysis
Steps: Token generation, syntax analysis, AST generation

Phase 3: Evaluation and interpretation
Steps: Solving expressions, simplification, printing intermediate evaluation results. Some of these phases and steps are also shown in Figure 1. Using the steps shown in Figure 1, one can implement a framework to process mathematical expressions. In this paper, we will work on algebraic expressions to illustrate some applications of the methodology. The methodology can be integrated with systems developed to solve many practical or real-world problems in education, business or industry. It has the potential to serve as a major component in all the systems for which a mathematical model can be developed. For example, Using the steps shown in Figure 1, one can implement a framework to process mathematical expressions. In this paper, we will work on algebraic expressions to illustrate some applications of the methodology. The methodology can be integrated with systems developed to solve many practical or real-world problems in education, business or industry. It has the potential to serve as a major component in all the systems for which a mathematical model can be developed. For example, a possible area of usage can be the solution of a linear or nonlinear system of equations derived from the analysis of electrical circuits. The other one can be the evaluation, refinement and application of many numerical analysis methods, including root-finding, function interpolation, polynomial approximation, curve fitting. It can also be used to identify and solve differential equations of various types.

BNF Grammar Definition
The BNF notation is used to define context-free grammars for formal languages, especially programming languages. It has simple notations and recursive structures. Many compiler generation tools, such as YACC [54], LEX [55], and JavaCC [56,57] use a BNF-like description of a source language.
Mathematical expressions can contain operations such as addition or subtraction, functions such as sin or cos, special symbols such as integral, etc. Given a grammar developed for a particular mathematical expression, all operators, functions, symbols, variables and numbers will be members of the terminal set. The nonterminal set will be determined based on the production rules of the grammar. The designed grammar must generate arithmetic expressions with an operator and its operands, or a mathematical function with arguments. An operand or argument itself might be a number, a variable, or another mathematical expression.
The production rules of grammar might be recursive, since there are operands of a type "expression", shortly called expr. In addition, the decimal (or integer) numbers can be generated up to desired number of digits. Every different kind of mathematical expressions requires the use of different grammars. In this section, a derivative system is implemented by developing an extended BNF Grammar with some modifications to the one presented in [58], which is shown in Listing 1. The grammar given in Listing 1 has five operators and six functions that can reside in simple mathematical expression. However, it can be modified with the insertion of some other operators, functions, and symbols.
When the above grammar is used to describe, for example, the expression "3 * x + xˆ2/2", it will confront a semantics problem. Since the grammar definition does not consider the priority of the operators, the expression will be given a different meaning from what is done in mathematics and thus will not be evaluated in the right order of operations. In the next section, the grammar will be modified to resolve such semantics problems.

Grammar Conversion
Parsing an expression means processing expression structure via a grammar. One of the most important connections between grammar and expression is the type of parse tree derivation. This connection can be determined by a parsing method, which works under some certain conditions. In this paper, we focus on LL parsers.
The grammar designed in Listing 1 has to be converted to use one of the conventional parsing methods. There are various tools developed for parser generation called compiler-compiler or CC. Each CC is suitable for a specific kind of parsing methods. These tools in fact are compiler generators where they take the syntax rules of a formal language as input, and return a compiler for that language as output.
In this paper, we use JavaCC as a parser generator, which is a compiler-compiler tool developed for the top-down parsing. Top-down parsers can easily work with public grammars.
It is easy to see that, given the grammar in Listing 1, all operators have the same level of precedence. As we know, this will make it an ambiguous grammar. In order to use a compiler-compiler tool like JavaCC, the grammar has to be LL(1). Listing 2 shows the equivalent LL(1) grammar, which is modified by considering the operator precedence and associativity.
Given the tree structure created by the grammar, the operators with higher priority will first be evaluated and the ones with lower priority later. If there is a need for other mathematical operators, they must be added in the grammar with the level of its priority. In this way, the expression "3 * x + xˆ2/2" will be evaluated consistently with mathematics.

Definition of Syntax Classes
Syntax is the writing rules of a language. Mathematical expressions, as well as other languages, have certain syntax where there is a finite combination of components. Numbers, variables, operations, functions, symbols of grouping, and other syntactic symbols are used in math expressions. Each component has a specific structure which needs to be defined.
We use syntax classes that are implemented using the object oriented concepts of Java. Table 1 shows some syntax classes and their attributes adapted to our work. As in Table 1 the additional syntax classes can be defined for other operators, functions, or symbols. In object-oriented programming, each rule is generally defined by a class, which is then used to evaluate the expressions. Listing 3 shows the definitions of some classes given in Table 1.
The syntax classes can be used to create some structure. The AST tree structure is the most suitable one for mathematical expressions. Unlike parse trees, an AST can hold essential sections of input in the form of a tree. An AST can be defined simultaneously with a parser that produces it. The syntax classes defined at this stage should be coded in accordance with the properties of their respective operators in mathematics. As seen in Listing 4, the Exp class is defined as abstract, and depending on the various operations that may be performed on expressions, methods can be added to this class. For example, to calculate the result of an expression, a method such as public abstract double Eval (int x); can be added in Exp class. The Listing 4 displays the definitions of this method for some operators.  Using the method defined in Listing 4, it is easy to calculate the numerical value of a mathematical expression such as "3 * x + xˆ2/2" with a given value for the variable x.

Parser Construction
The parser generator tools often create AST. The structure of AST depends on the language in which the tool generates code. There are many different parser tools generating parser code for various languages. Some of these tools are developed for code generation in imperative languages, such as yacc [54], and bison [59], and the others such as ml-yacc [60], and happy [61] generates code for functional languages, as well as those generating code for object-oriented languages, including t-gen [62] and JavaCup [63]. Each of these tools requires defining a special type of grammar. Some tools are suitable for LL(k), and some others are suitable for LR(k) etc. Therefore, after selecting a tool for the parser, the grammar must be developed according to the specifications of that parser generator.

Token Specification
A token manufacturer (scanner) with input analysis from the perspective of the word produces a series of tokens. Any word within the input data, which cannot divided into smaller parts, is called token. Tokens are all elements in terminal set (T ⊆ Σ) which is defined by the grammar given in Listing 2. For the grammar in Listing 2, the tokens are shown in Listing 5, following the specification rules of JavaCC. x" > | < LPR: "(" > | < RPR: ")" > } SKIP : { " " | "\t" | "\r" } In Listing 5 each token is defined by the keyword TOKEN. For simplicity, we separate all tokens and categorize them into the groups of numbers, operators, etc. The keyword SKIP specifies the characters which should be discarded. In a similar way, the other tokens in the grammar can be added into Listing 5.
In fact, at this stage, the tokens are defined by regular expressions, which are understood by a lexical analyzer produced via JavaCC. For example, the expression "3 * x + xˆ2/2" will have a stream of the following tokens:

Parser Definition
A parser analyzes input data in terms of productivity based on a series of produced tokens. It checks whether the sequence of tokens is generated or not, examining them from the perspective of grammar rules. Therefore, we need a mechanism for verification of tokens and their appearance order based on the language rules. Of course, in the process of analysis, the system must also do a semantic analysis for acceptable input data before evaluation. However, the syntax analyzer (parser) can guarantee the evaluation ability of those data due to the structures of mathematical expressions. The parser can be designed by hand-written functions or using parser generator tools. The use of a parser generation tool involves developing the desired grammar based on the description conditions of that parser. For example, a grammar for Yacc++ must be developed in LR and for CppCC in LL form. In this paper we use JavaCC for the parser generation and validity test of entries.
The name of functions or methods in JavaCC declaration is determined according to the non-terminal set in the grammar in Listing 2. In general, a method must be defined for each non-terminal in a grammar. In some cases it may be useful to combine several non-terminal symbols, defining only a method for them. For example, consider the non-terminal <expr> in Listing 1. For this non-terminal, there is a rule as <expr>→<term> <expr'>. Therefore, a method can be defined for it in the parse generator. But it can arise some difficulties in parse tree generation for the related non-terminal <expr'>. For such cases, these non-terminals can be merged, resulting in one non-terminal, and can be represented by only one method in the parse generator tool. Table 2 shows the typical examples of the merging operation. Table 2. The usual and combined rules for some non-terminals.

Normal Rules
Combined Rules All the parser methods are defined in accordance with the structure of the grammar rules. In Table 3, some JavaCC defined methods of the LL(1) grammar are shown. Table 3. Sample JavaCC method definitions for LL(1) grammar rules.

Grammar Rule
Corresponding Method The other methods for the grammar rules can be defined in the same way as seen in Table 3. The whole definitions of the tokens and rules must be specified with the extension ".jj", which is taken by JavaCC as input. The output of JavaCC is java code that serves as a parser for the related grammar. This parser can be used for determining the authenticity of input data. In Table 3, the tokens <EOL> and <EOF> represent the end of line and the end of data entries, respectively.
This stage can be used to check the correctness of the expression structure or lead to the production of the syntax tree. The mathematical expression defined in the previous stage is evaluated structurally based on a specific grammar. It is easy to see that the expression "3 * x + xˆ2/2" is well-formed, which has no syntax error.

Generating Abstract Syntax Tree (AST)
In the previous section, we have discussed about creating a parser to determine the accuracy of data entry. However, for being able to do some operation on mathematical expressions, it is necessary not only to detect the accuracy but also generate the desired data structure. One of the useful structures for mathematical expressions is the syntax tree.
A syntax tree (or mainly object tree) is composed of many nodes linked together in a hierarchical structure. Each node is derived from a syntax class, and is constructed by an object that represents a statement or expression of source data. The syntax tree is usually created with the help of a super class type. Subclasses that inherit from the same super class can be used to create the nodes of an object tree, but these nodes on the tree can be represented by the reference of super class.
By adding a various java statements in JavaCC, it is possible to generate AST. Listing 6 shows the commands to be added to the code in Table 3 to generate the nodes of AST.  Table 3 produce output data, verifying the input string. Figure 2 demonstrates the steps required to produce the AST for our mathematical grammar.  Table 3 produce output data, verifying the input string. Figure 2 demonstrates the steps required to produce the AST for our mathematical grammar. For example, the expression " 3 * +^2/2 " will be converted to an AST, as graphically illustrated in Figure 3.  For example, the expression "3 * x + xˆ2/2" will be converted to an AST, as graphically illustrated in Figure 3. For example, the expression " 3 * +^2/2 " will be converted to an AST, as graphically illustrated in Figure 3. In fact, this AST is programmatically constructed in the parser as follows:

Codes added to
new Num (2)), new Num (2))) To improve the readability of all AST examples in this paper, we adapt a more elegant representation of the above AST like  (2)), Num (2)))

Evaluation of Mathematical Expressions
The phase of verifying the input data results in the construction of the related AST. The next phase handles the evaluation of this AST. In general, a mathematical expression can be evaluated in two approaches, either directly or using AST of that expression. The first approach refers to the evaluation of the token components of the expression during the verification phase of the parser. The other approach involves evaluating the AST representation of the expression visiting its token residing nodes. These two approaches are described in the following sections.

Direct Evaluation of Mathematical Expressions
The evaluation of simple mathematical expressions can be conducted at the time of parsing. In this case, there is no need to create any data structure from an input expression and the desired evaluation can directly be embedded in the parser. As seen in the previous section, it is possible to  (2)), new Num (2))) To improve the readability of all AST examples in this paper, we adapt a more elegant representation of the above AST like  (2)), Num(2)))

Evaluation of Mathematical Expressions
The phase of verifying the input data results in the construction of the related AST. The next phase handles the evaluation of this AST. In general, a mathematical expression can be evaluated in two approaches, either directly or using AST of that expression. The first approach refers to the evaluation of the token components of the expression during the verification phase of the parser. The other approach involves evaluating the AST representation of the expression visiting its token residing nodes. These two approaches are described in the following sections.

Direct Evaluation of Mathematical Expressions
The evaluation of simple mathematical expressions can be conducted at the time of parsing. In this case, there is no need to create any data structure from an input expression and the desired evaluation can directly be embedded in the parser. As seen in the previous section, it is possible to issue programming language statements in the process of utilizing parser generator tools. So, the desired operation can be performed by adding the evaluation code into the parser methods. As an example, let us consider calculating a mathematical expression based on a certain value of a variable. For this purpose, the value of the variable is passed as an argument to the methods. Within each method, the corresponding operation is performed on the related piece of the expression, and the result is returned, which can be a double. Listing 7 shows some of these methods of in JavaCC.
A significant difference between the functions given in Listing 5 and Listing 6 is associated with the type of their return values. The functions in Listing 6 must always return a number. Given a simple example of the expression "3x 3 + 7x + 1" evaluated for x = 2, the combined process of parameter passing and evaluation will return 39.
Listing 7. Some JavaCC functions for string-based evaluation.

Evaluation of Mathematical Expressions Using AST
This approach works on the intermediate representation of expressions, which is demonstrated through some particular applications of the methodology in this paper. As we know, the parsing process produces a hierarchical structure of objects with the components of a source expression, namely AST. For an example, input string "3x + xˆ2/2" will be converted by the parser into an AST as follows: Plus(Time(Num(3), Var()), Divide(Pow(Var(), Num (2)), Num (2))).eval() where the class constructor Var represents the variable x. For the expressions with more than one variable, we can pass the name of the variable as an argument to the constructor. In this paper, we basically use the approach of adding methods into syntax classes. However, in some cases, a combination of two approaches is required to implement the evaluation. In this way, the instanceof operator is mainly used in the methods that are added into the syntax classes. This is due to the need to identify the type of the child of each node, when these nodes are visited. To show the intermediate solution steps, when a node is visited, we need to know if that node has the child for further evaluation. For example, if the type of the child node is Num, it is clear that such nodes would need no more evaluation.

Representation of Mathematical Expressions
On each evaluation step of a mathematical expression through the relevant AST, the resulting expression needs converting into one of human-readable formats such as LaTex, or MathML. This is especially necessary to display the current expression in the AST modified by an evaluation process. Traversing AST with the technique of binary search will allow us to get the proper terms to construct the desired output. Figure 4 shows the AST of the expression "(3cos (x + 1))/2".

Representation of Mathematical Expressions
On each evaluation step of a mathematical expression through the relevant AST, the resulting expression needs converting into one of human-readable formats such as LaTex, or MathML. This is especially necessary to display the current expression in the AST modified by an evaluation process. Traversing AST with the technique of binary search will allow us to get the proper terms to construct the desired output. Figure 4 shows the AST of the expression "(3cos (x + 1))/2".  (1)))), Num (2)) To display mathematical expressions on AST, they can be converted to different formats which are addressed in the following sections.

Human-Readable Format
By applying the format-converting methods to each class, the required output format can be generated. Displaying mathematical expressions in human-readable format needs the conversion of the expressions in syntax tree to a string that can be obtained from binary traverse of AST. Table 4 shows the Print methods for some classes.

Class Name
Print Method   (1)))), Num (2)) To display mathematical expressions on AST, they can be converted to different formats which are addressed in the following sections.

Human-Readable Format
By applying the format-converting methods to each class, the required output format can be generated. Displaying mathematical expressions in human-readable format needs the conversion of the expressions in syntax tree to a string that can be obtained from binary traverse of AST. Table 4 shows the Print methods for some classes. Table 4. Print method added to classes to generate human-readable output.

Class Name
Print Method The output of these methods can directly be displayed to the user. Additional codes and methods can be added to produce more pretty results. The output of the methods will be an expression such as, for example, "(3cos(x + 1))/2".

LaTex Format
LaTex is widely used by scientific community. Similar to other formats of displaying AST in output, a LaTex document can be created by adding outputting codes to parser codes. Table 5 shows the LaTex method provided by some syntax classes, which outputs the Latex-formatted data.
MathML also accept LaTex input. Therefore, one can export the result to LaTex format and then use MathML renderer to display it. As mentioned before, LaTex is a very popular format and is supported by many other tools. Table 5. LaTex method to generate LaTex statements.

MathML Format
MathMl has become very popular due to its use in web-pages. To product a string in MathML format, it is possible to use built-in functions within MathML SDK. However, by adding some simple Print methods, this can also be achieved with AST.
As in the previous section, each syntax class has its own print method, but the output will be wrapped between MathML tags. For example, Num and Var classes must be surrounded with <mi> and <mo> tags, respectively. Table 6 shows the MathML method for some classes.  The output of this method requires MathML parser/render, where it needs to be linked within the web-page. As an example, the raw view of "(3cos(x + 1))/2" as well as its rendered form are displayed in Table 7. Table 7. MathML example of "(3cos(x + 1))/2".

Automatic Simplification
One of important and underlying operations in symbolic computation is simplification. However, it has many difficulties in implementation, because some concepts of simplification are naturally challenging. For example, responding the question "which part is simplified?" will justify this claim.
Automatic simplification is defined as a collection of algebraic and trigonometric simplified transformations that are applied to an expression as a part of the evaluation process. Table 8 shows some simplifications in classes using the basic transformations. Table 8. Simplifications performed in classes.

Original Term Object Tree Simplification Results
Transformations, similar to generating output from AST, can be achieved by inserting methods into the simplifier component. More than one transformation might be applied for a simple operator or class.
The result of the simplification process is also an AST. It can be used instead of the initial AST as it might speed-up the evaluation time if any simplification is performed. Table 9 shows some methods to implement the simplification.
The simplification of expressions is not limited to basic operations that are listed in Table 8. There are other transformations that can be applied by combining basic properties of some operators. The following are some of these samples. As a rule, all simplification methods will be applied until no change is made. Table 9. An implementation of some simplification methods.

Class Name Corresponding Method
Exp public abstract Exp Simplify();

Similar Operands
The summation of two expressions that have similar types, numbers or variables, can easily be performed. Operators are merged and replaced with their evaluation result or more general term, Figure 5.

Similar Operands
The summation of two expressions that have similar types, numbers or variables, can easily be performed. Operators are merged and replaced with their evaluation result or more general term, Figure 5.

Similar Operands on Different Levels
Similar operands might be at different levels of AST, therefore normal evaluation of these cases due to different types of operands cannot be performed. Assume that we want to simplify the expression "2 + x + 6 + x". The equivalent AST for this expression is "Plus(Num(2),Plus(Var(), Plus(Num(6),Var())))".
The expression in Figure 7 can be simplified to "8 + 2*x"; however, operand types differ at each level of tree. The solution to perform more accurate transformation for Plus is to change the tree from binary to a list and then check if any evaluation can be performed or not. Figure 8 shows the changed structure from Figure 7.

Similar Operands on Different Levels
Similar operands might be at different levels of AST, therefore normal evaluation of these cases due to different types of operands cannot be performed. Assume that we want to simplify the expression "2 + x + 6 + x". The equivalent AST for this expression is "Plus(Num(2),Plus(Var(), Plus(Num(6),Var())))".
The expression in Figure 7 can be simplified to "8 + 2*x"; however, operand types differ at each level of tree. The solution to perform more accurate transformation for Plus is to change the tree from binary to a list and then check if any evaluation can be performed or not. Figure 8 shows the changed structure from Figure 7.

Similar Operands on Different Levels
Similar operands might be at different levels of AST, therefore normal evaluation of these cases due to different types of operands cannot be performed. Assume that we want to simplify the expression "2 + x + 6 + x". The equivalent AST for this expression is "Plus(Num(2),Plus(Var(), Plus(Num(6),Var())))".
The expression in Figure 7 can be simplified to "8 + 2*x"; however, operand types differ at each level of tree. The solution to perform more accurate transformation for Plus is to change the tree from binary to a list and then check if any evaluation can be performed or not. Figure 8 shows the changed structure from Figure 7.  The summation can be applied for all operands in the list, as the operator is a Plus node. To   The summation can be applied for all operands in the list, as the operator is a Plus node. To implement this transformation in code, an array list is used to keep all operands of operator nodes. The same code can also be used for Minus, Multiply, and Division nodes.
In each operator node, or class, instead of similar operators, a list of all operands is collected and merged together. Listing 9 shows the related code for collecting the operands of all similar operator nodes. The summation can be applied for all operands in the list, as the operator is a Plus node. To implement this transformation in code, an array list is used to keep all operands of operator nodes. The same code can also be used for Minus, Multiply, and Division nodes.
In each operator node, or class, instead of similar operators, a list of all operands is collected and merged together. Listing 9 shows the related code for collecting the operands of all similar operator nodes. In Listing 9, mergeList() is a simple method that concatenates two lists. Using basic distributive transformation, the list will be simplified. To add the new result back to the main AST, a new parse will be performed over the result and it will be added as a sub-AST. It is quite possible that some other operators within the Plus or Minus nodes may exist. Therefore, it is also needed to do the same simplifications over those nodes. An example of expression "x + 3 + 2*x" is displayed in Figure 9. In Listing 9, mergeList() is a simple method that concatenates two lists. Using basic distributive transformation, the list will be simplified. To add the new result back to the main AST, a new parse will be performed over the result and it will be added as a sub-AST. It is quite possible that some other operators within the Plus or Minus nodes may exist. Therefore, it is also needed to do the same simplifications over those nodes. An example of expression "x + 3 + 2*x" is displayed in Figure 9. If no simplification can be done, the process will be aborted. Similar concept is true for other operators.

Fraction Simplification
Numbers and variables can be evaluated and simplified for a fraction operator. This case is similar to basic division transformation. If we consider the structure of the Multiply and Division operators alike, then we can perform the simplification for expressions that have both numbers and variables. Figure 10 shows both the tree and list views of expression "6x/12". If no simplification can be done, the process will be aborted. Similar concept is true for other operators.

Fraction Simplification
Numbers and variables can be evaluated and simplified for a fraction operator. This case is similar to basic division transformation. If we consider the structure of the Multiply and Division operators alike, then we can perform the simplification for expressions that have both numbers and variables. Figure 10 shows both the tree and list views of expression "6x/12".

Fraction Simplification
Numbers and variables can be evaluated and simplified for a fraction operator. This case is similar to basic division transformation. If we consider the structure of the Multiply and Division operators alike, then we can perform the simplification for expressions that have both numbers and variables. Figure 10 shows both the tree and list views of expression "6x/12". In such hybrid cases of numbers and variables, each type will individually be evaluated with the same type and then the results will be merged back as a sub-AST to main AST. In the cases that a number cannot completely be divided by another number, a way for simplifying a fraction is to eliminate common parts or greatest common divisor (GCD). A typical example of the expression "35/30" is shown in Figure 11. If one operand is a fraction, and the one on the other side an integer, then integer operand must be converted to a fraction and then be evaluated for simplifications.
Listing 10 shows changes in Divide class to perform this simplification. In such hybrid cases of numbers and variables, each type will individually be evaluated with the same type and then the results will be merged back as a sub-AST to main AST. In the cases that a number cannot completely be divided by another number, a way for simplifying a fraction is to eliminate common parts or greatest common divisor (GCD). A typical example of the expression "35/30" is shown in Figure 11. If no simplification can be done, the process will be aborted. Similar concept is true for other operators.

Fraction Simplification
Numbers and variables can be evaluated and simplified for a fraction operator. This case is similar to basic division transformation. If we consider the structure of the Multiply and Division operators alike, then we can perform the simplification for expressions that have both numbers and variables. Figure 10 shows both the tree and list views of expression "6x/12". In such hybrid cases of numbers and variables, each type will individually be evaluated with the same type and then the results will be merged back as a sub-AST to main AST. In the cases that a number cannot completely be divided by another number, a way for simplifying a fraction is to eliminate common parts or greatest common divisor (GCD). A typical example of the expression "35/30" is shown in Figure 11. If one operand is a fraction, and the one on the other side an integer, then integer operand must be converted to a fraction and then be evaluated for simplifications.
Listing 10 shows changes in Divide class to perform this simplification. If one operand is a fraction, and the one on the other side an integer, then integer operand must be converted to a fraction and then be evaluated for simplifications.
Listing 10 shows changes in Divide class to perform this simplification. If two operands of a fraction are fractions, then they need to be transformed into multiplications and a fraction. We use one of fraction properties for this case, which is shown in Figure 12. If two operands of a fraction are fractions, then they need to be transformed into multiplications and a fraction. We use one of fraction properties for this case, which is shown in Figure 12.  Other complex simplifications can be performed if operator types of Plus or Minus are multiplications or divisions. Here is an example that shows a fraction expression as operands.  This case indicates that if one side of the operator is a fraction, the other side should be a fraction, too. So it has to be converted into a fraction and then will be simplified as a whole new expression. Some modifications applied to the Simplify() method of Plus is displayed in Listing 12. The same portions of code must be implemented for other classes. However, code factoring can be applied to reduce the number of changes in base codes for each class.

Exponential Simplifications
The use of the power operator is very convenient due to the removal of repeated multiplications Other complex simplifications can be performed if operator types of Plus or Minus are multiplications or divisions. Here is an example that shows a fraction expression as operands. 16 8 This case indicates that if one side of the operator is a fraction, the other side should be a fraction, too. So it has to be converted into a fraction and then will be simplified as a whole new expression. Some modifications applied to the Simplify() method of Plus is displayed in Listing 12.  The same portions of code must be implemented for other classes. However, code factoring can be applied to reduce the number of changes in base codes for each class.

Exponential Simplifications
The use of the power operator is very convenient due to the removal of repeated multiplications for numbers and variables. The exponent part is placed on the top of base by a number or an expression, and refers to the number of times it is multiplied by itself.
The power operator and exponential expressions can be simplified in various ways. An example would be the expression x a b c that is equivalent to ((x a ) b ) c or x a*b*c in terms of left-associativity. All exponentials will be considered to be multiplies and will be replaced by only one exponential. Figure 14 shows an example. The power operator and exponential expressions can be simplified in various ways. An example would be the expression that is equivalent to (( ) ) or x a*b*c in terms of left-associativity. All exponentials will be considered to be multiplies and will be replaced by only one exponential. Figure 14 shows an example. In these cases the power operator can be changed to multiple operators. Duplicate powers always appear in exp1 (i.e., left child). It is possible to identify this situation, examining the value of exp1. The Simplify method for Power class must contain the codes in Listing 13. There is another interpretation of the power operator where the right side of the expression has higher precedence that is to say; the operator is right-associative. For example, the expression will be evaluated as , instead of (( ) ) . Also there are some other cases for power expressions such as u n .v n and u n .v m .

Removal of Radical Expression in Denomination
If a radical expression appears as a dominator, it can be removed by multiplying that expression In these cases the power operator can be changed to multiple operators. Duplicate powers always appear in exp1 (i.e., left child). It is possible to identify this situation, examining the value of exp1. The Simplify method for Power class must contain the codes in Listing 13. There is another interpretation of the power operator where the right side of the expression has higher precedence that is to say; the operator is right-associative. For example, the expression x a b c will be evaluated as x (a (b c ) ) , instead of ((x a ) b ) c . Also there are some other cases for power expressions such as u n .v n and u n .v m .

Removal of Radical Expression in Denomination
If a radical expression appears as a dominator, it can be removed by multiplying that expression to nominator and itself. An example is 1 √ x where the simplified form will be √ x x . Another example for this case where the expression 3x

Equality of Expressions
The isEquals() method checks if two expressions are equivalent. The elements of expressions can have different permutations; therefore, isEquals() should detect these differences. An example would be 3 + 12 + , + 3 + 12, and + 12 + 3 . Figure 16 shows the related AST for each of these expressions. However, checking the similarity of expressions seems computationally exhaustive. One solution is to check all permutation of operators and operands and find a matching one. Another solution is to divide two equations; if two equations are equal, then the result will be 1 and a value "true" will be returned. Before division, if nominator and denominator are both zero, then isEquals() directly will return true, which is defined as seen in Listing 15.  Listing 14 shows codes added to Divide class to cover this case.

Equality of Expressions
The isEquals() method checks if two expressions are equivalent. The elements of expressions can have different permutations; therefore, isEquals() should detect these differences. An example would be 3x + 12 + x 2 , x 2 + 3x + 12, and x 2 + 12 + 3x. Figure 16 shows the related AST for each of these expressions.

Equality of Expressions
The isEquals() method checks if two expressions are equivalent. The elements of expressions can have different permutations; therefore, isEquals() should detect these differences. An example would be 3 + 12 + , + 3 + 12, and + 12 + 3 . Figure 16 shows the related AST for each of these expressions. However, checking the similarity of expressions seems computationally exhaustive. One solution is to check all permutation of operators and operands and find a matching one. Another solution is to divide two equations; if two equations are equal, then the result will be 1 and a value "true" will be returned. Before division, if nominator and denominator are both zero, then isEquals() directly will return true, which is defined as seen in Listing 15.  However, checking the similarity of expressions seems computationally exhaustive. One solution is to check all permutation of operators and operands and find a matching one. Another solution is to divide two equations; if two equations are equal, then the result will be 1 and a value "true" will be returned. Before division, if nominator and denominator are both zero, then isEquals() directly will return true, which is defined as seen in Listing 15. In addition to those presented above, there are many other formulas and equations that can be simplified. Here are some transformations for which we develop some code in this work.
However, it is not easy to correctly decide the selection of the related components of an expression for some simplifications. Each component can be a part of different simplifications. The result of the simplification may differ from what one expects, which can be handled by some controlling methods that decide whether it should allow a formula to be factored, expanded or ignored.

Controlling the Step-by-Step Solution
One goal of the paper is to help students or users to see the solution steps for a given mathematical expression. The solution comes into existence once a user evaluates the expression in an AST. However, a step-by-step solution will increase the user's understanding of handling an expression. Besides, for hundreds of random expressions, the solution can be produced via the tool prepared with this work, which will be helpful to increase the math solving skill for students.
Automatic evaluation and simplification on an expression are discussed in the previous sections. The solution process uses a method of the recursive implementation of simplification transformations.
The eval() method invoked by the root element of an AST recursively calls the eval() methods of the children. This process will continue, until it reaches to the leaves which are only numbers or variables. The return value of each eval() method is a number, variable or another expression node. It is worth mentioning that, on assigning values to variables, the result will be always a number. Finally the result of the evaluated nodes will be displayed to the user.
Simplifying an expression slightly differs from evaluating it, where all variables should be kept as strings, and also performing each transformation might change the view of the final output. Considering these two properties, at some point, depending on if a user wants to see the steps of the solution, the transformations at each level must be reported.
There are two main techniques that can be used to show each transformation: 1. Print the transformation into an output buffer, and continue.

2.
Return to the root node after performing each transformation In the first technique, there should always be an object which we can use as a pointer to the address of the output buffer. However, it is also possible to use a static object, or a global method which is accessible by all AST nodes. Each node should call a method to report the changes and therefore, the method must be imported into the classes such as Plus, Multiply and Sin. Other approaches like addressing one node or retrieving parent nodes with the transformations to them also require extra methods and data to access the parent nodes.
However, in the second technique, a flag is used to check if a simplification should be performed or not. In this method, once a change is applied to the related AST, it triggers the flag and stops the simplification process for other nodes. The effect of this action will be only one change at a time, and therefore, it must be done with a loop. In each time, we reset the flag and then continue the process until there is no more simplifications to perform in which case the flag status stays the same. Listing 16 shows the main loop for simplifications.

Expression Simplification Control
Each step of simplification can be controlled by a class called Controls which denotes which transformation to perform or not. As an example, we use a skip simplification method, isSkipSimplifying(), when we want to return to the main loop and report the current state of the AST. Another example is hasError() where we can perform illegal evaluations like division by zero, negative value for root square, etc.
Varieties of other flags are used to control each transformation. Some of these flags are listed in Table 10. These flags are customizable for each object. Listing 18 shows an example of how to control the removal of a fraction in dominator.
The same controls can be added to other objects as well. However, to control errors, some code will be added to eval() method of each class. Division by zero and other mathematical errors are semantic ones that should have to be prevented. Syntactical errors have been resolved once we create AST, so no such errors will occur.

Conclusions and Results
In this paper, we propose a grammar-based methodology for step-by-step solving of mathematical problems. The methodology is basically designed to handle algebraic expressions that can be evaluated or simplified into a more concise form. From this perspective, on the contrary of numerical computation methods, we aim to produce the exact values of mathematical expressions, using symbolic computation approaches. There are many algebra-related topics such as simplification, factorization, distribution and substitution that can easily be covered by the solution methodology. The study currently supports univariate operations on these algebra topics, but can also be adapted to operate on multivariate expressions. It can make a crucial contribution to the practical application of mathematics via software. The underlying structure can be used to develop mathematical problem-solving systems. The other outcome can be the easier production of educational systems, where the intermediate solution steps of a problem can be integrated with such systems to fulfill regular learning or teaching requirements.
The form of expressions is represented via LL(1) grammars that exhibit an unambiguous aspect. Using the JavaCC tool, we develop LL(1) parsers which always follow a unique derivation for every kind of mathematical expressions. The implementation of such parsers is relatively easy as it involves the mapping of the grammar rules into corresponding methods. We illustrate the use of the tool through the implementation of the different parts of the solution methodology.
We model an input expression by using Abstract Syntax Tree (AST) which has a hierarchical structure. The tree represents the precedence and associativity of operators, and thus establishes the semantic-based relations among its nodes. It is quite possible to make the different interpretations of an AST, however, we use it to evaluate simplify and optimize the expressions. The well-known applications such as LISP and Maxima use a similar tree structure for manipulation of expressions.
Using AST, the step-by-step solutions for mathematical expressions are proposed. The simplification ways of equations and similar expressions are discussed. Simplifying a node in an AST simply depends on the type of that node. Different occurrences of an operator or function node and its children confront different simplifications or transformations. Each transformation resolves a part of the complexity that exists in a node.
AST supports the execution of the evaluating operations in a recursive manner. In this way, the simplification process goes down in the tree until it encounters the leaves that contain numbers or variables and terminates when transformation cannot further be applied to the tree. However, there are some special cases where we need to define control flags, for example, to decide how to use algebraic identities (i.e., product and factoring formulas). This is to prevent those formulas from triggering several times, ensuring that no infinite loops occur.
A different type of mathematical expressions requires a different style of simplification. We introduce some basic and sophisticated transformations on AST nodes, but they can be extended to construct new ones operating on other states of nodes. The examples of basic transformations are commutative and power, and the examples of sophisticated transformations are linearization of nested operators; fraction, power and radical simplifications, and radical removal from fractions.
In terms of the step-by-step solution, these transformations of the simplification process are considered as the steps of solving the problem. The result of each transformation is a new AST; therefore this operation advances the solution one step towards the final one.
Various documents or reports can be produced to print the applied transformations and the resulting expression. We prefer to use a document formatting system in which the content of AST is printed. The differences between two consecutive prints of the output show the progress of solving the given input through a symbolic computation system.
The evaluation of AST is quite simple. The tree contains variables and numbers, therefore by initializing variables such as x, a, and b into some values, the numerical result can be calculated.
Several experiments are conducted to compare the benefits and drawbacks of the proposed methodology. We use Matlab Symbolic Computation Toolbox and a real person as our test competitors. The results are listed in Table 11. Table 11. Symbolic calculation of some math questions.